summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/lib/bdinfo.c16
-rw-r--r--arch/arm/lib/bootm.c3
-rw-r--r--arch/arm/mach-rockchip/sdram.c2
-rw-r--r--arch/m68k/lib/bdinfo.c2
-rw-r--r--arch/powerpc/lib/bdinfo.c4
-rw-r--r--arch/riscv/cpu/fu540/dram.c7
-rw-r--r--arch/riscv/cpu/generic/dram.c7
-rw-r--r--arch/riscv/include/asm/types.h4
-rw-r--r--arch/x86/cpu/qfw_cpu.c6
-rw-r--r--board/AndesTech/ax25-ae350/ax25-ae350.c2
-rw-r--r--cmd/bdinfo.c52
-rw-r--r--cmd/efidebug.c5
-rw-r--r--cmd/pxe_utils.c53
-rw-r--r--doc/driver-model/design.rst26
-rw-r--r--doc/usage/exception.rst5
-rw-r--r--doc/usage/index.rst1
-rw-r--r--doc/usage/load.rst74
-rw-r--r--drivers/core/device-remove.c96
-rw-r--r--drivers/core/root.c2
-rw-r--r--drivers/firmware/scmi/sandbox-scmi_devices.c3
-rw-r--r--drivers/mtd/nand/raw/brcmnand/brcmnand.c5
-rw-r--r--drivers/net/ftmac100.c10
-rw-r--r--drivers/pci/pcie_iproc.c2
-rw-r--r--drivers/serial/serial_sifive.c2
-rw-r--r--drivers/smem/msm_smem.c6
-rw-r--r--drivers/video/meson/meson_vpu.c2
-rw-r--r--drivers/watchdog/rti_wdt.c2
-rw-r--r--fs/fat/fat_write.c70
-rw-r--r--include/asm-generic/global_data.h2
-rw-r--r--include/command.h57
-rw-r--r--include/dm/device-internal.h15
-rw-r--r--include/dm/device.h15
-rw-r--r--include/init.h3
-rw-r--r--include/os.h2
-rw-r--r--lib/efi_loader/efi_device_path_to_text.c15
-rw-r--r--lib/efi_loader/efi_disk.c15
-rw-r--r--lib/efi_loader/efi_dt_fixup.c25
-rw-r--r--lib/efi_selftest/dtbdump.c85
-rw-r--r--lib/fdtdec.c2
-rw-r--r--test/dm/core.c94
-rw-r--r--test/dm/test-driver.c22
-rw-r--r--test/dm/virtio.c4
42 files changed, 582 insertions, 243 deletions
diff --git a/arch/arm/lib/bdinfo.c b/arch/arm/lib/bdinfo.c
index 25bc6e80f47..c905783bdc8 100644
--- a/arch/arm/lib/bdinfo.c
+++ b/arch/arm/lib/bdinfo.c
@@ -15,23 +15,23 @@ void arch_print_bdinfo(void)
{
struct bd_info *bd = gd->bd;
- bdinfo_print_num("arch_number", bd->bi_arch_number);
+ bdinfo_print_num_l("arch_number", bd->bi_arch_number);
#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
if (gd->arch.secure_ram & MEM_RESERVE_SECURE_SECURED) {
- bdinfo_print_num("Secure ram",
- gd->arch.secure_ram &
- MEM_RESERVE_SECURE_ADDR_MASK);
+ bdinfo_print_num_ll("Secure ram",
+ gd->arch.secure_ram &
+ MEM_RESERVE_SECURE_ADDR_MASK);
}
#endif
#ifdef CONFIG_RESV_RAM
if (gd->arch.resv_ram)
- bdinfo_print_num("Reserved ram", gd->arch.resv_ram);
+ bdinfo_print_num_ll("Reserved ram", gd->arch.resv_ram);
#endif
#if !(CONFIG_IS_ENABLED(SYS_ICACHE_OFF) && CONFIG_IS_ENABLED(SYS_DCACHE_OFF))
- bdinfo_print_num("TLB addr", gd->arch.tlb_addr);
+ bdinfo_print_num_l("TLB addr", gd->arch.tlb_addr);
#endif
- bdinfo_print_num("irq_sp", gd->irq_sp); /* irq stack pointer */
- bdinfo_print_num("sp start ", gd->start_addr_sp);
+ bdinfo_print_num_l("irq_sp", gd->irq_sp); /* irq stack pointer */
+ bdinfo_print_num_l("sp start ", gd->start_addr_sp);
/*
* TODO: Currently only support for davinci SOC's is added.
* Remove this check once all the board implement this.
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 1206e306db6..f46d51d6553 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -119,6 +119,9 @@ static void announce_and_cleanup(int fake)
* 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 | DM_REMOVE_NON_VITAL);
+
+ /* Remove all active vital devices next */
dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
cleanup_before_linux();
diff --git a/arch/arm/mach-rockchip/sdram.c b/arch/arm/mach-rockchip/sdram.c
index 4c637b77673..c3d5fed7db3 100644
--- a/arch/arm/mach-rockchip/sdram.c
+++ b/arch/arm/mach-rockchip/sdram.c
@@ -37,7 +37,7 @@ struct tos_parameter_t {
int dram_init_banksize(void)
{
size_t top = min((unsigned long)(gd->ram_size + CONFIG_SYS_SDRAM_BASE),
- gd->ram_top);
+ (unsigned long)(gd->ram_top));
#ifdef CONFIG_ARM64
/* Reserve 0x200000 for ATF bl31 */
diff --git a/arch/m68k/lib/bdinfo.c b/arch/m68k/lib/bdinfo.c
index 404e5f19ed8..92ea1752023 100644
--- a/arch/m68k/lib/bdinfo.c
+++ b/arch/m68k/lib/bdinfo.c
@@ -38,7 +38,7 @@ void arch_print_bdinfo(void)
bdinfo_print_mhz("busfreq", bd->bi_busfreq);
#if defined(CONFIG_SYS_MBAR)
- bdinfo_print_num("mbar", bd->bi_mbar_base);
+ bdinfo_print_num_l("mbar", bd->bi_mbar_base);
#endif
bdinfo_print_mhz("cpufreq", bd->bi_intfreq);
if (IS_ENABLED(CONFIG_PCI))
diff --git a/arch/powerpc/lib/bdinfo.c b/arch/powerpc/lib/bdinfo.c
index 36c9c99ee6f..b14e75b68ab 100644
--- a/arch/powerpc/lib/bdinfo.c
+++ b/arch/powerpc/lib/bdinfo.c
@@ -47,9 +47,9 @@ void arch_print_bdinfo(void)
bdinfo_print_mhz("busfreq", bd->bi_busfreq);
#if defined(CONFIG_MPC8xx) || defined(CONFIG_E500)
- bdinfo_print_num("immr_base", bd->bi_immr_base);
+ bdinfo_print_num_l("immr_base", bd->bi_immr_base);
#endif
- bdinfo_print_num("bootflags", bd->bi_bootflags);
+ bdinfo_print_num_l("bootflags", bd->bi_bootflags);
bdinfo_print_mhz("intfreq", bd->bi_intfreq);
#ifdef CONFIG_ENABLE_36BIT_PHYS
if (IS_ENABLED(CONFIG_PHYS_64BIT))
diff --git a/arch/riscv/cpu/fu540/dram.c b/arch/riscv/cpu/fu540/dram.c
index 1dc77efeca5..259da65a545 100644
--- a/arch/riscv/cpu/fu540/dram.c
+++ b/arch/riscv/cpu/fu540/dram.c
@@ -22,7 +22,6 @@ int dram_init_banksize(void)
ulong board_get_usable_ram_top(ulong total_size)
{
-#ifdef CONFIG_64BIT
/*
* Ensure that we run from first 4GB so that all
* addresses used by U-Boot are 32bit addresses.
@@ -31,8 +30,8 @@ ulong board_get_usable_ram_top(ulong total_size)
* devices work fine because DMA mapping APIs will
* provide 32bit DMA addresses only.
*/
- if (gd->ram_top > SZ_4G)
- return SZ_4G;
-#endif
+ if (gd->ram_top >= SZ_4G)
+ return SZ_4G - 1;
+
return gd->ram_top;
}
diff --git a/arch/riscv/cpu/generic/dram.c b/arch/riscv/cpu/generic/dram.c
index 1dc77efeca5..259da65a545 100644
--- a/arch/riscv/cpu/generic/dram.c
+++ b/arch/riscv/cpu/generic/dram.c
@@ -22,7 +22,6 @@ int dram_init_banksize(void)
ulong board_get_usable_ram_top(ulong total_size)
{
-#ifdef CONFIG_64BIT
/*
* Ensure that we run from first 4GB so that all
* addresses used by U-Boot are 32bit addresses.
@@ -31,8 +30,8 @@ ulong board_get_usable_ram_top(ulong total_size)
* devices work fine because DMA mapping APIs will
* provide 32bit DMA addresses only.
*/
- if (gd->ram_top > SZ_4G)
- return SZ_4G;
-#endif
+ if (gd->ram_top >= SZ_4G)
+ return SZ_4G - 1;
+
return gd->ram_top;
}
diff --git a/arch/riscv/include/asm/types.h b/arch/riscv/include/asm/types.h
index b800b2d221b..49f7a5d6b3a 100644
--- a/arch/riscv/include/asm/types.h
+++ b/arch/riscv/include/asm/types.h
@@ -35,8 +35,8 @@ typedef u64 dma_addr_t;
typedef u32 dma_addr_t;
#endif
-typedef unsigned long phys_addr_t;
-typedef unsigned long phys_size_t;
+typedef unsigned long long phys_addr_t;
+typedef unsigned long long phys_size_t;
#endif /* __KERNEL__ */
diff --git a/arch/x86/cpu/qfw_cpu.c b/arch/x86/cpu/qfw_cpu.c
index a35de878b5d..b959eadddef 100644
--- a/arch/x86/cpu/qfw_cpu.c
+++ b/arch/x86/cpu/qfw_cpu.c
@@ -17,10 +17,16 @@ int qemu_cpu_fixup(void)
int ret;
int cpu_num;
int cpu_online;
+ struct uclass *uc;
struct udevice *dev, *pdev;
struct cpu_plat *plat;
char *cpu;
+ /* This will cause the CPUs devices to be bound */
+ ret = uclass_get(UCLASS_CPU, &uc);
+ if (ret)
+ return ret;
+
/* first we need to find '/cpus' */
for (device_find_first_child(dm_root(), &pdev);
pdev;
diff --git a/board/AndesTech/ax25-ae350/ax25-ae350.c b/board/AndesTech/ax25-ae350/ax25-ae350.c
index 59a43e4dcc4..3125233488f 100644
--- a/board/AndesTech/ax25-ae350/ax25-ae350.c
+++ b/board/AndesTech/ax25-ae350/ax25-ae350.c
@@ -77,7 +77,7 @@ int smc_init(void)
if (addr == FDT_ADDR_T_NONE)
return -EINVAL;
- regs = (struct ftsmc020_bank *)addr;
+ regs = (struct ftsmc020_bank *)(uintptr_t)addr;
regs->cr &= ~FTSMC020_BANK_WPROT;
return 0;
diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c
index 8d8daa6336a..dfd50ae8491 100644
--- a/cmd/bdinfo.c
+++ b/cmd/bdinfo.c
@@ -18,11 +18,16 @@
DECLARE_GLOBAL_DATA_PTR;
-void bdinfo_print_num(const char *name, ulong value)
+void bdinfo_print_num_l(const char *name, ulong value)
{
printf("%-12s= 0x%0*lx\n", name, 2 * (int)sizeof(value), value);
}
+void bdinfo_print_num_ll(const char *name, unsigned long long value)
+{
+ printf("%-12s= 0x%.*llx\n", name, 2 * (int)sizeof(ulong), value);
+}
+
static void print_eth(int idx)
{
char name[10], *val;
@@ -36,12 +41,6 @@ static void print_eth(int idx)
printf("%-12s= %s\n", name, val);
}
-static void print_phys_addr(const char *name, phys_addr_t value)
-{
- printf("%-12s= 0x%.*llx\n", name, 2 * (int)sizeof(ulong),
- (unsigned long long)value);
-}
-
void bdinfo_print_mhz(const char *name, unsigned long hz)
{
char buf[32];
@@ -55,9 +54,9 @@ static void print_bi_dram(const struct bd_info *bd)
for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
if (bd->bi_dram[i].size) {
- bdinfo_print_num("DRAM bank", i);
- bdinfo_print_num("-> start", bd->bi_dram[i].start);
- bdinfo_print_num("-> size", bd->bi_dram[i].size);
+ bdinfo_print_num_l("DRAM bank", i);
+ bdinfo_print_num_ll("-> start", bd->bi_dram[i].start);
+ bdinfo_print_num_ll("-> size", bd->bi_dram[i].size);
}
}
}
@@ -77,9 +76,10 @@ static void show_video_info(void)
if (device_active(dev)) {
struct video_priv *upriv = dev_get_uclass_priv(dev);
- print_phys_addr("FB base", (ulong)upriv->fb);
+ bdinfo_print_num_ll("FB base", (ulong)upriv->fb);
if (upriv->copy_fb)
- print_phys_addr("FB copy", (ulong)upriv->copy_fb);
+ bdinfo_print_num_ll("FB copy",
+ (ulong)upriv->copy_fb);
printf("%-12s= %dx%dx%d\n", "FB size", upriv->xsize,
upriv->ysize, 1 << upriv->bpix);
}
@@ -91,36 +91,36 @@ int do_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
struct bd_info *bd = gd->bd;
#ifdef DEBUG
- bdinfo_print_num("bd address", (ulong)bd);
+ bdinfo_print_num_l("bd address", (ulong)bd);
#endif
- bdinfo_print_num("boot_params", (ulong)bd->bi_boot_params);
+ bdinfo_print_num_l("boot_params", (ulong)bd->bi_boot_params);
print_bi_dram(bd);
if (IS_ENABLED(CONFIG_SYS_HAS_SRAM)) {
- bdinfo_print_num("sramstart", (ulong)bd->bi_sramstart);
- bdinfo_print_num("sramsize", (ulong)bd->bi_sramsize);
+ bdinfo_print_num_l("sramstart", (ulong)bd->bi_sramstart);
+ bdinfo_print_num_l("sramsize", (ulong)bd->bi_sramsize);
}
- bdinfo_print_num("flashstart", (ulong)bd->bi_flashstart);
- bdinfo_print_num("flashsize", (ulong)bd->bi_flashsize);
- bdinfo_print_num("flashoffset", (ulong)bd->bi_flashoffset);
+ bdinfo_print_num_l("flashstart", (ulong)bd->bi_flashstart);
+ bdinfo_print_num_l("flashsize", (ulong)bd->bi_flashsize);
+ bdinfo_print_num_l("flashoffset", (ulong)bd->bi_flashoffset);
printf("baudrate = %u bps\n", gd->baudrate);
- bdinfo_print_num("relocaddr", gd->relocaddr);
- bdinfo_print_num("reloc off", gd->reloc_off);
+ bdinfo_print_num_l("relocaddr", gd->relocaddr);
+ bdinfo_print_num_l("reloc off", gd->reloc_off);
printf("%-12s= %u-bit\n", "Build", (uint)sizeof(void *) * 8);
if (IS_ENABLED(CONFIG_CMD_NET)) {
printf("current eth = %s\n", eth_get_name());
print_eth(0);
printf("IP addr = %s\n", env_get("ipaddr"));
}
- bdinfo_print_num("fdt_blob", (ulong)gd->fdt_blob);
- bdinfo_print_num("new_fdt", (ulong)gd->new_fdt);
- bdinfo_print_num("fdt_size", (ulong)gd->fdt_size);
+ bdinfo_print_num_l("fdt_blob", (ulong)gd->fdt_blob);
+ bdinfo_print_num_l("new_fdt", (ulong)gd->new_fdt);
+ bdinfo_print_num_l("fdt_size", (ulong)gd->fdt_size);
if (IS_ENABLED(CONFIG_DM_VIDEO))
show_video_info();
#if defined(CONFIG_LCD) || defined(CONFIG_VIDEO)
- bdinfo_print_num("FB base ", gd->fb_base);
+ bdinfo_print_num_l("FB base ", gd->fb_base);
#endif
#if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
- bdinfo_print_num("multi_dtb_fit", (ulong)gd->multi_dtb_fit);
+ bdinfo_print_num_l("multi_dtb_fit", (ulong)gd->multi_dtb_fit);
#endif
if (gd->fdt_blob) {
struct lmb lmb;
diff --git a/cmd/efidebug.c b/cmd/efidebug.c
index 83bc2196a5a..bbbcb0a5464 100644
--- a/cmd/efidebug.c
+++ b/cmd/efidebug.c
@@ -16,6 +16,7 @@
#include <log.h>
#include <malloc.h>
#include <mapmem.h>
+#include <part.h>
#include <search.h>
#include <linux/ctype.h>
@@ -502,6 +503,10 @@ static const struct {
"Device-Tree Fixup",
EFI_DT_FIXUP_PROTOCOL_GUID,
},
+ {
+ "System Partition",
+ PARTITION_SYSTEM_GUID
+ },
/* Configuration table GUIDs */
{
"ACPI table",
diff --git a/cmd/pxe_utils.c b/cmd/pxe_utils.c
index 3526a651d79..71c5af4c25d 100644
--- a/cmd/pxe_utils.c
+++ b/cmd/pxe_utils.c
@@ -492,16 +492,16 @@ static int label_boot(struct cmd_tbl *cmdtp, struct pxe_label *label)
env_get("gatewayip"), env_get("netmask"));
}
-#ifdef CONFIG_CMD_NET
- if (label->ipappend & 0x2) {
- int err;
-
- strcpy(mac_str, " BOOTIF=");
- err = format_mac_pxe(mac_str + 8, sizeof(mac_str) - 8);
- if (err < 0)
- mac_str[0] = '\0';
+ if (IS_ENABLED(CONFIG_CMD_NET)) {
+ if (label->ipappend & 0x2) {
+ int err;
+
+ strcpy(mac_str, " BOOTIF=");
+ err = format_mac_pxe(mac_str + 8, sizeof(mac_str) - 8);
+ if (err < 0)
+ mac_str[0] = '\0';
+ }
}
-#endif
if ((label->ipappend & 0x3) || label->append) {
char bootargs[CONFIG_SYS_CBSIZE] = "";
@@ -649,15 +649,16 @@ static int label_boot(struct cmd_tbl *cmdtp, struct pxe_label *label)
/* Try bootm for legacy and FIT format image */
if (genimg_get_format(buf) != IMAGE_FORMAT_INVALID)
do_bootm(cmdtp, 0, bootm_argc, bootm_argv);
-#ifdef CONFIG_CMD_BOOTI
/* Try booting an AArch64 Linux kernel image */
- else
+ else if (IS_ENABLED(CONFIG_CMD_BOOTI))
do_booti(cmdtp, 0, bootm_argc, bootm_argv);
-#elif defined(CONFIG_CMD_BOOTZ)
/* Try booting a Image */
- else
+ else if (IS_ENABLED(CONFIG_CMD_BOOTZ))
do_bootz(cmdtp, 0, bootm_argc, bootm_argv);
-#endif
+ /* Try booting an x86_64 Linux kernel image */
+ else if (IS_ENABLED(CONFIG_CMD_ZBOOT))
+ do_zboot_parent(cmdtp, 0, bootm_argc, bootm_argv, NULL);
+
unmap_sysmem(buf);
cleanup:
@@ -1424,20 +1425,20 @@ void handle_pxe_menu(struct cmd_tbl *cmdtp, struct pxe_menu *cfg)
struct menu *m;
int err;
-#ifdef CONFIG_CMD_BMP
- /* display BMP if available */
- if (cfg->bmp) {
- if (get_relfile(cmdtp, cfg->bmp, image_load_addr)) {
- if (CONFIG_IS_ENABLED(CMD_CLS))
- run_command("cls", 0);
- bmp_display(image_load_addr,
- BMP_ALIGN_CENTER, BMP_ALIGN_CENTER);
- } else {
- printf("Skipping background bmp %s for failure\n",
- cfg->bmp);
+ if (IS_ENABLED(CONFIG_CMD_BMP)) {
+ /* display BMP if available */
+ if (cfg->bmp) {
+ if (get_relfile(cmdtp, cfg->bmp, image_load_addr)) {
+ if (CONFIG_IS_ENABLED(CMD_CLS))
+ run_command("cls", 0);
+ bmp_display(image_load_addr,
+ BMP_ALIGN_CENTER, BMP_ALIGN_CENTER);
+ } else {
+ printf("Skipping background bmp %s for failure\n",
+ cfg->bmp);
+ }
}
}
-#endif
m = pxe_menu_to_menu(cfg);
if (!m)
diff --git a/doc/driver-model/design.rst b/doc/driver-model/design.rst
index ffed7d5f79a..4e5cecbab6a 100644
--- a/doc/driver-model/design.rst
+++ b/doc/driver-model/design.rst
@@ -725,7 +725,7 @@ The steps are:
2. If plat_auto is non-zero, then the platform data space
is allocated. This is only useful for device tree operation, since
- otherwise you would have to specific the platform data in the
+ otherwise you would have to specify the platform data in the
U_BOOT_DRVINFO() declaration. The space is allocated for the device and
zeroed. It will be accessible as dev->plat.
@@ -861,8 +861,8 @@ remove it. This performs the probe steps in reverse:
be dynamically allocated, and thus needs to be deallocated during the
remove() method, either:
- - if the plat_auto is non-zero, the deallocation
- happens automatically within the driver model core; or
+ - if the plat_auto is non-zero, the deallocation happens automatically
+ within the driver model core in the unbind stage; or
- when plat_auto is 0, both the allocation (in probe()
or preferably of_to_plat()) and the deallocation in remove()
@@ -880,6 +880,26 @@ If a parent has children these will be destroyed first. After this point
the device does not exist and its memory has be deallocated.
+Special cases for removal
+-------------------------
+
+Some devices need to do clean-up before the OS is called. For example, a USB
+driver may want to stop the bus. This can be done in the remove() method.
+Some special flags are used to determine whether to remove the device:
+
+ DM_FLAG_OS_PREPARE - indicates that the device needs to get ready for OS
+ boot. The device will be removed just before the OS is booted
+ DM_REMOVE_ACTIVE_DMA - indicates that the device uses DMA. This is
+ effectively the same as DM_FLAG_OS_PREPARE, so the device is removed
+ before the OS is booted
+ DM_FLAG_VITAL - indicates that the device is 'vital' to the operation of
+ other devices. It is possible to remove this device after all regular
+ devices are removed. This is useful e.g. for a clock, which need to
+ be active during the device-removal phase.
+
+The dm_remove_devices_flags() function can be used to remove devices based on
+their driver flags.
+
Data Structures
---------------
diff --git a/doc/usage/exception.rst b/doc/usage/exception.rst
index 412a03ba0f3..db1490f0055 100644
--- a/doc/usage/exception.rst
+++ b/doc/usage/exception.rst
@@ -61,8 +61,3 @@ Examples
pc = 0x56076dd1a0f9, pc_reloc = 0x540f9
resetting ...
-
-Return value
-------------
-
-The return value $? is always set to 0 (true).
diff --git a/doc/usage/index.rst b/doc/usage/index.rst
index 83cfbafd905..5754958d7e4 100644
--- a/doc/usage/index.rst
+++ b/doc/usage/index.rst
@@ -23,6 +23,7 @@ Shell commands
exit
false
for
+ load
loady
mbr
pstore
diff --git a/doc/usage/load.rst b/doc/usage/load.rst
new file mode 100644
index 00000000000..1efee773179
--- /dev/null
+++ b/doc/usage/load.rst
@@ -0,0 +1,74 @@
+.. SPDX-License-Identifier: GPL-2.0+:
+
+load command
+============
+
+Synopsis
+--------
+
+::
+
+ load <interface> [<dev[:part]> [<addr> [<filename> [bytes [pos]]]]]
+
+Description
+-----------
+
+The load command is used to read a file from a filesystem into memory.
+
+The number of transferred bytes is saved in the environment variable filesize.
+The load address is saved in the environment variable fileaddr.
+
+interface
+ interface for accessing the block device (mmc, sata, scsi, usb, ....)
+
+dev
+ device number
+
+part
+ partition number, defaults to 0 (whole device)
+
+addr
+ load address, defaults to environment variable loadaddr or if loadaddr is
+ not set to configuration variable CONFIG_SYS_LOAD_ADDR
+
+filename
+ path to file, defaults to environment variable bootfile
+
+bytes
+ maximum number of bytes to load
+
+pos
+ number of bytes to skip
+
+addr, bytes, pos are hexadecimal numbers.
+
+Example
+-------
+
+::
+
+ => load mmc 0:1 ${kernel_addr_r} snp.efi
+ 149280 bytes read in 11 ms (12.9 MiB/s)
+ =>
+ => load mmc 0:1 ${kernel_addr_r} snp.efi 1000000
+ 149280 bytes read in 9 ms (15.8 MiB/s)
+ =>
+ => load mmc 0:1 ${kernel_addr_r} snp.efi 1000000 100
+ 149024 bytes read in 10 ms (14.2 MiB/s)
+ =>
+ => load mmc 0:1 ${kernel_addr_r} snp.efi 10
+ 16 bytes read in 1 ms (15.6 KiB/s)
+ =>
+
+Configuration
+-------------
+
+The load command is only available if CONFIG_CMD_FS_GENERIC=y.
+
+Return value
+------------
+
+The return value $? is set to 0 (true) if the file was successfully loaded
+even if the number of bytes is less then the specified length.
+
+If an error occurs, the return value $? is set to 1 (false).
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index 7e8f3afb2d6..616dcf07859 100644
--- a/drivers/core/device-remove.c
+++ b/drivers/core/device-remove.c
@@ -8,6 +8,8 @@
* Pavel Herrmann <morpheus.ibis@gmail.com>
*/
+#define LOG_CATEGORY LOGC_DM
+
#include <common.h>
#include <errno.h>
#include <log.h>
@@ -45,20 +47,24 @@ int device_chld_remove(struct udevice *dev, struct driver *drv,
uint flags)
{
struct udevice *pos, *n;
- int ret;
+ int result = 0;
assert(dev);
list_for_each_entry_safe(pos, n, &dev->child_head, sibling_node) {
+ int ret;
+
if (drv && (pos->driver != drv))
continue;
ret = device_remove(pos, flags);
- if (ret)
+ if (ret == -EPROBE_DEFER)
+ result = ret;
+ else if (ret && ret != -EKEYREJECTED)
return ret;
}
- return 0;
+ return result;
}
int device_unbind(struct udevice *dev)
@@ -149,13 +155,43 @@ void device_free(struct udevice *dev)
devres_release_probe(dev);
}
-static bool flags_remove(uint flags, uint drv_flags)
+/**
+ * flags_remove() - Figure out whether to remove a device
+ *
+ * If this is called with @flags == DM_REMOVE_NON_VITAL | DM_REMOVE_ACTIVE_DMA,
+ * then it returns 0 (=go head and remove) if the device is not matked vital
+ * but is marked DM_REMOVE_ACTIVE_DMA.
+ *
+ * If this is called with @flags == DM_REMOVE_ACTIVE_DMA,
+ * then it returns 0 (=go head and remove) if the device is marked
+ * DM_REMOVE_ACTIVE_DMA, regardless of whether it is marked vital.
+ *
+ * @flags: Flags passed to device_remove()
+ * @drv_flags: Driver flags
+ * @return 0 if the device should be removed,
+ * -EKEYREJECTED if @flags includes a flag in DM_REMOVE_ACTIVE_ALL but
+ * @drv_flags does not (indicates that this device has nothing to do for
+ * DMA shutdown or OS prepare)
+ * -EPROBE_DEFER if @flags is DM_REMOVE_NON_VITAL but @drv_flags contains
+ * DM_FLAG_VITAL (indicates the device is vital and should not be removed)
+ */
+static int flags_remove(uint flags, uint drv_flags)
{
- if ((flags & DM_REMOVE_NORMAL) ||
- (flags && (drv_flags & (DM_FLAG_ACTIVE_DMA | DM_FLAG_OS_PREPARE))))
- return true;
+ if (!(flags & DM_REMOVE_NORMAL)) {
+ bool vital_match;
+ bool active_match;
+
+ active_match = !(flags & DM_REMOVE_ACTIVE_ALL) ||
+ (drv_flags & flags);
+ vital_match = !(flags & DM_REMOVE_NON_VITAL) ||
+ !(drv_flags & DM_FLAG_VITAL);
+ if (!vital_match)
+ return -EPROBE_DEFER;
+ if (!active_match)
+ return -EKEYREJECTED;
+ }
- return false;
+ return 0;
}
int device_remove(struct udevice *dev, uint flags)
@@ -169,22 +205,32 @@ int device_remove(struct udevice *dev, uint flags)
if (!(dev_get_flags(dev) & DM_FLAG_ACTIVATED))
return 0;
+ /*
+ * If the child returns EKEYREJECTED, continue. It just means that it
+ * didn't match the flags.
+ */
+ ret = device_chld_remove(dev, NULL, flags);
+ 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) {
+ log_debug("%s: When removing: flags=%x, drv->flags=%x, err=%d\n",
+ dev->name, flags, drv->flags, ret);
+ return ret;
+ }
ret = uclass_pre_remove_device(dev);
if (ret)
return ret;
- ret = device_chld_remove(dev, NULL, flags);
- if (ret)
- goto err;
-
- /*
- * Remove the device if called with the "normal" remove flag set,
- * or if the remove flag matches any of the drivers remove flags
- */
- if (drv->remove && flags_remove(flags, drv->flags)) {
+ if (drv->remove) {
ret = drv->remove(dev);
if (ret)
goto err_remove;
@@ -200,28 +246,20 @@ int device_remove(struct udevice *dev, uint flags)
if (!(flags & DM_REMOVE_NO_PD) &&
!(drv->flags &
- (DM_FLAG_DEFAULT_PD_CTRL_OFF | DM_FLAG_REMOVE_WITH_PD_ON)) &&
+ (DM_FLAG_DEFAULT_PD_CTRL_OFF | DM_FLAG_LEAVE_PD_ON)) &&
dev != gd->cur_serial_dev)
dev_power_domain_off(dev);
- if (flags_remove(flags, drv->flags)) {
- device_free(dev);
+ device_free(dev);
- dev_bic_flags(dev, DM_FLAG_ACTIVATED);
- }
+ dev_bic_flags(dev, DM_FLAG_ACTIVATED);
- return ret;
+ return 0;
err_remove:
/* We can't put the children back */
dm_warn("%s: Device '%s' failed to remove, but children are gone\n",
__func__, dev->name);
-err:
- ret = uclass_post_probe_device(dev);
- if (ret) {
- dm_warn("%s: Device '%s' failed to post_probe on error path\n",
- __func__, dev->name);
- }
return ret;
}
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 2bfa75b4725..7ef2ec2da27 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -162,6 +162,8 @@ int dm_init(bool of_live)
int dm_uninit(void)
{
+ /* Remove non-vital devices first */
+ device_remove(dm_root(), DM_REMOVE_NON_VITAL);
device_remove(dm_root(), DM_REMOVE_NORMAL);
device_unbind(dm_root());
gd->dm_root = NULL;
diff --git a/drivers/firmware/scmi/sandbox-scmi_devices.c b/drivers/firmware/scmi/sandbox-scmi_devices.c
index 414da6f4df1..1a6fafbf531 100644
--- a/drivers/firmware/scmi/sandbox-scmi_devices.c
+++ b/drivers/firmware/scmi/sandbox-scmi_devices.c
@@ -50,6 +50,9 @@ static int sandbox_scmi_devices_remove(struct udevice *dev)
int ret = 0;
size_t n;
+ if (!devices)
+ return 0;
+
for (n = 0; n < SCMI_TEST_DEVICES_RD_COUNT; n++) {
int ret2 = reset_free(devices->reset + n);
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
index 7349a9bc99e..99a1c2e6e2e 100644
--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
@@ -2526,10 +2526,7 @@ int brcmnand_probe(struct udevice *dev, struct brcmnand_soc *soc)
if (ret)
return ret;
} else {
- ret = PTR_ERR(ctrl->clk);
- if (ret == -EPROBE_DEFER)
- return ret;
-
+ /* Ignore PTR_ERR(ctrl->clk) */
ctrl->clk = NULL;
}
diff --git a/drivers/net/ftmac100.c b/drivers/net/ftmac100.c
index 0d672374fda..fc578b03752 100644
--- a/drivers/net/ftmac100.c
+++ b/drivers/net/ftmac100.c
@@ -35,7 +35,7 @@ struct ftmac100_data {
*/
static void ftmac100_reset(struct ftmac100_data *priv)
{
- struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
+ struct ftmac100 *ftmac100 = (struct ftmac100 *)(uintptr_t)priv->iobase;
debug ("%s()\n", __func__);
@@ -56,7 +56,7 @@ static void ftmac100_reset(struct ftmac100_data *priv)
static void ftmac100_set_mac(struct ftmac100_data *priv ,
const unsigned char *mac)
{
- struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
+ struct ftmac100 *ftmac100 = (struct ftmac100 *)(uintptr_t)priv->iobase;
unsigned int maddr = mac[0] << 8 | mac[1];
unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
@@ -71,7 +71,7 @@ static void ftmac100_set_mac(struct ftmac100_data *priv ,
*/
static void _ftmac100_halt(struct ftmac100_data *priv)
{
- struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
+ struct ftmac100 *ftmac100 = (struct ftmac100 *)(uintptr_t)priv->iobase;
debug ("%s()\n", __func__);
writel (0, &ftmac100->maccr);
}
@@ -81,7 +81,7 @@ static void _ftmac100_halt(struct ftmac100_data *priv)
*/
static int _ftmac100_init(struct ftmac100_data *priv, unsigned char enetaddr[6])
{
- struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
+ struct ftmac100 *ftmac100 = (struct ftmac100 *)(uintptr_t)priv->iobase;
struct ftmac100_txdes *txdes = priv->txdes;
struct ftmac100_rxdes *rxdes = priv->rxdes;
unsigned int maccr;
@@ -186,7 +186,7 @@ static int __ftmac100_recv(struct ftmac100_data *priv)
*/
static int _ftmac100_send(struct ftmac100_data *priv, void *packet, int length)
{
- struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase;
+ struct ftmac100 *ftmac100 = (struct ftmac100 *)(uintptr_t)priv->iobase;
struct ftmac100_txdes *curr_des = priv->txdes;
ulong start;
diff --git a/drivers/pci/pcie_iproc.c b/drivers/pci/pcie_iproc.c
index 6725ff64372..12ce9d525ca 100644
--- a/drivers/pci/pcie_iproc.c
+++ b/drivers/pci/pcie_iproc.c
@@ -1283,5 +1283,5 @@ U_BOOT_DRIVER(pci_iproc) = {
.probe = iproc_pcie_probe,
.remove = iproc_pcie_remove,
.priv_auto = sizeof(struct iproc_pcie),
- .flags = DM_REMOVE_OS_PREPARE,
+ .flags = DM_FLAG_OS_PREPARE,
};
diff --git a/drivers/serial/serial_sifive.c b/drivers/serial/serial_sifive.c
index d26fe7e7704..97bf20c967a 100644
--- a/drivers/serial/serial_sifive.c
+++ b/drivers/serial/serial_sifive.c
@@ -178,7 +178,7 @@ static int sifive_serial_of_to_plat(struct udevice *dev)
{
struct sifive_uart_plat *plat = dev_get_plat(dev);
- plat->regs = (struct uart_sifive *)dev_read_addr(dev);
+ plat->regs = (struct uart_sifive *)(uintptr_t)dev_read_addr(dev);
if (IS_ERR(plat->regs))
return PTR_ERR(plat->regs);
diff --git a/drivers/smem/msm_smem.c b/drivers/smem/msm_smem.c
index 597d425d11f..26462151b3a 100644
--- a/drivers/smem/msm_smem.c
+++ b/drivers/smem/msm_smem.c
@@ -437,7 +437,7 @@ static int qcom_smem_alloc(unsigned int host, unsigned int item, size_t size)
int ret;
if (!__smem)
- return -EPROBE_DEFER;
+ return -ENOMEM;
if (item < SMEM_ITEM_LAST_FIXED) {
dev_err(__smem->dev,
@@ -559,7 +559,7 @@ static void *qcom_smem_get(unsigned int host, unsigned int item, size_t *size)
{
struct smem_partition_header *phdr;
size_t cacheln;
- void *ptr = ERR_PTR(-EPROBE_DEFER);
+ void *ptr = ERR_PTR(-ENOMEM);
if (!__smem)
return ptr;
@@ -597,7 +597,7 @@ static int qcom_smem_get_free_space(unsigned int host)
unsigned int ret;
if (!__smem)
- return -EPROBE_DEFER;
+ return -ENOMEM;
if (host < SMEM_HOST_COUNT && __smem->partitions[host]) {
phdr = __smem->partitions[host];
diff --git a/drivers/video/meson/meson_vpu.c b/drivers/video/meson/meson_vpu.c
index ca6933a6c54..558f9ba766c 100644
--- a/drivers/video/meson/meson_vpu.c
+++ b/drivers/video/meson/meson_vpu.c
@@ -212,5 +212,5 @@ U_BOOT_DRIVER(meson_vpu) = {
.probe = meson_vpu_probe,
.bind = meson_vpu_bind,
.priv_auto = sizeof(struct meson_vpu_priv),
- .flags = DM_FLAG_PRE_RELOC | DM_FLAG_REMOVE_WITH_PD_ON,
+ .flags = DM_FLAG_PRE_RELOC | DM_FLAG_LEAVE_PD_ON,
};
diff --git a/drivers/watchdog/rti_wdt.c b/drivers/watchdog/rti_wdt.c
index f64a39f6579..8335b20ae84 100644
--- a/drivers/watchdog/rti_wdt.c
+++ b/drivers/watchdog/rti_wdt.c
@@ -119,5 +119,5 @@ U_BOOT_DRIVER(rti_wdt) = {
.ops = &rti_wdt_ops,
.probe = rti_wdt_probe,
.priv_auto = sizeof(struct rti_wdt_priv),
- .flags = DM_FLAG_REMOVE_WITH_PD_ON,
+ .flags = DM_FLAG_LEAVE_PD_ON,
};
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index b43a27b2056..8ff2f6def08 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -1237,12 +1237,38 @@ again:
}
*last_slash_cont = '\0';
- *basename = last_slash_cont + 1;
+ filename = last_slash_cont + 1;
} else {
*dirname = "/"; /* root by default */
- *basename = filename;
}
+ /*
+ * The FAT32 File System Specification v1.03 requires leading and
+ * trailing spaces as well as trailing periods to be ignored.
+ */
+ for (; *filename == ' '; ++filename)
+ ;
+
+ /* Keep special entries '.' and '..' */
+ if (filename[0] == '.' &&
+ (!filename[1] || (filename[1] == '.' && !filename[2])))
+ goto done;
+
+ /* Remove trailing periods and spaces */
+ for (p = filename + strlen(filename) - 1; p >= filename; --p) {
+ switch (*p) {
+ case ' ':
+ case '.':
+ *p = 0;
+ break;
+ default:
+ goto done;
+ }
+ }
+
+done:
+ *basename = filename;
+
return 0;
}
@@ -1259,8 +1285,10 @@ again:
static int normalize_longname(char *l_filename, const char *filename)
{
const char *p, illegal[] = "<>:\"/\\|?*";
+ size_t len;
- if (strlen(filename) >= VFAT_MAXLEN_BYTES)
+ len = strlen(filename);
+ if (!len || len >= VFAT_MAXLEN_BYTES || filename[len - 1] == '.')
return -1;
for (p = filename; *p; ++p) {
@@ -1299,9 +1327,8 @@ int file_fat_write_at(const char *filename, loff_t pos, void *buffer,
goto exit;
}
- filename = basename;
- if (normalize_longname(l_filename, filename)) {
- printf("FAT: illegal filename (%s)\n", filename);
+ if (normalize_longname(l_filename, basename)) {
+ printf("FAT: illegal filename (%s)\n", basename);
ret = -EINVAL;
goto exit;
}
@@ -1349,15 +1376,6 @@ int file_fat_write_at(const char *filename, loff_t pos, void *buffer,
char shortname[SHORT_NAME_SIZE];
int ndent;
- if (itr->is_root) {
- /* root dir cannot have "." or ".." */
- if (!strcmp(l_filename, ".") ||
- !strcmp(l_filename, "..")) {
- ret = -EINVAL;
- goto exit;
- }
- }
-
if (pos) {
/* No hole allowed */
ret = -EINVAL;
@@ -1365,7 +1383,7 @@ int file_fat_write_at(const char *filename, loff_t pos, void *buffer,
}
/* Check if long name is needed */
- ndent = set_name(itr, filename, shortname);
+ ndent = set_name(itr, basename, shortname);
if (ndent < 0) {
ret = ndent;
goto exit;
@@ -1375,7 +1393,7 @@ int file_fat_write_at(const char *filename, loff_t pos, void *buffer,
goto exit;
if (ndent > 1) {
/* Set long name entries */
- ret = fill_dir_slot(itr, filename, shortname);
+ ret = fill_dir_slot(itr, basename, shortname);
if (ret)
goto exit;
}
@@ -1611,31 +1629,31 @@ exit:
return ret;
}
-int fat_mkdir(const char *new_dirname)
+int fat_mkdir(const char *dirname)
{
dir_entry *retdent;
fsdata datablock = { .fatbuf = NULL, };
fsdata *mydata = &datablock;
fat_itr *itr = NULL;
- char *dirname_copy, *parent, *dirname;
+ char *dirname_copy, *parent, *basename;
char l_dirname[VFAT_MAXLEN_BYTES];
int ret = -1;
loff_t actwrite;
unsigned int bytesperclust;
dir_entry *dotdent = NULL;
- dirname_copy = strdup(new_dirname);
+ dirname_copy = strdup(dirname);
if (!dirname_copy)
goto exit;
- split_filename(dirname_copy, &parent, &dirname);
- if (!strlen(dirname)) {
+ split_filename(dirname_copy, &parent, &basename);
+ if (!strlen(basename)) {
ret = -EINVAL;
goto exit;
}
- if (normalize_longname(l_dirname, dirname)) {
- printf("FAT: illegal filename (%s)\n", dirname);
+ if (normalize_longname(l_dirname, basename)) {
+ printf("FAT: illegal filename (%s)\n", basename);
ret = -EINVAL;
goto exit;
}
@@ -1678,7 +1696,7 @@ int fat_mkdir(const char *new_dirname)
}
/* Check if long name is needed */
- ndent = set_name(itr, dirname, shortname);
+ ndent = set_name(itr, basename, shortname);
if (ndent < 0) {
ret = ndent;
goto exit;
@@ -1688,7 +1706,7 @@ int fat_mkdir(const char *new_dirname)
goto exit;
if (ndent > 1) {
/* Set long name entries */
- ret = fill_dir_slot(itr, dirname, shortname);
+ ret = fill_dir_slot(itr, basename, shortname);
if (ret)
goto exit;
}
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index b6f707e97e5..998beb01760 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -147,7 +147,7 @@ struct global_data {
/**
* @ram_top: top address of RAM used by U-Boot
*/
- unsigned long ram_top;
+ phys_addr_t ram_top;
/**
* @relocaddr: start address of U-Boot in RAM
*
diff --git a/include/command.h b/include/command.h
index e229bf2825c..747f8f80958 100644
--- a/include/command.h
+++ b/include/command.h
@@ -55,8 +55,8 @@ struct cmd_tbl {
};
#if defined(CONFIG_CMD_RUN)
-extern int do_run(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[]);
+int do_run(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
#endif
/* common/command.c */
@@ -69,7 +69,7 @@ int complete_subcmdv(struct cmd_tbl *cmdtp, int count, int argc,
char *const argv[], char last_char, int maxv,
char *cmdv[]);
-extern int cmd_usage(const struct cmd_tbl *cmdtp);
+int cmd_usage(const struct cmd_tbl *cmdtp);
/* Dummy ->cmd and ->cmd_rep wrappers. */
int cmd_always_repeatable(struct cmd_tbl *cmdtp, int flag, int argc,
@@ -85,10 +85,10 @@ static inline bool cmd_is_repeatable(struct cmd_tbl *cmdtp)
}
#ifdef CONFIG_AUTO_COMPLETE
-extern int var_complete(int argc, char *const argv[], char last_char, int maxv,
- char *cmdv[]);
-extern int cmd_auto_complete(const char *const prompt, char *buf, int *np,
- int *colp);
+int var_complete(int argc, char *const argv[], char last_char, int maxv,
+ char *cmdv[]);
+int cmd_auto_complete(const char *const prompt, char *buf, int *np,
+ int *colp);
#endif
/**
@@ -145,13 +145,13 @@ int cmd_get_data_size(char *arg, int default_size);
#endif
#ifdef CONFIG_CMD_BOOTD
-extern int do_bootd(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[]);
+int do_bootd(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
#endif
#ifdef CONFIG_CMD_BOOTM
-extern int do_bootm(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[]);
-extern int bootm_maybe_autostart(struct cmd_tbl *cmdtp, const char *cmd);
+int do_bootm(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int bootm_maybe_autostart(struct cmd_tbl *cmdtp, const char *cmd);
#else
static inline int bootm_maybe_autostart(struct cmd_tbl *cmdtp, const char *cmd)
{
@@ -159,28 +159,31 @@ static inline int bootm_maybe_autostart(struct cmd_tbl *cmdtp, const char *cmd)
}
#endif
-extern int do_bootz(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[]);
+int do_bootz(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
-extern int do_booti(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[]);
+int do_booti(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
-extern int common_diskboot(struct cmd_tbl *cmdtp, const char *intf, int argc,
- char *const argv[]);
+int do_zboot_parent(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[], int *repeatable);
-extern int do_reset(struct cmd_tbl *cmdtp, int flag, int argc,
+int common_diskboot(struct cmd_tbl *cmdtp, const char *intf, int argc,
char *const argv[]);
-extern int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[]);
-extern unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc,
- char *const argv[]);
+int do_reset(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int do_poweroff(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+
+unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc,
+ char *const argv[]);
#if defined(CONFIG_CMD_NVEDIT_EFI)
-extern int do_env_print_efi(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[]);
-extern int do_env_set_efi(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[]);
+int do_env_print_efi(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
+int do_env_set_efi(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[]);
#endif
/**
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h
index 639bbd293d9..39406c3f352 100644
--- a/include/dm/device-internal.h
+++ b/include/dm/device-internal.h
@@ -123,7 +123,9 @@ int device_probe(struct udevice *dev);
*
* @dev: Pointer to device to remove
* @flags: Flags for selective device removal (DM_REMOVE_...)
- * @return 0 if OK, -ve on error (an error here is normally a very bad thing)
+ * @return 0 if OK, -EKEYREJECTED if not removed due to flags, -EPROBE_DEFER if
+ * this is a vital device and flags is DM_REMOVE_NON_VITAL, other -ve on
+ * error (such an error here is normally a very bad thing)
*/
#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
int device_remove(struct udevice *dev, uint flags);
@@ -173,10 +175,19 @@ static inline int device_chld_unbind(struct udevice *dev, struct driver *drv)
/**
* device_chld_remove() - Stop all device's children
+ *
+ * This continues through all children recursively stopping part-way through if
+ * an error occurs. Return values of -EKEYREJECTED are ignored and processing
+ * continues, since they just indicate that the child did not elect to be
+ * removed based on the value of @flags. Return values of -EPROBE_DEFER cause
+ * processing of other children to continue, but the function will return
+ * -EPROBE_DEFER.
+ *
* @dev: The device whose children are to be removed
* @drv: The targeted driver
* @flags: Flag, if this functions is called in the pre-OS stage
- * @return 0 on success, -ve on error
+ * @return 0 on success, -EPROBE_DEFER if any child failed to remove, other
+ * -ve on error
*/
#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
int device_chld_remove(struct udevice *dev, struct driver *drv,
diff --git a/include/dm/device.h b/include/dm/device.h
index e665558444b..28533ce0b6d 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -71,12 +71,22 @@ struct driver_info;
* Device is removed without switching off its power domain. This might
* be required, i. e. for serial console (debug) output when booting OS.
*/
-#define DM_FLAG_REMOVE_WITH_PD_ON (1 << 13)
+#define DM_FLAG_LEAVE_PD_ON (1 << 13)
+
+/*
+ * Device is vital to the operation of other devices. It is possible to remove
+ * removed this device after all regular devices are removed. This is useful
+ * e.g. for clock, which need to be active during the device-removal phase.
+ */
+#define DM_FLAG_VITAL (1 << 14)
/*
* One or multiple of these flags are passed to device_remove() so that
* a selective device removal as specified by the remove-stage and the
* driver flags can be done.
+ *
+ * DO NOT use these flags in your driver's @flags value...
+ * use the above DM_FLAG_... values instead
*/
enum {
/* Normal remove, remove all devices */
@@ -88,7 +98,8 @@ enum {
/* Remove devices which need some final OS preparation steps */
DM_REMOVE_OS_PREPARE = DM_FLAG_OS_PREPARE,
- /* Add more use cases here */
+ /* Remove only devices that are not marked vital */
+ DM_REMOVE_NON_VITAL = DM_FLAG_VITAL,
/* Remove devices with any active flag */
DM_REMOVE_ACTIVE_ALL = DM_REMOVE_ACTIVE_DMA | DM_REMOVE_OS_PREPARE,
diff --git a/include/init.h b/include/init.h
index 980be279936..88f84599e9e 100644
--- a/include/init.h
+++ b/include/init.h
@@ -326,7 +326,8 @@ void relocate_code(ulong start_addr_sp, struct global_data *new_gd,
#endif
/* Print a numeric value (for use in arch_print_bdinfo()) */
-void bdinfo_print_num(const char *name, ulong value);
+void bdinfo_print_num_l(const char *name, ulong value);
+void bdinfo_print_num_ll(const char *name, unsigned long long value);
/* Print a clock speed in MHz */
void bdinfo_print_mhz(const char *name, unsigned long hz);
diff --git a/include/os.h b/include/os.h
index e192e32d592..65bcb232cab 100644
--- a/include/os.h
+++ b/include/os.h
@@ -341,7 +341,7 @@ void os_localtime(struct rtc_time *rt);
/**
* os_abort() - raise SIGABRT to exit sandbox (e.g. to debugger)
*/
-void os_abort(void);
+void os_abort(void) __attribute__((noreturn));
/**
* os_mprotect_allow() - Remove write-protection on a region of memory
diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c
index 5ae4833fa78..1aaa9f94fa4 100644
--- a/lib/efi_loader/efi_device_path_to_text.c
+++ b/lib/efi_loader/efi_device_path_to_text.c
@@ -244,6 +244,21 @@ static char *dp_media(char *s, struct efi_device_path *dp)
cddp->partition_start, cddp->partition_size);
break;
}
+ case DEVICE_PATH_SUB_TYPE_VENDOR_PATH: {
+ int i, n;
+ struct efi_device_path_vendor *vdp =
+ (struct efi_device_path_vendor *)dp;
+
+ s += sprintf(s, "VenMedia(%pUl", &vdp->guid);
+ n = (int)vdp->dp.length - sizeof(struct efi_device_path_vendor);
+ if (n > 0) {
+ s += sprintf(s, ",");
+ for (i = 0; i < n; ++i)
+ s += sprintf(s, "%02x", vdp->vendor_data[i]);
+ }
+ s += sprintf(s, ")");
+ break;
+ }
case DEVICE_PATH_SUB_TYPE_FILE_PATH: {
struct efi_device_path_file_path *fp =
(struct efi_device_path_file_path *)dp;
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index d0aad0252a5..1f6b817dead 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -19,6 +19,7 @@
struct efi_system_partition efi_system_partition;
const efi_guid_t efi_block_io_guid = EFI_BLOCK_IO_PROTOCOL_GUID;
+const efi_guid_t efi_system_partition_guid = PARTITION_SYSTEM_GUID;
/**
* struct efi_disk_obj - EFI disk object
@@ -362,6 +363,7 @@ static efi_status_t efi_disk_add_dev(
{
struct efi_disk_obj *diskobj;
struct efi_object *handle;
+ const efi_guid_t *guid = NULL;
efi_status_t ret;
/* Don't add empty devices */
@@ -400,6 +402,8 @@ static efi_status_t efi_disk_add_dev(
efi_free_pool(node);
diskobj->offset = part_info->start;
diskobj->media.last_block = part_info->size - 1;
+ if (part_info->bootable & PART_EFI_SYSTEM_PARTITION)
+ guid = &efi_system_partition_guid;
} else {
diskobj->dp = efi_dp_from_part(desc, part);
diskobj->offset = 0;
@@ -417,7 +421,8 @@ static efi_status_t efi_disk_add_dev(
handle = &diskobj->header;
ret = EFI_CALL(efi_install_multiple_protocol_interfaces(
&handle, &efi_guid_device_path, diskobj->dp,
- &efi_block_io_guid, &diskobj->ops, NULL));
+ &efi_block_io_guid, &diskobj->ops,
+ guid, NULL, NULL));
if (ret != EFI_SUCCESS)
return ret;
@@ -467,13 +472,7 @@ static efi_status_t efi_disk_add_dev(
/* Store first EFI system partition */
if (part && !efi_system_partition.if_type) {
- int r;
- struct disk_partition info;
-
- r = part_get_info(desc, part, &info);
- if (r)
- return EFI_DEVICE_ERROR;
- if (info.bootable & PART_EFI_SYSTEM_PARTITION) {
+ if (part_info->bootable & PART_EFI_SYSTEM_PARTITION) {
efi_system_partition.if_type = desc->if_type;
efi_system_partition.devnum = desc->devnum;
efi_system_partition.part = part;
diff --git a/lib/efi_loader/efi_dt_fixup.c b/lib/efi_loader/efi_dt_fixup.c
index 3850ab3b0fe..6de57b84d20 100644
--- a/lib/efi_loader/efi_dt_fixup.c
+++ b/lib/efi_loader/efi_dt_fixup.c
@@ -110,6 +110,7 @@ efi_dt_fixup(struct efi_dt_fixup_protocol *this, void *dtb,
{
efi_status_t ret;
size_t required_size;
+ size_t total_size;
bootm_headers_t img = { 0 };
EFI_ENTRY("%p, %p, %p, %d", this, dtb, buffer_size, flags);
@@ -124,20 +125,20 @@ efi_dt_fixup(struct efi_dt_fixup_protocol *this, void *dtb,
goto out;
}
if (flags & EFI_DT_APPLY_FIXUPS) {
+ /* Check size */
required_size = fdt_off_dt_strings(dtb) +
fdt_size_dt_strings(dtb) +
0x3000;
- } else {
- required_size = fdt_totalsize(dtb);
- }
- if (required_size > *buffer_size) {
- *buffer_size = required_size;
- ret = EFI_BUFFER_TOO_SMALL;
- goto out;
- }
- fdt_set_totalsize(dtb, *buffer_size);
+ total_size = fdt_totalsize(dtb);
+ if (required_size < total_size)
+ required_size = total_size;
+ if (required_size > *buffer_size) {
+ *buffer_size = required_size;
+ ret = EFI_BUFFER_TOO_SMALL;
+ goto out;
+ }
- if (flags & EFI_DT_APPLY_FIXUPS) {
+ fdt_set_totalsize(dtb, *buffer_size);
if (image_setup_libfdt(&img, dtb, 0, NULL)) {
log_err("failed to process device tree\n");
ret = EFI_INVALID_PARAMETER;
@@ -147,10 +148,10 @@ efi_dt_fixup(struct efi_dt_fixup_protocol *this, void *dtb,
if (flags & EFI_DT_RESERVE_MEMORY)
efi_carve_out_dt_rsv(dtb);
- if (EFI_DT_INSTALL_TABLE) {
+ if (flags & EFI_DT_INSTALL_TABLE) {
ret = efi_install_configuration_table(&efi_guid_fdt, dtb);
if (ret != EFI_SUCCESS) {
- log_err("ERROR: failed to install device tree\n");
+ log_err("failed to install device tree\n");
goto out;
}
}
diff --git a/lib/efi_selftest/dtbdump.c b/lib/efi_selftest/dtbdump.c
index 953b264d9d4..38ab9f8bf0e 100644
--- a/lib/efi_selftest/dtbdump.c
+++ b/lib/efi_selftest/dtbdump.c
@@ -9,6 +9,7 @@
#include <common.h>
#include <efi_api.h>
#include <efi_dt_fixup.h>
+#include <part.h>
#define BUFFER_SIZE 64
#define ESC 0x17
@@ -27,6 +28,7 @@ static efi_handle_t handle;
static struct efi_system_table *systable;
static const efi_guid_t efi_dt_fixup_protocol_guid = EFI_DT_FIXUP_PROTOCOL_GUID;
static const efi_guid_t efi_file_info_guid = EFI_FILE_INFO_GUID;
+static const efi_guid_t efi_system_partition_guid = PARTITION_SYSTEM_GUID;
/**
* print() - print string
@@ -231,6 +233,52 @@ void do_help(void)
}
/**
+ * open_file_system() - open simple file system protocol
+ *
+ * file_system: interface of the simple file system protocol
+ * Return: status code
+ */
+static efi_status_t
+open_file_system(struct efi_simple_file_system_protocol **file_system)
+{
+ struct efi_loaded_image *loaded_image;
+ efi_status_t ret;
+ efi_handle_t *handle_buffer = NULL;
+ efi_uintn_t count;
+
+ ret = bs->open_protocol(handle, &loaded_image_guid,
+ (void **)&loaded_image, NULL, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (ret != EFI_SUCCESS) {
+ error(L"Loaded image protocol not found\r\n");
+ return ret;
+ }
+
+ /* Open the simple file system protocol on the same partition */
+ ret = bs->open_protocol(loaded_image->device_handle,
+ &guid_simple_file_system_protocol,
+ (void **)file_system, NULL, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (ret == EFI_SUCCESS)
+ return ret;
+
+ /* Open the simple file system protocol on the UEFI system partition */
+ ret = bs->locate_handle_buffer(BY_PROTOCOL, &efi_system_partition_guid,
+ NULL, &count, &handle_buffer);
+ if (ret == EFI_SUCCESS && handle_buffer)
+ ret = bs->open_protocol(handle_buffer[0],
+ &guid_simple_file_system_protocol,
+ (void **)file_system, NULL, NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (ret != EFI_SUCCESS)
+ error(L"Failed to open simple file system protocol\r\n");
+ if (handle)
+ bs->free_pool(handle_buffer);
+
+ return ret;
+}
+
+/**
* do_load() - load and install device-tree
*
* @filename: file name
@@ -239,7 +287,6 @@ void do_help(void)
efi_status_t do_load(u16 *filename)
{
struct efi_dt_fixup_protocol *dt_fixup_prot;
- struct efi_loaded_image *loaded_image;
struct efi_simple_file_system_protocol *file_system;
struct efi_file_handle *root = NULL, *file = NULL;
u64 addr = 0;
@@ -258,22 +305,9 @@ efi_status_t do_load(u16 *filename)
filename = skip_whitespace(filename);
- ret = bs->open_protocol(handle, &loaded_image_guid,
- (void **)&loaded_image, NULL, NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- if (ret != EFI_SUCCESS) {
- error(L"Loaded image protocol not found\r\n");
- return ret;
- }
- /* Open the simple file system protocol */
- ret = bs->open_protocol(loaded_image->device_handle,
- &guid_simple_file_system_protocol,
- (void **)&file_system, NULL, NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- if (ret != EFI_SUCCESS) {
- error(L"Failed to open simple file system protocol\r\n");
+ ret = open_file_system(&file_system);
+ if (ret != EFI_SUCCESS)
goto out;
- }
/* Open volume */
ret = file_system->open_volume(file_system, &root);
@@ -389,7 +423,6 @@ out:
*/
efi_status_t do_save(u16 *filename)
{
- struct efi_loaded_image *loaded_image;
struct efi_simple_file_system_protocol *file_system;
efi_uintn_t dtb_size;
struct efi_file_handle *root, *file;
@@ -409,23 +442,9 @@ efi_status_t do_save(u16 *filename)
filename = skip_whitespace(filename);
- ret = bs->open_protocol(handle, &loaded_image_guid,
- (void **)&loaded_image, NULL, NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- if (ret != EFI_SUCCESS) {
- error(L"Loaded image protocol not found\r\n");
- return ret;
- }
-
- /* Open the simple file system protocol */
- ret = bs->open_protocol(loaded_image->device_handle,
- &guid_simple_file_system_protocol,
- (void **)&file_system, NULL, NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- if (ret != EFI_SUCCESS) {
- error(L"Failed to open simple file system protocol\r\n");
+ ret = open_file_system(&file_system);
+ if (ret != EFI_SUCCESS)
return ret;
- }
/* Open volume */
ret = file_system->open_volume(file_system, &root);
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index a2d2fb4e1fe..e048f7777d6 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -1572,7 +1572,7 @@ int fdtdec_setup(void)
return -1;
}
# elif defined(CONFIG_OF_PRIOR_STAGE)
- gd->fdt_blob = (void *)prior_stage_fdt_address;
+ gd->fdt_blob = (void *)(uintptr_t)prior_stage_fdt_address;
# endif
# ifndef CONFIG_SPL_BUILD
/* Allow the early environment to override the fdt address */
diff --git a/test/dm/core.c b/test/dm/core.c
index 1f5ca570dc7..bfd6565d952 100644
--- a/test/dm/core.c
+++ b/test/dm/core.c
@@ -72,6 +72,14 @@ static struct driver_info driver_info_act_dma = {
.name = "test_act_dma_drv",
};
+static struct driver_info driver_info_vital_clk = {
+ .name = "test_vital_clk_drv",
+};
+
+static struct driver_info driver_info_act_dma_vital_clk = {
+ .name = "test_act_dma_vital_clk_drv",
+};
+
void dm_leak_check_start(struct unit_test_state *uts)
{
uts->start = mallinfo();
@@ -883,6 +891,92 @@ static int dm_test_remove_active_dma(struct unit_test_state *uts)
}
DM_TEST(dm_test_remove_active_dma, 0);
+/* Test removal of 'vital' devices */
+static int dm_test_remove_vital(struct unit_test_state *uts)
+{
+ struct dm_test_state *dms = uts->priv;
+ struct udevice *normal, *dma, *vital, *dma_vital;
+
+ /* Skip the behaviour in test_post_probe() */
+ dms->skip_post_probe = 1;
+
+ ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual,
+ &normal));
+ ut_assertnonnull(normal);
+
+ ut_assertok(device_bind_by_name(dms->root, false, &driver_info_act_dma,
+ &dma));
+ ut_assertnonnull(dma);
+
+ ut_assertok(device_bind_by_name(dms->root, false,
+ &driver_info_vital_clk, &vital));
+ ut_assertnonnull(vital);
+
+ ut_assertok(device_bind_by_name(dms->root, false,
+ &driver_info_act_dma_vital_clk,
+ &dma_vital));
+ ut_assertnonnull(dma_vital);
+
+ /* Probe the devices */
+ ut_assertok(device_probe(normal));
+ ut_assertok(device_probe(dma));
+ ut_assertok(device_probe(vital));
+ ut_assertok(device_probe(dma_vital));
+
+ /* Check that devices are active right now */
+ ut_asserteq(true, device_active(normal));
+ ut_asserteq(true, device_active(dma));
+ ut_asserteq(true, device_active(vital));
+ ut_asserteq(true, device_active(dma_vital));
+
+ /* Remove active devices via selective remove flag */
+ dm_remove_devices_flags(DM_REMOVE_NON_VITAL | DM_REMOVE_ACTIVE_ALL);
+
+ /*
+ * Check that this only has an effect on the dma device, since two
+ * devices are vital and the third does not have active DMA
+ */
+ ut_asserteq(true, device_active(normal));
+ ut_asserteq(false, device_active(dma));
+ ut_asserteq(true, device_active(vital));
+ ut_asserteq(true, device_active(dma_vital));
+
+ /* Remove active devices via selective remove flag */
+ ut_assertok(device_probe(dma));
+ dm_remove_devices_flags(DM_REMOVE_ACTIVE_ALL);
+
+ /* This should have affected both active-dma devices */
+ ut_asserteq(true, device_active(normal));
+ ut_asserteq(false, device_active(dma));
+ ut_asserteq(true, device_active(vital));
+ ut_asserteq(false, device_active(dma_vital));
+
+ /* Remove non-vital devices */
+ ut_assertok(device_probe(dma));
+ ut_assertok(device_probe(dma_vital));
+ dm_remove_devices_flags(DM_REMOVE_NON_VITAL);
+
+ /* This should have affected only non-vital devices */
+ ut_asserteq(false, device_active(normal));
+ ut_asserteq(false, device_active(dma));
+ ut_asserteq(true, device_active(vital));
+ ut_asserteq(true, device_active(dma_vital));
+
+ /* Remove vital devices via normal remove flag */
+ ut_assertok(device_probe(normal));
+ ut_assertok(device_probe(dma));
+ dm_remove_devices_flags(DM_REMOVE_NORMAL);
+
+ /* Check that all devices are inactive right now */
+ ut_asserteq(false, device_active(normal));
+ ut_asserteq(false, device_active(dma));
+ ut_asserteq(false, device_active(vital));
+ ut_asserteq(false, device_active(dma_vital));
+
+ return 0;
+}
+DM_TEST(dm_test_remove_vital, 0);
+
static int dm_test_uclass_before_ready(struct unit_test_state *uts)
{
struct uclass *uc;
diff --git a/test/dm/test-driver.c b/test/dm/test-driver.c
index a67f5d3f982..ca7626a0668 100644
--- a/test/dm/test-driver.c
+++ b/test/dm/test-driver.c
@@ -170,3 +170,25 @@ U_BOOT_DRIVER(test_act_dma_drv) = {
.unbind = test_manual_unbind,
.flags = DM_FLAG_ACTIVE_DMA,
};
+
+U_BOOT_DRIVER(test_vital_clk_drv) = {
+ .name = "test_vital_clk_drv",
+ .id = UCLASS_TEST,
+ .ops = &test_manual_ops,
+ .bind = test_manual_bind,
+ .probe = test_manual_probe,
+ .remove = test_manual_remove,
+ .unbind = test_manual_unbind,
+ .flags = DM_FLAG_VITAL,
+};
+
+U_BOOT_DRIVER(test_act_dma_vital_clk_drv) = {
+ .name = "test_act_dma_vital_clk_drv",
+ .id = UCLASS_TEST,
+ .ops = &test_manual_ops,
+ .bind = test_manual_bind,
+ .probe = test_manual_probe,
+ .remove = test_manual_remove,
+ .unbind = test_manual_unbind,
+ .flags = DM_FLAG_VITAL | DM_FLAG_ACTIVE_DMA,
+};
diff --git a/test/dm/virtio.c b/test/dm/virtio.c
index ad355981cf4..9a7e658cceb 100644
--- a/test/dm/virtio.c
+++ b/test/dm/virtio.c
@@ -123,7 +123,9 @@ static int dm_test_virtio_remove(struct unit_test_state *uts)
/* check the device can be successfully removed */
dev_or_flags(dev, DM_FLAG_ACTIVATED);
- ut_assertok(device_remove(bus, DM_REMOVE_ACTIVE_ALL));
+ ut_asserteq(-EKEYREJECTED, device_remove(bus, DM_REMOVE_ACTIVE_ALL));
+
+ ut_asserteq(false, device_active(dev));
return 0;
}