summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arc/lib/bootm.c8
-rw-r--r--arch/arm/lib/bootm.c50
-rw-r--r--arch/m68k/lib/bootm.c2
-rw-r--r--arch/microblaze/lib/bootm.c8
-rw-r--r--arch/mips/lib/bootm.c7
-rw-r--r--arch/nios2/lib/bootm.c2
-rw-r--r--arch/powerpc/lib/bootm.c7
-rw-r--r--arch/riscv/include/asm/u-boot-riscv.h1
-rw-r--r--arch/riscv/lib/bootm.c39
-rw-r--r--arch/sandbox/lib/bootm.c1
-rw-r--r--arch/sh/lib/bootm.c2
-rw-r--r--arch/x86/lib/bootm.c14
-rw-r--r--arch/xtensa/lib/bootm.c2
-rw-r--r--boot/bootm.c25
-rw-r--r--drivers/core/device-remove.c34
-rw-r--r--include/bootm.h10
-rw-r--r--include/bootstage.h8
17 files changed, 90 insertions, 130 deletions
diff --git a/arch/arc/lib/bootm.c b/arch/arc/lib/bootm.c
index 91bce5235a5..91165a06a46 100644
--- a/arch/arc/lib/bootm.c
+++ b/arch/arc/lib/bootm.c
@@ -50,17 +50,13 @@ static void boot_jump_linux(struct bootm_headers *images, int flag)
{
ulong kernel_entry;
unsigned int r0, r2;
- int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
-
kernel_entry = images->ep;
debug("## Transferring control to Linux (at address %08lx)...\n",
kernel_entry);
bootstage_mark(BOOTSTAGE_ID_RUN_OS);
- printf("\nStarting kernel ...%s\n\n", fake ?
- "(fake run for tracing)" : "");
- bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
+ bootm_final(flag);
if (CONFIG_IS_ENABLED(OF_LIBFDT) && images->ft_len) {
r0 = 2;
@@ -72,7 +68,7 @@ static void boot_jump_linux(struct bootm_headers *images, int flag)
cleanup_before_linux();
- if (!fake)
+ if (!(flag & BOOTM_STATE_OS_FAKE_GO))
board_jump_and_run(kernel_entry, r0, 0, r2);
}
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 019eca95780..727b9c5ca5b 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -42,42 +42,6 @@ DECLARE_GLOBAL_DATA_PTR;
static struct tag *params;
-__weak void board_quiesce_devices(void)
-{
-}
-
-/**
- * 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)
-{
- bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
-#ifdef CONFIG_BOOTSTAGE_FDT
- bootstage_fdt_add_report();
-#endif
- bootstage_stash_default();
-#ifdef CONFIG_BOOTSTAGE_REPORT
- bootstage_report();
-#endif
-
- board_quiesce_devices();
-
- printf("\nStarting kernel ...%s\n\n", fake ?
- "(fake run for tracing)" : "");
- /*
- * 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_active() ensures that vital devices are removed in
- * a second round.
- */
- dm_remove_devices_active();
-
- cleanup_before_linux();
-}
-
static void setup_start_tag (struct bd_info *bd)
{
params = (struct tag *)bd->bi_boot_params;
@@ -294,8 +258,6 @@ static void boot_jump_linux(struct bootm_headers *images, int flag)
{
void (*kernel_entry)(void *fdt_addr, void *res0, void *res1,
void *res2);
- int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
-
kernel_entry = (void (*)(void *fdt_addr, void *res0, void *res1,
void *res2))images->ep;
@@ -303,9 +265,10 @@ static void boot_jump_linux(struct bootm_headers *images, int flag)
(ulong) kernel_entry);
bootstage_mark(BOOTSTAGE_ID_RUN_OS);
- announce_and_cleanup(fake);
+ bootm_final(flag);
+ cleanup_before_linux();
- if (!fake) {
+ if (!(flag & BOOTM_STATE_OS_FAKE_GO)) {
#ifdef CONFIG_ARMV8_PSCI
armv8_setup_psci();
#endif
@@ -340,8 +303,6 @@ static void boot_jump_linux(struct bootm_headers *images, int flag)
char *s;
void (*kernel_entry)(int zero, int arch, uint params);
unsigned long r2;
- int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
-
kernel_entry = (void (*)(int, int, uint))images->ep;
#ifdef CONFIG_CPU_V7M
ulong addr = (ulong)kernel_entry | 1;
@@ -366,14 +327,15 @@ static void boot_jump_linux(struct bootm_headers *images, int flag)
debug("## Transferring control to Linux (at address %08lx)" \
"...\n", (ulong) kernel_entry);
bootstage_mark(BOOTSTAGE_ID_RUN_OS);
- announce_and_cleanup(fake);
+ bootm_final(flag);
+ cleanup_before_linux();
if (CONFIG_IS_ENABLED(OF_LIBFDT) && images->ft_len)
r2 = (unsigned long)images->ft_addr;
else
r2 = gd->bd->bi_boot_params;
- if (fake)
+ if (flag & BOOTM_STATE_OS_FAKE_GO)
return;
#ifdef CONFIG_ARMV7_NONSEC
diff --git a/arch/m68k/lib/bootm.c b/arch/m68k/lib/bootm.c
index 1fa112f8dbf..7d65f3ea1a8 100644
--- a/arch/m68k/lib/bootm.c
+++ b/arch/m68k/lib/bootm.c
@@ -62,6 +62,8 @@ int do_bootm_linux(int flag, struct bootm_info *bmi)
bootstage_mark(BOOTSTAGE_ID_RUN_OS);
+ bootm_final(0);
+
/*
* Linux Kernel Parameters (passing board info data):
* sp+00: Ignore, side effect of using jsr to jump to kernel
diff --git a/arch/microblaze/lib/bootm.c b/arch/microblaze/lib/bootm.c
index 2410515f4ac..b54c902602f 100644
--- a/arch/microblaze/lib/bootm.c
+++ b/arch/microblaze/lib/bootm.c
@@ -26,8 +26,6 @@ static void boot_jump_linux(struct bootm_headers *images, int flag)
ulong dt = (ulong)images->ft_addr;
ulong rd_start = images->initrd_start;
ulong cmdline = images->cmdline_start;
- int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
-
thekernel = (void (*)(char *, ulong, ulong))images->ep;
debug("## Transferring control to Linux (at address 0x%08lx) ",
@@ -36,13 +34,11 @@ static void boot_jump_linux(struct bootm_headers *images, int flag)
cmdline, rd_start, dt);
bootstage_mark(BOOTSTAGE_ID_RUN_OS);
- printf("\nStarting kernel ...%s\n\n", fake ?
- "(fake run for tracing)" : "");
- bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
+ bootm_final(flag);
flush_cache_all();
- if (!fake) {
+ if (!(flag & BOOTM_STATE_OS_FAKE_GO)) {
/*
* Linux Kernel Parameters (passing device tree):
* r5: pointer to command line
diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
index 87195100023..066c830f3fa 100644
--- a/arch/mips/lib/bootm.c
+++ b/arch/mips/lib/bootm.c
@@ -268,12 +268,7 @@ static void boot_jump_linux(struct bootm_headers *images)
if (CONFIG_IS_ENABLED(MALTA))
linux_extra = gd->ram_size;
-#if IS_ENABLED(CONFIG_BOOTSTAGE_FDT)
- bootstage_fdt_add_report();
-#endif
-#if IS_ENABLED(CONFIG_BOOTSTAGE_REPORT)
- bootstage_report();
-#endif
+ bootm_final(0);
if (CONFIG_IS_ENABLED(RESTORE_EXCEPTION_VECTOR_BASE))
trap_restore();
diff --git a/arch/nios2/lib/bootm.c b/arch/nios2/lib/bootm.c
index 294ebfb508b..6004e83bf0c 100644
--- a/arch/nios2/lib/bootm.c
+++ b/arch/nios2/lib/bootm.c
@@ -41,6 +41,8 @@ int do_bootm_linux(int flag, struct bootm_info *bmi)
if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
return 1;
+ bootm_final(0);
+
/* flushes data and instruction caches before calling the kernel */
disable_interrupts();
flush_dcache_all();
diff --git a/arch/powerpc/lib/bootm.c b/arch/powerpc/lib/bootm.c
index dc44bf3ab3a..f9351a17a48 100644
--- a/arch/powerpc/lib/bootm.c
+++ b/arch/powerpc/lib/bootm.c
@@ -54,12 +54,7 @@ static void boot_jump_linux(struct bootm_headers *images)
bootstage_mark(BOOTSTAGE_ID_RUN_OS);
-#ifdef CONFIG_BOOTSTAGE_FDT
- bootstage_fdt_add_report();
-#endif
-#ifdef CONFIG_BOOTSTAGE_REPORT
- bootstage_report();
-#endif
+ bootm_final(0);
#if defined(CONFIG_SYS_INIT_RAM_LOCK) && !defined(CONFIG_E500)
unlock_ram_in_cache();
diff --git a/arch/riscv/include/asm/u-boot-riscv.h b/arch/riscv/include/asm/u-boot-riscv.h
index 543a1688db8..3a8fdb57136 100644
--- a/arch/riscv/include/asm/u-boot-riscv.h
+++ b/arch/riscv/include/asm/u-boot-riscv.h
@@ -16,7 +16,6 @@ int cleanup_before_linux(void);
/* board/.../... */
int board_init(void);
-void board_quiesce_devices(void);
int riscv_board_reserved_mem_fixup(void *fdt);
int riscv_fdt_copy_resv_mem_node(const void *src_fdt, void *dest_fdt);
diff --git a/arch/riscv/lib/bootm.c b/arch/riscv/lib/bootm.c
index 9544907ab1e..69c9ca5c487 100644
--- a/arch/riscv/lib/bootm.c
+++ b/arch/riscv/lib/bootm.c
@@ -25,39 +25,6 @@
DECLARE_GLOBAL_DATA_PTR;
-__weak void board_quiesce_devices(void)
-{
-}
-
-/**
- * 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)
-{
- 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
-#if CONFIG_IS_ENABLED(BOOTSTAGE_REPORT)
- bootstage_report();
-#endif
-
- board_quiesce_devices();
-
- /*
- * 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_active();
-
- cleanup_before_linux();
-}
-
static void boot_prep_linux(struct bootm_headers *images)
{
if (CONFIG_IS_ENABLED(OF_LIBFDT) && IS_ENABLED(CONFIG_LMB) && images->ft_len) {
@@ -75,7 +42,6 @@ static void boot_prep_linux(struct bootm_headers *images)
static void boot_jump_linux(struct bootm_headers *images, int flag)
{
void (*kernel)(ulong hart, void *dtb);
- int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
#ifdef CONFIG_SMP
int ret;
#endif
@@ -87,9 +53,10 @@ static void boot_jump_linux(struct bootm_headers *images, int flag)
debug("## Transferring control to kernel (at address %08lx) ...\n",
(ulong)kernel);
- announce_and_cleanup(fake);
+ bootm_final(flag);
+ cleanup_before_linux();
- if (!fake) {
+ if (!(flag & BOOTM_STATE_OS_FAKE_GO)) {
if (CONFIG_IS_ENABLED(OF_LIBFDT) && images->ft_len) {
#ifdef CONFIG_SMP
ret = smp_call_function(images->ep,
diff --git a/arch/sandbox/lib/bootm.c b/arch/sandbox/lib/bootm.c
index 44ba8b52e13..7a5f6f7d36e 100644
--- a/arch/sandbox/lib/bootm.c
+++ b/arch/sandbox/lib/bootm.c
@@ -73,6 +73,7 @@ int do_bootm_linux(int flag, struct bootm_info *bmi)
if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) {
bootstage_mark(BOOTSTAGE_ID_RUN_OS);
+ bootm_final(flag);
printf("## Transferring control to Linux (at address %08lx)...\n",
images->ep);
printf("sandbox: continuing, as we cannot run Linux\n");
diff --git a/arch/sh/lib/bootm.c b/arch/sh/lib/bootm.c
index 1c118870dad..81d5957edaa 100644
--- a/arch/sh/lib/bootm.c
+++ b/arch/sh/lib/bootm.c
@@ -92,6 +92,8 @@ int do_bootm_linux(int flag, struct bootm_info *bmi)
images->rd_end - images->rd_start);
}
+ bootm_final(0);
+
/* Boot kernel */
kernel();
diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c
index 7a94dc877e3..cde4fbf3557 100644
--- a/arch/x86/lib/bootm.c
+++ b/arch/x86/lib/bootm.c
@@ -34,22 +34,10 @@ DECLARE_GLOBAL_DATA_PTR;
void bootm_announce_and_cleanup(void)
{
- printf("\nStarting kernel ...\n\n");
-
#ifdef CONFIG_SYS_COREBOOT
timestamp_add_now(TS_START_KERNEL);
#endif
- bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
-#if IS_ENABLED(CONFIG_BOOTSTAGE_REPORT)
- bootstage_report();
-#endif
-
- /*
- * 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_active();
+ bootm_final(0);
}
#if defined(CONFIG_OF_LIBFDT) && !defined(CONFIG_OF_NO_KERNEL)
diff --git a/arch/xtensa/lib/bootm.c b/arch/xtensa/lib/bootm.c
index 2958f207397..c19ac9d1f9a 100644
--- a/arch/xtensa/lib/bootm.c
+++ b/arch/xtensa/lib/bootm.c
@@ -178,6 +178,8 @@ int do_bootm_linux(int flag, struct bootm_info *bmi)
printf("Transferring Control to Linux @0x%08lx ...\n\n",
(ulong)images->ep);
+ bootm_final(flag);
+
flush_dcache_range((unsigned long)params_start, (unsigned long)params);
if (flag & BOOTM_STATE_OS_FAKE_GO)
diff --git a/boot/bootm.c b/boot/bootm.c
index 280efb26e90..4836d6b2d41 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -7,6 +7,7 @@
#ifndef USE_HOSTCC
#include <bootm.h>
#include <bootstage.h>
+#include <dm/root.h>
#include <cli.h>
#include <command.h>
#include <cpu_func.h>
@@ -1194,6 +1195,30 @@ void __weak switch_to_non_secure_mode(void)
{
}
+void bootm_final(int flag)
+{
+ printf("\nStarting kernel ...%s\n\n",
+ (flag & BOOTM_STATE_OS_FAKE_GO) ?
+ " (fake run for tracing)" : "");
+
+ bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
+
+ if (IS_ENABLED(CONFIG_BOOTSTAGE_FDT) && IS_ENABLED(CONFIG_CMD_FDT))
+ bootstage_fdt_add_report();
+ bootstage_stash_default();
+ if (IS_ENABLED(CONFIG_BOOTSTAGE_REPORT))
+ bootstage_report();
+
+ board_quiesce_devices();
+
+ /*
+ * 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_active();
+}
+
#else /* USE_HOSTCC */
#if defined(CONFIG_FIT_SIGNATURE)
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index 437080ed778..557afb8d817 100644
--- a/drivers/core/device-remove.c
+++ b/drivers/core/device-remove.c
@@ -198,7 +198,7 @@ static int flags_remove(uint flags, uint drv_flags)
int device_remove(struct udevice *dev, uint flags)
{
const struct driver *drv;
- int ret;
+ int ret, cret;
if (!dev)
return -EINVAL;
@@ -211,24 +211,34 @@ int device_remove(struct udevice *dev, uint flags)
return ret;
/*
+ * Remove the device if called with the "normal" remove flag set,
+ * or if the remove flag matches any of the drivers remove flags
+ */
+ drv = dev->driver;
+ assert(drv);
+ cret = flags_remove(flags, drv->flags);
+
+ /*
+ * Remove all children. If this device is being removed due to
+ * active-DMA or OS-prepare flags, drop the active-flag requirement
+ * for children so they are removed even without matching active
+ * flags, since a deactivated device must not have activated
+ * children. Preserve other flags (e.g. DM_REMOVE_NON_VITAL) so
+ * that vital children are still protected.
+ *
* If the child returns EKEYREJECTED, continue. It just means that it
* didn't match the flags.
*/
- ret = device_chld_remove(dev, NULL, flags);
+ ret = device_chld_remove(dev, NULL,
+ cret ? flags :
+ (flags & ~DM_REMOVE_ACTIVE_ALL));
if (ret && ret != -EKEYREJECTED)
return ret;
- /*
- * Remove the device if called with the "normal" remove flag set,
- * or if the remove flag matches any of the drivers remove flags
- */
- drv = dev->driver;
- assert(drv);
- ret = flags_remove(flags, drv->flags);
- if (ret) {
+ if (cret) {
log_debug("%s: When removing: flags=%x, drv->flags=%x, err=%d\n",
- dev->name, flags, drv->flags, ret);
- return ret;
+ dev->name, flags, drv->flags, cret);
+ return cret;
}
ret = uclass_pre_remove_device(dev);
diff --git a/include/bootm.h b/include/bootm.h
index 4060cec7fc0..f6958be751a 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -321,4 +321,14 @@ void zimage_dump(struct boot_params *base_ptr, bool show_cmdline);
*/
int bootm_boot_start(ulong addr, const char *cmdline);
+/**
+ * bootm_final() - Announce and do cleanup before boot
+ *
+ * This performs the common pre-boot steps: printing the "Starting kernel"
+ * message, recording bootstage data, and removing active devices.
+ *
+ * @flag: Boot state flags (BOOTM_STATE_OS_FAKE_GO prints a fake-run message)
+ */
+void bootm_final(int flag);
+
#endif
diff --git a/include/bootstage.h b/include/bootstage.h
index 528d0ca0614..62fb99110f0 100644
--- a/include/bootstage.h
+++ b/include/bootstage.h
@@ -435,6 +435,14 @@ static inline uint32_t bootstage_accum(enum bootstage_id id)
return 0;
}
+static inline void bootstage_report(void)
+{
+}
+
+static inline void bootstage_fdt_add_report(void)
+{
+}
+
static inline int bootstage_stash(void *base, int size)
{
return 0; /* Pretend to succeed */