[U-Boot] [PATCH v2 26/29] riscv: align bootm implementation with that of other architectures

Lukas Auer lukas.auer at aisec.fraunhofer.de
Tue Oct 30 12:55:49 UTC 2018


The bootm implementation of RISC-V diverges from that of other
architectures. Update it to match the implementation of other
architectures. The ARM implementation is used as a reference.

This adds the following features and changes to RISC-V.
* Add support for the BOOTM_STATE_OS_FAKE_GO command
* Call the remove function on devices with the removal flag set before
booting Linux
* Force disconnect USB devices from the host before booting Linux
* Print and add bootstage information to the device tree before booting
Linux

Signed-off-by: Lukas Auer <lukas.auer at aisec.fraunhofer.de>
Reviewed-by: Bin Meng <bmeng.cn at gmail.com>
---

Changes in v2:
- Rebase onto u-boot-dm/next

 arch/riscv/lib/bootm.c | 99 ++++++++++++++++++++++++++++++------------
 1 file changed, 71 insertions(+), 28 deletions(-)

diff --git a/arch/riscv/lib/bootm.c b/arch/riscv/lib/bootm.c
index c1cf618806..4e349f5614 100644
--- a/arch/riscv/lib/bootm.c
+++ b/arch/riscv/lib/bootm.c
@@ -8,6 +8,8 @@
 
 #include <common.h>
 #include <command.h>
+#include <dm.h>
+#include <dm/root.h>
 #include <image.h>
 #include <asm/byteorder.h>
 #include <asm/csr.h>
@@ -26,27 +28,41 @@ int arch_fixup_fdt(void *blob)
 	return 0;
 }
 
-int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
+/**
+ * announce_and_cleanup() - Print message and prepare for kernel boot
+ *
+ * @fake: non-zero to do everything except actually boot
+ */
+static void announce_and_cleanup(int fake)
 {
-	void	(*kernel)(ulong hart, void *dtb);
-
-	/*
-	 * allow the PREP bootm subcommand, it is required for bootm to work
-	 */
-	if (flag & BOOTM_STATE_OS_PREP)
-		return 0;
+	printf("\nStarting kernel ...%s\n\n", fake ?
+		"(fake run for tracing)" : "");
+	bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
+#ifdef CONFIG_BOOTSTAGE_FDT
+	bootstage_fdt_add_report();
+#endif
+#ifdef CONFIG_BOOTSTAGE_REPORT
+	bootstage_report();
+#endif
 
-	if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
-		return 1;
+#ifdef CONFIG_USB_DEVICE
+	udc_disconnect();
+#endif
 
-	kernel = (void (*)(ulong, void *))images->ep;
-	invalidate_icache_all();
+	board_quiesce_devices();
 
-	bootstage_mark(BOOTSTAGE_ID_RUN_OS);
+	/*
+	 * Call remove function of all devices with a removal flag set.
+	 * This may be useful for last-stage operations, like cancelling
+	 * of DMA operation or releasing device internal buffers.
+	 */
+	dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
 
-	debug("## Transferring control to Linux (at address %08lx) ...\n",
-	       (ulong)kernel);
+	cleanup_before_linux();
+}
 
+static void boot_prep_linux(bootm_headers_t *images)
+{
 	if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) {
 #ifdef CONFIG_OF_LIBFDT
 		debug("using: FDT\n");
@@ -55,24 +71,51 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
 			hang();
 		}
 #endif
+	} else {
+		printf("Device tree not found or missing FDT support\n");
+		hang();
 	}
+}
 
-	/* we assume that the kernel is in place */
-	printf("\nStarting kernel ...\n\n");
+static void boot_jump_linux(bootm_headers_t *images, int flag)
+{
+	void (*kernel)(ulong hart, void *dtb);
+	int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
 
-	/*
-	 * Call remove function of all devices with a removal flag set.
-	 * This may be useful for last-stage operations, like cancelling
-	 * of DMA operation or releasing device internal buffers.
-	 */
-	dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
+	kernel = (void (*)(ulong, void *))images->ep;
+	invalidate_icache_all();
 
-	cleanup_before_linux();
+	bootstage_mark(BOOTSTAGE_ID_RUN_OS);
 
-	if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
-		kernel(csr_read(mhartid), images->ft_addr);
+	debug("## Transferring control to Linux (at address %08lx) ...\n",
+	      (ulong)kernel);
 
-	/* does not return */
+	announce_and_cleanup(fake);
 
-	return 1;
+	if (!fake) {
+		if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
+			kernel(csr_read(mhartid), images->ft_addr);
+	}
+}
+
+int do_bootm_linux(int flag, int argc, char * const argv[],
+		   bootm_headers_t *images)
+{
+	/* No need for those on RISC-V */
+	if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)
+		return -1;
+
+	if (flag & BOOTM_STATE_OS_PREP) {
+		boot_prep_linux(images);
+		return 0;
+	}
+
+	if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) {
+		boot_jump_linux(images, flag);
+		return 0;
+	}
+
+	boot_prep_linux(images);
+	boot_jump_linux(images, flag);
+	return 0;
 }
-- 
2.17.2



More information about the U-Boot mailing list