diff options
133 files changed, 2257 insertions, 617 deletions
diff --git a/arch/arc/lib/bootm.c b/arch/arc/lib/bootm.c index 628addd87e..07b2c1540d 100644 --- a/arch/arc/lib/bootm.c +++ b/arch/arc/lib/bootm.c @@ -22,10 +22,10 @@ static int cleanup_before_linux(void) return 0; } -__weak int board_prep_linux(bootm_headers_t *images) { return 0; } +__weak int board_prep_linux(struct bootm_headers *images) { return 0; } /* Subcommand: PREP */ -static int boot_prep_linux(bootm_headers_t *images) +static int boot_prep_linux(struct bootm_headers *images) { int ret; @@ -49,7 +49,7 @@ __weak void board_jump_and_run(ulong entry, int zero, int arch, uint params) } /* Subcommand: GO */ -static void boot_jump_linux(bootm_headers_t *images, int flag) +static void boot_jump_linux(struct bootm_headers *images, int flag) { ulong kernel_entry; unsigned int r0, r2; @@ -79,7 +79,7 @@ static void boot_jump_linux(bootm_headers_t *images, int flag) board_jump_and_run(kernel_entry, r0, 0, r2); } -int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) +int do_bootm_linux(int flag, int argc, char *argv[], struct bootm_headers *images) { /* No need for those on ARC */ if ((flag & BOOTM_STATE_OS_BD_T) || (flag & BOOTM_STATE_OS_CMDLINE)) diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 9f086f3b90..e414ef8267 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -192,10 +192,10 @@ static void do_nonsec_virt_switch(void) } #endif -__weak void board_prep_linux(bootm_headers_t *images) { } +__weak void board_prep_linux(struct bootm_headers *images) { } /* Subcommand: PREP */ -static void boot_prep_linux(bootm_headers_t *images) +static void boot_prep_linux(struct bootm_headers *images) { char *commandline = env_get("bootargs"); @@ -288,7 +288,7 @@ static void switch_to_el1(void) #endif /* Subcommand: GO */ -static void boot_jump_linux(bootm_headers_t *images, int flag) +static void boot_jump_linux(struct bootm_headers *images, int flag) { #ifdef CONFIG_ARM64 void (*kernel_entry)(void *fdt_addr, void *res0, void *res1, @@ -379,7 +379,7 @@ static void boot_jump_linux(bootm_headers_t *images, int flag) * they are called if subcommand is equal 0. */ int do_bootm_linux(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { /* No need for those on ARM */ if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE) @@ -401,7 +401,7 @@ int do_bootm_linux(int flag, int argc, char *const argv[], } #if defined(CONFIG_BOOTM_VXWORKS) -void boot_prep_vxworks(bootm_headers_t *images) +void boot_prep_vxworks(struct bootm_headers *images) { #if defined(CONFIG_OF_LIBFDT) int off; @@ -416,7 +416,8 @@ void boot_prep_vxworks(bootm_headers_t *images) #endif cleanup_before_linux(); } -void boot_jump_vxworks(bootm_headers_t *images) + +void boot_jump_vxworks(struct bootm_headers *images) { #if defined(CONFIG_ARM64) && defined(CONFIG_ARMV8_PSCI) armv8_setup_psci(); diff --git a/arch/arm/mach-aspeed/ast2600/spl.c b/arch/arm/mach-aspeed/ast2600/spl.c index 53c8a15bf9..0952e73a45 100644 --- a/arch/arm/mach-aspeed/ast2600/spl.c +++ b/arch/arm/mach-aspeed/ast2600/spl.c @@ -56,9 +56,9 @@ out: return BOOT_DEVICE_RAM; } -struct image_header *spl_get_load_buffer(ssize_t offset, size_t size) +struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size) { - return (struct image_header *)(CONFIG_SYS_LOAD_ADDR); + return (struct legacy_img_hdr *)(CONFIG_SYS_LOAD_ADDR); } #ifdef CONFIG_SPL_OS_BOOT diff --git a/arch/arm/mach-imx/hab.c b/arch/arm/mach-imx/hab.c index 0d1a7766be..c6747b257c 100644 --- a/arch/arm/mach-imx/hab.c +++ b/arch/arm/mach-imx/hab.c @@ -589,7 +589,7 @@ static ulong get_image_ivt_offset(ulong img_addr) switch (genimg_get_format(buf)) { #if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT) case IMAGE_FORMAT_LEGACY: - return (image_get_image_size((image_header_t *)img_addr) + return (image_get_image_size((struct legacy_img_hdr *)img_addr) + 0x1000 - 1) & ~(0x1000 - 1); #endif #if CONFIG_IS_ENABLED(FIT) diff --git a/arch/arm/mach-imx/spl_imx_romapi.c b/arch/arm/mach-imx/spl_imx_romapi.c index 07bf07beee..aa5d23a6fb 100644 --- a/arch/arm/mach-imx/spl_imx_romapi.c +++ b/arch/arm/mach-imx/spl_imx_romapi.c @@ -72,7 +72,7 @@ static int spl_romapi_load_image_seekable(struct spl_image_info *spl_image, int ret; u32 offset; u32 pagesize, size; - struct image_header *header; + struct legacy_img_hdr *header; u32 image_offset; ret = rom_api_query_boot_infor(QUERY_IVT_OFF, &offset); @@ -84,14 +84,14 @@ static int spl_romapi_load_image_seekable(struct spl_image_info *spl_image, return -1; } - header = (struct image_header *)(CONFIG_SPL_IMX_ROMAPI_LOADADDR); + header = (struct legacy_img_hdr *)(CONFIG_SPL_IMX_ROMAPI_LOADADDR); printf("image offset 0x%x, pagesize 0x%x, ivt offset 0x%x\n", image_offset, pagesize, offset); offset = spl_romapi_get_uboot_base(image_offset, rom_bt_dev); - size = ALIGN(sizeof(struct image_header), pagesize); + size = ALIGN(sizeof(struct legacy_img_hdr), pagesize); ret = rom_api_download_image((u8 *)header, offset, size); if (ret != ROM_API_OKAY) { diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c index 3962f2800f..14c37acbce 100644 --- a/arch/arm/mach-k3/common.c +++ b/arch/arm/mach-k3/common.c @@ -493,7 +493,7 @@ bool soc_is_j7200(void) } #ifdef CONFIG_ARM64 -void board_prep_linux(bootm_headers_t *images) +void board_prep_linux(struct bootm_headers *images) { debug("Linux kernel Image start = 0x%lx end = 0x%lx\n", images->os.start, images->os.end); diff --git a/arch/arm/mach-k3/sysfw-loader.c b/arch/arm/mach-k3/sysfw-loader.c index b3beeca947..aea640b570 100644 --- a/arch/arm/mach-k3/sysfw-loader.c +++ b/arch/arm/mach-k3/sysfw-loader.c @@ -88,10 +88,10 @@ static void *sysfw_load_address; * Populate SPL hook to override the default load address used by the SPL * loader function with a custom address for SYSFW loading. */ -struct image_header *spl_get_load_buffer(ssize_t offset, size_t size) +struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size) { if (sysfw_loaded) - return (struct image_header *)(CONFIG_SYS_TEXT_BASE + offset); + return (struct legacy_img_hdr *)(CONFIG_SYS_TEXT_BASE + offset); else if (sysfw_load_address) return sysfw_load_address; else @@ -490,7 +490,7 @@ void k3_sysfw_loader(bool rom_loaded_sysfw, sysfw_loaded = true; /* Ensure the SYSFW image is in FIT format */ - if (image_get_magic((const image_header_t *)sysfw_load_address) != + if (image_get_magic((const struct legacy_img_hdr *)sysfw_load_address) != FDT_MAGIC) panic("SYSFW image not in FIT format!\n"); diff --git a/arch/arm/mach-keystone/cmd_mon.c b/arch/arm/mach-keystone/cmd_mon.c index e26296b6da..4734e4c714 100644 --- a/arch/arm/mach-keystone/cmd_mon.c +++ b/arch/arm/mach-keystone/cmd_mon.c @@ -17,7 +17,7 @@ static int do_mon_install(struct cmd_tbl *cmdtp, int flag, int argc, { u32 addr, dpsc_base = 0x1E80000, freq, load_addr, size; int rcode = 0; - struct image_header *header; + struct legacy_img_hdr *header; u32 ecrypt_bm_addr = 0; if (argc < 2) @@ -27,7 +27,7 @@ static int do_mon_install(struct cmd_tbl *cmdtp, int flag, int argc, addr = hextoul(argv[1], NULL); - header = (struct image_header *)addr; + header = (struct legacy_img_hdr *)addr; if (image_get_magic(header) != IH_MAGIC) { printf("## Please update monitor image\n"); @@ -36,7 +36,7 @@ static int do_mon_install(struct cmd_tbl *cmdtp, int flag, int argc, load_addr = image_get_load(header); size = image_get_data_size(header); - memcpy((void *)load_addr, (void *)(addr + sizeof(struct image_header)), + memcpy((void *)load_addr, (void *)(addr + sizeof(struct legacy_img_hdr)), size); if (argc >= 3) diff --git a/arch/arm/mach-socfpga/board.c b/arch/arm/mach-socfpga/board.c index 7267163222..b49006c6c8 100644 --- a/arch/arm/mach-socfpga/board.c +++ b/arch/arm/mach-socfpga/board.c @@ -114,7 +114,7 @@ void board_fit_image_post_process(const void *fit, int node, void **p_image, #endif #if !IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_FIT) -void board_prep_linux(bootm_headers_t *images) +void board_prep_linux(struct bootm_headers *images) { if (!images->fit_uname_cfg) { if (IS_ENABLED(CONFIG_SOCFPGA_SECURE_VAB_AUTH) && diff --git a/arch/arm/mach-sunxi/spl_spi_sunxi.c b/arch/arm/mach-sunxi/spl_spi_sunxi.c index de9aa68c4a..925bf85f2d 100644 --- a/arch/arm/mach-sunxi/spl_spi_sunxi.c +++ b/arch/arm/mach-sunxi/spl_spi_sunxi.c @@ -335,10 +335,10 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) { int ret = 0; - struct image_header *header; - header = (struct image_header *)(CONFIG_SYS_TEXT_BASE); + struct legacy_img_hdr *header; uint32_t load_offset = sunxi_get_spl_size(); + header = (struct legacy_img_hdr *)CONFIG_SYS_TEXT_BASE; load_offset = max_t(uint32_t, load_offset, CONFIG_SYS_SPI_U_BOOT_OFFS); spi0_init(); diff --git a/arch/arm/mach-tegra/xusb-padctl-common.c b/arch/arm/mach-tegra/xusb-padctl-common.c index 8bdd44ad7a..388ec49968 100644 --- a/arch/arm/mach-tegra/xusb-padctl-common.c +++ b/arch/arm/mach-tegra/xusb-padctl-common.c @@ -282,7 +282,7 @@ int tegra_xusb_process_nodes(ofnode nodes[], unsigned int count, debug("%s: count=%d\n", __func__, count); for (i = 0; i < count; i++) { debug("%s: i=%d, node=%p\n", __func__, i, nodes[i].np); - if (!ofnode_is_available(nodes[i])) + if (!ofnode_is_enabled(nodes[i])) continue; padctl.socdata = socdata; diff --git a/arch/m68k/lib/bootm.c b/arch/m68k/lib/bootm.c index 9cade92954..c1c9bdceb5 100644 --- a/arch/m68k/lib/bootm.c +++ b/arch/m68k/lib/bootm.c @@ -36,7 +36,7 @@ void arch_lmb_reserve(struct lmb *lmb) } int do_bootm_linux(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { int ret; struct bd_info *kbd; diff --git a/arch/microblaze/lib/bootm.c b/arch/microblaze/lib/bootm.c index 31b6659cdf..4a5421497e 100644 --- a/arch/microblaze/lib/bootm.c +++ b/arch/microblaze/lib/bootm.c @@ -37,7 +37,7 @@ void arch_lmb_reserve(struct lmb *lmb) arch_lmb_reserve_generic(lmb, get_sp(), gd->ram_top, 4096); } -static void boot_jump_linux(bootm_headers_t *images, int flag) +static void boot_jump_linux(struct bootm_headers *images, int flag) { void (*thekernel)(char *cmdline, ulong rd, ulong dt); ulong dt = (ulong)images->ft_addr; @@ -71,7 +71,7 @@ static void boot_jump_linux(bootm_headers_t *images, int flag) } } -static void boot_prep_linux(bootm_headers_t *images) +static void boot_prep_linux(struct bootm_headers *images) { if (CONFIG_IS_ENABLED(OF_LIBFDT) && CONFIG_IS_ENABLED(LMB) && images->ft_len) { debug("using: FDT\n"); @@ -83,7 +83,7 @@ static void boot_prep_linux(bootm_headers_t *images) } int do_bootm_linux(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { images->cmdline_start = (ulong)env_get("bootargs"); diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c index cab8da4860..5fda914e6b 100644 --- a/arch/mips/lib/bootm.c +++ b/arch/mips/lib/bootm.c @@ -71,7 +71,7 @@ static void linux_cmdline_dump(void) debug(" arg %03d: %s\n", i, linux_argv[i]); } -static void linux_cmdline_legacy(bootm_headers_t *images) +static void linux_cmdline_legacy(struct bootm_headers *images) { const char *bootargs, *next, *quote; @@ -111,7 +111,7 @@ static void linux_cmdline_legacy(bootm_headers_t *images) } } -static void linux_cmdline_append(bootm_headers_t *images) +static void linux_cmdline_append(struct bootm_headers *images) { char buf[24]; ulong mem, rd_start, rd_size; @@ -164,7 +164,7 @@ static void linux_env_set(const char *env_name, const char *env_val) } } -static void linux_env_legacy(bootm_headers_t *images) +static void linux_env_legacy(struct bootm_headers *images) { char env_buf[12]; const char *cp; @@ -213,7 +213,7 @@ static void linux_env_legacy(bootm_headers_t *images) } } -static int boot_reloc_fdt(bootm_headers_t *images) +static int boot_reloc_fdt(struct bootm_headers *images) { /* * In case of legacy uImage's, relocation of FDT is already done @@ -243,7 +243,7 @@ int arch_fixup_fdt(void *blob) } #endif -static int boot_setup_fdt(bootm_headers_t *images) +static int boot_setup_fdt(struct bootm_headers *images) { images->initrd_start = virt_to_phys((void *)images->initrd_start); images->initrd_end = virt_to_phys((void *)images->initrd_end); @@ -251,7 +251,7 @@ static int boot_setup_fdt(bootm_headers_t *images) &images->lmb); } -static void boot_prep_linux(bootm_headers_t *images) +static void boot_prep_linux(struct bootm_headers *images) { if (CONFIG_IS_ENABLED(MIPS_BOOT_FDT) && images->ft_len) { boot_reloc_fdt(images); @@ -271,7 +271,7 @@ static void boot_prep_linux(bootm_headers_t *images) } } -static void boot_jump_linux(bootm_headers_t *images) +static void boot_jump_linux(struct bootm_headers *images) { typedef void __noreturn (*kernel_entry_t)(int, ulong, ulong, ulong); kernel_entry_t kernel = (kernel_entry_t) images->ep; @@ -302,7 +302,7 @@ static void boot_jump_linux(bootm_headers_t *images) } int do_bootm_linux(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { /* No need for those on MIPS */ if (flag & BOOTM_STATE_OS_BD_T) diff --git a/arch/mips/mach-jz47xx/jz4780/jz4780.c b/arch/mips/mach-jz47xx/jz4780/jz4780.c index a57ec7802b..4c40bd86fd 100644 --- a/arch/mips/mach-jz47xx/jz4780/jz4780.c +++ b/arch/mips/mach-jz47xx/jz4780/jz4780.c @@ -30,7 +30,7 @@ void board_init_f(ulong dummy) typedef void __noreturn (*image_entry_noargs_t)(void); struct mmc *mmc; unsigned long count; - struct image_header *header; + struct legacy_img_hdr *header; int ret; /* Set global data pointer */ @@ -58,8 +58,8 @@ void board_init_f(ulong dummy) if (ret) hang(); - header = (struct image_header *)(CONFIG_SYS_TEXT_BASE - - sizeof(struct image_header)); + header = (struct legacy_img_hdr *)(CONFIG_SYS_TEXT_BASE - + sizeof(struct legacy_img_hdr)); count = blk_dread(mmc_get_blk_desc(mmc), CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR, diff --git a/arch/mips/mach-mtmips/mt7621/spl/spl.c b/arch/mips/mach-mtmips/mt7621/spl/spl.c index 91eebc6c1f..aa5b267bb9 100644 --- a/arch/mips/mach-mtmips/mt7621/spl/spl.c +++ b/arch/mips/mach-mtmips/mt7621/spl/spl.c @@ -64,7 +64,7 @@ void board_boot_order(u32 *spl_boot_list) unsigned long spl_nor_get_uboot_base(void) { const struct tpl_info *tpli; - const image_header_t *hdr; + const struct legacy_img_hdr *hdr; u32 addr; addr = FLASH_MMAP_BASE + TPL_INFO_OFFSET; @@ -72,7 +72,7 @@ unsigned long spl_nor_get_uboot_base(void) if (tpli->magic == TPL_INFO_MAGIC) { addr = FLASH_MMAP_BASE + tpli->size; - hdr = (const image_header_t *)KSEG1ADDR(addr); + hdr = (const struct legacy_img_hdr *)KSEG1ADDR(addr); if (image_get_magic(hdr) == IH_MAGIC) { addr += sizeof(*hdr) + image_get_size(hdr); diff --git a/arch/mips/mach-mtmips/mt7621/tpl/tpl.c b/arch/mips/mach-mtmips/mt7621/tpl/tpl.c index 2a828907a3..d77592da5f 100644 --- a/arch/mips/mach-mtmips/mt7621/tpl/tpl.c +++ b/arch/mips/mach-mtmips/mt7621/tpl/tpl.c @@ -116,7 +116,7 @@ static void mt7621_cache_init(void) void __noreturn tpl_main(void) { - const image_header_t *hdr = (const image_header_t *)__image_copy_end; + const struct legacy_img_hdr *hdr = (const struct legacy_img_hdr *)__image_copy_end; image_entry_noargs_t image_entry; u32 loadaddr, size; uintptr_t data; @@ -132,7 +132,7 @@ void __noreturn tpl_main(void) image_entry = (image_entry_noargs_t)image_get_ep(hdr); /* Load TPL image to L2 cache */ - data = (uintptr_t)__image_copy_end + sizeof(struct image_header); + data = (uintptr_t)__image_copy_end + sizeof(struct legacy_img_hdr); fill_lock_l2cache(data, loadaddr, size); /* Jump to SPL */ diff --git a/arch/nios2/lib/bootm.c b/arch/nios2/lib/bootm.c index 3cb59bd977..06c094d0f1 100644 --- a/arch/nios2/lib/bootm.c +++ b/arch/nios2/lib/bootm.c @@ -17,7 +17,7 @@ DECLARE_GLOBAL_DATA_PTR; #define NIOS_MAGIC 0x534f494e /* enable command line and initrd passing */ int do_bootm_linux(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { void (*kernel)(int, int, int, char *) = (void *)images->ep; char *commandline = env_get("bootargs"); diff --git a/arch/powerpc/lib/bootm.c b/arch/powerpc/lib/bootm.c index b92df9543e..512787854c 100644 --- a/arch/powerpc/lib/bootm.c +++ b/arch/powerpc/lib/bootm.c @@ -45,7 +45,7 @@ static void set_clocks_in_mhz (struct bd_info *kbd); #define CONFIG_SYS_LINUX_LOWMEM_MAX_SIZE (768*1024*1024) #endif -static void boot_jump_linux(bootm_headers_t *images) +static void boot_jump_linux(struct bootm_headers *images) { void (*kernel)(struct bd_info *, ulong r4, ulong r5, ulong r6, ulong r7, ulong r8, ulong r9); @@ -151,7 +151,7 @@ void arch_lmb_reserve(struct lmb *lmb) return ; } -static void boot_prep_linux(bootm_headers_t *images) +static void boot_prep_linux(struct bootm_headers *images) { #ifdef CONFIG_MP /* @@ -163,7 +163,7 @@ static void boot_prep_linux(bootm_headers_t *images) #endif } -static int boot_cmdline_linux(bootm_headers_t *images) +static int boot_cmdline_linux(struct bootm_headers *images) { ulong of_size = images->ft_len; struct lmb *lmb = &images->lmb; @@ -184,7 +184,7 @@ static int boot_cmdline_linux(bootm_headers_t *images) return ret; } -static int boot_bd_t_linux(bootm_headers_t *images) +static int boot_bd_t_linux(struct bootm_headers *images) { ulong of_size = images->ft_len; struct lmb *lmb = &images->lmb; @@ -205,7 +205,7 @@ static int boot_bd_t_linux(bootm_headers_t *images) return ret; } -static int boot_body_linux(bootm_headers_t *images) +static int boot_body_linux(struct bootm_headers *images) { int ret; @@ -224,7 +224,7 @@ static int boot_body_linux(bootm_headers_t *images) } noinline int do_bootm_linux(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { int ret; @@ -273,7 +273,7 @@ static void set_clocks_in_mhz (struct bd_info *kbd) } #if defined(CONFIG_BOOTM_VXWORKS) -void boot_prep_vxworks(bootm_headers_t *images) +void boot_prep_vxworks(struct bootm_headers *images) { #if defined(CONFIG_OF_LIBFDT) int off; @@ -305,7 +305,7 @@ void boot_prep_vxworks(bootm_headers_t *images) #endif } -void boot_jump_vxworks(bootm_headers_t *images) +void boot_jump_vxworks(struct bootm_headers *images) { /* PowerPC VxWorks boot interface conforms to the ePAPR standard * general purpuse registers: diff --git a/arch/riscv/lib/andes_plic.c b/arch/riscv/lib/andes_plic.c index 5e113ee8c9..68514758a8 100644 --- a/arch/riscv/lib/andes_plic.c +++ b/arch/riscv/lib/andes_plic.c @@ -71,7 +71,7 @@ int riscv_init_ipi(void) continue; /* skip if hart is marked as not available */ - if (!ofnode_is_available(node)) + if (!ofnode_is_enabled(node)) continue; /* read hart ID of CPU */ diff --git a/arch/riscv/lib/bootm.c b/arch/riscv/lib/bootm.c index 670d9c9ebc..f5f8b4c733 100644 --- a/arch/riscv/lib/bootm.c +++ b/arch/riscv/lib/bootm.c @@ -62,7 +62,7 @@ static void announce_and_cleanup(int fake) cleanup_before_linux(); } -static void boot_prep_linux(bootm_headers_t *images) +static void boot_prep_linux(struct bootm_headers *images) { if (CONFIG_IS_ENABLED(OF_LIBFDT) && CONFIG_IS_ENABLED(LMB) && images->ft_len) { debug("using: FDT\n"); @@ -76,7 +76,7 @@ static void boot_prep_linux(bootm_headers_t *images) } } -static void boot_jump_linux(bootm_headers_t *images, int flag) +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); @@ -107,7 +107,7 @@ static void boot_jump_linux(bootm_headers_t *images, int flag) } int do_bootm_linux(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { /* No need for those on RISC-V */ if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE) @@ -129,7 +129,7 @@ int do_bootm_linux(int flag, int argc, char *const argv[], } int do_bootm_vxworks(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { return do_bootm_linux(flag, argc, argv, images); } diff --git a/arch/riscv/lib/smp.c b/arch/riscv/lib/smp.c index c0f65af191..4f073a016f 100644 --- a/arch/riscv/lib/smp.c +++ b/arch/riscv/lib/smp.c @@ -27,7 +27,7 @@ static int send_ipi_many(struct ipi_data *ipi, int wait) ofnode_for_each_subnode(node, cpus) { /* skip if hart is marked as not available in the device tree */ - if (!ofnode_is_available(node)) + if (!ofnode_is_enabled(node)) continue; /* read hart ID of CPU */ diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c index d077948dd7..636d3545b9 100644 --- a/arch/sandbox/cpu/cpu.c +++ b/arch/sandbox/cpu/cpu.c @@ -3,19 +3,22 @@ * Copyright (c) 2011 The Chromium OS Authors. */ +#define LOG_CATEGORY LOGC_SANDBOX + #include <common.h> #include <bootstage.h> #include <cpu_func.h> #include <errno.h> #include <log.h> -#include <asm/global_data.h> -#include <linux/delay.h> -#include <linux/libfdt.h> #include <os.h> +#include <asm/global_data.h> #include <asm/io.h> #include <asm/malloc.h> #include <asm/setjmp.h> #include <asm/state.h> +#include <dm/ofnode.h> +#include <linux/delay.h> +#include <linux/libfdt.h> DECLARE_GLOBAL_DATA_PTR; @@ -373,3 +376,28 @@ ulong timer_get_boot_us(void) return (count - base_count) / 1000; } + +int sandbox_load_other_fdt(void **fdtp, int *sizep) +{ + const char *orig; + int ret, size; + void *fdt = *fdtp; + + ret = state_load_other_fdt(&orig, &size); + if (ret) { + log_err("Cannot read other FDT\n"); + return log_msg_ret("ld", ret); + } + + if (!*fdtp) { + fdt = os_malloc(size); + if (!fdt) + return log_msg_ret("mem", -ENOMEM); + *sizep = size; + } + + memcpy(fdt, orig, *sizep); + *fdtp = fdt; + + return 0; +} diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 90a84e93c7..642be164a3 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -205,21 +205,19 @@ SANDBOX_CMDLINE_OPT_SHORT(default_fdt, 'D', 0, static int sandbox_cmdline_cb_test_fdt(struct sandbox_state *state, const char *arg) { - const char *fmt = "/arch/sandbox/dts/test.dtb"; - char *p; + char buf[256]; char *fname; int len; - len = strlen(state->argv[0]) + strlen(fmt) + 1; + len = state_get_rel_filename("arch/sandbox/dts/test.dtb", buf, + sizeof(buf)); + if (len < 0) + return len; + fname = os_malloc(len); if (!fname) return -ENOMEM; - strcpy(fname, state->argv[0]); - p = strrchr(fname, '/'); - if (!p) - p = fname + strlen(fname); - len -= p - fname; - snprintf(p, len, fmt); + strcpy(fname, buf); state->fdt_fname = fname; return 0; diff --git a/arch/sandbox/cpu/state.c b/arch/sandbox/cpu/state.c index e0d01125bb..fcc4a337e5 100644 --- a/arch/sandbox/cpu/state.c +++ b/arch/sandbox/cpu/state.c @@ -396,6 +396,54 @@ bool autoboot_set_keyed(bool autoboot_keyed) return old_val; } +int state_get_rel_filename(const char *rel_path, char *buf, int size) +{ + struct sandbox_state *state = state_get_current(); + int rel_len, prog_len; + char *p; + int len; + + rel_len = strlen(rel_path); + p = strrchr(state->argv[0], '/'); + prog_len = p ? p - state->argv[0] : 0; + + /* allow space for a / and a terminator */ + len = prog_len + 1 + rel_len + 1; + if (len > size) + return -ENOSPC; + strncpy(buf, state->argv[0], prog_len); + buf[prog_len] = '/'; + strcpy(buf + prog_len + 1, rel_path); + + return len; +} + +int state_load_other_fdt(const char **bufp, int *sizep) +{ + struct sandbox_state *state = state_get_current(); + char fname[256]; + int len, ret; + + /* load the file if needed */ + if (!state->other_fdt_buf) { + len = state_get_rel_filename("arch/sandbox/dts/other.dtb", + fname, sizeof(fname)); + if (len < 0) + return len; + + ret = os_read_file(fname, &state->other_fdt_buf, + &state->other_size); + if (ret) { + log_err("Cannot read file '%s'\n", fname); + return ret; + } + } + *bufp = state->other_fdt_buf; + *sizep = state->other_size; + + return 0; +} + int state_init(void) { state = &main_state; diff --git a/arch/sandbox/dts/Makefile b/arch/sandbox/dts/Makefile index 6cbc9bbcaa..b6a88479b2 100644 --- a/arch/sandbox/dts/Makefile +++ b/arch/sandbox/dts/Makefile @@ -5,7 +5,7 @@ dtb-$(CONFIG_SANDBOX) += sandbox64.dtb else dtb-$(CONFIG_SANDBOX) += sandbox.dtb endif -dtb-$(CONFIG_UT_DM) += test.dtb +dtb-$(CONFIG_UT_DM) += test.dtb other.dtb dtb-$(CONFIG_CMD_EXTENSION) += overlay0.dtbo overlay1.dtbo include $(srctree)/scripts/Makefile.dts diff --git a/arch/sandbox/dts/other.dts b/arch/sandbox/dts/other.dts new file mode 100644 index 0000000000..395a792322 --- /dev/null +++ b/arch/sandbox/dts/other.dts @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Other devicetree file for running sandbox tests + * + * This used for tests which want to check they can access multiple device + * trees. This one is loaded and checks are made that it is actually visible. + */ + +/dts-v1/; + +/ { + compatible = "sandbox-other"; + #address-cells = <1>; + #size-cells = <1>; + + node { + target = <&target 3 4>; + + subnode { + compatible = "sandbox-other2"; + str-prop = "other"; + }; + + subnode2 { + }; + }; + + target: target { + compatible = "sandbox-other2"; + #gpio-cells = <2>; + str-prop = "other"; + reg = <0x8000 0x100>; + status = "disabled"; + }; +}; diff --git a/arch/sandbox/include/asm/malloc.h b/arch/sandbox/include/asm/malloc.h index a1467b5ead..8aaaa9cb87 100644 --- a/arch/sandbox/include/asm/malloc.h +++ b/arch/sandbox/include/asm/malloc.h @@ -6,6 +6,7 @@ */ #ifndef __ASM_MALLOC_H +#define __ASM_MALLOC_H void *malloc(size_t size); void free(void *ptr); diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h index 07c768ae5d..fd42daad51 100644 --- a/arch/sandbox/include/asm/state.h +++ b/arch/sandbox/include/asm/state.h @@ -108,6 +108,9 @@ struct sandbox_state { bool hwspinlock; /* Hardware Spinlock status */ bool allow_memio; /* Allow readl() etc. to work */ + void *other_fdt_buf; /* 'other' FDT blob used by tests */ + int other_size; /* size of other FDT blob */ + /* * This struct is getting large. * @@ -266,6 +269,33 @@ void state_reset_for_test(struct sandbox_state *state); void state_show(struct sandbox_state *state); /** + * state_get_rel_filename() - Get a filename relative to the executable + * + * This uses argv[0] to obtain a filename path + * + * @rel_path: Relative path to build, e.g. "arch/sandbox/dts/test.dtb". Must not + * have a trailing / + * @buf: Buffer to use to return the filename + * @size: Size of buffer + * @return length of filename (including terminator), -ENOSPC if @size is too + * small + */ +int state_get_rel_filename(const char *rel_path, char *buf, int size); + +/** + * state_load_other_fdt() - load the 'other' FDT into a buffer + * + * This loads the other.dtb file into a buffer. This is typically used in tests. + * + * @bufp: Place to put allocated buffer pointer. The buffer is read using + * os_read_file() which calls os_malloc(), so does affect U-Boot's own malloc() + * space + * @sizep: Returns the size of the buffer + * @return 0 if OK, -ve on error + */ +int state_load_other_fdt(const char **bufp, int *sizep); + +/** * Initialize the test system state */ int state_init(void); diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h index 53a036b3ab..0406085917 100644 --- a/arch/sandbox/include/asm/test.h +++ b/arch/sandbox/include/asm/test.h @@ -11,6 +11,8 @@ #include <video.h> #include <pci_ids.h> +struct unit_test_state; + /* The sandbox driver always permits an I2C device with this address */ #define SANDBOX_I2C_TEST_ADDR 0x59 @@ -315,4 +317,21 @@ int sandbox_sdl_set_bpp(struct udevice *dev, enum video_log2_bpp l2bpp); */ void sandbox_set_fake_efi_mgr_dev(struct udevice *dev, bool fake_dev); +/** + * sandbox_load_other_fdt() - load the 'other' FDT into the test state + * + * This copies the other.dtb file into the test state, so that a fresh version + * can be used for a test that is about to run. + * + * If @uts->other_fdt is NULL, as it is when first set up, this allocates a + * buffer for the other FDT and sets @uts->other_fdt_size to its size. + * + * In any case, the other FDT is copied from the sandbox state into + * @uts->other_fdt ready for use. + * + * @uts: Unit test state + * @return 0 if OK, -ve on error + */ +int sandbox_load_other_fdt(void **fdtp, int *sizep); + #endif diff --git a/arch/sandbox/lib/bootm.c b/arch/sandbox/lib/bootm.c index d1d460b84a..c1742f94de 100644 --- a/arch/sandbox/lib/bootm.c +++ b/arch/sandbox/lib/bootm.c @@ -50,7 +50,7 @@ int bootz_setup(ulong image, ulong *start, ulong *end) return ret; } -int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) +int do_bootm_linux(int flag, int argc, char *argv[], struct bootm_headers *images) { if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) { bootstage_mark(BOOTSTAGE_ID_RUN_OS); diff --git a/arch/sh/lib/bootm.c b/arch/sh/lib/bootm.c index 7ea04442b8..a5fad6c46c 100644 --- a/arch/sh/lib/bootm.c +++ b/arch/sh/lib/bootm.c @@ -40,7 +40,7 @@ static unsigned long sh_check_cmd_arg(char *cmdline, char *key, int base) } int do_bootm_linux(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { /* Linux kernel load address */ void (*kernel) (void) = (void (*)(void))images->ep; diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c index 1bcdb3e30d..eafcddfa24 100644 --- a/arch/x86/lib/bootm.c +++ b/arch/x86/lib/bootm.c @@ -69,10 +69,10 @@ int arch_fixup_memory_node(void *blob) #endif /* Subcommand: PREP */ -static int boot_prep_linux(bootm_headers_t *images) +static int boot_prep_linux(struct bootm_headers *images) { char *cmd_line_dest = NULL; - image_header_t *hdr; + struct legacy_img_hdr *hdr; int is_zimage = 0; void *data = NULL; size_t len; @@ -201,7 +201,7 @@ int boot_linux_kernel(ulong setup_base, ulong load_address, bool image_64bit) } /* Subcommand: GO */ -static int boot_jump_linux(bootm_headers_t *images) +static int boot_jump_linux(struct bootm_headers *images) { debug("## Transferring control to Linux (at address %08lx, kernel %08lx) ...\n", images->ep, images->os.load); @@ -211,7 +211,7 @@ static int boot_jump_linux(bootm_headers_t *images) } int do_bootm_linux(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { /* No need for those on x86 */ if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE) diff --git a/arch/xtensa/lib/bootm.c b/arch/xtensa/lib/bootm.c index 277af18168..fee3392815 100644 --- a/arch/xtensa/lib/bootm.c +++ b/arch/xtensa/lib/bootm.c @@ -134,7 +134,7 @@ static struct bp_tag *setup_fdt_tag(struct bp_tag *params, void *fdt_start) * Boot Linux. */ -int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) +int do_bootm_linux(int flag, int argc, char *argv[], struct bootm_headers *images) { struct bp_tag *params, *params_start; ulong initrd_start, initrd_end; diff --git a/board/synopsys/hsdk/hsdk.c b/board/synopsys/hsdk/hsdk.c index 226fbba629..4308c7e440 100644 --- a/board/synopsys/hsdk/hsdk.c +++ b/board/synopsys/hsdk/hsdk.c @@ -844,7 +844,7 @@ static int hsdk_go_run(u32 cpu_start_reg) return 0; } -int board_prep_linux(bootm_headers_t *images) +int board_prep_linux(struct bootm_headers *images) { int ret, ofst; char mask[15]; diff --git a/board/ti/ks2_evm/board.c b/board/ti/ks2_evm/board.c index 0c5c2c9146..5ba3aa35a9 100644 --- a/board/ti/ks2_evm/board.c +++ b/board/ti/ks2_evm/board.c @@ -64,9 +64,9 @@ int dram_init(void) return 0; } -struct image_header *spl_get_load_buffer(ssize_t offset, size_t size) +struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size) { - return (struct image_header *)(CONFIG_SYS_TEXT_BASE); + return (struct legacy_img_hdr *)(CONFIG_SYS_TEXT_BASE); } int board_init(void) diff --git a/boot/boot_fit.c b/boot/boot_fit.c index dfc2a3117d..4a493b3684 100644 --- a/boot/boot_fit.c +++ b/boot/boot_fit.c @@ -57,14 +57,14 @@ static int fdt_offset(const void *fit) void *locate_dtb_in_fit(const void *fit) { - struct image_header *header; + struct legacy_img_hdr *header; int size; int ret; size = fdt_totalsize(fit); size = (size + 3) & ~3; - header = (struct image_header *)fit; + header = (struct legacy_img_hdr *)fit; if (image_get_magic(header) != FDT_MAGIC) { debug("No FIT image appended to U-boot\n"); diff --git a/boot/bootm.c b/boot/bootm.c index e3233fdf89..5b20b418db 100644 --- a/boot/bootm.c +++ b/boot/bootm.c @@ -41,10 +41,10 @@ DECLARE_GLOBAL_DATA_PTR; -bootm_headers_t images; /* pointers to os/initrd/fdt images */ +struct bootm_headers images; /* pointers to os/initrd/fdt images */ static const void *boot_get_kernel(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[], bootm_headers_t *images, + char *const argv[], struct bootm_headers *images, ulong *os_data, ulong *os_len); __weak void board_quiesce_devices(void) @@ -52,7 +52,7 @@ __weak void board_quiesce_devices(void) } #ifdef CONFIG_LMB -static void boot_start_lmb(bootm_headers_t *images) +static void boot_start_lmb(struct bootm_headers *images) { ulong mem_start; phys_size_t mem_size; @@ -65,7 +65,7 @@ static void boot_start_lmb(bootm_headers_t *images) } #else #define lmb_reserve(lmb, base, size) -static inline void boot_start_lmb(bootm_headers_t *images) { } +static inline void boot_start_lmb(struct bootm_headers *images) { } #endif static int bootm_start(struct cmd_tbl *cmdtp, int flag, int argc, @@ -397,9 +397,9 @@ static int handle_decomp_error(int comp_type, size_t uncomp_size, #endif #ifndef USE_HOSTCC -static int bootm_load_os(bootm_headers_t *images, int boot_progress) +static int bootm_load_os(struct bootm_headers *images, int boot_progress) { - image_info_t os = images->os; + struct image_info os = images->os; ulong load = os.load; ulong load_end; ulong blob_start = os.start; @@ -688,7 +688,7 @@ int bootm_process_cmdline_env(int flags) * unless the image type is standalone. */ int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[], int states, bootm_headers_t *images, + char *const argv[], int states, struct bootm_headers *images, int boot_progress) { boot_os_fn *boot_fn; @@ -825,9 +825,9 @@ err: * pointer to a legacy image header if valid image was found * otherwise return NULL */ -static image_header_t *image_get_kernel(ulong img_addr, int verify) +static struct legacy_img_hdr *image_get_kernel(ulong img_addr, int verify) { - image_header_t *hdr = (image_header_t *)img_addr; + struct legacy_img_hdr *hdr = (struct legacy_img_hdr *)img_addr; if (!image_check_magic(hdr)) { puts("Bad Magic Number\n"); @@ -878,11 +878,11 @@ static image_header_t *image_get_kernel(ulong img_addr, int verify) * address and length, otherwise NULL */ static const void *boot_get_kernel(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[], bootm_headers_t *images, + char *const argv[], struct bootm_headers *images, ulong *os_data, ulong *os_len) { #if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT) - image_header_t *hdr; + struct legacy_img_hdr *hdr; #endif ulong img_addr; const void *buf; @@ -940,7 +940,7 @@ static const void *boot_get_kernel(struct cmd_tbl *cmdtp, int flag, int argc, * kernel decompression. */ memmove(&images->legacy_hdr_os_copy, hdr, - sizeof(image_header_t)); + sizeof(struct legacy_img_hdr)); /* save pointer to image header */ images->legacy_hdr_os = hdr; @@ -1002,7 +1002,7 @@ static int bootm_host_load_image(const void *fit, int req_image_type, { const char *fit_uname_config = NULL; ulong data, len; - bootm_headers_t images; + struct bootm_headers images; int noffset; ulong load_end, buf_size; uint8_t image_type; diff --git a/boot/bootm_os.c b/boot/bootm_os.c index 079224ce58..99ff0e6c02 100644 --- a/boot/bootm_os.c +++ b/boot/bootm_os.c @@ -24,7 +24,7 @@ DECLARE_GLOBAL_DATA_PTR; static int do_bootm_standalone(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { int (*appl)(int, char *const[]); @@ -65,10 +65,11 @@ static void __maybe_unused fit_unsupported_reset(const char *msg) #ifdef CONFIG_BOOTM_NETBSD static int do_bootm_netbsd(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { - void (*loader)(struct bd_info *, image_header_t *, char *, char *); - image_header_t *os_hdr, *hdr; + void (*loader)(struct bd_info *bd, struct legacy_img_hdr *hdr, + char *console, char *cmdline); + struct legacy_img_hdr *os_hdr, *hdr; ulong kernel_data, kernel_len; char *cmdline; @@ -115,7 +116,7 @@ static int do_bootm_netbsd(int flag, int argc, char *const argv[], cmdline = ""; } - loader = (void (*)(struct bd_info *, image_header_t *, char *, char *))images->ep; + loader = (void (*)(struct bd_info *, struct legacy_img_hdr *, char *, char *))images->ep; printf("## Transferring control to NetBSD stage-2 loader (at address %08lx) ...\n", (ulong)loader); @@ -137,7 +138,7 @@ static int do_bootm_netbsd(int flag, int argc, char *const argv[], #ifdef CONFIG_BOOTM_RTEMS static int do_bootm_rtems(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { void (*entry_point)(struct bd_info *); @@ -170,7 +171,7 @@ static int do_bootm_rtems(int flag, int argc, char *const argv[], #if defined(CONFIG_BOOTM_OSE) static int do_bootm_ose(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { void (*entry_point)(void); @@ -203,7 +204,7 @@ static int do_bootm_ose(int flag, int argc, char *const argv[], #if defined(CONFIG_BOOTM_PLAN9) static int do_bootm_plan9(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { void (*entry_point)(void); char *s; @@ -252,7 +253,7 @@ static int do_bootm_plan9(int flag, int argc, char *const argv[], #if defined(CONFIG_BOOTM_VXWORKS) && \ (defined(CONFIG_PPC) || defined(CONFIG_ARM)) -static void do_bootvx_fdt(bootm_headers_t *images) +static void do_bootvx_fdt(struct bootm_headers *images) { #if defined(CONFIG_OF_LIBFDT) int ret; @@ -311,7 +312,7 @@ static void do_bootvx_fdt(bootm_headers_t *images) } static int do_bootm_vxworks_legacy(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { if (flag != BOOTM_STATE_OS_GO) return 0; @@ -329,7 +330,7 @@ static int do_bootm_vxworks_legacy(int flag, int argc, char *const argv[], } int do_bootm_vxworks(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { char *bootargs; int pos; @@ -365,7 +366,7 @@ int do_bootm_vxworks(int flag, int argc, char *const argv[], #if defined(CONFIG_CMD_ELF) static int do_bootm_qnxelf(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { char *local_args[2]; char str[16]; @@ -403,7 +404,7 @@ static int do_bootm_qnxelf(int flag, int argc, char *const argv[], #ifdef CONFIG_INTEGRITY static int do_bootm_integrity(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { void (*entry_point)(void); @@ -436,7 +437,7 @@ static int do_bootm_integrity(int flag, int argc, char *const argv[], #ifdef CONFIG_BOOTM_OPENRTOS static int do_bootm_openrtos(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { void (*entry_point)(void); @@ -462,7 +463,7 @@ static int do_bootm_openrtos(int flag, int argc, char *const argv[], #ifdef CONFIG_BOOTM_OPTEE static int do_bootm_tee(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { int ret; @@ -490,7 +491,7 @@ static int do_bootm_tee(int flag, int argc, char *const argv[], #ifdef CONFIG_BOOTM_EFI static int do_bootm_efi(int flag, int argc, char *const argv[], - bootm_headers_t *images) + struct bootm_headers *images) { int ret; efi_status_t efi_ret; @@ -589,7 +590,7 @@ __weak void board_preboot_os(void) } int boot_selected_os(int argc, char *const argv[], int state, - bootm_headers_t *images, boot_os_fn *boot_fn) + struct bootm_headers *images, boot_os_fn *boot_fn) { arch_preboot_os(); board_preboot_os(); diff --git a/boot/image-android.c b/boot/image-android.c index 1fbbbba1eb..2628db3741 100644 --- a/boot/image-android.c +++ b/boot/image-android.c @@ -63,7 +63,7 @@ int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify, ulong *os_data, ulong *os_len) { u32 kernel_addr = android_image_get_kernel_addr(hdr); - const struct image_header *ihdr = (const struct image_header *) + const struct legacy_img_hdr *ihdr = (const struct legacy_img_hdr *) ((uintptr_t)hdr + hdr->page_size); /* @@ -159,8 +159,8 @@ ulong android_image_get_kcomp(const struct andr_img_hdr *hdr) { const void *p = (void *)((uintptr_t)hdr + hdr->page_size); - if (image_get_magic((image_header_t *)p) == IH_MAGIC) - return image_get_comp((image_header_t *)p); + if (image_get_magic((struct legacy_img_hdr *)p) == IH_MAGIC) + return image_get_comp((struct legacy_img_hdr *)p); else if (get_unaligned_le32(p) == LZ4F_MAGIC) return IH_COMP_LZ4; else diff --git a/boot/image-board.c b/boot/image-board.c index 98f903f93f..34d1e5f18b 100644 --- a/boot/image-board.c +++ b/boot/image-board.c @@ -40,10 +40,10 @@ DECLARE_GLOBAL_DATA_PTR; * pointer to a ramdisk image header, if image was found and valid * otherwise, return NULL */ -static const image_header_t *image_get_ramdisk(ulong rd_addr, u8 arch, - int verify) +static const struct legacy_img_hdr *image_get_ramdisk(ulong rd_addr, u8 arch, + int verify) { - const image_header_t *rd_hdr = (const image_header_t *)rd_addr; + const struct legacy_img_hdr *rd_hdr = (const struct legacy_img_hdr *)rd_addr; if (!image_check_magic(rd_hdr)) { puts("Bad Magic Number\n"); @@ -273,9 +273,9 @@ ulong genimg_get_kernel_addr(char * const img_addr) int genimg_get_format(const void *img_addr) { if (CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)) { - const image_header_t *hdr; + const struct legacy_img_hdr *hdr; - hdr = (const image_header_t *)img_addr; + hdr = (const struct legacy_img_hdr *)img_addr; if (image_check_magic(hdr)) return IMAGE_FORMAT_LEGACY; } @@ -301,7 +301,7 @@ int genimg_get_format(const void *img_addr) * 0, no FIT support or no configuration found * 1, configuration found */ -int genimg_has_config(bootm_headers_t *images) +int genimg_has_config(struct bootm_headers *images) { if (CONFIG_IS_ENABLED(FIT) && images->fit_uname_cfg) return 1; @@ -320,7 +320,7 @@ int genimg_has_config(bootm_headers_t *images) * Return: 0 if OK, -ENOPKG if no ramdisk (but an error should not be reported), * other -ve value on other error */ -static int select_ramdisk(bootm_headers_t *images, const char *select, u8 arch, +static int select_ramdisk(struct bootm_headers *images, const char *select, u8 arch, ulong *rd_datap, ulong *rd_lenp) { const char *fit_uname_config; @@ -389,7 +389,7 @@ static int select_ramdisk(bootm_headers_t *images, const char *select, u8 arch, switch (genimg_get_format(buf)) { case IMAGE_FORMAT_LEGACY: if (CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)) { - const image_header_t *rd_hdr; + const struct legacy_img_hdr *rd_hdr; printf("## Loading init Ramdisk from Legacy Image at %08lx ...\n", rd_addr); @@ -482,7 +482,7 @@ static int select_ramdisk(bootm_headers_t *images, const char *select, u8 arch, * 1, if ramdisk image is found but corrupted, or invalid * rd_start and rd_end are set to 0 if no ramdisk exists */ -int boot_get_ramdisk(int argc, char *const argv[], bootm_headers_t *images, +int boot_get_ramdisk(int argc, char *const argv[], struct bootm_headers *images, u8 arch, ulong *rd_start, ulong *rd_end) { ulong rd_data, rd_len; @@ -646,7 +646,7 @@ error: return -1; } -int boot_get_setup(bootm_headers_t *images, u8 arch, +int boot_get_setup(struct bootm_headers *images, u8 arch, ulong *setup_start, ulong *setup_len) { if (!CONFIG_IS_ENABLED(FIT)) @@ -655,7 +655,7 @@ int boot_get_setup(bootm_headers_t *images, u8 arch, return boot_get_setup_fit(images, arch, setup_start, setup_len); } -int boot_get_fpga(int argc, char *const argv[], bootm_headers_t *images, +int boot_get_fpga(int argc, char *const argv[], struct bootm_headers *images, u8 arch, const ulong *ld_start, ulong * const ld_len) { ulong tmp_img_addr, img_data, img_len; @@ -758,7 +758,7 @@ static void fit_loadable_process(u8 img_type, fit_loadable_handler->handler(img_data, img_len); } -int boot_get_loadable(int argc, char *const argv[], bootm_headers_t *images, +int boot_get_loadable(int argc, char *const argv[], struct bootm_headers *images, u8 arch, const ulong *ld_start, ulong * const ld_len) { /* @@ -919,7 +919,7 @@ int boot_get_kbd(struct lmb *lmb, struct bd_info **kbd) return 0; } -int image_setup_linux(bootm_headers_t *images) +int image_setup_linux(struct bootm_headers *images) { ulong of_size = images->ft_len; char **of_flat_tree = &images->ft_addr; diff --git a/boot/image-fdt.c b/boot/image-fdt.c index e75d051c87..884e089f2d 100644 --- a/boot/image-fdt.c +++ b/boot/image-fdt.c @@ -37,9 +37,9 @@ static void fdt_error(const char *msg) } #if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT) -static const image_header_t *image_get_fdt(ulong fdt_addr) +static const struct legacy_img_hdr *image_get_fdt(ulong fdt_addr) { - const image_header_t *fdt_hdr = map_sysmem(fdt_addr, 0); + const struct legacy_img_hdr *fdt_hdr = map_sysmem(fdt_addr, 0); image_print_contents(fdt_hdr); @@ -291,7 +291,7 @@ error: * other -ve value on other error */ -static int select_fdt(bootm_headers_t *images, const char *select, u8 arch, +static int select_fdt(struct bootm_headers *images, const char *select, u8 arch, ulong *fdt_addrp) { const char *buf; @@ -358,7 +358,7 @@ static int select_fdt(bootm_headers_t *images, const char *select, u8 arch, switch (genimg_get_format(buf)) { #if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT) case IMAGE_FORMAT_LEGACY: { - const image_header_t *fdt_hdr; + const struct legacy_img_hdr *fdt_hdr; ulong load, load_end; ulong image_start, image_data, image_end; @@ -470,7 +470,7 @@ static int select_fdt(bootm_headers_t *images, const char *select, u8 arch, * of_flat_tree and of_size are set to 0 if no fdt exists */ int boot_get_fdt(int flag, int argc, char *const argv[], uint8_t arch, - bootm_headers_t *images, char **of_flat_tree, ulong *of_size) + struct bootm_headers *images, char **of_flat_tree, ulong *of_size) { ulong img_addr; ulong fdt_addr; @@ -602,7 +602,7 @@ __weak int arch_fixup_fdt(void *blob) return 0; } -int image_setup_libfdt(bootm_headers_t *images, void *blob, +int image_setup_libfdt(struct bootm_headers *images, void *blob, int of_size, struct lmb *lmb) { ulong *initrd_start = &images->initrd_start; @@ -669,6 +669,7 @@ int image_setup_libfdt(bootm_headers_t *images, void *blob, struct event_ft_fixup fixup; fixup.tree = oftree_default(); + fixup.images = images; ret = event_notify(EVT_FT_FIXUP, &fixup, sizeof(fixup)); if (ret) { printf("ERROR: fdt fixup event failed: %d\n", ret); diff --git a/boot/image-fit.c b/boot/image-fit.c index f16eab9df3..6e503f827d 100644 --- a/boot/image-fit.c +++ b/boot/image-fit.c @@ -1969,8 +1969,8 @@ static int fit_image_select(const void *fit, int rd_noffset, int verify) return 0; } -int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name, - ulong addr) +int fit_get_node_from_config(struct bootm_headers *images, + const char *prop_name, ulong addr) { int cfg_noffset; void *fit_hdr; @@ -2031,7 +2031,7 @@ static const char *fit_get_image_type_property(int type) return "unknown"; } -int fit_image_load(bootm_headers_t *images, ulong addr, +int fit_image_load(struct bootm_headers *images, ulong addr, const char **fit_unamep, const char **fit_uname_configp, int arch, int image_type, int bootstage_id, enum fit_load_op load_op, ulong *datap, ulong *lenp) @@ -2289,8 +2289,8 @@ int fit_image_load(bootm_headers_t *images, ulong addr, return noffset; } -int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch, - ulong *setup_start, ulong *setup_len) +int boot_get_setup_fit(struct bootm_headers *images, uint8_t arch, + ulong *setup_start, ulong *setup_len) { int noffset; ulong addr; @@ -2310,9 +2310,9 @@ int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch, } #ifndef USE_HOSTCC -int boot_get_fdt_fit(bootm_headers_t *images, ulong addr, - const char **fit_unamep, const char **fit_uname_configp, - int arch, ulong *datap, ulong *lenp) +int boot_get_fdt_fit(struct bootm_headers *images, ulong addr, + const char **fit_unamep, const char **fit_uname_configp, + int arch, ulong *datap, ulong *lenp) { int fdt_noffset, cfg_noffset, count; const void *fit; diff --git a/boot/image.c b/boot/image.c index a0d0cc2403..9f95b3260a 100644 --- a/boot/image.c +++ b/boot/image.c @@ -220,11 +220,11 @@ static const struct table_info table_info[IH_COUNT] = { /*****************************************************************************/ /* Legacy format routines */ /*****************************************************************************/ -int image_check_hcrc(const image_header_t *hdr) +int image_check_hcrc(const struct legacy_img_hdr *hdr) { ulong hcrc; ulong len = image_get_header_size(); - image_header_t header; + struct legacy_img_hdr header; /* Copy header so we can blank CRC field for re-calculation */ memmove(&header, (char *)hdr, image_get_header_size()); @@ -235,7 +235,7 @@ int image_check_hcrc(const image_header_t *hdr) return (hcrc == image_get_hcrc(hdr)); } -int image_check_dcrc(const image_header_t *hdr) +int image_check_dcrc(const struct legacy_img_hdr *hdr) { ulong data = image_get_data(hdr); ulong len = image_get_data_size(hdr); @@ -257,7 +257,7 @@ int image_check_dcrc(const image_header_t *hdr) * returns: * number of components */ -ulong image_multi_count(const image_header_t *hdr) +ulong image_multi_count(const struct legacy_img_hdr *hdr) { ulong i, count = 0; uint32_t *size; @@ -290,7 +290,7 @@ ulong image_multi_count(const image_header_t *hdr) * data address and size of the component, if idx is valid * 0 in data and len, if idx is out of range */ -void image_multi_getimg(const image_header_t *hdr, ulong idx, +void image_multi_getimg(const struct legacy_img_hdr *hdr, ulong idx, ulong *data, ulong *len) { int i; @@ -326,7 +326,7 @@ void image_multi_getimg(const image_header_t *hdr, ulong idx, } } -static void image_print_type(const image_header_t *hdr) +static void image_print_type(const struct legacy_img_hdr *hdr) { const char __maybe_unused *os, *arch, *type, *comp; @@ -352,7 +352,7 @@ static void image_print_type(const image_header_t *hdr) */ void image_print_contents(const void *ptr) { - const image_header_t *hdr = (const image_header_t *)ptr; + const struct legacy_img_hdr *hdr = (const struct legacy_img_hdr *)ptr; const char __maybe_unused *p; p = IMAGE_INDENT_STRING; diff --git a/boot/vbe_simple.c b/boot/vbe_simple.c index 0fc57388f3..61b6322ebe 100644 --- a/boot/vbe_simple.c +++ b/boot/vbe_simple.c @@ -240,7 +240,7 @@ static int bootmeth_vbe_simple_ft_fixup(void *ctx, struct event *event) continue; /* Check if there is a node to fix up */ - node = ofnode_path_root(tree, "/chosen/fwupd"); + node = oftree_path(tree, "/chosen/fwupd"); if (!ofnode_valid(node)) continue; node = ofnode_find_subnode(node, dev->name); diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 8ab0ff5a64..3041873afb 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -281,7 +281,7 @@ efi_status_t efi_install_fdt(void *fdt) return EFI_SUCCESS; } #else - bootm_headers_t img = { 0 }; + struct bootm_headers img = { 0 }; efi_status_t ret; if (fdt == EFI_FDT_USE_INTERNAL) { diff --git a/cmd/booti.c b/cmd/booti.c index 397d4b8323..6ac39193db 100644 --- a/cmd/booti.c +++ b/cmd/booti.c @@ -21,7 +21,7 @@ DECLARE_GLOBAL_DATA_PTR; * Image booting support */ static int booti_start(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[], bootm_headers_t *images) + char *const argv[], struct bootm_headers *images) { int ret; ulong ld; diff --git a/cmd/bootm.c b/cmd/bootm.c index 9fe8ce4a27..d764a27002 100644 --- a/cmd/bootm.c +++ b/cmd/bootm.c @@ -511,7 +511,7 @@ static int do_imls_nand(void) continue; for (off = 0; off < mtd->size; off += mtd->erasesize) { - const image_header_t *header; + const struct legacy_img_hdr *header; int ret; if (nand_block_isbad(mtd, off)) @@ -529,7 +529,7 @@ static int do_imls_nand(void) switch (genimg_get_format(buffer)) { #if defined(CONFIG_LEGACY_IMAGE_FORMAT) case IMAGE_FORMAT_LEGACY: - header = (const image_header_t *)buffer; + header = (const struct legacy_img_hdr *)buffer; len = image_get_image_size(header); nand_imls_legacyimage(mtd, nand_dev, off, len); diff --git a/cmd/bootz.c b/cmd/bootz.c index 4f024bde5f..f1423573d2 100644 --- a/cmd/bootz.c +++ b/cmd/bootz.c @@ -25,7 +25,7 @@ int __weak bootz_setup(ulong image, ulong *start, ulong *end) * zImage booting support */ static int bootz_start(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[], bootm_headers_t *images) + char *const argv[], struct bootm_headers *images) { int ret; ulong zi_start, zi_end; diff --git a/cmd/disk.c b/cmd/disk.c index cb3b990ba3..3d7bc2f601 100644 --- a/cmd/disk.c +++ b/cmd/disk.c @@ -20,7 +20,7 @@ int common_diskboot(struct cmd_tbl *cmdtp, const char *intf, int argc, ulong cnt; struct disk_partition info; #if defined(CONFIG_LEGACY_IMAGE_FORMAT) - image_header_t *hdr; + struct legacy_img_hdr *hdr; #endif struct blk_desc *dev_desc; @@ -68,7 +68,7 @@ int common_diskboot(struct cmd_tbl *cmdtp, const char *intf, int argc, switch (genimg_get_format((void *) addr)) { #if defined(CONFIG_LEGACY_IMAGE_FORMAT) case IMAGE_FORMAT_LEGACY: - hdr = (image_header_t *) addr; + hdr = (struct legacy_img_hdr *)addr; bootstage_mark(BOOTSTAGE_ID_IDE_FORMAT); diff --git a/cmd/fpga.c b/cmd/fpga.c index 9cf7651d8c..8c64e957db 100644 --- a/cmd/fpga.c +++ b/cmd/fpga.c @@ -288,7 +288,7 @@ static int do_fpga_loadmk(struct cmd_tbl *cmdtp, int flag, int argc, #if defined(CONFIG_LEGACY_IMAGE_FORMAT) case IMAGE_FORMAT_LEGACY: { - image_header_t *hdr = (image_header_t *)fpga_data; + struct legacy_img_hdr *hdr = (struct legacy_img_hdr *)fpga_data; ulong data; u8 comp; diff --git a/cmd/nand.c b/cmd/nand.c index e730484d0b..5bb43794e9 100644 --- a/cmd/nand.c +++ b/cmd/nand.c @@ -975,7 +975,7 @@ static int nand_load_image(struct cmd_tbl *cmdtp, struct mtd_info *mtd, char *s; size_t cnt; #if defined(CONFIG_LEGACY_IMAGE_FORMAT) - image_header_t *hdr; + struct legacy_img_hdr *hdr; #endif #if defined(CONFIG_FIT) const void *fit_hdr = NULL; @@ -1004,7 +1004,7 @@ static int nand_load_image(struct cmd_tbl *cmdtp, struct mtd_info *mtd, switch (genimg_get_format ((void *)addr)) { #if defined(CONFIG_LEGACY_IMAGE_FORMAT) case IMAGE_FORMAT_LEGACY: - hdr = (image_header_t *)addr; + hdr = (struct legacy_img_hdr *)addr; bootstage_mark(BOOTSTAGE_ID_NAND_TYPE); image_print_contents (hdr); diff --git a/cmd/source.c b/cmd/source.c index 81e015b64e..698d9f86d9 100644 --- a/cmd/source.c +++ b/cmd/source.c @@ -46,7 +46,7 @@ int image_source_script(ulong addr, const char *fit_uname) { ulong len; #if defined(CONFIG_LEGACY_IMAGE_FORMAT) - const image_header_t *hdr; + const struct legacy_img_hdr *hdr; #endif u32 *data; int verify; diff --git a/cmd/ximg.c b/cmd/ximg.c index 63b200430c..1c40fd27a0 100644 --- a/cmd/ximg.c +++ b/cmd/ximg.c @@ -42,7 +42,7 @@ do_imgextract(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) int part = 0; #if defined(CONFIG_LEGACY_IMAGE_FORMAT) ulong count; - image_header_t *hdr = NULL; + struct legacy_img_hdr *hdr = NULL; #endif #if defined(CONFIG_FIT) const char *uname = NULL; @@ -78,7 +78,7 @@ do_imgextract(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) printf("## Copying part %d from legacy image " "at %08lx ...\n", part, addr); - hdr = (image_header_t *)addr; + hdr = (struct legacy_img_hdr *)addr; if (!image_check_magic(hdr)) { printf("Bad Magic Number\n"); return 1; diff --git a/common/Kconfig b/common/Kconfig index 6591acd2fd..6608a4f0fc 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -577,7 +577,7 @@ config EVENT help This enables sending and processing of events, to allow interested parties to be alerted when something happens. This is an attempt to - step the flow of weak functions, hooks, functions in board_f.c + stem the flow of weak functions, hooks, functions in board_f.c and board_r.c and the Kconfig options below. See doc/develop/event.rst for more information. diff --git a/common/board_r.c b/common/board_r.c index 50670b5615..6e1ad2bfce 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -234,6 +234,8 @@ static int initr_dm(void) { int ret; + oftree_reset(); + /* Save the pre-reloc driver model and start a new one */ gd->dm_root_f = gd->dm_root; gd->dm_root = NULL; diff --git a/common/dlmalloc.c b/common/dlmalloc.c index f48cd2a333..41c7230424 100644 --- a/common/dlmalloc.c +++ b/common/dlmalloc.c @@ -596,6 +596,9 @@ ulong mem_malloc_start = 0; ulong mem_malloc_end = 0; ulong mem_malloc_brk = 0; +static bool malloc_testing; /* enable test mode */ +static int malloc_max_allocs; /* return NULL after this many calls to malloc() */ + void *sbrk(ptrdiff_t increment) { ulong old = mem_malloc_brk; @@ -1307,6 +1310,11 @@ Void_t* mALLOc(bytes) size_t bytes; return malloc_simple(bytes); #endif + if (CONFIG_IS_ENABLED(UNIT_TEST) && malloc_testing) { + if (--malloc_max_allocs < 0) + return NULL; + } + /* check if mem_malloc_init() was run */ if ((mem_malloc_start == 0) && (mem_malloc_end == 0)) { /* not initialized yet */ @@ -2470,6 +2478,17 @@ int initf_malloc(void) return 0; } +void malloc_enable_testing(int max_allocs) +{ + malloc_testing = true; + malloc_max_allocs = max_allocs; +} + +void malloc_disable_testing(void) +{ + malloc_testing = false; +} + /* History: diff --git a/common/spl/spl.c b/common/spl/spl.c index 828f72f30b..752b5b247c 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -227,7 +227,7 @@ __weak void spl_board_prepare_for_boot(void) /* Nothing to do! */ } -__weak struct image_header *spl_get_load_buffer(ssize_t offset, size_t size) +__weak struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size) { return map_sysmem(CONFIG_SYS_TEXT_BASE + offset, 0); } @@ -258,9 +258,9 @@ void spl_set_header_raw_uboot(struct spl_image_info *spl_image) #if CONFIG_IS_ENABLED(LOAD_FIT_FULL) /* Parse and load full fitImage in SPL */ static int spl_load_fit_image(struct spl_image_info *spl_image, - const struct image_header *header) + const struct legacy_img_hdr *header) { - bootm_headers_t images; + struct bootm_headers images; const char *fit_uname_config = NULL; uintptr_t fdt_hack; const char *uname; @@ -359,7 +359,7 @@ __weak int spl_parse_board_header(struct spl_image_info *spl_image, } __weak int spl_parse_legacy_header(struct spl_image_info *spl_image, - const struct image_header *header) + const struct legacy_img_hdr *header) { /* LEGACY image not supported */ debug("Legacy boot image support not enabled, proceeding to other boot methods\n"); @@ -368,7 +368,7 @@ __weak int spl_parse_legacy_header(struct spl_image_info *spl_image, int spl_parse_image_header(struct spl_image_info *spl_image, const struct spl_boot_device *bootdev, - const struct image_header *header) + const struct legacy_img_hdr *header) { #if CONFIG_IS_ENABLED(LOAD_FIT_FULL) int ret = spl_load_fit_image(spl_image, header); diff --git a/common/spl/spl_ext.c b/common/spl/spl_ext.c index ebd914c492..f117c630bf 100644 --- a/common/spl/spl_ext.c +++ b/common/spl/spl_ext.c @@ -15,7 +15,7 @@ int spl_load_image_ext(struct spl_image_info *spl_image, const char *filename) { s32 err; - struct image_header *header; + struct legacy_img_hdr *header; loff_t filelen, actlen; struct disk_partition part_info = {}; @@ -41,7 +41,7 @@ int spl_load_image_ext(struct spl_image_info *spl_image, puts("spl: ext4fs_open failed\n"); goto end; } - err = ext4fs_read((char *)header, 0, sizeof(struct image_header), &actlen); + err = ext4fs_read((char *)header, 0, sizeof(struct legacy_img_hdr), &actlen); if (err < 0) { puts("spl: ext4fs_read failed\n"); goto end; diff --git a/common/spl/spl_fat.c b/common/spl/spl_fat.c index 5b270541fc..f8a5b80a3b 100644 --- a/common/spl/spl_fat.c +++ b/common/spl/spl_fat.c @@ -60,7 +60,7 @@ int spl_load_image_fat(struct spl_image_info *spl_image, const char *filename) { int err; - struct image_header *header; + struct legacy_img_hdr *header; err = spl_register_fat_device(block_dev, partition); if (err) @@ -68,7 +68,7 @@ int spl_load_image_fat(struct spl_image_info *spl_image, header = spl_get_load_buffer(-sizeof(*header), sizeof(*header)); - err = file_fat_read(filename, header, sizeof(struct image_header)); + err = file_fat_read(filename, header, sizeof(struct legacy_img_hdr)); if (err <= 0) goto end; @@ -78,7 +78,7 @@ int spl_load_image_fat(struct spl_image_info *spl_image, if (err <= 0) goto end; err = spl_parse_image_header(spl_image, bootdev, - (struct image_header *)CONFIG_SYS_LOAD_ADDR); + (struct legacy_img_hdr *)CONFIG_SYS_LOAD_ADDR); if (err == -EAGAIN) return err; if (err == 0) diff --git a/common/spl/spl_legacy.c b/common/spl/spl_legacy.c index ae8731c782..b3624dfbb7 100644 --- a/common/spl/spl_legacy.c +++ b/common/spl/spl_legacy.c @@ -16,9 +16,9 @@ #define LZMA_LEN (1 << 20) int spl_parse_legacy_header(struct spl_image_info *spl_image, - const struct image_header *header) + const struct legacy_img_hdr *header) { - u32 header_size = sizeof(struct image_header); + u32 header_size = sizeof(struct legacy_img_hdr); /* check uImage header CRC */ if (IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_CRC_CHECK) && @@ -67,7 +67,7 @@ int spl_parse_legacy_header(struct spl_image_info *spl_image, * following switch/case statement in spl_load_legacy_img() away due to * Dead Code Elimination. */ -static inline int spl_image_get_comp(const struct image_header *hdr) +static inline int spl_image_get_comp(const struct legacy_img_hdr *hdr) { if (IS_ENABLED(CONFIG_SPL_LZMA)) return image_get_comp(hdr); @@ -81,7 +81,7 @@ int spl_load_legacy_img(struct spl_image_info *spl_image, { __maybe_unused SizeT lzma_len; __maybe_unused void *src; - struct image_header hdr; + struct legacy_img_hdr hdr; ulong dataptr; int ret; diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 23a395e63d..e4135b2048 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -20,7 +20,7 @@ static int mmc_load_legacy(struct spl_image_info *spl_image, struct spl_boot_device *bootdev, struct mmc *mmc, - ulong sector, struct image_header *header) + ulong sector, struct legacy_img_hdr *header) { u32 image_offset_sectors; u32 image_size_sectors; @@ -83,7 +83,7 @@ int mmc_load_image_raw_sector(struct spl_image_info *spl_image, struct mmc *mmc, unsigned long sector) { unsigned long count; - struct image_header *header; + struct legacy_img_hdr *header; struct blk_desc *bd = mmc_get_blk_desc(mmc); int ret = 0; diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c index 7b7579a2df..a16738818c 100644 --- a/common/spl/spl_nand.c +++ b/common/spl/spl_nand.c @@ -78,7 +78,7 @@ struct mtd_info * __weak nand_get_mtd(void) static int spl_nand_load_element(struct spl_image_info *spl_image, struct spl_boot_device *bootdev, - int offset, struct image_header *header) + int offset, struct legacy_img_hdr *header) { struct mtd_info *mtd = nand_get_mtd(); int bl_len = mtd ? mtd->writesize : 1; @@ -133,7 +133,7 @@ static int spl_nand_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) { int err; - struct image_header *header; + struct legacy_img_hdr *header; int *src __attribute__((unused)); int *dst __attribute__((unused)); diff --git a/common/spl/spl_net.c b/common/spl/spl_net.c index a853e6aead..b2c901b554 100644 --- a/common/spl/spl_net.c +++ b/common/spl/spl_net.c @@ -28,7 +28,7 @@ static ulong spl_net_load_read(struct spl_load_info *load, ulong sector, static int spl_net_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) { - struct image_header *header = (struct image_header *)image_load_addr; + struct legacy_img_hdr *header = (struct legacy_img_hdr *)image_load_addr; int rv; env_init(); diff --git a/common/spl/spl_nor.c b/common/spl/spl_nor.c index 7986e930d2..281c6136f5 100644 --- a/common/spl/spl_nor.c +++ b/common/spl/spl_nor.c @@ -26,7 +26,7 @@ unsigned long __weak spl_nor_get_uboot_base(void) static int spl_nor_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) { - __maybe_unused const struct image_header *header; + __maybe_unused const struct legacy_img_hdr *header; __maybe_unused struct spl_load_info load; /* @@ -41,7 +41,7 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, * Load Linux from its location in NOR flash to its defined * location in SDRAM */ - header = (const struct image_header *)CONFIG_SYS_OS_BASE; + header = (const struct legacy_img_hdr *)CONFIG_SYS_OS_BASE; #ifdef CONFIG_SPL_LOAD_FIT if (image_get_magic(header) == FDT_MAGIC) { int ret; @@ -72,7 +72,7 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, memcpy((void *)spl_image->load_addr, (void *)(CONFIG_SYS_OS_BASE + - sizeof(struct image_header)), + sizeof(struct legacy_img_hdr)), spl_image->size); #ifdef CONFIG_SYS_SPL_ARGS_ADDR spl_image->arg = (void *)CONFIG_SYS_SPL_ARGS_ADDR; @@ -92,7 +92,7 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, * defined location in SDRAM */ #ifdef CONFIG_SPL_LOAD_FIT - header = (const struct image_header *)spl_nor_get_uboot_base(); + header = (const struct legacy_img_hdr *)spl_nor_get_uboot_base(); if (image_get_magic(header) == FDT_MAGIC) { debug("Found FIT format U-Boot\n"); load.bl_len = 1; diff --git a/common/spl/spl_onenand.c b/common/spl/spl_onenand.c index f80769a027..53a8c6de89 100644 --- a/common/spl/spl_onenand.c +++ b/common/spl/spl_onenand.c @@ -18,7 +18,7 @@ static int spl_onenand_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) { - struct image_header *header; + struct legacy_img_hdr *header; int ret; debug("spl: onenand\n"); diff --git a/common/spl/spl_ram.c b/common/spl/spl_ram.c index d64710878c..2b1ac19152 100644 --- a/common/spl/spl_ram.c +++ b/common/spl/spl_ram.c @@ -41,9 +41,9 @@ static ulong spl_ram_load_read(struct spl_load_info *load, ulong sector, static int spl_ram_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) { - struct image_header *header; + struct legacy_img_hdr *header; - header = (struct image_header *)CONFIG_SPL_LOAD_FIT_ADDRESS; + header = (struct legacy_img_hdr *)CONFIG_SPL_LOAD_FIT_ADDRESS; if (CONFIG_IS_ENABLED(IMAGE_PRE_LOAD)) { unsigned long addr = (unsigned long)header; @@ -53,7 +53,7 @@ static int spl_ram_load_image(struct spl_image_info *spl_image, return ret; addr += image_load_offset; - header = (struct image_header *)addr; + header = (struct legacy_img_hdr *)addr; } #if CONFIG_IS_ENABLED(DFU) @@ -87,7 +87,7 @@ static int spl_ram_load_image(struct spl_image_info *spl_image, u_boot_pos = (ulong)spl_get_load_buffer(-sizeof(*header), sizeof(*header)); } - header = (struct image_header *)map_sysmem(u_boot_pos, 0); + header = (struct legacy_img_hdr *)map_sysmem(u_boot_pos, 0); spl_parse_image_header(spl_image, bootdev, header); } diff --git a/common/spl/spl_sata.c b/common/spl/spl_sata.c index 6c36f2ca66..9ae0273068 100644 --- a/common/spl/spl_sata.c +++ b/common/spl/spl_sata.c @@ -30,7 +30,7 @@ static int spl_sata_load_image_raw(struct spl_image_info *spl_image, struct spl_boot_device *bootdev, struct blk_desc *stor_dev, unsigned long sector) { - struct image_header *header; + struct legacy_img_hdr *header; unsigned long count; u32 image_size_sectors; u32 image_offset_sectors; diff --git a/common/spl/spl_semihosting.c b/common/spl/spl_semihosting.c index df6aeb2951..5b5e842a11 100644 --- a/common/spl/spl_semihosting.c +++ b/common/spl/spl_semihosting.c @@ -27,7 +27,7 @@ static int spl_smh_load_image(struct spl_image_info *spl_image, const char *filename = CONFIG_SPL_FS_LOAD_PAYLOAD_NAME; int ret; long fd, len; - struct image_header *header = + struct legacy_img_hdr *header = spl_get_load_buffer(-sizeof(*header), sizeof(*header)); fd = smh_open(filename, MODE_READ | MODE_BINARY); @@ -43,7 +43,7 @@ static int spl_smh_load_image(struct spl_image_info *spl_image, } len = ret; - ret = smh_read_full(fd, header, sizeof(struct image_header)); + ret = smh_read_full(fd, header, sizeof(struct legacy_img_hdr)); if (ret) { log_debug("could not read image header: %d\n", ret); goto out; diff --git a/common/spl/spl_spi.c b/common/spl/spl_spi.c index d959ad1145..da6742416e 100644 --- a/common/spl/spl_spi.c +++ b/common/spl/spl_spi.c @@ -26,7 +26,7 @@ static int spi_load_image_os(struct spl_image_info *spl_image, struct spl_boot_device *bootdev, struct spi_flash *flash, - struct image_header *header) + struct legacy_img_hdr *header) { int err; @@ -92,7 +92,7 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, int err = 0; unsigned int payload_offs; struct spi_flash *flash; - struct image_header *header; + struct legacy_img_hdr *header; unsigned int sf_bus = spl_spi_boot_bus(); unsigned int sf_cs = spl_spi_boot_cs(); @@ -139,7 +139,7 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, if (err) return err; err = spl_parse_image_header(spl_image, bootdev, - (struct image_header *)CONFIG_SYS_LOAD_ADDR); + (struct legacy_img_hdr *)CONFIG_SYS_LOAD_ADDR); } else if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && image_get_magic(header) == FDT_MAGIC) { struct spl_load_info load; diff --git a/common/spl/spl_ubi.c b/common/spl/spl_ubi.c index bdf5cc4c38..fb804f0208 100644 --- a/common/spl/spl_ubi.c +++ b/common/spl/spl_ubi.c @@ -15,7 +15,7 @@ int spl_ubi_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) { - struct image_header *header; + struct legacy_img_hdr *header; struct ubispl_info info; struct ubispl_load volumes[2]; int ret = 1; @@ -54,7 +54,7 @@ int spl_ubi_load_image(struct spl_image_info *spl_image, ret = ubispl_load_volumes(&info, volumes, 2); if (!ret) { - header = (struct image_header *)volumes[0].load_addr; + header = (struct legacy_img_hdr *)volumes[0].load_addr; spl_parse_image_header(spl_image, bootdev, header); puts("Linux loaded.\n"); goto out; diff --git a/common/spl/spl_xip.c b/common/spl/spl_xip.c index e9a40b0ec7..1258d85e63 100644 --- a/common/spl/spl_xip.c +++ b/common/spl/spl_xip.c @@ -25,6 +25,6 @@ static int spl_xip(struct spl_image_info *spl_image, } #endif return(spl_parse_image_header(spl_image, bootdev, - (const struct image_header *)CONFIG_SYS_UBOOT_BASE)); + (const struct legacy_img_hdr *)CONFIG_SYS_UBOOT_BASE)); } SPL_LOAD_IMAGE_METHOD("XIP", 0, BOOT_DEVICE_XIP, spl_xip); diff --git a/common/spl/spl_ymodem.c b/common/spl/spl_ymodem.c index fdd5261042..038b443845 100644 --- a/common/spl/spl_ymodem.c +++ b/common/spl/spl_ymodem.c @@ -96,7 +96,7 @@ int spl_ymodem_load_image(struct spl_image_info *spl_image, int ret; connection_info_t info; char buf[BUF_SIZE]; - struct image_header *ih = NULL; + struct legacy_img_hdr *ih = NULL; ulong addr = 0; info.mode = xyzModem_ymodem; @@ -111,9 +111,9 @@ int spl_ymodem_load_image(struct spl_image_info *spl_image, goto end_stream; if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL) && - image_get_magic((struct image_header *)buf) == FDT_MAGIC) { + image_get_magic((struct legacy_img_hdr *)buf) == FDT_MAGIC) { addr = CONFIG_SYS_LOAD_ADDR; - ih = (struct image_header *)addr; + ih = (struct legacy_img_hdr *)addr; memcpy((void *)addr, buf, res); size += res; @@ -129,7 +129,7 @@ int spl_ymodem_load_image(struct spl_image_info *spl_image, if (ret) return ret; } else if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && - image_get_magic((struct image_header *)buf) == FDT_MAGIC) { + image_get_magic((struct legacy_img_hdr *)buf) == FDT_MAGIC) { struct spl_load_info load; struct ymodem_fit_info info; @@ -147,7 +147,7 @@ int spl_ymodem_load_image(struct spl_image_info *spl_image, while ((res = xyzModem_stream_read(buf, BUF_SIZE, &err)) > 0) size += res; } else { - ih = (struct image_header *)buf; + ih = (struct legacy_img_hdr *)buf; ret = spl_parse_image_header(spl_image, bootdev, ih); if (ret) goto end_stream; @@ -158,7 +158,7 @@ int spl_ymodem_load_image(struct spl_image_info *spl_image, #endif addr = spl_image->load_addr; memcpy((void *)addr, buf, res); - ih = (struct image_header *)addr; + ih = (struct legacy_img_hdr *)addr; size += res; addr += res; @@ -177,7 +177,7 @@ end_stream: #ifdef CONFIG_SPL_GZIP if (!(IS_ENABLED(CONFIG_SPL_LOAD_FIT) && - image_get_magic((struct image_header *)buf) == FDT_MAGIC) && + image_get_magic((struct legacy_img_hdr *)buf) == FDT_MAGIC) && (ih->ih_comp == IH_COMP_GZIP)) { if (gunzip((void *)(spl_image->load_addr + sizeof(*ih)), CONFIG_SYS_BOOTM_LEN, diff --git a/common/splash_source.c b/common/splash_source.c index 2c03cbdf92..87e55a54f8 100644 --- a/common/splash_source.c +++ b/common/splash_source.c @@ -327,17 +327,17 @@ static int splash_load_fit(struct splash_location *location, u32 bmp_load_addr) int external_splash_addr; int external_splash_size; bool is_splash_external = false; - struct image_header *img_header; + struct legacy_img_hdr *img_header; const u32 *fit_header; u32 fit_size; - const size_t header_size = sizeof(struct image_header); + const size_t header_size = sizeof(struct legacy_img_hdr); /* Read in image header */ res = splash_storage_read_raw(location, bmp_load_addr, header_size); if (res < 0) return res; - img_header = (struct image_header *)bmp_load_addr; + img_header = (struct legacy_img_hdr *)bmp_load_addr; if (image_get_magic(img_header) != FDT_MAGIC) { printf("Could not find FDT magic\n"); return -EINVAL; diff --git a/doc/develop/driver-model/livetree.rst b/doc/develop/driver-model/livetree.rst index faf3eb5b5f..55aa3eac92 100644 --- a/doc/develop/driver-model/livetree.rst +++ b/doc/develop/driver-model/livetree.rst @@ -235,20 +235,9 @@ tree either present or absent. This is to make sure that the flat tree functions work correctly even with OF_LIVE is enabled. But if a test modifies the flat device tree, then the live tree can become invalid. Any live tree tests that run after that point will use a corrupted tree, e.g. with an incorrect property name -or worse. To deal with this we use a flag UT_TESTF_LIVE_OR_FLAT then ensures -that tests which write to the flat tree are not run if OF_LIVE is enabled. Only -the live tree version of the test is run, when OF_LIVE is enabled, with -sandbox_flattree running the flat tree version. - -This is of course a work-around, even if a reasonable one. One solution to this -problem would be to make a copy of the flat tree before the test and restore it -afterwards, in the same memory location, so that the live tree pointers work -again. Another would be to regenerate the live tree if a test modified the flat -tree. - -Neither of these solutions is currently implemented, since the situation that -causes the problem can only occur in sandbox tests, is somewhat esoteric and -the UT_TESTF_LIVE_OR_FLAT flag deals with it in a reasonable way. +or worse. To deal with this we take a copy of the device tree and restore it +after any test that modifies it. Note that this copy is not made on other +boards, only sandbox. Multiple livetrees @@ -261,11 +250,14 @@ a flat tree. It would be helpful to use livetree for fixups, since adding a lot of nodes and properties would involve less memory copying and be more efficient. As a step towards this, an `oftree` type has been introduced. It is normally set to -oftree_default() but can be set to other values. Eventually this should allow -the use of FDT fixups using the ofnode interface, instead of the low-level -libfdt one. +oftree_default() but can be set to other values using oftree_from_fdt(). +So long as OF_LIVE is disabled, it is possible to do fixups using the ofnode +interface. The OF_LIVE support required addition of the flattening step at the +end. -See dm_test_ofnode_root() for some examples. +See dm_test_ofnode_root() for some examples. The ofnode_path_root() function +causes a flat device tree to be 'registered' such that it can be used by the +ofnode interface. Internal implementation @@ -329,10 +321,9 @@ Adding a new function for device-tree access involves the following steps: Future work ----------- -Live tree support was introduced in U-Boot 2017.07. There is still quite a bit -of work to do to flesh this out: +Live tree support was introduced in U-Boot 2017.07. Some possible enhancements +are: -- tests for all access functions -- more support for livetree modification -- addition of more access functions as needed - support for livetree in SPL and before relocation (if desired) +- freeing leaked memory caused by writing new nodes / property values to the + livetree (ofnode_write_prop()) diff --git a/doc/uImage.FIT/source_file_format.txt b/doc/uImage.FIT/source_file_format.txt index 6870111840..0a03c942bd 100644 --- a/doc/uImage.FIT/source_file_format.txt +++ b/doc/uImage.FIT/source_file_format.txt @@ -23,7 +23,7 @@ in the system memory and passed to bootm as a arguments. Some of them may be missing: FDT is not present for legacy platforms, ramdisk is always optional. Additionally, old uImage format has been extended to support multi sub-images but the support is limited by simple format of the legacy uImage structure. -Single binary header 'struct image_header' is not flexible enough to cover all +Single binary header 'struct legacy_img_hdr' is not flexible enough to cover all possible scenarios. All those factors combined clearly show that there is a need for new, more diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig index 007dc6a1de..c9bf5de433 100644 --- a/drivers/core/Kconfig +++ b/drivers/core/Kconfig @@ -400,6 +400,30 @@ config DM_DEV_READ_INLINE bool default y if !OF_LIVE +config OFNODE_MULTI_TREE + bool "Allow the ofnode interface to access any tree" + default y if EVENT && !DM_DEV_READ_INLINE && !DM_INLINE_OFNODE + help + Normally U-Boot makes use of its control FDT, the one used to bind + devices and provide options. In some cases, U-Boot must also process + a separate FDT, e.g. one provided by the operating system, which + needs additions to the /chosen node. + + This works fine with live tree (OF_LIVE), but with flat tree the + offset provided in ofnode is only useful with the control FDT. This + option adds a 'tree ID' to the offset, so that multiple trees can + be used. Call oftree_from_fdt() to register a new tree. + +config OFNODE_MULTI_TREE_MAX + int "Maximum number of FDTs" + range 2 8 + depends on OFNODE_MULTI_TREE + default 4 + help + Sets the maximum number of device trees which can be used with the + ofnode interface when using flat trees (OF_LIVE). This is only + available in U-Boot proper and only after relocation. + config ACPIGEN bool "Support ACPI table generation in driver model" default y if SANDBOX || (GENERATE_ACPI_TABLE && !QEMU) diff --git a/drivers/core/fdtaddr.c b/drivers/core/fdtaddr.c index c3a50a2b0c..91bcd1a2c2 100644 --- a/drivers/core/fdtaddr.c +++ b/drivers/core/fdtaddr.c @@ -21,6 +21,8 @@ DECLARE_GLOBAL_DATA_PTR; fdt_addr_t devfdt_get_addr_index(const struct udevice *dev, int index) { #if CONFIG_IS_ENABLED(OF_REAL) + int offset = dev_of_offset(dev); + int parent = dev_of_offset(dev->parent); fdt_addr_t addr; if (CONFIG_IS_ENABLED(OF_TRANSLATE)) { @@ -28,21 +30,19 @@ fdt_addr_t devfdt_get_addr_index(const struct udevice *dev, int index) int len = 0; int na, ns; - na = fdt_address_cells(gd->fdt_blob, - dev_of_offset(dev->parent)); + na = fdt_address_cells(gd->fdt_blob, parent); if (na < 1) { debug("bad #address-cells\n"); return FDT_ADDR_T_NONE; } - ns = fdt_size_cells(gd->fdt_blob, dev_of_offset(dev->parent)); + ns = fdt_size_cells(gd->fdt_blob, parent); if (ns < 0) { debug("bad #size-cells\n"); return FDT_ADDR_T_NONE; } - reg = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "reg", - &len); + reg = fdt_getprop(gd->fdt_blob, offset, "reg", &len); if (!reg || (len <= (index * sizeof(fdt32_t) * (na + ns)))) { debug("Req index out of range\n"); return FDT_ADDR_T_NONE; @@ -56,7 +56,7 @@ fdt_addr_t devfdt_get_addr_index(const struct udevice *dev, int index) * bus setups. */ addr = fdt_translate_address((void *)gd->fdt_blob, - dev_of_offset(dev), reg); + offset, reg); } else { /* Non translatable if #size-cells == 0 */ addr = fdt_read_number(reg, na); @@ -66,9 +66,9 @@ fdt_addr_t devfdt_get_addr_index(const struct udevice *dev, int index) * Use the "simple" translate function for less complex * bus setups. */ - addr = fdtdec_get_addr_size_auto_parent(gd->fdt_blob, - dev_of_offset(dev->parent), dev_of_offset(dev), - "reg", index, NULL, false); + addr = fdtdec_get_addr_size_auto_parent(gd->fdt_blob, parent, + offset, "reg", index, + NULL, false); if (CONFIG_IS_ENABLED(SIMPLE_BUS) && addr != FDT_ADDR_T_NONE) { if (device_get_uclass_id(dev->parent) == UCLASS_SIMPLE_BUS) diff --git a/drivers/core/of_access.c b/drivers/core/of_access.c index df007e642b..85f7da5a49 100644 --- a/drivers/core/of_access.c +++ b/drivers/core/of_access.c @@ -445,14 +445,15 @@ struct device_node *of_find_node_by_prop_value(struct device_node *from, return np; } -struct device_node *of_find_node_by_phandle(phandle handle) +struct device_node *of_find_node_by_phandle(struct device_node *root, + phandle handle) { struct device_node *np; if (!handle) return NULL; - for_each_of_allnodes(np) + for_each_of_allnodes_from(root, np) if (np->phandle == handle) break; (void)of_node_get(np); @@ -470,8 +471,7 @@ struct device_node *of_find_node_by_phandle(phandle handle) * @len: requested length of property value * * Return: the property value on success, -EINVAL if the property does not - * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the - * property data isn't large enough. + * exist and -EOVERFLOW if the property data isn't large enough. */ static void *of_find_property_value_of_size(const struct device_node *np, const char *propname, u32 len) @@ -480,8 +480,6 @@ static void *of_find_property_value_of_size(const struct device_node *np, if (!prop) return ERR_PTR(-EINVAL); - if (!prop->value) - return ERR_PTR(-ENODATA); if (len > prop->length) return ERR_PTR(-EOVERFLOW); @@ -697,7 +695,7 @@ static int __of_parse_phandle_with_args(const struct device_node *np, * below. */ if (cells_name || cur_index == index) { - node = of_find_node_by_phandle(phandle); + node = of_find_node_by_phandle(NULL, phandle); if (!node) { debug("%s: could not find phandle\n", np->full_name); @@ -946,9 +944,6 @@ int of_write_prop(struct device_node *np, const char *propname, int len, pp_last = pp; } - if (!pp_last) - return -ENOENT; - /* Property does not exist -> append new property */ new = malloc(sizeof(struct property)); if (!new) @@ -964,7 +959,73 @@ int of_write_prop(struct device_node *np, const char *propname, int len, new->length = len; new->next = NULL; - pp_last->next = new; + if (pp_last) + pp_last->next = new; + else + np->properties = new; + + return 0; +} + +int of_add_subnode(struct device_node *parent, const char *name, int len, + struct device_node **childp) +{ + struct device_node *child, *new, *last_sibling = NULL; + char *new_name, *full_name; + int parent_fnl; + + if (len == -1) + len = strlen(name); + __for_each_child_of_node(parent, child) { + /* + * make sure we don't use a child called "trevor" when we are + * searching for "trev". + */ + if (!strncmp(child->name, name, len) && strlen(name) == len) { + *childp = child; + return -EEXIST; + } + last_sibling = child; + } + + /* Subnode does not exist -> append new subnode */ + new = calloc(1, sizeof(struct device_node)); + if (!new) + return -ENOMEM; + + new_name = memdup(name, len + 1); + if (!new_name) { + free(new); + return -ENOMEM; + } + new_name[len] = '\0'; + + /* + * if the parent is the root node (named "") we don't need to prepend + * its full path + */ + parent_fnl = *parent->name ? strlen(parent->full_name) : 0; + full_name = calloc(1, parent_fnl + 1 + len + 1); + if (!full_name) { + free(new_name); + free(new); + return -ENOMEM; + } + new->name = new_name; /* assign to constant pointer */ + + strcpy(full_name, parent->full_name); /* "" for root node */ + full_name[parent_fnl] = '/'; + strlcpy(&full_name[parent_fnl + 1], name, len + 1); + new->full_name = full_name; + + /* Add as last sibling of the parent */ + if (last_sibling) + last_sibling->sibling = new; + if (!parent->child) + parent->child = new; + new->parent = parent; + + *childp = new; return 0; } diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 42f3c09a51..14bbfe7232 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -4,6 +4,8 @@ * Written by Simon Glass <sjg@chromium.org> */ +#define LOG_CATEGORY LOGC_DT + #include <common.h> #include <dm.h> #include <fdtdec.h> @@ -18,6 +20,186 @@ #include <linux/ioport.h> #include <asm/global_data.h> +DECLARE_GLOBAL_DATA_PTR; + +#if CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) +static void *oftree_list[CONFIG_OFNODE_MULTI_TREE_MAX]; +static int oftree_count; + +void oftree_reset(void) +{ + if (gd->flags & GD_FLG_RELOC) { + oftree_count = 0; + oftree_list[oftree_count++] = (void *)gd->fdt_blob; + } +} + +static int oftree_find(const void *fdt) +{ + int i; + + for (i = 0; i < oftree_count; i++) { + if (fdt == oftree_list[i]) + return i; + } + + return -1; +} + +static oftree oftree_ensure(void *fdt) +{ + oftree tree; + int i; + + if (gd->flags & GD_FLG_RELOC) { + i = oftree_find(fdt); + if (i == -1) { + if (oftree_count == CONFIG_OFNODE_MULTI_TREE_MAX) { + log_warning("Too many registered device trees (max %d)\n", + CONFIG_OFNODE_MULTI_TREE_MAX); + return oftree_null(); + } + + /* register the new tree */ + i = oftree_count++; + oftree_list[i] = fdt; + log_debug("oftree: registered tree %d: %p\n", i, fdt); + } + } else { + if (fdt != gd->fdt_blob) { + log_debug("Cannot only access control FDT before relocation\n"); + return oftree_null(); + } + } + + tree.fdt = fdt; + + return tree; +} + +void *ofnode_lookup_fdt(ofnode node) +{ + if (gd->flags & GD_FLG_RELOC) { + uint i = OFTREE_TREE_ID(node.of_offset); + + if (i > oftree_count) { + log_debug("Invalid tree ID %x\n", i); + return NULL; + } + + return oftree_list[i]; + } else { + return (void *)gd->fdt_blob; + } +} + +void *ofnode_to_fdt(ofnode node) +{ +#ifdef OF_CHECKS + if (of_live_active()) + return NULL; +#endif + if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) && ofnode_valid(node)) + return ofnode_lookup_fdt(node); + + /* Use the control FDT by default */ + return (void *)gd->fdt_blob; +} + +/** + * ofnode_to_offset() - convert an ofnode to a flat DT offset + * + * This cannot be called if the reference contains a node pointer. + * + * @node: Reference containing offset (possibly invalid) + * Return: DT offset (can be -1) + */ +int ofnode_to_offset(ofnode node) +{ +#ifdef OF_CHECKS + if (of_live_active()) + return -1; +#endif + if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) && node.of_offset >= 0) + return OFTREE_OFFSET(node.of_offset); + + return node.of_offset; +} + +oftree oftree_from_fdt(void *fdt) +{ + oftree tree; + + if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE)) + return oftree_ensure(fdt); + + tree.fdt = fdt; + + return tree; +} + +/** + * noffset_to_ofnode() - convert a DT offset to an ofnode + * + * @other_node: Node in the same tree to use as a reference + * @of_offset: DT offset (either valid, or -1) + * Return: reference to the associated DT offset + */ +ofnode noffset_to_ofnode(ofnode other_node, int of_offset) +{ + ofnode node; + + if (of_live_active()) + node.np = NULL; + else if (!CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) || of_offset < 0 || + !ofnode_valid(other_node)) + node.of_offset = of_offset; + else + node.of_offset = OFTREE_MAKE_NODE(other_node.of_offset, + of_offset); + + return node; +} + +#else /* !OFNODE_MULTI_TREE */ + +static inline int oftree_find(const void *fdt) +{ + return 0; +} + +#endif /* OFNODE_MULTI_TREE */ + +/** + * ofnode_from_tree_offset() - get an ofnode from a tree offset (flat tree) + * + * Looks up the tree and returns an ofnode with the correct of_offset (i.e. + * containing the tree ID). + * + * If @offset is < 0 then this returns an ofnode with that offset and no tree + * ID. + * + * @tree: tree to check + * @offset: offset within that tree (can be < 0) + * @return node for that offset, with the correct ID + */ +static ofnode ofnode_from_tree_offset(oftree tree, int offset) +{ + ofnode node; + + if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) && offset >= 0) { + int tree_id = oftree_find(tree.fdt); + + if (tree_id == -1) + return ofnode_null(); + node.of_offset = OFTREE_NODE(tree_id, offset); + } else { + node.of_offset = offset; + } + + return node; +} + bool ofnode_name_eq(ofnode node, const char *name) { const char *node_name; @@ -119,8 +301,8 @@ int ofnode_read_u32_index(ofnode node, const char *propname, int index, return of_read_u32_index(ofnode_to_np(node), propname, index, outp); - cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname, - &len); + cell = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node), + propname, &len); if (!cell) { debug("(not found)\n"); return -EINVAL; @@ -165,8 +347,8 @@ int ofnode_read_u64(ofnode node, const char *propname, u64 *outp) if (ofnode_is_np(node)) return of_read_u64(ofnode_to_np(node), propname, outp); - cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname, - &len); + cell = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node), + propname, &len); if (!cell || len < sizeof(*cell)) { debug("(not found)\n"); return -EINVAL; @@ -217,7 +399,7 @@ const void *ofnode_read_prop(ofnode node, const char *propname, int *sizep) len = prop->length; } } else { - val = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), + val = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node), propname, &len); } if (!val) { @@ -268,7 +450,7 @@ ofnode ofnode_find_subnode(ofnode node, const char *subnode_name) debug("%s: %s: ", __func__, subnode_name); if (ofnode_is_np(node)) { - const struct device_node *np = ofnode_to_np(node); + struct device_node *np = ofnode_to_np(node); for (np = np->child; np; np = np->sibling) { if (!strcmp(subnode_name, np->name)) @@ -276,9 +458,9 @@ ofnode ofnode_find_subnode(ofnode node, const char *subnode_name) } subnode = np_to_ofnode(np); } else { - int ooffset = fdt_subnode_offset(gd->fdt_blob, + int ooffset = fdt_subnode_offset(ofnode_to_fdt(node), ofnode_to_offset(node), subnode_name); - subnode = offset_to_ofnode(ooffset); + subnode = noffset_to_ofnode(node, ooffset); } debug("%s\n", ofnode_valid(subnode) ? ofnode_get_name(subnode) : "<none>"); @@ -296,9 +478,20 @@ int ofnode_read_u32_array(ofnode node, const char *propname, return of_read_u32_array(ofnode_to_np(node), propname, out_values, sz); } else { - return fdtdec_get_int_array(gd->fdt_blob, - ofnode_to_offset(node), propname, - out_values, sz); + int ret; + + ret = fdtdec_get_int_array(ofnode_to_fdt(node), + ofnode_to_offset(node), propname, + out_values, sz); + + /* get the error right, but space is more important in SPL */ + if (!IS_ENABLED(CONFIG_SPL_BUILD)) { + if (ret == -FDT_ERR_NOTFOUND) + return -EINVAL; + else if (ret == -FDT_ERR_BADLAYOUT) + return -EOVERFLOW; + } + return ret; } } @@ -308,7 +501,7 @@ bool ofnode_is_enabled(ofnode node) if (ofnode_is_np(node)) { return of_device_is_available(ofnode_to_np(node)); } else { - return fdtdec_get_is_enabled(gd->fdt_blob, + return fdtdec_get_is_enabled(ofnode_to_fdt(node), ofnode_to_offset(node)); } } @@ -319,8 +512,8 @@ ofnode ofnode_first_subnode(ofnode node) if (ofnode_is_np(node)) return np_to_ofnode(node.np->child); - return offset_to_ofnode( - fdt_first_subnode(gd->fdt_blob, ofnode_to_offset(node))); + return noffset_to_ofnode(node, + fdt_first_subnode(ofnode_to_fdt(node), ofnode_to_offset(node))); } ofnode ofnode_next_subnode(ofnode node) @@ -329,8 +522,8 @@ ofnode ofnode_next_subnode(ofnode node) if (ofnode_is_np(node)) return np_to_ofnode(node.np->sibling); - return offset_to_ofnode( - fdt_next_subnode(gd->fdt_blob, ofnode_to_offset(node))); + return noffset_to_ofnode(node, + fdt_next_subnode(ofnode_to_fdt(node), ofnode_to_offset(node))); } #endif /* !DM_INLINE_OFNODE */ @@ -342,7 +535,7 @@ ofnode ofnode_get_parent(ofnode node) if (ofnode_is_np(node)) parent = np_to_ofnode(of_get_parent(ofnode_to_np(node))); else - parent.of_offset = fdt_parent_offset(gd->fdt_blob, + parent.of_offset = fdt_parent_offset(ofnode_to_fdt(node), ofnode_to_offset(node)); return parent; @@ -356,9 +549,9 @@ const char *ofnode_get_name(ofnode node) } if (ofnode_is_np(node)) - return strrchr(node.np->full_name, '/') + 1; + return node.np->name; - return fdt_get_name(gd->fdt_blob, ofnode_to_offset(node), NULL); + return fdt_get_name(ofnode_to_fdt(node), ofnode_to_offset(node), NULL); } int ofnode_get_path(ofnode node, char *buf, int buflen) @@ -375,7 +568,7 @@ int ofnode_get_path(ofnode node, char *buf, int buflen) } else { int res; - res = fdt_get_path(gd->fdt_blob, ofnode_to_offset(node), buf, + res = fdt_get_path(ofnode_to_fdt(node), ofnode_to_offset(node), buf, buflen); if (!res) return res; @@ -391,7 +584,7 @@ ofnode ofnode_get_by_phandle(uint phandle) ofnode node; if (of_live_active()) - node = np_to_ofnode(of_find_node_by_phandle(phandle)); + node = np_to_ofnode(of_find_node_by_phandle(NULL, phandle)); else node.of_offset = fdt_node_offset_by_phandle(gd->fdt_blob, phandle); @@ -399,6 +592,20 @@ ofnode ofnode_get_by_phandle(uint phandle) return node; } +ofnode oftree_get_by_phandle(oftree tree, uint phandle) +{ + ofnode node; + + if (of_live_active()) + node = np_to_ofnode(of_find_node_by_phandle(tree.np, phandle)); + else + node = ofnode_from_tree_offset(tree, + fdt_node_offset_by_phandle(oftree_lookup_fdt(tree), + phandle)); + + return node; +} + static fdt_addr_t __ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size, bool translate) { @@ -431,7 +638,7 @@ static fdt_addr_t __ofnode_get_addr_size_index(ofnode node, int index, } else { na = ofnode_read_simple_addr_cells(ofnode_get_parent(node)); ns = ofnode_read_simple_size_cells(ofnode_get_parent(node)); - return fdtdec_get_addr_size_fixed(gd->fdt_blob, + return fdtdec_get_addr_size_fixed(ofnode_to_fdt(node), ofnode_to_offset(node), "reg", index, na, ns, size, translate); @@ -479,7 +686,7 @@ int ofnode_stringlist_search(ofnode node, const char *property, } else { int ret; - ret = fdt_stringlist_search(gd->fdt_blob, + ret = fdt_stringlist_search(ofnode_to_fdt(node), ofnode_to_offset(node), property, string); if (ret == -FDT_ERR_NOTFOUND) @@ -500,7 +707,8 @@ int ofnode_read_string_index(ofnode node, const char *property, int index, } else { int len; - *outp = fdt_stringlist_get(gd->fdt_blob, ofnode_to_offset(node), + *outp = fdt_stringlist_get(ofnode_to_fdt(node), + ofnode_to_offset(node), property, index, &len); if (len < 0) return -EINVAL; @@ -513,7 +721,7 @@ int ofnode_read_string_count(ofnode node, const char *property) if (ofnode_is_np(node)) { return of_property_count_strings(ofnode_to_np(node), property); } else { - return fdt_stringlist_count(gd->fdt_blob, + return fdt_stringlist_count(ofnode_to_fdt(node), ofnode_to_offset(node), property); } } @@ -582,7 +790,7 @@ int ofnode_parse_phandle_with_args(ofnode node, const char *list_name, struct fdtdec_phandle_args args; int ret; - ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, + ret = fdtdec_parse_phandle_with_args(ofnode_to_fdt(node), ofnode_to_offset(node), list_name, cells_name, cell_count, index, &args); @@ -601,7 +809,7 @@ int ofnode_count_phandle_with_args(ofnode node, const char *list_name, return of_count_phandle_with_args(ofnode_to_np(node), list_name, cells_name, cell_count); else - return fdtdec_parse_phandle_with_args(gd->fdt_blob, + return fdtdec_parse_phandle_with_args(ofnode_to_fdt(node), ofnode_to_offset(node), list_name, cells_name, cell_count, -1, NULL); } @@ -614,15 +822,27 @@ ofnode ofnode_path(const char *path) return offset_to_ofnode(fdt_path_offset(gd->fdt_blob, path)); } -ofnode ofnode_path_root(oftree tree, const char *path) +ofnode oftree_root(oftree tree) { - if (of_live_active()) + if (of_live_active()) { + return np_to_ofnode(tree.np); + } else { + return ofnode_from_tree_offset(tree, 0); + } +} + +ofnode oftree_path(oftree tree, const char *path) +{ + if (of_live_active()) { return np_to_ofnode(of_find_node_opts_by_path(tree.np, path, NULL)); - else if (*path != '/' && tree.fdt != gd->fdt_blob) + } else if (*path != '/' && tree.fdt != gd->fdt_blob) { return ofnode_null(); /* Aliases only on control FDT */ - else - return offset_to_ofnode(fdt_path_offset(tree.fdt, path)); + } else { + int offset = fdt_path_offset(tree.fdt, path); + + return ofnode_from_tree_offset(tree, offset); + } } const void *ofnode_read_chosen_prop(const char *propname, int *sizep) @@ -776,11 +996,11 @@ const void *ofnode_get_property(ofnode node, const char *propname, int *lenp) if (ofnode_is_np(node)) return of_get_property(ofnode_to_np(node), propname, lenp); else - return fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), + return fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node), propname, lenp); } -int ofnode_get_first_property(ofnode node, struct ofprop *prop) +int ofnode_first_property(ofnode node, struct ofprop *prop) { prop->node = node; @@ -790,7 +1010,7 @@ int ofnode_get_first_property(ofnode node, struct ofprop *prop) return -FDT_ERR_NOTFOUND; } else { prop->offset = - fdt_first_property_offset(gd->fdt_blob, + fdt_first_property_offset(ofnode_to_fdt(node), ofnode_to_offset(prop->node)); if (prop->offset < 0) return prop->offset; @@ -799,7 +1019,7 @@ int ofnode_get_first_property(ofnode node, struct ofprop *prop) return 0; } -int ofnode_get_next_property(struct ofprop *prop) +int ofnode_next_property(struct ofprop *prop) { if (ofnode_is_np(prop->node)) { prop->prop = of_get_next_property(ofnode_to_np(prop->node), @@ -807,8 +1027,9 @@ int ofnode_get_next_property(struct ofprop *prop) if (!prop->prop) return -FDT_ERR_NOTFOUND; } else { - prop->offset = fdt_next_property_offset(gd->fdt_blob, - prop->offset); + prop->offset = + fdt_next_property_offset(ofnode_to_fdt(prop->node), + prop->offset); if (prop->offset < 0) return prop->offset; } @@ -816,27 +1037,18 @@ int ofnode_get_next_property(struct ofprop *prop) return 0; } -const void *ofnode_get_property_by_prop(const struct ofprop *prop, - const char **propname, int *lenp) +const void *ofprop_get_property(const struct ofprop *prop, + const char **propname, int *lenp) { if (ofnode_is_np(prop->node)) return of_get_property_by_prop(ofnode_to_np(prop->node), prop->prop, propname, lenp); else - return fdt_getprop_by_offset(gd->fdt_blob, + return fdt_getprop_by_offset(ofnode_to_fdt(prop->node), prop->offset, propname, lenp); } -bool ofnode_is_available(ofnode node) -{ - if (ofnode_is_np(node)) - return of_device_is_available(ofnode_to_np(node)); - else - return fdtdec_get_is_enabled(gd->fdt_blob, - ofnode_to_offset(node)); -} - fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property, fdt_size_t *sizep) { @@ -857,7 +1069,7 @@ fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property, else return of_read_number(prop, na); } else { - return fdtdec_get_addr_size(gd->fdt_blob, + return fdtdec_get_addr_size(ofnode_to_fdt(node), ofnode_to_offset(node), property, sizep); } @@ -876,7 +1088,7 @@ const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname, return (uint8_t *)prop; } else { - return fdtdec_locate_byte_array(gd->fdt_blob, + return fdtdec_locate_byte_array(ofnode_to_fdt(node), ofnode_to_offset(node), propname, sz); } } @@ -1012,10 +1224,10 @@ int ofnode_read_addr_cells(ofnode node) if (ofnode_is_np(node)) { return of_n_addr_cells(ofnode_to_np(node)); } else { - int parent = fdt_parent_offset(gd->fdt_blob, + int parent = fdt_parent_offset(ofnode_to_fdt(node), ofnode_to_offset(node)); - return fdt_address_cells(gd->fdt_blob, parent); + return fdt_address_cells(ofnode_to_fdt(node), parent); } } @@ -1024,10 +1236,10 @@ int ofnode_read_size_cells(ofnode node) if (ofnode_is_np(node)) { return of_n_size_cells(ofnode_to_np(node)); } else { - int parent = fdt_parent_offset(gd->fdt_blob, + int parent = fdt_parent_offset(ofnode_to_fdt(node), ofnode_to_offset(node)); - return fdt_size_cells(gd->fdt_blob, parent); + return fdt_size_cells(ofnode_to_fdt(node), parent); } } @@ -1036,7 +1248,8 @@ int ofnode_read_simple_addr_cells(ofnode node) if (ofnode_is_np(node)) return of_simple_addr_cells(ofnode_to_np(node)); else - return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node)); + return fdt_address_cells(ofnode_to_fdt(node), + ofnode_to_offset(node)); } int ofnode_read_simple_size_cells(ofnode node) @@ -1044,7 +1257,8 @@ int ofnode_read_simple_size_cells(ofnode node) if (ofnode_is_np(node)) return of_simple_size_cells(ofnode_to_np(node)); else - return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node)); + return fdt_size_cells(ofnode_to_fdt(node), + ofnode_to_offset(node)); } bool ofnode_pre_reloc(ofnode node) @@ -1081,7 +1295,8 @@ int ofnode_read_resource(ofnode node, uint index, struct resource *res) struct fdt_resource fres; int ret; - ret = fdt_get_resource(gd->fdt_blob, ofnode_to_offset(node), + ret = fdt_get_resource(ofnode_to_fdt(node), + ofnode_to_offset(node), "reg", index, &fres); if (ret < 0) return -EINVAL; @@ -1110,7 +1325,8 @@ u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr) if (ofnode_is_np(node)) return of_translate_address(ofnode_to_np(node), in_addr); else - return fdt_translate_address(gd->fdt_blob, ofnode_to_offset(node), in_addr); + return fdt_translate_address(ofnode_to_fdt(node), + ofnode_to_offset(node), in_addr); } u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr) @@ -1118,7 +1334,8 @@ u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr) if (ofnode_is_np(node)) return of_translate_dma_address(ofnode_to_np(node), in_addr); else - return fdt_translate_dma_address(gd->fdt_blob, ofnode_to_offset(node), in_addr); + return fdt_translate_dma_address(ofnode_to_fdt(node), + ofnode_to_offset(node), in_addr); } int ofnode_get_dma_range(ofnode node, phys_addr_t *cpu, dma_addr_t *bus, u64 *size) @@ -1126,7 +1343,8 @@ int ofnode_get_dma_range(ofnode node, phys_addr_t *cpu, dma_addr_t *bus, u64 *si if (ofnode_is_np(node)) return of_get_dma_range(ofnode_to_np(node), cpu, bus, size); else - return fdt_get_dma_range(gd->fdt_blob, ofnode_to_offset(node), + return fdt_get_dma_range(ofnode_to_fdt(node), + ofnode_to_offset(node), cpu, bus, size); } @@ -1136,7 +1354,7 @@ int ofnode_device_is_compatible(ofnode node, const char *compat) return of_device_is_compatible(ofnode_to_np(node), compat, NULL, NULL); else - return !fdt_node_check_compatible(gd->fdt_blob, + return !fdt_node_check_compatible(ofnode_to_fdt(node), ofnode_to_offset(node), compat); } @@ -1148,8 +1366,9 @@ ofnode ofnode_by_compatible(ofnode from, const char *compat) (struct device_node *)ofnode_to_np(from), NULL, compat)); } else { - return offset_to_ofnode(fdt_node_offset_by_compatible( - gd->fdt_blob, ofnode_to_offset(from), compat)); + return noffset_to_ofnode(from, + fdt_node_offset_by_compatible(ofnode_to_fdt(from), + ofnode_to_offset(from), compat)); } } @@ -1161,22 +1380,35 @@ ofnode ofnode_by_prop_value(ofnode from, const char *propname, (struct device_node *)ofnode_to_np(from), propname, propval, proplen)); } else { - return offset_to_ofnode(fdt_node_offset_by_prop_value( - gd->fdt_blob, ofnode_to_offset(from), - propname, propval, proplen)); + return noffset_to_ofnode(from, + fdt_node_offset_by_prop_value(ofnode_to_fdt(from), + ofnode_to_offset(from), propname, propval, + proplen)); } } int ofnode_write_prop(ofnode node, const char *propname, const void *value, - int len) + int len, bool copy) { - if (of_live_active()) - return of_write_prop(ofnode_to_npw(node), propname, len, value); - else - return fdt_setprop((void *)gd->fdt_blob, ofnode_to_offset(node), - propname, value, len); + if (of_live_active()) { + void *newval; + int ret; - return 0; + if (copy) { + newval = malloc(len); + if (!newval) + return log_ret(-ENOMEM); + memcpy(newval, value, len); + value = newval; + } + ret = of_write_prop(ofnode_to_np(node), propname, len, value); + if (ret && copy) + free(newval); + return ret; + } else { + return fdt_setprop(ofnode_to_fdt(node), ofnode_to_offset(node), + propname, value, len); + } } int ofnode_write_string(ofnode node, const char *propname, const char *value) @@ -1185,7 +1417,8 @@ int ofnode_write_string(ofnode node, const char *propname, const char *value) debug("%s: %s = %s", __func__, propname, value); - return ofnode_write_prop(node, propname, value, strlen(value) + 1); + return ofnode_write_prop(node, propname, value, strlen(value) + 1, + false); } int ofnode_write_u32(ofnode node, const char *propname, u32 value) @@ -1200,7 +1433,7 @@ int ofnode_write_u32(ofnode node, const char *propname, u32 value) return -ENOMEM; *val = cpu_to_fdt32(value); - return ofnode_write_prop(node, propname, val, sizeof(value)); + return ofnode_write_prop(node, propname, val, sizeof(value), false); } int ofnode_set_enabled(ofnode node, bool value) @@ -1289,3 +1522,62 @@ phy_interface_t ofnode_read_phy_mode(ofnode node) return PHY_INTERFACE_MODE_NA; } + +int ofnode_add_subnode(ofnode node, const char *name, ofnode *subnodep) +{ + ofnode subnode; + int ret = 0; + + assert(ofnode_valid(node)); + + if (ofnode_is_np(node)) { + struct device_node *np, *child; + + np = (struct device_node *)ofnode_to_np(node); + ret = of_add_subnode(np, name, -1, &child); + if (ret && ret != -EEXIST) + return ret; + subnode = np_to_ofnode(child); + } else { + void *fdt = ofnode_to_fdt(node); + int poffset = ofnode_to_offset(node); + int offset; + + offset = fdt_add_subnode(fdt, poffset, name); + if (offset == -FDT_ERR_EXISTS) { + offset = fdt_subnode_offset(fdt, poffset, name); + ret = -EEXIST; + } + if (offset < 0) + return -EINVAL; + subnode = noffset_to_ofnode(node, offset); + } + + *subnodep = subnode; + + return ret; /* 0 or -EEXIST */ +} + +int ofnode_copy_props(ofnode src, ofnode dst) +{ + struct ofprop prop; + + ofnode_for_each_prop(prop, src) { + const char *name; + const char *val; + int len, ret; + + val = ofprop_get_property(&prop, &name, &len); + if (!val) { + log_debug("Cannot read prop (err=%d)\n", len); + return log_msg_ret("get", -EINVAL); + } + ret = ofnode_write_prop(dst, name, val, len, true); + if (ret) { + log_debug("Cannot write prop (err=%d)\n", ret); + return log_msg_ret("wr", -EINVAL); + } + } + + return 0; +} diff --git a/drivers/core/read.c b/drivers/core/read.c index 07ab8ab41c..3e5fea87d8 100644 --- a/drivers/core/read.c +++ b/drivers/core/read.c @@ -287,18 +287,18 @@ const void *dev_read_prop(const struct udevice *dev, const char *propname, int dev_read_first_prop(const struct udevice *dev, struct ofprop *prop) { - return ofnode_get_first_property(dev_ofnode(dev), prop); + return ofnode_first_property(dev_ofnode(dev), prop); } int dev_read_next_prop(struct ofprop *prop) { - return ofnode_get_next_property(prop); + return ofnode_next_property(prop); } const void *dev_read_prop_by_prop(struct ofprop *prop, const char **propname, int *lenp) { - return ofnode_get_property_by_prop(prop, propname, lenp); + return ofprop_get_property(prop, propname, lenp); } int dev_read_alias_seq(const struct udevice *dev, int *devnump) diff --git a/drivers/cpu/imx8_cpu.c b/drivers/cpu/imx8_cpu.c index abddbef57b..b8eb2d2800 100644 --- a/drivers/cpu/imx8_cpu.c +++ b/drivers/cpu/imx8_cpu.c @@ -144,7 +144,7 @@ static int cpu_imx_get_count(const struct udevice *dev) ofnode_for_each_subnode(node, dev_ofnode(dev->parent)) { const char *device_type; - if (!ofnode_is_available(node)) + if (!ofnode_is_enabled(node)) continue; device_type = ofnode_read_string(node, "device_type"); diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c index b30dceba37..d6484d7f4b 100644 --- a/drivers/cpu/riscv_cpu.c +++ b/drivers/cpu/riscv_cpu.c @@ -77,7 +77,7 @@ static int riscv_cpu_get_count(const struct udevice *dev) const char *device_type; /* skip if hart is marked as not available in the device tree */ - if (!ofnode_is_available(node)) + if (!ofnode_is_enabled(node)) continue; device_type = ofnode_read_string(node, "device_type"); diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c index acd29924f7..8c0fb27b53 100644 --- a/drivers/crypto/fsl/jr.c +++ b/drivers/crypto/fsl/jr.c @@ -853,7 +853,7 @@ static int caam_jr_probe(struct udevice *dev) /* Check for enabled job ring node */ ofnode_for_each_subnode(node, dev_ofnode(dev)) { - if (!ofnode_is_available(node)) + if (!ofnode_is_enabled(node)) continue; jr_node = ofnode_read_u32_default(node, "reg", -1); diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c index 2b6211c4e6..c3f3d1f440 100644 --- a/drivers/firmware/scmi/scmi_agent-uclass.c +++ b/drivers/firmware/scmi/scmi_agent-uclass.c @@ -65,7 +65,7 @@ static int scmi_bind_protocols(struct udevice *dev) struct driver *drv = NULL; u32 protocol_id; - if (!ofnode_is_available(node)) + if (!ofnode_is_enabled(node)) continue; if (ofnode_read_u32(node, "reg", &protocol_id)) diff --git a/drivers/fpga/socfpga_arria10.c b/drivers/fpga/socfpga_arria10.c index e86e3b7431..3b785e67d0 100644 --- a/drivers/fpga/socfpga_arria10.c +++ b/drivers/fpga/socfpga_arria10.c @@ -555,14 +555,14 @@ static int first_loading_rbf_to_buffer(struct udevice *dev, /* Load image header into buffer */ ret = request_firmware_into_buf(dev, fpga_loadfs->fpga_fsinfo->filename, - buffer_p, sizeof(struct image_header), + buffer_p, sizeof(struct legacy_img_hdr), 0); if (ret < 0) { debug("FPGA: Failed to read image header from flash.\n"); return -ENOENT; } - if (image_get_magic((struct image_header *)buffer_p) != FDT_MAGIC) { + if (image_get_magic((struct legacy_img_hdr *)buffer_p) != FDT_MAGIC) { debug("FPGA: No FDT magic was found.\n"); return -EBADF; } diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 56aa58b58b..4886392a1c 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -895,7 +895,7 @@ int add_mtd_partitions_of(struct mtd_info *master) else parts = ofnode_find_subnode(master->flash_node, "partitions"); - if (!ofnode_valid(parts) || !ofnode_is_available(parts) || + if (!ofnode_valid(parts) || !ofnode_is_enabled(parts) || !ofnode_device_is_compatible(parts, "fixed-partitions")) return 0; @@ -905,7 +905,7 @@ int add_mtd_partitions_of(struct mtd_info *master) fdt_addr_t offset; fdt_size_t size; - if (!ofnode_is_available(child)) + if (!ofnode_is_enabled(child)) continue; offset = ofnode_get_addr_size_index_notrans(child, 0, &size); diff --git a/drivers/mtd/nand/raw/zynq_nand.c b/drivers/mtd/nand/raw/zynq_nand.c index 10e9cd18b0..14cb2ba704 100644 --- a/drivers/mtd/nand/raw/zynq_nand.c +++ b/drivers/mtd/nand/raw/zynq_nand.c @@ -1095,7 +1095,7 @@ static int zynq_nand_probe(struct udevice *dev) } } - if (!ofnode_is_available(of_nand)) { + if (!ofnode_is_enabled(of_nand)) { debug("Nand node in dt disabled\n"); return dm_scan_fdt_dev(dev); } diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index 8bc2b46d40..bbc4434ddb 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -1078,7 +1078,7 @@ static int device_get_phy_addr(struct fec_priv *priv, struct udevice *dev) return ret; } - if (!ofnode_is_available(phandle_args.node)) + if (!ofnode_is_enabled(phandle_args.node)) return -ENOENT; priv->phy_of_node = phandle_args.node; diff --git a/drivers/net/fsl_enetc.c b/drivers/net/fsl_enetc.c index d43a85b498..1fd5089cc4 100644 --- a/drivers/net/fsl_enetc.c +++ b/drivers/net/fsl_enetc.c @@ -323,7 +323,7 @@ static int enetc_probe(struct udevice *dev) struct enetc_priv *priv = dev_get_priv(dev); int res; - if (ofnode_valid(dev_ofnode(dev)) && !ofnode_is_available(dev_ofnode(dev))) { + if (ofnode_valid(dev_ofnode(dev)) && !ofnode_is_enabled(dev_ofnode(dev))) { enetc_dbg(dev, "interface disabled\n"); return -ENODEV; } diff --git a/drivers/net/mscc_eswitch/felix_switch.c b/drivers/net/mscc_eswitch/felix_switch.c index 709c9e3ef5..2e5f45e574 100644 --- a/drivers/net/mscc_eswitch/felix_switch.c +++ b/drivers/net/mscc_eswitch/felix_switch.c @@ -287,7 +287,7 @@ static int felix_probe(struct udevice *dev) int err; if (ofnode_valid(dev_ofnode(dev)) && - !ofnode_is_available(dev_ofnode(dev))) { + !ofnode_is_enabled(dev_ofnode(dev))) { dev_dbg(dev, "switch disabled\n"); return -ENODEV; } diff --git a/drivers/net/sja1105.c b/drivers/net/sja1105.c index 4ca8709e34..48f044c647 100644 --- a/drivers/net/sja1105.c +++ b/drivers/net/sja1105.c @@ -3316,7 +3316,7 @@ static int sja1105_probe(struct udevice *dev) int rc; if (ofnode_valid(dev_ofnode(dev)) && - !ofnode_is_available(dev_ofnode(dev))) { + !ofnode_is_enabled(dev_ofnode(dev))) { dev_dbg(dev, "switch disabled\n"); return -ENODEV; } diff --git a/drivers/net/ti/am65-cpsw-nuss.c b/drivers/net/ti/am65-cpsw-nuss.c index 9580fa37ea..b79e06290a 100644 --- a/drivers/net/ti/am65-cpsw-nuss.c +++ b/drivers/net/ti/am65-cpsw-nuss.c @@ -719,7 +719,7 @@ static int am65_cpsw_probe_nuss(struct udevice *dev) node_name = ofnode_get_name(node); - disabled = !ofnode_is_available(node); + disabled = !ofnode_is_enabled(node); ret = ofnode_read_u32(node, "reg", &port_id); if (ret) { diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 16a6a699f9..058b2f6359 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -766,7 +766,7 @@ static int pci_find_and_bind_driver(struct udevice *parent, if (ofnode_valid(dev_ofnode(parent))) pci_dev_find_ofnode(parent, bdf, &node); - if (ofnode_valid(node) && !ofnode_is_available(node)) { + if (ofnode_valid(node) && !ofnode_is_enabled(node)) { debug("%s: Ignoring disabled device\n", __func__); return log_msg_ret("dis", -EPERM); } diff --git a/drivers/pci/pci_mvebu.c b/drivers/pci/pci_mvebu.c index 5bd340a421..93a7508d8a 100644 --- a/drivers/pci/pci_mvebu.c +++ b/drivers/pci/pci_mvebu.c @@ -740,7 +740,7 @@ static int mvebu_pcie_bind(struct udevice *parent) /* First phase: Fill mvebu_pcie struct for each port */ ofnode_for_each_subnode(subnode, dev_ofnode(parent)) { - if (!ofnode_is_available(subnode)) + if (!ofnode_is_enabled(subnode)) continue; pcie = calloc(1, sizeof(*pcie)); diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c index bc489d5ec8..29d54117e9 100644 --- a/drivers/pci/pci_tegra.c +++ b/drivers/pci/pci_tegra.c @@ -531,7 +531,7 @@ static int tegra_pcie_parse_dt(struct udevice *dev, enum tegra_pci_id id, lanes |= num_lanes << (index << 3); - if (!ofnode_is_available(subnode)) + if (!ofnode_is_enabled(subnode)) continue; port = malloc(sizeof(*port)); diff --git a/drivers/pci/pcie_mediatek.c b/drivers/pci/pcie_mediatek.c index 051a3bc969..c6e30e2462 100644 --- a/drivers/pci/pcie_mediatek.c +++ b/drivers/pci/pcie_mediatek.c @@ -657,7 +657,7 @@ static int mtk_pcie_probe(struct udevice *dev) struct fdt_pci_addr addr; u32 slot = 0; - if (!ofnode_is_available(subnode)) + if (!ofnode_is_enabled(subnode)) continue; err = ofnode_read_pci_addr(subnode, 0, "reg", &addr); @@ -696,7 +696,7 @@ static int mtk_pcie_probe_v2(struct udevice *dev) pcie->priv = dev; dev_for_each_subnode(subnode, dev) { - if (!ofnode_is_available(subnode)) + if (!ofnode_is_enabled(subnode)) continue; err = ofnode_read_pci_addr(subnode, 0, "reg", &addr); diff --git a/drivers/power/pmic/sandbox.c b/drivers/power/pmic/sandbox.c index d7870915de..acfeae2df9 100644 --- a/drivers/power/pmic/sandbox.c +++ b/drivers/power/pmic/sandbox.c @@ -4,11 +4,14 @@ * Przemyslaw Marczak <p.marczak@samsung.com> */ +#define LOG_CATEGORY UCLASS_PMIC + #include <common.h> #include <fdtdec.h> #include <errno.h> #include <dm.h> #include <i2c.h> +#include <log.h> #include <power/pmic.h> #include <power/regulator.h> #include <power/sandbox_pmic.h> @@ -28,7 +31,7 @@ static int sandbox_pmic_write(struct udevice *dev, uint reg, const uint8_t *buff, int len) { if (dm_i2c_write(dev, reg, buff, len)) { - pr_err("write error to device: %p register: %#x!\n", dev, reg); + log_err("write error to device: %p register: %#x!\n", dev, reg); return -EIO; } @@ -39,7 +42,7 @@ static int sandbox_pmic_read(struct udevice *dev, uint reg, uint8_t *buff, int len) { if (dm_i2c_read(dev, reg, buff, len)) { - pr_err("read error from device: %p register: %#x!\n", dev, reg); + log_err("read error from device: %p register: %#x!\n", dev, reg); return -EIO; } @@ -49,8 +52,7 @@ static int sandbox_pmic_read(struct udevice *dev, uint reg, static int sandbox_pmic_bind(struct udevice *dev) { if (!pmic_bind_children(dev, dev_ofnode(dev), pmic_children_info)) - pr_err("%s:%d PMIC: %s - no child found!", __func__, __LINE__, - dev->name); + log_err("PMIC: %s - no child found!\n", dev->name); /* Always return success for this device - allows for PMIC I/O */ return 0; diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c index 74548ab603..af4b167e17 100644 --- a/drivers/usb/gadget/f_sdp.c +++ b/drivers/usb/gadget/f_sdp.c @@ -835,7 +835,7 @@ static int sdp_handle_in_ep(struct spl_image_info *spl_image, printf("Found header at 0x%08x\n", sdp_func->jmp_address); - image_header_t *header = + struct legacy_img_hdr *header = sdp_ptr(sdp_func->jmp_address); #ifdef CONFIG_SPL_LOAD_FIT if (image_get_magic(header) == FDT_MAGIC) { diff --git a/env/common.c b/env/common.c index 8dd05ff76d..8beb8e6aa4 100644 --- a/env/common.c +++ b/env/common.c @@ -539,12 +539,12 @@ void env_import_fdt(void) return; } - for (res = ofnode_get_first_property(node, &prop); + for (res = ofnode_first_property(node, &prop); !res; - res = ofnode_get_next_property(&prop)) { + res = ofnode_next_property(&prop)) { const char *name, *val; - val = ofnode_get_property_by_prop(&prop, &name, NULL); + val = ofprop_get_property(&prop, &name, NULL); env_set(name, val); } } diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 4aeb61f08c..2d55fe2ac0 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -646,6 +646,10 @@ enum gd_flags { * @GD_FLG_SMP_READY: SMP initialization is complete */ GD_FLG_SMP_READY = 0x80000, + /** + * @GD_FLG_FDT_CHANGED: Device tree change has been detected by tests + */ + GD_FLG_FDT_CHANGED = 0x100000, }; #endif /* __ASSEMBLY__ */ diff --git a/include/bootm.h b/include/bootm.h index 7ed5650fca..044a4797ed 100644 --- a/include/bootm.h +++ b/include/bootm.h @@ -33,7 +33,7 @@ struct cmd_tbl; * not return. */ typedef int boot_os_fn(int flag, int argc, char *const argv[], - bootm_headers_t *images); + struct bootm_headers *images); extern boot_os_fn do_bootm_linux; extern boot_os_fn do_bootm_vxworks; @@ -47,7 +47,7 @@ int bootm_host_load_images(const void *fit, int cfg_noffset); #endif int boot_selected_os(int argc, char *const argv[], int state, - bootm_headers_t *images, boot_os_fn *boot_fn); + struct bootm_headers *images, boot_os_fn *boot_fn); ulong bootm_disable_interrupts(void); @@ -56,7 +56,7 @@ int bootm_find_images(int flag, int argc, char *const argv[], ulong start, ulong size); int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[], int states, bootm_headers_t *images, + char *const argv[], int states, struct bootm_headers *images, int boot_progress); void arch_preboot_os(void); diff --git a/include/configs/uniphier.h b/include/configs/uniphier.h index 15ae0844c1..d9e95abcc1 100644 --- a/include/configs/uniphier.h +++ b/include/configs/uniphier.h @@ -169,7 +169,7 @@ /* only for SPL */ -/* subtract sizeof(struct image_header) */ +/* subtract sizeof(struct legacy_img_hdr) */ #define CONFIG_SYS_UBOOT_BASE (0x130000 - 0x40) #endif /* __CONFIG_UNIPHIER_H__ */ diff --git a/include/dm/device.h b/include/dm/device.h index 12c6ba37ff..f3f953c9af 100644 --- a/include/dm/device.h +++ b/include/dm/device.h @@ -253,7 +253,7 @@ static inline void dev_bic_flags(struct udevice *dev, u32 bic) * @dev: device to check * Return: reference of the device's DT node */ -static inline ofnode dev_ofnode(const struct udevice *dev) +static inline __attribute_const__ ofnode dev_ofnode(const struct udevice *dev) { #if CONFIG_IS_ENABLED(OF_REAL) return dev->node_; @@ -273,7 +273,7 @@ static inline ofnode dev_ofnode(const struct udevice *dev) #define dev_get_dma_offset(_dev) 0 #endif -static inline int dev_of_offset(const struct udevice *dev) +static inline __attribute_const__ int dev_of_offset(const struct udevice *dev) { #if CONFIG_IS_ENABLED(OF_REAL) return ofnode_to_offset(dev_ofnode(dev)); @@ -282,7 +282,7 @@ static inline int dev_of_offset(const struct udevice *dev) #endif } -static inline bool dev_has_ofnode(const struct udevice *dev) +static inline __attribute_const__ bool dev_has_ofnode(const struct udevice *dev) { #if CONFIG_IS_ENABLED(OF_REAL) return ofnode_valid(dev_ofnode(dev)); diff --git a/include/dm/of.h b/include/dm/of.h index 9c9065b793..fce7cef0ff 100644 --- a/include/dm/of.h +++ b/include/dm/of.h @@ -31,10 +31,21 @@ struct property { /** * struct device_node: Device tree node * - * @name: Node name + * The top of this tree is typically gd->of_root which points to the root node. + * + * The head of the list of children for the root node (and any other node) is + * in @child, with @sibling providing a link to the next child. + * + * Each child has a pointer to its parent in @parent. + * + * A node may have properties in which case the head of the list of properties + * @properties pointers to the first one, with struct property->@next pointing + * to the next one. + * + * @name: Node name, "" for the root node * @type: Node type (value of device_type property) or "<NULL>" if none * @phandle: Phandle value of this none, or 0 if none - * @full_name: Full path to node, e.g. "/bus@1/spi@1100" + * @full_name: Full path to node, e.g. "/bus@1/spi@1100" ("/" for the root node) * @properties: Pointer to head of list of properties, or NULL if none * @parent: Pointer to parent node, or NULL if this is the root node * @child: Pointer to head of child node list, or NULL if no children diff --git a/include/dm/of_access.h b/include/dm/of_access.h index 83f34f0d2a..c556a18f7d 100644 --- a/include/dm/of_access.h +++ b/include/dm/of_access.h @@ -258,11 +258,13 @@ struct device_node *of_find_node_by_prop_value(struct device_node *from, /** * of_find_node_by_phandle() - Find a node given a phandle * + * @root: root node to start from (NULL for default device tree) * @handle: phandle of the node to find * * Return: node pointer, or NULL if not found */ -struct device_node *of_find_node_by_phandle(phandle handle); +struct device_node *of_find_node_by_phandle(struct device_node *root, + phandle handle); /** * of_read_u8() - Find and read a 8-bit integer from a property @@ -325,8 +327,7 @@ int of_read_u32(const struct device_node *np, const char *propname, u32 *outp); * @outp: pointer to return value, modified only if return value is 0. * * Return: - * 0 on success, -EINVAL if the property does not exist, - * -ENODATA if property does not have a value, and -EOVERFLOW if the + * 0 on success, -EINVAL if the property does not exist, or -EOVERFLOW if the * property data isn't large enough. */ int of_read_u32_index(const struct device_node *np, const char *propname, @@ -343,8 +344,7 @@ int of_read_u32_index(const struct device_node *np, const char *propname, * @outp: pointer to return value, modified only if return value is 0. * * Return: - * 0 on success, -EINVAL if the property does not exist, - * -ENODATA if property does not have a value, and -EOVERFLOW if the + * 0 on success, -EINVAL if the property does not exist, or -EOVERFLOW if the * property data isn't large enough. */ int of_read_u64(const struct device_node *np, const char *propname, u64 *outp); @@ -360,8 +360,8 @@ int of_read_u64(const struct device_node *np, const char *propname, u64 *outp); * @out_values: pointer to return value, modified only if return value is 0. * @sz: number of array elements to read * Return: - * 0 on success, -EINVAL if the property does not exist, -ENODATA - * if property does not have a value, and -EOVERFLOW is longer than sz. + * 0 on success, -EINVAL if the property does not exist, or -EOVERFLOW if + * longer than sz. */ int of_read_u32_array(const struct device_node *np, const char *propname, u32 *out_values, size_t sz); @@ -563,4 +563,19 @@ struct device_node *of_get_stdout(void); int of_write_prop(struct device_node *np, const char *propname, int len, const void *value); +/** + * of_add_subnode() - add a new subnode to a node + * + * @node: parent node to add to + * @name: name of subnode + * @len: length of name (so the caller does not need to nul-terminate a + * partial string), or -1 for strlen(@name) + * @subnodep: returns pointer to new subnode (valid if the function returns 0 + * or -EEXIST) + * Returns 0 if OK, -EEXIST if already exists, -ENOMEM if out of memory, other + * -ve on other error + */ +int of_add_subnode(struct device_node *node, const char *name, int len, + struct device_node **subnodep); + #endif diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index f6085231bb..7aae2c29ef 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -27,70 +27,147 @@ struct ofnode_phandle_args { uint32_t args[OF_MAX_PHANDLE_ARGS]; }; +#if CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) /** - * ofnode_to_np() - convert an ofnode to a live DT node pointer + * oftree_reset() - reset the state of the oftree list * - * This cannot be called if the reference contains an offset. + * Reset the oftree list so it can be started again. This should be called + * once the control FDT is in place, but before the ofnode interface is used. + */ +void oftree_reset(void); + +/** + * ofnode_to_fdt() - convert an ofnode to a flat DT pointer * - * @node: Reference containing struct device_node * (possibly invalid) - * Return: pointer to device node (can be NULL) + * This cannot be called if the reference contains a node pointer. + * + * @node: Reference containing offset (possibly invalid) + * Return: DT offset (can be NULL) + */ +__attribute_const__ void *ofnode_to_fdt(ofnode node); + +/** + * ofnode_to_offset() - convert an ofnode to a flat DT offset + * + * This cannot be called if the reference contains a node pointer. + * + * @node: Reference containing offset (possibly invalid) + * Return: DT offset (can be -1) + */ +__attribute_const__ int ofnode_to_offset(ofnode node); + +/** + * oftree_from_fdt() - Returns an oftree from a flat device tree pointer + * + * @fdt: Device tree to use + * + * Returns: reference to the given node */ -static inline const struct device_node *ofnode_to_np(ofnode node) +oftree oftree_from_fdt(void *fdt); + +/** + * noffset_to_ofnode() - convert a DT offset to an ofnode + * + * @other_node: Node in the same tree to use as a reference + * @of_offset: DT offset (either valid, or -1) + * Return: reference to the associated DT offset + */ +ofnode noffset_to_ofnode(ofnode other_node, int of_offset); + +#else /* !OFNODE_MULTI_TREE */ +static inline void oftree_reset(void) {} + +static inline void *ofnode_to_fdt(ofnode node) { #ifdef OF_CHECKS - if (!of_live_active()) + if (of_live_active()) return NULL; #endif - return node.np; + /* Use the control FDT by default */ + return (void *)gd->fdt_blob; } +static inline __attribute_const__ int ofnode_to_offset(ofnode node) +{ +#ifdef OF_CHECKS + if (of_live_active()) + return -1; +#endif + return node.of_offset; +} + +static inline oftree oftree_from_fdt(void *fdt) +{ + oftree tree; + + /* we cannot access other trees without OFNODE_MULTI_TREE */ + if (fdt == gd->fdt_blob) + tree.fdt = fdt; + else + tree.fdt = NULL; + + return tree; +} + +static inline ofnode noffset_to_ofnode(ofnode other_node, int of_offset) +{ + ofnode node; + + if (of_live_active()) + node.np = NULL; + else + node.of_offset = of_offset; + + return node; +} + +#endif /* OFNODE_MULTI_TREE */ + /** - * ofnode_to_npw() - convert an ofnode to a writeable live DT node pointer + * ofnode_to_np() - convert an ofnode to a live DT node pointer * * This cannot be called if the reference contains an offset. * * @node: Reference containing struct device_node * (possibly invalid) * Return: pointer to device node (can be NULL) */ -static inline struct device_node *ofnode_to_npw(ofnode node) +static inline struct device_node *ofnode_to_np(ofnode node) { #ifdef OF_CHECKS if (!of_live_active()) return NULL; #endif - /* Drop constant */ - return (struct device_node *)node.np; + return node.np; } /** - * ofnode_to_offset() - convert an ofnode to a flat DT offset - * - * This cannot be called if the reference contains a node pointer. + * ofnode_valid() - check if an ofnode is valid * * @node: Reference containing offset (possibly invalid) - * Return: DT offset (can be -1) + * Return: true if the reference contains a valid ofnode, false if not */ -static inline int ofnode_to_offset(ofnode node) +static inline bool ofnode_valid(ofnode node) { -#ifdef OF_CHECKS if (of_live_active()) - return -1; -#endif - return node.of_offset; + return node.np != NULL; + else + return node.of_offset >= 0; } /** - * ofnode_valid() - check if an ofnode is valid + * oftree_lookup_fdt() - obtain the FDT pointer from an oftree * - * @node: Reference containing offset (possibly invalid) - * Return: true if the reference contains a valid ofnode, false if it is NULL + * This can only be called when flat tree is enabled + * + * @tree: Tree to look at + * @return FDT pointer from the tree */ -static inline bool ofnode_valid(ofnode node) +static inline void *oftree_lookup_fdt(oftree tree) { if (of_live_active()) - return node.np != NULL; + return NULL; else - return node.of_offset >= 0; + return tree.fdt; } /** @@ -117,7 +194,7 @@ static inline ofnode offset_to_ofnode(int of_offset) * @np: Live node pointer (can be NULL) * Return: reference to the associated node pointer */ -static inline ofnode np_to_ofnode(const struct device_node *np) +static inline ofnode np_to_ofnode(struct device_node *np) { ofnode node; @@ -165,6 +242,38 @@ static inline bool ofnode_equal(ofnode ref1, ofnode ref2) } /** + * oftree_valid() - check if an oftree is valid + * + * @tree: Reference containing oftree + * Return: true if the reference contains a valid oftree, false if node + */ +static inline bool oftree_valid(oftree tree) +{ + if (of_live_active()) + return tree.np; + else + return tree.fdt; +} + +/** + * oftree_null() - Obtain a null oftree + * + * This returns an oftree which points to no tree. It works both with the flat + * tree and livetree. + */ +static inline oftree oftree_null(void) +{ + oftree tree; + + if (of_live_active()) + tree.np = NULL; + else + tree.fdt = NULL; + + return tree; +} + +/** * ofnode_null() - Obtain a null ofnode * * This returns an ofnode which points to no node. It works both with the flat @@ -195,6 +304,20 @@ static inline ofnode ofnode_root(void) } /** + * ofprop_valid() - check if an ofprop is valid + * + * @prop: Pointer to ofprop to check + * Return: true if the reference contains a valid ofprop, false if not + */ +static inline bool ofprop_valid(struct ofprop *prop) +{ + if (of_live_active()) + return prop->prop; + else + return prop->offset >= 0; +} + +/** * oftree_default() - Returns the default device tree (U-Boot's control FDT) * * Returns: reference to the control FDT @@ -212,6 +335,21 @@ static inline oftree oftree_default(void) } /** + * oftree_from_np() - Returns an oftree from a node pointer + * + * @root: Root node of the tree + * Returns: reference to the given node + */ +static inline oftree oftree_from_np(struct device_node *root) +{ + oftree tree; + + tree.np = root; + + return tree; +} + +/** * ofnode_name_eq() - Check if the node name is equivalent to a given name * ignoring the unit address * @@ -377,12 +515,12 @@ const char *ofnode_read_string(ofnode node, const char *propname); * @propname: name of the property to read * @out_values: pointer to return value, modified only if return value is 0 * @sz: number of array elements to read - * Return: 0 if OK, -ve on error + * Return: 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough * * Search for a property in a device node and read 32-bit value(s) from - * it. Returns 0 on success, -EINVAL if the property does not exist, - * -ENODATA if property does not have a value, and -EOVERFLOW if the - * property data isn't large enough. + * it. * * The out_values is modified only if a valid u32 value can be decoded. */ @@ -484,7 +622,7 @@ ofnode ofnode_get_parent(ofnode node); * ofnode_get_name() - get the name of a node * * @node: valid node to look up - * Return: name of node + * Return: name of node (for the root node this is "") */ const char *ofnode_get_name(ofnode node); @@ -501,12 +639,23 @@ int ofnode_get_path(ofnode node, char *buf, int buflen); /** * ofnode_get_by_phandle() - get ofnode from phandle * + * This uses the default (control) device tree + * * @phandle: phandle to look up * Return: ofnode reference to the phandle */ ofnode ofnode_get_by_phandle(uint phandle); /** + * oftree_get_by_phandle() - get ofnode from phandle + * + * @tree: tree to use + * @phandle: phandle to look up + * Return: ofnode reference to the phandle + */ +ofnode oftree_get_by_phandle(oftree tree, uint phandle); + +/** * ofnode_read_size() - read the size of a property * * @node: node to check @@ -723,18 +872,28 @@ int ofnode_count_phandle_with_args(ofnode node, const char *list_name, ofnode ofnode_path(const char *path); /** - * ofnode_path_root() - find a node by full path from a root node + * oftree_path() - find a node by full path from a root node * * @tree: Device tree to use * @path: Full path to node, e.g. "/bus/spi@1" * Return: reference to the node found. Use ofnode_valid() to check if it exists */ -ofnode ofnode_path_root(oftree tree, const char *path); +ofnode oftree_path(oftree tree, const char *path); + +/** + * oftree_root() - get the root node of a tree + * + * @tree: Device tree to use + * Return: reference to the root node + */ +ofnode oftree_root(oftree tree); /** * ofnode_read_chosen_prop() - get the value of a chosen property * - * This looks for a property within the /chosen node and returns its value + * This looks for a property within the /chosen node and returns its value. + * + * This only works with the control FDT. * * @propname: Property name to look for * @sizep: Returns size of property, or `FDT_ERR_...` error code if function @@ -749,6 +908,8 @@ const void *ofnode_read_chosen_prop(const char *propname, int *sizep); * This looks for a property within the /chosen node and returns its value, * checking that it is a valid nul-terminated string * + * This only works with the control FDT. + * * @propname: Property name to look for * Return: string value if found, else NULL */ @@ -760,6 +921,8 @@ const char *ofnode_read_chosen_string(const char *propname); * This looks up a named property in the chosen node and uses that as a path to * look up a code. * + * This only works with the control FDT. + * * @propname: Property name to look for * Return: the referenced node if present, else ofnode_null() */ @@ -770,6 +933,8 @@ ofnode ofnode_get_chosen_node(const char *propname); * * This looks for a property within the /aliases node and returns its value * + * This only works with the control FDT. + * * @propname: Property name to look for * @sizep: Returns size of property, or `FDT_ERR_...` error code if function * returns NULL @@ -783,6 +948,8 @@ const void *ofnode_read_aliases_prop(const char *propname, int *sizep); * This looks up a named property in the aliases node and uses that as a path to * look up a code. * + * This only works with the control FDT. + * * @propname: Property name to look for * Return: the referenced node if present, else ofnode_null() */ @@ -815,48 +982,64 @@ int ofnode_decode_display_timing(ofnode node, int index, const void *ofnode_get_property(ofnode node, const char *propname, int *lenp); /** - * ofnode_get_first_property()- get the reference of the first property + * ofnode_first_property()- get the reference of the first property * * Get reference to the first property of the node, it is used to iterate - * and read all the property with ofnode_get_property_by_prop(). + * and read all the property with ofprop_get_property(). * * @node: node to read * @prop: place to put argument reference * Return: 0 if OK, -ve on error. -FDT_ERR_NOTFOUND if not found */ -int ofnode_get_first_property(ofnode node, struct ofprop *prop); +int ofnode_first_property(ofnode node, struct ofprop *prop); /** - * ofnode_get_next_property() - get the reference of the next property + * ofnode_next_property() - get the reference of the next property * * Get reference to the next property of the node, it is used to iterate - * and read all the property with ofnode_get_property_by_prop(). + * and read all the property with ofprop_get_property(). * * @prop: reference of current argument and place to put reference of next one * Return: 0 if OK, -ve on error. -FDT_ERR_NOTFOUND if not found */ -int ofnode_get_next_property(struct ofprop *prop); +int ofnode_next_property(struct ofprop *prop); /** - * ofnode_get_property_by_prop() - get a pointer to the value of a property + * ofnode_for_each_prop() - iterate over all properties of a node * - * Get value for the property identified by the provided reference. + * @prop: struct ofprop + * @node: node (lvalue, ofnode) * - * @prop: reference on property - * @propname: If non-NULL, place to property name on success, - * @lenp: If non-NULL, place to put length on success - * Return: 0 if OK, -ve on error. -FDT_ERR_NOTFOUND if not found + * This is a wrapper around a for loop and is used like this:: + * + * ofnode node; + * struct ofprop prop; + * + * ofnode_for_each_prop(prop, node) { + * ...use prop... + * } + * + * Note that this is implemented as a macro and @prop is used as + * iterator in the loop. The parent variable can be a constant or even a + * literal. */ -const void *ofnode_get_property_by_prop(const struct ofprop *prop, - const char **propname, int *lenp); +#define ofnode_for_each_prop(prop, node) \ + for (ofnode_first_property(node, &prop); \ + ofprop_valid(&prop); \ + ofnode_next_property(&prop)) /** - * ofnode_is_available() - check if a node is marked available + * ofprop_get_property() - get a pointer to the value of a property * - * @node: node to check - * Return: true if node's 'status' property is "okay" (or is missing) + * Get value for the property identified by the provided reference. + * + * @prop: reference on property + * @propname: If non-NULL, place to property name on success, + * @lenp: If non-NULL, place to put length on success, or error code on failure + * Return: pointer to property, or NULL if not found */ -bool ofnode_is_available(ofnode node); +const void *ofprop_get_property(const struct ofprop *prop, + const char **propname, int *lenp); /** * ofnode_get_addr_size() - get address and size from a property @@ -1046,8 +1229,9 @@ ofnode ofnode_by_compatible(ofnode from, const char *compat); * Find the next node after @from that has a @propname with a value * @propval and a length @proplen. * - * @from: ofnode to start from (use ofnode_null() to start at the - * beginning) + * @from: ofnode to start from. Use ofnode_null() to start at the + * beginning, or the return value from oftree_root() to start at the first + * child of the root * @propname: property name to check * @propval: property value to search for * @proplen: length of the value in propval @@ -1166,19 +1350,23 @@ int ofnode_device_is_compatible(ofnode node, const char *compat); /** * ofnode_write_prop() - Set a property of a ofnode * - * Note that the value passed to the function is *not* allocated by the - * function itself, but must be allocated by the caller if necessary. However - * it does allocate memory for the property struct and name. + * Note that if @copy is false, the value passed to the function is *not* + * allocated by the function itself, but must be allocated by the caller if + * necessary. However it does allocate memory for the property struct and name. * * @node: The node for whose property should be set * @propname: The name of the property to set * @value: The new value of the property (must be valid prior to calling * the function) * @len: The length of the new value of the property + * @copy: true to allocate memory for the value. This only has any effect with + * live tree, since flat tree handles this automatically. It allows a + * node's value to be written to the tree, without requiring that the + * caller allocate it * Return: 0 if successful, -ve on error */ int ofnode_write_prop(ofnode node, const char *propname, const void *value, - int len); + int len, bool copy); /** * ofnode_write_string() - Set a string property of a ofnode @@ -1251,7 +1439,9 @@ phy_interface_t ofnode_read_phy_mode(ofnode mac_node); * * This reads a property from the /config node of the devicetree. * - * See doc/config.txt for bindings + * This only works with the control FDT. + * + * See doc/device-tree-bindings/config.txt for bindings * * @prop_name: property name to look up * Return: true, if it exists, false if not @@ -1263,7 +1453,7 @@ bool ofnode_conf_read_bool(const char *prop_name); * * This reads a property from the /config node of the devicetree. * - * See doc/config.txt for bindings + * See doc/device-tree-bindings/config.txt for bindings * * @prop_name: property name to look up * @default_val: default value to return if the property is not found @@ -1276,7 +1466,9 @@ int ofnode_conf_read_int(const char *prop_name, int default_val); * * This reads a property from the /config node of the devicetree. * - * See doc/config.txt for bindings + * This only works with the control FDT. + * + * See doc/device-tree-bindings/config.txt for bindings * * @prop_name: property name to look up * Return: string value, if found, or NULL if not @@ -1298,6 +1490,35 @@ static inline const char *ofnode_conf_read_str(const char *prop_name) { return NULL; } + #endif /* CONFIG_DM */ +/** + * of_add_subnode() - add a new subnode to a node + * + * @parent: parent node to add to + * @name: name of subnode + * @nodep: returns pointer to new subnode (valid if the function returns 0 + * or -EEXIST) + * Returns 0 if OK, -EEXIST if already exists, -ENOMEM if out of memory, other + * -ve on other error + */ +int ofnode_add_subnode(ofnode parent, const char *name, ofnode *nodep); + +/** + * ofnode_copy_props() - copy all properties from one node to another + * + * Makes a copy of all properties from the source note in the destination node. + * Existing properties in the destination node remain unchanged, except that + * any with the same name are overwritten, including changing the size of the + * property. + * + * For livetree, properties are copied / allocated, so the source tree does not + * need to be present afterwards. + * + * @src: Source node to read properties from + * @dst: Destination node to write properties too + */ +int ofnode_copy_props(ofnode src, ofnode dst); + #endif diff --git a/include/dm/ofnode_decl.h b/include/dm/ofnode_decl.h index 266253d5e3..5c2115aab0 100644 --- a/include/dm/ofnode_decl.h +++ b/include/dm/ofnode_decl.h @@ -31,18 +31,47 @@ * this increases code size slightly due to the subtraction. Since it offers no * real benefit, the approach described here seems best. * - * For now these points use constant types, since we don't allow writing - * the DT. + * Where multiple trees are in use, this works without any trouble with live + * tree, except for aliases, such as ofnode_path("mmc0"), which only work on the + * control FDT. When the flat tree is in use, the trees are registered and a + * 'tree ID' is encoded into the top bits of @of_offset - see immediately below + * for the associated macro definitions. Note that 64-bit machines use the same + * encoding, even though there is more space available. This is partly because + * the FDT format contains 32-bit values for things like the string-table + * offset, therefore 64-bit offsets cannot be supported anyway. + * + * For the multiple-tree case, an invalid offset (i.e. with of_offset < 0) is + * still invalid. It does not contain a tree ID. So there is no way of knowing + * which tree produced the invalid offset. * * @np: Pointer to device node, used for live tree * @of_offset: Pointer into flat device tree, used for flat tree. Note that this * is not a really a pointer to a node: it is an offset value. See above. */ typedef union ofnode_union { - const struct device_node *np; + struct device_node *np; long of_offset; } ofnode; +/* shift for the tree ID within of_offset */ +#define OF_TREE_SHIFT 28 + +/* mask to obtain the device tree offset from of_offset */ +#define OF_TREE_MASK ((1 << OF_TREE_SHIFT) - 1) + +/* encode a tree ID and node offset into an of_offset value */ +#define OFTREE_NODE(tree_id, offs) ((tree_id) << OF_TREE_SHIFT | (offs)) + +/* decode the node offset from an of_offset value */ +#define OFTREE_OFFSET(of_offs) ((of_offs) & OF_TREE_MASK) + +/* decode the tree ID from an of_offset value */ +#define OFTREE_TREE_ID(of_offs) ((of_offs) >> OF_TREE_SHIFT) + +/* encode a node offset in the tree given by another node's of_offset value */ +#define OFTREE_MAKE_NODE(other_of_offset, offs) \ + (((offs) & OF_TREE_MASK) | ((other_of_offset) & ~OF_TREE_MASK)) + /** * struct ofprop - reference to a property of a device tree node * @@ -57,7 +86,7 @@ typedef union ofnode_union { * * @node: Pointer to device node * @offset: Pointer into flat device tree, used for flat tree. - * @prop: Pointer to property, used for live treee. + * @prop: Pointer to property, used for live tree. */ struct ofprop { diff --git a/include/dm/read.h b/include/dm/read.h index 122b9cd15b..cc4f16196f 100644 --- a/include/dm/read.h +++ b/include/dm/read.h @@ -569,7 +569,7 @@ const void *dev_read_prop(const struct udevice *dev, const char *propname, int dev_read_first_prop(const struct udevice *dev, struct ofprop *prop); /** - * ofnode_get_next_property() - get the reference of the next property + * ofnode_next_property() - get the reference of the next property * * Get reference to the next property of the node, it is used to iterate * and read all the property with dev_read_prop_by_prop(). @@ -1079,19 +1079,19 @@ static inline const void *dev_read_prop(const struct udevice *dev, static inline int dev_read_first_prop(const struct udevice *dev, struct ofprop *prop) { - return ofnode_get_first_property(dev_ofnode(dev), prop); + return ofnode_first_property(dev_ofnode(dev), prop); } static inline int dev_read_next_prop(struct ofprop *prop) { - return ofnode_get_next_property(prop); + return ofnode_next_property(prop); } static inline const void *dev_read_prop_by_prop(struct ofprop *prop, const char **propname, int *lenp) { - return ofnode_get_property_by_prop(prop, propname, lenp); + return ofprop_get_property(prop, propname, lenp); } static inline int dev_read_alias_seq(const struct udevice *dev, int *devnump) diff --git a/include/event.h b/include/event.h index e8f2f55c63..3e6dcbc3dd 100644 --- a/include/event.h +++ b/include/event.h @@ -60,9 +60,11 @@ union event_data { * struct event_ft_fixup - FDT fixup before booting * * @tree: tree to update + * @images: images which are being booted */ struct event_ft_fixup { oftree tree; + struct bootm_headers *images; } ft_fixup; }; @@ -143,8 +145,8 @@ static inline const char *event_spy_id(struct evspy_info *spy) * vbe_simple.c - so for now, make it global. */ #define EVENT_SPY(_type, _func) \ - __used ll_entry_declare(struct evspy_info, _type, evspy_info) = \ - _ESPY_REC(_type, _func) + __used ll_entry_declare(struct evspy_info, _type ## _3_ ## _func, \ + evspy_info) = _ESPY_REC(_type, _func) /** * event_register - register a new spy diff --git a/include/image.h b/include/image.h index 03424f0521..eb2513c5b7 100644 --- a/include/image.h +++ b/include/image.h @@ -263,7 +263,7 @@ enum { * Legacy format image header, * all data in network byte order (aka natural aka bigendian). */ -typedef struct image_header { +struct legacy_img_hdr { uint32_t ih_magic; /* Image Header Magic Number */ uint32_t ih_hcrc; /* Image Header CRC Checksum */ uint32_t ih_time; /* Image Creation Timestamp */ @@ -276,28 +276,28 @@ typedef struct image_header { uint8_t ih_type; /* Image Type */ uint8_t ih_comp; /* Compression Type */ uint8_t ih_name[IH_NMLEN]; /* Image Name */ -} image_header_t; +}; -typedef struct image_info { +struct image_info { ulong start, end; /* start/end of blob */ ulong image_start, image_len; /* start of image within blob, len of image */ ulong load; /* load addr for the image */ uint8_t comp, type, os; /* compression, type of image, os type */ uint8_t arch; /* CPU architecture */ -} image_info_t; +}; /* * Legacy and FIT format headers used by do_bootm() and do_bootm_<os>() * routines. */ -typedef struct bootm_headers { +struct bootm_headers { /* * Legacy os image header, if it is a multi component image * then boot_get_ramdisk() and get_fdt() will attempt to get * data from second and third component accordingly. */ - image_header_t *legacy_hdr_os; /* image header pointer */ - image_header_t legacy_hdr_os_copy; /* header copy */ + struct legacy_img_hdr *legacy_hdr_os; /* image header pointer */ + struct legacy_img_hdr legacy_hdr_os_copy; /* header copy */ ulong legacy_hdr_valid; /* @@ -324,7 +324,7 @@ typedef struct bootm_headers { int fit_noffset_setup;/* x86 setup subimage node offset */ #ifndef USE_HOSTCC - image_info_t os; /* os image info */ + struct image_info os; /* os image info */ ulong ep; /* entry point of OS */ ulong rd_start, rd_end;/* ramdisk start/end */ @@ -341,24 +341,24 @@ typedef struct bootm_headers { int verify; /* env_get("verify")[0] != 'n' */ -#define BOOTM_STATE_START (0x00000001) -#define BOOTM_STATE_FINDOS (0x00000002) -#define BOOTM_STATE_FINDOTHER (0x00000004) -#define BOOTM_STATE_LOADOS (0x00000008) -#define BOOTM_STATE_RAMDISK (0x00000010) -#define BOOTM_STATE_FDT (0x00000020) -#define BOOTM_STATE_OS_CMDLINE (0x00000040) -#define BOOTM_STATE_OS_BD_T (0x00000080) -#define BOOTM_STATE_OS_PREP (0x00000100) -#define BOOTM_STATE_OS_FAKE_GO (0x00000200) /* 'Almost' run the OS */ -#define BOOTM_STATE_OS_GO (0x00000400) -#define BOOTM_STATE_PRE_LOAD 0x00000800 +#define BOOTM_STATE_START 0x00000001 +#define BOOTM_STATE_FINDOS 0x00000002 +#define BOOTM_STATE_FINDOTHER 0x00000004 +#define BOOTM_STATE_LOADOS 0x00000008 +#define BOOTM_STATE_RAMDISK 0x00000010 +#define BOOTM_STATE_FDT 0x00000020 +#define BOOTM_STATE_OS_CMDLINE 0x00000040 +#define BOOTM_STATE_OS_BD_T 0x00000080 +#define BOOTM_STATE_OS_PREP 0x00000100 +#define BOOTM_STATE_OS_FAKE_GO 0x00000200 /* 'Almost' run the OS */ +#define BOOTM_STATE_OS_GO 0x00000400 +#define BOOTM_STATE_PRE_LOAD 0x00000800 int state; #if defined(CONFIG_LMB) && !defined(USE_HOSTCC) struct lmb lmb; /* for memory mgmt */ #endif -} bootm_headers_t; +}; #ifdef CONFIG_LMB #define images_lmb(_images) (&(_images)->lmb) @@ -366,7 +366,7 @@ typedef struct bootm_headers { #define images_lmb(_images) NULL #endif -extern bootm_headers_t images; +extern struct bootm_headers images; /* * Some systems (for example LWMON) have very short watchdog periods; @@ -530,7 +530,7 @@ enum fit_load_op { FIT_LOAD_REQUIRED, /* Must be provided */ }; -int boot_get_setup(bootm_headers_t *images, uint8_t arch, ulong *setup_start, +int boot_get_setup(struct bootm_headers *images, uint8_t arch, ulong *setup_start, ulong *setup_len); /* Image format types, returned by _get_format() routine */ @@ -544,11 +544,11 @@ ulong genimg_get_kernel_addr_fit(char * const img_addr, const char **fit_uname_kernel); ulong genimg_get_kernel_addr(char * const img_addr); int genimg_get_format(const void *img_addr); -int genimg_has_config(bootm_headers_t *images); +int genimg_has_config(struct bootm_headers *images); -int boot_get_fpga(int argc, char *const argv[], bootm_headers_t *images, +int boot_get_fpga(int argc, char *const argv[], struct bootm_headers *images, uint8_t arch, const ulong *ld_start, ulong * const ld_len); -int boot_get_ramdisk(int argc, char *const argv[], bootm_headers_t *images, +int boot_get_ramdisk(int argc, char *const argv[], struct bootm_headers *images, uint8_t arch, ulong *rd_start, ulong *rd_end); /** @@ -572,10 +572,10 @@ int boot_get_ramdisk(int argc, char *const argv[], bootm_headers_t *images, * 0, if only valid images or no images are found * error code, if an error occurs during fit_image_load */ -int boot_get_loadable(int argc, char *const argv[], bootm_headers_t *images, +int boot_get_loadable(int argc, char *const argv[], struct bootm_headers *images, uint8_t arch, const ulong *ld_start, ulong *const ld_len); -int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch, +int boot_get_setup_fit(struct bootm_headers *images, uint8_t arch, ulong *setup_start, ulong *setup_len); /** @@ -599,9 +599,9 @@ int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch, * * Return: node offset of base image, or -ve error code on error */ -int boot_get_fdt_fit(bootm_headers_t *images, ulong addr, - const char **fit_unamep, const char **fit_uname_configp, - int arch, ulong *datap, ulong *lenp); +int boot_get_fdt_fit(struct bootm_headers *images, ulong addr, + const char **fit_unamep, const char **fit_uname_configp, + int arch, ulong *datap, ulong *lenp); /** * fit_image_load() - load an image from a FIT @@ -633,7 +633,7 @@ int boot_get_fdt_fit(bootm_headers_t *images, ulong addr, * @param lenp Returns length of loaded image * Return: node offset of image, or -ve error code on error */ -int fit_image_load(bootm_headers_t *images, ulong addr, +int fit_image_load(struct bootm_headers *images, ulong addr, const char **fit_unamep, const char **fit_uname_configp, int arch, int image_type, int bootstage_id, enum fit_load_op load_op, ulong *datap, ulong *lenp); @@ -677,11 +677,11 @@ int image_source_script(ulong addr, const char *fit_uname); * @param prop_name Property name to look up (FIT_..._PROP) * @param addr Address of FIT in memory */ -int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name, - ulong addr); +int fit_get_node_from_config(struct bootm_headers *images, + const char *prop_name, ulong addr); int boot_get_fdt(int flag, int argc, char *const argv[], uint8_t arch, - bootm_headers_t *images, + struct bootm_headers *images, char **of_flat_tree, ulong *of_size); void boot_fdt_add_mem_rsv_regions(struct lmb *lmb, void *fdt_blob); int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size); @@ -696,11 +696,11 @@ int boot_get_kbd(struct lmb *lmb, struct bd_info **kbd); /*******************************************************************/ static inline uint32_t image_get_header_size(void) { - return (sizeof(image_header_t)); + return sizeof(struct legacy_img_hdr); } #define image_get_hdr_l(f) \ - static inline uint32_t image_get_##f(const image_header_t *hdr) \ + static inline uint32_t image_get_##f(const struct legacy_img_hdr *hdr) \ { \ return uimage_to_cpu(hdr->ih_##f); \ } @@ -713,7 +713,7 @@ image_get_hdr_l(ep) /* image_get_ep */ image_get_hdr_l(dcrc) /* image_get_dcrc */ #define image_get_hdr_b(f) \ - static inline uint8_t image_get_##f(const image_header_t *hdr) \ + static inline uint8_t image_get_##f(const struct legacy_img_hdr *hdr) \ { \ return hdr->ih_##f; \ } @@ -722,12 +722,12 @@ image_get_hdr_b(arch) /* image_get_arch */ image_get_hdr_b(type) /* image_get_type */ image_get_hdr_b(comp) /* image_get_comp */ -static inline char *image_get_name(const image_header_t *hdr) +static inline char *image_get_name(const struct legacy_img_hdr *hdr) { return (char *)hdr->ih_name; } -static inline uint32_t image_get_data_size(const image_header_t *hdr) +static inline uint32_t image_get_data_size(const struct legacy_img_hdr *hdr) { return image_get_size(hdr); } @@ -743,22 +743,23 @@ static inline uint32_t image_get_data_size(const image_header_t *hdr) * returns: * image payload data start address */ -static inline ulong image_get_data(const image_header_t *hdr) +static inline ulong image_get_data(const struct legacy_img_hdr *hdr) { return ((ulong)hdr + image_get_header_size()); } -static inline uint32_t image_get_image_size(const image_header_t *hdr) +static inline uint32_t image_get_image_size(const struct legacy_img_hdr *hdr) { return (image_get_size(hdr) + image_get_header_size()); } -static inline ulong image_get_image_end(const image_header_t *hdr) + +static inline ulong image_get_image_end(const struct legacy_img_hdr *hdr) { return ((ulong)hdr + image_get_image_size(hdr)); } #define image_set_hdr_l(f) \ - static inline void image_set_##f(image_header_t *hdr, uint32_t val) \ + static inline void image_set_##f(struct legacy_img_hdr *hdr, uint32_t val) \ { \ hdr->ih_##f = cpu_to_uimage(val); \ } @@ -771,7 +772,7 @@ image_set_hdr_l(ep) /* image_set_ep */ image_set_hdr_l(dcrc) /* image_set_dcrc */ #define image_set_hdr_b(f) \ - static inline void image_set_##f(image_header_t *hdr, uint8_t val) \ + static inline void image_set_##f(struct legacy_img_hdr *hdr, uint8_t val) \ { \ hdr->ih_##f = val; \ } @@ -780,13 +781,13 @@ image_set_hdr_b(arch) /* image_set_arch */ image_set_hdr_b(type) /* image_set_type */ image_set_hdr_b(comp) /* image_set_comp */ -static inline void image_set_name(image_header_t *hdr, const char *name) +static inline void image_set_name(struct legacy_img_hdr *hdr, const char *name) { strncpy(image_get_name(hdr), name, IH_NMLEN); } -int image_check_hcrc(const image_header_t *hdr); -int image_check_dcrc(const image_header_t *hdr); +int image_check_hcrc(const struct legacy_img_hdr *hdr); +int image_check_dcrc(const struct legacy_img_hdr *hdr); #ifndef USE_HOSTCC ulong env_get_bootm_low(void); phys_size_t env_get_bootm_size(void); @@ -794,15 +795,17 @@ phys_size_t env_get_bootm_mapsize(void); #endif void memmove_wd(void *to, void *from, size_t len, ulong chunksz); -static inline int image_check_magic(const image_header_t *hdr) +static inline int image_check_magic(const struct legacy_img_hdr *hdr) { return (image_get_magic(hdr) == IH_MAGIC); } -static inline int image_check_type(const image_header_t *hdr, uint8_t type) + +static inline int image_check_type(const struct legacy_img_hdr *hdr, uint8_t type) { return (image_get_type(hdr) == type); } -static inline int image_check_arch(const image_header_t *hdr, uint8_t arch) + +static inline int image_check_arch(const struct legacy_img_hdr *hdr, uint8_t arch) { /* Let's assume that sandbox can load any architecture */ if (!tools_build() && IS_ENABLED(CONFIG_SANDBOX)) @@ -810,19 +813,20 @@ static inline int image_check_arch(const image_header_t *hdr, uint8_t arch) return (image_get_arch(hdr) == arch) || (image_get_arch(hdr) == IH_ARCH_ARM && arch == IH_ARCH_ARM64); } -static inline int image_check_os(const image_header_t *hdr, uint8_t os) + +static inline int image_check_os(const struct legacy_img_hdr *hdr, uint8_t os) { return (image_get_os(hdr) == os); } -ulong image_multi_count(const image_header_t *hdr); -void image_multi_getimg(const image_header_t *hdr, ulong idx, +ulong image_multi_count(const struct legacy_img_hdr *hdr); +void image_multi_getimg(const struct legacy_img_hdr *hdr, ulong idx, ulong *data, ulong *len); void image_print_contents(const void *hdr); #ifndef USE_HOSTCC -static inline int image_check_target_arch(const image_header_t *hdr) +static inline int image_check_target_arch(const struct legacy_img_hdr *hdr) { #ifndef IH_ARCH_DEFAULT # error "please define IH_ARCH_DEFAULT in your arch asm/u-boot.h" @@ -871,7 +875,7 @@ int image_decomp(int comp, ulong load, ulong image_start, int type, * @lmb: Points to logical memory block structure * Return: 0 if ok, <0 on failure */ -int image_setup_libfdt(bootm_headers_t *images, void *blob, +int image_setup_libfdt(struct bootm_headers *images, void *blob, int of_size, struct lmb *lmb); /** @@ -883,7 +887,7 @@ int image_setup_libfdt(bootm_headers_t *images, void *blob, * @param images Images information * Return: 0 if ok, <0 on failure */ -int image_setup_linux(bootm_headers_t *images); +int image_setup_linux(struct bootm_headers *images); /** * bootz_setup() - Extract stat and size of a Linux xImage diff --git a/include/log.h b/include/log.h index df497bad18..8a7b961bbf 100644 --- a/include/log.h +++ b/include/log.h @@ -322,7 +322,10 @@ void __assert_fail(const char *assertion, const char *file, unsigned int line, * * or: * - * return log_msg_ret("fred failed", fred_call()); + * return log_msg_ret("get", fred_call()); + * + * It is recommended to use <= 3 characters for the name since this will only + * use 4 bytes in rodata */ #define log_ret(_ret) ({ \ int __ret = (_ret); \ diff --git a/include/malloc.h b/include/malloc.h index e8c8b254c0..161ccbd129 100644 --- a/include/malloc.h +++ b/include/malloc.h @@ -883,6 +883,18 @@ extern Void_t* sbrk(); void malloc_simple_info(void); +/** + * malloc_enable_testing() - Put malloc() into test mode + * + * This only works if UNIT_TESTING is enabled + * + * @max_allocs: return -ENOMEM after max_allocs calls to malloc() + */ +void malloc_enable_testing(int max_allocs); + +/** malloc_disable_testing() - Put malloc() into normal mode */ +void malloc_disable_testing(void); + #if CONFIG_IS_ENABLED(SYS_MALLOC_SIMPLE) #define malloc malloc_simple #define realloc realloc_simple diff --git a/include/spl.h b/include/spl.h index aac6648f94..0fc3686bbc 100644 --- a/include/spl.h +++ b/include/spl.h @@ -17,7 +17,7 @@ #include <mmc.h> struct blk_desc; -struct image_header; +struct legacy_img_hdr; /* Value in r0 indicates we booted from U-Boot */ #define UBOOT_NOT_LOADED_FROM_SPL 0x13578642 @@ -29,7 +29,7 @@ struct image_header; #define MMCSD_MODE_EMMCBOOT 3 struct blk_desc; -struct image_header; +struct legacy_img_hdr; struct spl_boot_device; /* @@ -476,7 +476,7 @@ void spl_set_header_raw_uboot(struct spl_image_info *spl_image); */ int spl_parse_image_header(struct spl_image_info *spl_image, const struct spl_boot_device *bootdev, - const struct image_header *header); + const struct legacy_img_hdr *header); void spl_board_prepare_for_linux(void); @@ -865,7 +865,7 @@ void spl_perform_fixups(struct spl_image_info *spl_image); * Returns memory area which can be populated by partial image data, * ie. uImage or fitImage header. */ -struct image_header *spl_get_load_buffer(ssize_t offset, size_t size); +struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size); void spl_save_restore_data(void); #endif diff --git a/include/tee/optee.h b/include/tee/optee.h index 5412bc7386..77729450bb 100644 --- a/include/tee/optee.h +++ b/include/tee/optee.h @@ -30,7 +30,7 @@ struct optee_header { }; static inline uint32_t -optee_image_get_entry_point(const struct image_header *hdr) +optee_image_get_entry_point(const struct legacy_img_hdr *hdr) { struct optee_header *optee_hdr = (struct optee_header *)(hdr + 1); @@ -38,7 +38,7 @@ optee_image_get_entry_point(const struct image_header *hdr) } static inline uint32_t -optee_image_get_load_addr(const struct image_header *hdr) +optee_image_get_load_addr(const struct legacy_img_hdr *hdr) { return optee_image_get_entry_point(hdr) - sizeof(struct optee_header); } diff --git a/include/test/test.h b/include/test/test.h index 2b68331b54..3bbd77c38b 100644 --- a/include/test/test.h +++ b/include/test/test.h @@ -20,6 +20,12 @@ * @testdev: Test device * @force_fail_alloc: Force all memory allocs to fail * @skip_post_probe: Skip uclass post-probe processing + * @fdt_chksum: crc8 of the device tree contents + * @fdt_copy: Copy of the device tree + * @fdt_size: Size of the device-tree copy + * @other_fdt: Buffer for the other FDT (UT_TESTF_OTHER_FDT) + * @other_fdt_size: Size of the other FDT (UT_TESTF_OTHER_FDT) + * @of_other: Live tree for the other FDT * @runs_per_test: Number of times to run each test (typically 1) * @expect_str: Temporary string used to hold expected string value * @actual_str: Temporary string used to hold actual string value @@ -33,6 +39,12 @@ struct unit_test_state { struct udevice *testdev; int force_fail_alloc; int skip_post_probe; + uint fdt_chksum; + void *fdt_copy; + uint fdt_size; + void *other_fdt; + int other_fdt_size; + struct device_node *of_other; int runs_per_test; char expect_str[512]; char actual_str[512]; @@ -48,8 +60,7 @@ enum { UT_TESTF_CONSOLE_REC = BIT(5), /* needs console recording */ /* do extra driver model init and uninit */ UT_TESTF_DM = BIT(6), - /* live or flat device tree, but not both in the same executable */ - UT_TESTF_LIVE_OR_FLAT = BIT(4), + UT_TESTF_OTHER_FDT = BIT(7), /* read in other device tree */ }; /** @@ -128,13 +139,24 @@ enum { */ struct udevice *testbus_get_clear_removed(void); -static inline void arch_reset_for_test(void) -{ #ifdef CONFIG_SANDBOX #include <asm/state.h> +#include <asm/test.h> +#endif +static inline void arch_reset_for_test(void) +{ +#ifdef CONFIG_SANDBOX state_reset_for_test(state_get_current()); #endif } +static inline int test_load_other_fdt(struct unit_test_state *uts) +{ + int ret = 0; +#ifdef CONFIG_SANDBOX + ret = sandbox_load_other_fdt(&uts->other_fdt, &uts->other_fdt_size); +#endif + return ret; +} #endif /* __TEST_TEST_H */ diff --git a/include/test/ut.h b/include/test/ut.h index f7d1d18f7c..f7217aa8ac 100644 --- a/include/test/ut.h +++ b/include/test/ut.h @@ -119,6 +119,11 @@ int ut_check_console_end(struct unit_test_state *uts); */ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); +/* Report a failure, with printf() string */ +#define ut_reportf(fmt, args...) \ + ut_failf(uts, __FILE__, __LINE__, __func__, "report", \ + fmt, ##args) + /* Assert that a condition is non-zero */ #define ut_assert(cond) \ if (!(cond)) { \ diff --git a/lib/efi_loader/efi_dt_fixup.c b/lib/efi_loader/efi_dt_fixup.c index d3923e5dba..838023c78f 100644 --- a/lib/efi_loader/efi_dt_fixup.c +++ b/lib/efi_loader/efi_dt_fixup.c @@ -145,7 +145,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 }; + struct bootm_headers img = { 0 }; EFI_ENTRY("%p, %p, %p, %d", this, dtb, buffer_size, flags); diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 96b6b71a60..64c5b3da15 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -13,7 +13,6 @@ #include <log.h> #include <malloc.h> #include <net.h> -#include <dm/of_extra.h> #include <env.h> #include <errno.h> #include <fdtdec.h> @@ -24,6 +23,8 @@ #include <serial.h> #include <asm/global_data.h> #include <asm/sections.h> +#include <dm/ofnode.h> +#include <dm/of_extra.h> #include <linux/ctype.h> #include <linux/lzo.h> #include <linux/ioport.h> @@ -1058,7 +1059,7 @@ ofnode get_next_memory_node(ofnode mem) { do { mem = ofnode_by_prop_value(mem, "device_type", "memory", 7); - } while (!ofnode_is_available(mem)); + } while (!ofnode_is_enabled(mem)); return mem; } @@ -1668,6 +1669,8 @@ int fdtdec_setup(void) ret = fdtdec_prepare_fdt(); if (!ret) ret = fdtdec_board_setup(gd->fdt_blob); + oftree_reset(); + return ret; } diff --git a/lib/of_live.c b/lib/of_live.c index 30cae9ab88..1b5964d09a 100644 --- a/lib/of_live.c +++ b/lib/of_live.c @@ -97,6 +97,10 @@ static void *unflatten_dt_node(const void *blob, void *mem, int *poffset, char *fn; fn = (char *)np + sizeof(*np); + if (new_format) { + np->name = pathp; + has_name = 1; + } np->full_name = fn; if (new_format) { /* rebuild full path for new format */ @@ -202,7 +206,8 @@ static void *unflatten_dt_node(const void *blob, void *mem, int *poffset, } if (!dryrun) { *prev_pp = NULL; - np->name = of_get_property(np, "name", NULL); + if (!has_name) + np->name = of_get_property(np, "name", NULL); np->type = of_get_property(np, "device_type", NULL); if (!np->name) diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c index 3bf4351c84..5b7046432f 100644 --- a/net/dsa-uclass.c +++ b/net/dsa-uclass.c @@ -432,7 +432,7 @@ static int dsa_post_bind(struct udevice *dev) * skip registration if port id not found or if the port * is explicitly disabled in DT */ - if (!ofnode_valid(pnode) || !ofnode_is_available(pnode)) + if (!ofnode_valid(pnode) || !ofnode_is_enabled(pnode)) continue; err = device_bind_driver_to_node(dev, DSA_PORT_CHILD_DRV_NAME, diff --git a/scripts/event_dump.py b/scripts/event_dump.py index 751f41b183..6aadddf28d 100755 --- a/scripts/event_dump.py +++ b/scripts/event_dump.py @@ -17,8 +17,10 @@ sys.path.insert(1, os.path.join(our_path, '../tools')) from binman import elf from patman import tools +# A typical symbol looks like this: +# _u_boot_list_2_evspy_info_2_EVT_MISC_INIT_F_3_sandbox_misc_init_f PREFIX = '_u_boot_list_2_evspy_info_2_' -RE_EVTYPE = re.compile('%s(.*)' % PREFIX) +RE_EVTYPE = re.compile('%s(.*)_3_.*' % PREFIX) def show_sym(fname, data, endian, evtype, sym): """Show information about an evspy entry diff --git a/test/boot/vbe_simple.c b/test/boot/vbe_simple.c index 2f6979cafc..8acd777f4c 100644 --- a/test/boot/vbe_simple.c +++ b/test/boot/vbe_simple.c @@ -74,29 +74,25 @@ static int vbe_simple_test_base(struct unit_test_state *uts) node_ofs = fdt_add_subnode(fdt_buf, node_ofs, "firmware0"); ut_assert(node_ofs > 0); - /* - * This can only work on the live tree, since the ofnode interface for - * flat tree assumes that ofnode points to the control FDT - */ - ut_assertok(unflatten_device_tree(fdt_buf, &np)); + if (of_live_active()) { + ut_assertok(unflatten_device_tree(fdt_buf, &np)); + fixup.tree = oftree_from_np(np); + } else { + fixup.tree = oftree_from_fdt(fdt_buf); + } /* * It would be better to call image_setup_libfdt() here, but that * function does not allow passing an ofnode. We can pass fdt_buf but - * when it comes to send the evenr, it creates an ofnode that uses the + * when it comes to send the event, it creates an ofnode that uses the * control FDT, since it has no way of accessing the live tree created * here. * - * Two fix this we need: - * - image_setup_libfdt() is updated to use ofnode - * - ofnode updated to support access to an FDT other than the control - * FDT. This is partially implemented with live tree, but not with - * flat tree + * Two fix this we need image_setup_libfdt() is updated to use ofnode */ - fixup.tree.np = np; ut_assertok(event_notify(EVT_FT_FIXUP, &fixup, sizeof(fixup))); - node = ofnode_path_root(fixup.tree, "/chosen/fwupd/firmware0"); + node = oftree_path(fixup.tree, "/chosen/fwupd/firmware0"); version = ofnode_read_string(node, "cur-version"); ut_assertnonnull(version); @@ -111,5 +107,4 @@ static int vbe_simple_test_base(struct unit_test_state *uts) return 0; } -BOOTSTD_TEST(vbe_simple_test_base, UT_TESTF_DM | UT_TESTF_SCAN_FDT | - UT_TESTF_LIVE_TREE); +BOOTSTD_TEST(vbe_simple_test_base, UT_TESTF_DM | UT_TESTF_SCAN_FDT); diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index f80993f892..41811ec3bb 100644 --- a/test/dm/ofnode.c +++ b/test/dm/ofnode.c @@ -1,4 +1,20 @@ // SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2022 Google LLC + * + * There are two types of tests in this file: + * - normal ones which act on the control FDT (gd->fdt_blob or gd->of_root) + * - 'other' ones which act on the 'other' FDT (other.dts) + * + * The 'other' ones have an _ot suffix. + * + * The latter are used to check behaviour with multiple device trees, + * particularly with flat tree, where a tree ID is included in ofnode as part of + * the node offset. These tests are typically just for making sure that the + * offset makes it to libfdt correctly and that the resulting return value is + * correctly turned into an ofnode. The 'other' tests do not fully check the + * behaviour of each ofnode function, since that is done by the normal ones. + */ #include <common.h> #include <dm.h> @@ -13,6 +29,68 @@ #include <test/test.h> #include <test/ut.h> +/** + * get_other_oftree() - Convert a flat tree into an oftree object + * + * @uts: Test state + * @return: oftree object for the 'other' FDT (see sandbox' other.dts) + */ +oftree get_other_oftree(struct unit_test_state *uts) +{ + oftree tree; + + if (of_live_active()) + tree = oftree_from_np(uts->of_other); + else + tree = oftree_from_fdt(uts->other_fdt); + + /* An invalid tree may cause failure or crashes */ + if (!oftree_valid(tree)) + ut_reportf("test needs the UT_TESTF_OTHER_FDT flag"); + + return tree; +} + +/** + * get_oftree() - Convert a flat tree into an oftree object + * + * @uts: Test state + * @fdt: Pointer to flat tree + * @treep: Returns the tree, on success + * Return: 0 if OK, 1 if the tree failed to unflatten, -EOVERFLOW if there are + * too many flat trees to allow another one to be registers (see + * oftree_ensure()) + */ +int get_oftree(struct unit_test_state *uts, void *fdt, oftree *treep) +{ + oftree tree; + + if (of_live_active()) { + struct device_node *root; + + ut_assertok(unflatten_device_tree(fdt, &root)); + tree = oftree_from_np(root); + } else { + tree = oftree_from_fdt(fdt); + if (!oftree_valid(tree)) + return -EOVERFLOW; + } + *treep = tree; + + return 0; +} + +/** + * free_oftree() - Free memory used by get_oftree() + * + * @tree: Tree to free + */ +void free_oftree(oftree tree) +{ + if (of_live_active()) + free(tree.np); +} + static int dm_test_ofnode_compatible(struct unit_test_state *uts) { ofnode root_node = ofnode_path("/"); @@ -22,7 +100,21 @@ static int dm_test_ofnode_compatible(struct unit_test_state *uts) return 0; } -DM_TEST(dm_test_ofnode_compatible, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +DM_TEST(dm_test_ofnode_compatible, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* check ofnode_device_is_compatible() with the 'other' FDT */ +static int dm_test_ofnode_compatible_ot(struct unit_test_state *uts) +{ + oftree otree = get_other_oftree(uts); + ofnode oroot = oftree_root(otree); + + ut_assert(ofnode_valid(oroot)); + ut_assert(ofnode_device_is_compatible(oroot, "sandbox-other")); + + return 0; +} +DM_TEST(dm_test_ofnode_compatible_ot, UT_TESTF_OTHER_FDT); static int dm_test_ofnode_get_by_phandle(struct unit_test_state *uts) { @@ -36,37 +128,76 @@ static int dm_test_ofnode_get_by_phandle(struct unit_test_state *uts) /* test unknown phandle */ ut_assert(!ofnode_valid(ofnode_get_by_phandle(0x1000000))); + ut_assert(ofnode_valid(oftree_get_by_phandle(oftree_default(), 1))); + return 0; } DM_TEST(dm_test_ofnode_get_by_phandle, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); -static int dm_test_ofnode_by_prop_value(struct unit_test_state *uts) +static int dm_test_ofnode_get_by_phandle_ot(struct unit_test_state *uts) { - const char propname[] = "compatible"; - const char propval[] = "denx,u-boot-fdt-test"; + oftree otree = get_other_oftree(uts); + ofnode node; + + ut_assert(ofnode_valid(oftree_get_by_phandle(oftree_default(), 1))); + node = oftree_get_by_phandle(otree, 1); + ut_assert(ofnode_valid(node)); + ut_asserteq_str("target", ofnode_get_name(node)); + + return 0; +} +DM_TEST(dm_test_ofnode_get_by_phandle_ot, UT_TESTF_OTHER_FDT); + +static int check_prop_values(struct unit_test_state *uts, ofnode start, + const char *propname, const char *propval, + int expect_count) +{ + int proplen = strlen(propval) + 1; const char *str; - ofnode node = ofnode_null(); + ofnode node; + int count; /* Find first matching node, there should be at least one */ - node = ofnode_by_prop_value(node, propname, propval, sizeof(propval)); + node = ofnode_by_prop_value(start, propname, propval, proplen); ut_assert(ofnode_valid(node)); str = ofnode_read_string(node, propname); ut_assert(str && !strcmp(str, propval)); /* Find the rest of the matching nodes */ + count = 1; while (true) { - node = ofnode_by_prop_value(node, propname, propval, - sizeof(propval)); + node = ofnode_by_prop_value(node, propname, propval, proplen); if (!ofnode_valid(node)) break; str = ofnode_read_string(node, propname); - ut_assert(str && !strcmp(str, propval)); + ut_asserteq_str(propval, str); + count++; } + ut_asserteq(expect_count, count); + + return 0; +} + +static int dm_test_ofnode_by_prop_value(struct unit_test_state *uts) +{ + ut_assertok(check_prop_values(uts, ofnode_null(), "compatible", + "denx,u-boot-fdt-test", 11)); return 0; } DM_TEST(dm_test_ofnode_by_prop_value, UT_TESTF_SCAN_FDT); +static int dm_test_ofnode_by_prop_value_ot(struct unit_test_state *uts) +{ + oftree otree = get_other_oftree(uts); + + ut_assertok(check_prop_values(uts, oftree_root(otree), "str-prop", + "other", 2)); + + return 0; +} +DM_TEST(dm_test_ofnode_by_prop_value_ot, UT_TESTF_OTHER_FDT); + static int dm_test_ofnode_fmap(struct unit_test_state *uts) { struct fmap_entry entry; @@ -108,6 +239,25 @@ static int dm_test_ofnode_read(struct unit_test_state *uts) } DM_TEST(dm_test_ofnode_read, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +static int dm_test_ofnode_read_ot(struct unit_test_state *uts) +{ + oftree otree = get_other_oftree(uts); + const char *val; + ofnode node; + int size; + + node = oftree_path(otree, "/node/subnode"); + ut_assert(ofnode_valid(node)); + + val = ofnode_read_prop(node, "str-prop", &size); + ut_assertnonnull(val); + ut_asserteq_str("other", val); + ut_asserteq(6, size); + + return 0; +} +DM_TEST(dm_test_ofnode_read_ot, UT_TESTF_OTHER_FDT); + static int dm_test_ofnode_phandle(struct unit_test_state *uts) { struct ofnode_phandle_args args; @@ -183,6 +333,34 @@ static int dm_test_ofnode_phandle(struct unit_test_state *uts) } DM_TEST(dm_test_ofnode_phandle, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +static int dm_test_ofnode_phandle_ot(struct unit_test_state *uts) +{ + oftree otree = get_other_oftree(uts); + struct ofnode_phandle_args args; + ofnode node; + int ret; + + node = oftree_path(otree, "/node"); + + /* Test ofnode_count_phandle_with_args with cell name */ + ret = ofnode_count_phandle_with_args(node, "missing", "#gpio-cells", 0); + ut_asserteq(-ENOENT, ret); + ret = ofnode_count_phandle_with_args(node, "target", "#invalid", 0); + ut_asserteq(-EINVAL, ret); + ret = ofnode_count_phandle_with_args(node, "target", "#gpio-cells", 0); + ut_asserteq(1, ret); + + ret = ofnode_parse_phandle_with_args(node, "target", "#gpio-cells", 0, + 0, &args); + ut_assertok(ret); + ut_asserteq(2, args.args_count); + ut_asserteq(3, args.args[0]); + ut_asserteq(4, args.args[1]); + + return 0; +} +DM_TEST(dm_test_ofnode_phandle_ot, UT_TESTF_OTHER_FDT); + static int dm_test_ofnode_read_chosen(struct unit_test_state *uts) { const char *str; @@ -255,6 +433,27 @@ static int dm_test_ofnode_get_child_count(struct unit_test_state *uts) DM_TEST(dm_test_ofnode_get_child_count, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +static int dm_test_ofnode_get_child_count_ot(struct unit_test_state *uts) +{ + oftree otree = get_other_oftree(uts); + ofnode node, child_node; + u32 val; + + node = oftree_path(otree, "/node"); + ut_assert(ofnode_valid(node)); + + val = ofnode_get_child_count(node); + ut_asserteq(2, val); + + child_node = ofnode_first_subnode(node); + ut_assert(ofnode_valid(child_node)); + val = ofnode_get_child_count(child_node); + ut_asserteq(0, val); + + return 0; +} +DM_TEST(dm_test_ofnode_get_child_count_ot, UT_TESTF_OTHER_FDT); + static int dm_test_ofnode_is_enabled(struct unit_test_state *uts) { ofnode root_node = ofnode_path("/"); @@ -267,6 +466,19 @@ static int dm_test_ofnode_is_enabled(struct unit_test_state *uts) } DM_TEST(dm_test_ofnode_is_enabled, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +static int dm_test_ofnode_is_enabled_ot(struct unit_test_state *uts) +{ + oftree otree = get_other_oftree(uts); + ofnode root_node = oftree_root(otree); + ofnode node = oftree_path(otree, "/target"); + + ut_assert(ofnode_is_enabled(root_node)); + ut_assert(!ofnode_is_enabled(node)); + + return 0; +} +DM_TEST(dm_test_ofnode_is_enabled_ot, UT_TESTF_OTHER_FDT); + static int dm_test_ofnode_get_reg(struct unit_test_state *uts) { ofnode node; @@ -303,27 +515,59 @@ static int dm_test_ofnode_get_reg(struct unit_test_state *uts) } DM_TEST(dm_test_ofnode_get_reg, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +static int dm_test_ofnode_get_reg_ot(struct unit_test_state *uts) +{ + oftree otree = get_other_oftree(uts); + ofnode node = oftree_path(otree, "/target"); + fdt_addr_t addr; + + addr = ofnode_get_addr(node); + ut_asserteq(0x8000, addr); + + return 0; +} +DM_TEST(dm_test_ofnode_get_reg_ot, UT_TESTF_OTHER_FDT); + static int dm_test_ofnode_get_path(struct unit_test_state *uts) { const char *path = "/translation-test@8000/noxlatebus@3,300/dev@42"; char buf[64]; ofnode node; - int res; node = ofnode_path(path); ut_assert(ofnode_valid(node)); - res = ofnode_get_path(node, buf, 64); - ut_asserteq(0, res); + ut_assertok(ofnode_get_path(node, buf, sizeof(buf))); ut_asserteq_str(path, buf); - res = ofnode_get_path(node, buf, 32); - ut_asserteq(-ENOSPC, res); + ut_asserteq(-ENOSPC, ofnode_get_path(node, buf, 32)); + + ut_assertok(ofnode_get_path(ofnode_root(), buf, 32)); + ut_asserteq_str("/", buf); return 0; } DM_TEST(dm_test_ofnode_get_path, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +static int dm_test_ofnode_get_path_ot(struct unit_test_state *uts) +{ + oftree otree = get_other_oftree(uts); + const char *path = "/node/subnode"; + ofnode node = oftree_path(otree, path); + char buf[64]; + + ut_assert(ofnode_valid(node)); + + ut_assertok(ofnode_get_path(node, buf, sizeof(buf))); + ut_asserteq_str(path, buf); + + ut_assertok(ofnode_get_path(oftree_root(otree), buf, 32)); + ut_asserteq_str("/", buf); + + return 0; +} +DM_TEST(dm_test_ofnode_get_path_ot, UT_TESTF_OTHER_FDT); + static int dm_test_ofnode_conf(struct unit_test_state *uts) { ut_assert(!ofnode_conf_read_bool("missing")); @@ -483,13 +727,17 @@ DM_TEST(dm_test_ofnode_get_phy, 0); * @uts: Test state * @fdt: Place to write FDT * @size: Maximum size of space for fdt + * @id: id value to add to the tree ('id' property in root node) */ -static int make_ofnode_fdt(struct unit_test_state *uts, void *fdt, int size) +static int make_ofnode_fdt(struct unit_test_state *uts, void *fdt, int size, + int id) { ut_assertok(fdt_create(fdt, size)); ut_assertok(fdt_finish_reservemap(fdt)); ut_assert(fdt_begin_node(fdt, "") >= 0); + ut_assertok(fdt_property_u32(fdt, "id", id)); + ut_assert(fdt_begin_node(fdt, "aliases") >= 0); ut_assertok(fdt_property_string(fdt, "mmc0", "/new-mmc")); ut_assertok(fdt_end_node(fdt)); @@ -505,37 +753,41 @@ static int make_ofnode_fdt(struct unit_test_state *uts, void *fdt, int size) static int dm_test_ofnode_root(struct unit_test_state *uts) { - struct device_node *root = NULL; char fdt[256]; oftree tree; ofnode node; + int ret; /* Check that aliases work on the control FDT */ node = ofnode_get_aliases_node("ethernet3"); ut_assert(ofnode_valid(node)); ut_asserteq_str("sbe5", ofnode_get_name(node)); - ut_assertok(make_ofnode_fdt(uts, fdt, sizeof(fdt))); - if (of_live_active()) { - ut_assertok(unflatten_device_tree(fdt, &root)); - tree.np = root; - } else { - tree.fdt = fdt; - } + ut_assert(!oftree_valid(oftree_null())); + + ut_assertok(make_ofnode_fdt(uts, fdt, sizeof(fdt), 0)); + ret = get_oftree(uts, fdt, &tree); + + /* skip the rest of this test if multiple FDTs are not supported */ + if (ret == -EOVERFLOW) + return 0; + + ut_assertok(ret); + ut_assert(oftree_valid(tree)); /* Make sure they don't work on this new tree */ - node = ofnode_path_root(tree, "mmc0"); + node = oftree_path(tree, "mmc0"); ut_assert(!ofnode_valid(node)); /* It should appear in the new tree */ - node = ofnode_path_root(tree, "/new-mmc"); + node = oftree_path(tree, "/new-mmc"); ut_assert(ofnode_valid(node)); /* ...and not in the control FDT */ - node = ofnode_path_root(oftree_default(), "/new-mmc"); + node = oftree_path(oftree_default(), "/new-mmc"); ut_assert(!ofnode_valid(node)); - free(root); + free_oftree(tree); return 0; } @@ -570,7 +822,8 @@ static int dm_test_ofnode_livetree_writing(struct unit_test_state *uts) ut_asserteq_64(FDT_ADDR_T_NONE, dev_read_addr(dev)); /* reg = 0x42, size = 0x100 */ ut_assertok(ofnode_write_prop(node, "reg", - "\x00\x00\x00\x42\x00\x00\x01\x00", 8)); + "\x00\x00\x00\x42\x00\x00\x01\x00", 8, + false)); ut_asserteq(0x42, dev_read_addr(dev)); /* Test disabling devices */ @@ -584,11 +837,71 @@ static int dm_test_ofnode_livetree_writing(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_ofnode_livetree_writing, - UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_LIVE_OR_FLAT); + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int check_write_prop(struct unit_test_state *uts, ofnode node) +{ + char prop[] = "middle-name"; + char name[10]; + int len; + + strcpy(name, "cecil"); + len = strlen(name) + 1; + ut_assertok(ofnode_write_prop(node, prop, name, len, false)); + ut_asserteq_str(name, ofnode_read_string(node, prop)); + + /* change the underlying value, this should mess up the live tree */ + strcpy(name, "tony"); + if (of_live_active()) { + ut_asserteq_str(name, ofnode_read_string(node, prop)); + } else { + ut_asserteq_str("cecil", ofnode_read_string(node, prop)); + } + + /* try again, this time copying the property */ + strcpy(name, "mary"); + ut_assertok(ofnode_write_prop(node, prop, name, len, true)); + ut_asserteq_str(name, ofnode_read_string(node, prop)); + strcpy(name, "leah"); + + /* both flattree and livetree behave the same */ + ut_asserteq_str("mary", ofnode_read_string(node, prop)); + + return 0; +} + +/* writing the tree with and without copying the property */ +static int dm_test_ofnode_write_copy(struct unit_test_state *uts) +{ + ofnode node; + + node = ofnode_path("/a-test"); + ut_assertok(check_write_prop(uts, node)); + + return 0; +} +DM_TEST(dm_test_ofnode_write_copy, UT_TESTF_SCAN_FDT); + +static int dm_test_ofnode_write_copy_ot(struct unit_test_state *uts) +{ + oftree otree = get_other_oftree(uts); + ofnode node, check_node; + + node = oftree_path(otree, "/node"); + ut_assertok(check_write_prop(uts, node)); + + /* make sure the control FDT is not touched */ + check_node = ofnode_path("/node"); + ut_assertnull(ofnode_read_string(check_node, "middle-name")); + + return 0; +} +DM_TEST(dm_test_ofnode_write_copy_ot, UT_TESTF_OTHER_FDT); static int dm_test_ofnode_u32(struct unit_test_state *uts) { ofnode node; + u32 val; node = ofnode_path("/lcd"); ut_assert(ofnode_valid(node)); @@ -597,7 +910,328 @@ static int dm_test_ofnode_u32(struct unit_test_state *uts) ut_asserteq(1367, ofnode_read_u32_default(node, "xres", 123)); ut_assertok(ofnode_write_u32(node, "xres", 1366)); + node = ofnode_path("/backlight"); + ut_assertok(ofnode_read_u32_index(node, "brightness-levels", 0, &val)); + ut_asserteq(0, val); + ut_assertok(ofnode_read_u32_index(node, "brightness-levels", 1, &val)); + ut_asserteq(16, val); + ut_assertok(ofnode_read_u32_index(node, "brightness-levels", 8, &val)); + ut_asserteq(255, val); + ut_asserteq(-EOVERFLOW, + ofnode_read_u32_index(node, "brightness-levels", 9, &val)); + ut_asserteq(-EINVAL, ofnode_read_u32_index(node, "missing", 0, &val)); + + return 0; +} +DM_TEST(dm_test_ofnode_u32, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_ofnode_u32_array(struct unit_test_state *uts) +{ + ofnode node; + u32 val[10]; + + node = ofnode_path("/a-test"); + ut_assert(ofnode_valid(node)); + ut_assertok(ofnode_read_u32_array(node, "int-value", val, 1)); + ut_asserteq(-EINVAL, ofnode_read_u32_array(node, "missing", val, 1)); + ut_asserteq(-EOVERFLOW, ofnode_read_u32_array(node, "bool-value", val, + 1)); + + memset(val, '\0', sizeof(val)); + ut_assertok(ofnode_read_u32_array(node, "int-array", val + 1, 3)); + ut_asserteq(0, val[0]); + ut_asserteq(5678, val[1]); + ut_asserteq(9123, val[2]); + ut_asserteq(4567, val[3]); + ut_asserteq(0, val[4]); + ut_asserteq(-EOVERFLOW, ofnode_read_u32_array(node, "int-array", val, + 4)); + + return 0; +} +DM_TEST(dm_test_ofnode_u32_array, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_ofnode_u64(struct unit_test_state *uts) +{ + ofnode node; + u64 val; + + node = ofnode_path("/a-test"); + ut_assert(ofnode_valid(node)); + ut_assertok(ofnode_read_u64(node, "int64-value", &val)); + ut_asserteq_64(0x1111222233334444, val); + ut_asserteq(-EINVAL, ofnode_read_u64(node, "missing", &val)); + + return 0; +} +DM_TEST(dm_test_ofnode_u64, UT_TESTF_SCAN_FDT); + +static int dm_test_ofnode_add_subnode(struct unit_test_state *uts) +{ + ofnode node, check, subnode; + char buf[128]; + + node = ofnode_path("/lcd"); + ut_assert(ofnode_valid(node)); + ut_assertok(ofnode_add_subnode(node, "edmund", &subnode)); + check = ofnode_path("/lcd/edmund"); + ut_asserteq(subnode.of_offset, check.of_offset); + ut_assertok(ofnode_get_path(subnode, buf, sizeof(buf))); + ut_asserteq_str("/lcd/edmund", buf); + + if (of_live_active()) { + struct device_node *child; + + ut_assertok(of_add_subnode((void *)ofnode_to_np(node), "edmund", + 2, &child)); + ut_asserteq_str("ed", child->name); + ut_asserteq_str("/lcd/ed", child->full_name); + check = ofnode_path("/lcd/ed"); + ut_asserteq_ptr(child, check.np); + ut_assertok(ofnode_get_path(np_to_ofnode(child), buf, + sizeof(buf))); + ut_asserteq_str("/lcd/ed", buf); + } + + /* An existing node should be returned with -EEXIST */ + ut_asserteq(-EEXIST, ofnode_add_subnode(node, "edmund", &check)); + ut_asserteq(subnode.of_offset, check.of_offset); + + /* add a root node */ + node = ofnode_path("/"); + ut_assert(ofnode_valid(node)); + ut_assertok(ofnode_add_subnode(node, "lcd2", &subnode)); + check = ofnode_path("/lcd2"); + ut_asserteq(subnode.of_offset, check.of_offset); + ut_assertok(ofnode_get_path(subnode, buf, sizeof(buf))); + ut_asserteq_str("/lcd2", buf); + + if (of_live_active()) { + ulong start; + int i; + + /* + * Make sure each of the three malloc()checks in + * of_add_subnode() work + */ + for (i = 0; i < 3; i++) { + malloc_enable_testing(i); + start = ut_check_free(); + ut_asserteq(-ENOMEM, ofnode_add_subnode(node, "anthony", + &check)); + ut_assertok(ut_check_delta(start)); + } + + /* This should pass since we allow 3 allocations */ + malloc_enable_testing(3); + ut_assertok(ofnode_add_subnode(node, "anthony", &check)); + malloc_disable_testing(); + } + + /* write to the empty node */ + ut_assertok(ofnode_write_string(subnode, "example", "text")); + + return 0; +} +DM_TEST(dm_test_ofnode_add_subnode, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_ofnode_for_each_prop(struct unit_test_state *uts) +{ + ofnode node, subnode; + struct ofprop prop; + int count; + + node = ofnode_path("/buttons"); + count = 0; + + /* we expect "compatible" for each node */ + ofnode_for_each_prop(prop, node) + count++; + ut_asserteq(1, count); + + /* there are two nodes, each with 2 properties */ + ofnode_for_each_subnode(subnode, node) + ofnode_for_each_prop(prop, subnode) + count++; + ut_asserteq(5, count); + + return 0; +} +DM_TEST(dm_test_ofnode_for_each_prop, UT_TESTF_SCAN_FDT); + +static int dm_test_ofnode_by_compatible(struct unit_test_state *uts) +{ + const char *compat = "denx,u-boot-fdt-test"; + ofnode node; + int count; + + count = 0; + for (node = ofnode_null(); + node = ofnode_by_compatible(node, compat), ofnode_valid(node);) + count++; + ut_asserteq(11, count); + + return 0; +} +DM_TEST(dm_test_ofnode_by_compatible, UT_TESTF_SCAN_FDT); + +static int dm_test_ofnode_by_compatible_ot(struct unit_test_state *uts) +{ + const char *compat = "sandbox-other2"; + oftree otree = get_other_oftree(uts); + ofnode node; + int count; + + count = 0; + for (node = oftree_root(otree); + node = ofnode_by_compatible(node, compat), ofnode_valid(node);) + count++; + ut_asserteq(2, count); + + return 0; +} +DM_TEST(dm_test_ofnode_by_compatible_ot, UT_TESTF_OTHER_FDT); + +static int dm_test_ofnode_find_subnode(struct unit_test_state *uts) +{ + ofnode node, subnode; + + node = ofnode_path("/buttons"); + + subnode = ofnode_find_subnode(node, "btn1"); + ut_assert(ofnode_valid(subnode)); + ut_asserteq_str("btn1", ofnode_get_name(subnode)); + + subnode = ofnode_find_subnode(node, "btn"); + ut_assert(!ofnode_valid(subnode)); + + return 0; +} +DM_TEST(dm_test_ofnode_find_subnode, UT_TESTF_SCAN_FDT); + +static int dm_test_ofnode_find_subnode_ot(struct unit_test_state *uts) +{ + oftree otree = get_other_oftree(uts); + ofnode node, subnode; + + node = oftree_path(otree, "/node"); + + subnode = ofnode_find_subnode(node, "subnode"); + ut_assert(ofnode_valid(subnode)); + ut_asserteq_str("subnode", ofnode_get_name(subnode)); + + subnode = ofnode_find_subnode(node, "btn"); + ut_assert(!ofnode_valid(subnode)); + + return 0; +} +DM_TEST(dm_test_ofnode_find_subnode_ot, UT_TESTF_OTHER_FDT); + +static int dm_test_ofnode_get_name(struct unit_test_state *uts) +{ + ofnode node; + + node = ofnode_path("/buttons"); + ut_assert(ofnode_valid(node)); + ut_asserteq_str("buttons", ofnode_get_name(node)); + ut_asserteq_str("", ofnode_get_name(ofnode_root())); + + return 0; +} +DM_TEST(dm_test_ofnode_get_name, UT_TESTF_SCAN_FDT); + +/* try to access more FDTs than is supported */ +static int dm_test_ofnode_too_many(struct unit_test_state *uts) +{ + const int max_trees = CONFIG_IS_ENABLED(OFNODE_MULTI_TREE, + (CONFIG_OFNODE_MULTI_TREE_MAX), (1)); + const int fdt_size = 256; + const int num_trees = max_trees + 1; + char fdt[num_trees][fdt_size]; + int i; + + for (i = 0; i < num_trees; i++) { + oftree tree; + int ret; + + ut_assertok(make_ofnode_fdt(uts, fdt[i], fdt_size, i)); + ret = get_oftree(uts, fdt[i], &tree); + + /* + * With flat tree we have the control FDT using one slot. Live + * tree has no limit since it uses pointers, not integer tree + * IDs + */ + if (of_live_active() || i < max_trees - 1) { + ut_assertok(ret); + } else { + /* + * tree should be invalid when we try to register too + * many trees + */ + ut_asserteq(-EOVERFLOW, ret); + } + } + + return 0; +} +DM_TEST(dm_test_ofnode_too_many, UT_TESTF_SCAN_FDT); + +static int check_copy_props(struct unit_test_state *uts, ofnode src, + ofnode dst) +{ + u32 reg[2], val; + + ut_assertok(ofnode_copy_props(src, dst)); + + ut_assertok(ofnode_read_u32(dst, "ping-expect", &val)); + ut_asserteq(3, val); + + ut_asserteq_str("denx,u-boot-fdt-test", + ofnode_read_string(dst, "compatible")); + + /* check that a property with the same name is overwritten */ + ut_assertok(ofnode_read_u32_array(dst, "reg", reg, ARRAY_SIZE(reg))); + ut_asserteq(3, reg[0]); + ut_asserteq(1, reg[1]); + + /* reset the compatible so the live tree does not change */ + ut_assertok(ofnode_write_string(dst, "compatible", "nothing")); + + return 0; +} + +static int dm_test_ofnode_copy_props(struct unit_test_state *uts) +{ + ofnode src, dst; + + /* + * These nodes are chosen so that the src node is before the destination + * node in the tree. This doesn't matter with livetree, but with + * flattree any attempt to insert a property earlier in the tree will + * mess up the offsets after it. + */ + src = ofnode_path("/b-test"); + dst = ofnode_path("/some-bus"); + + ut_assertok(check_copy_props(uts, src, dst)); + + /* check a property that is in the destination already */ + ut_asserteq_str("mux0", ofnode_read_string(dst, "mux-control-names")); + + return 0; +} +DM_TEST(dm_test_ofnode_copy_props, UT_TESTF_SCAN_FDT); + +static int dm_test_ofnode_copy_props_ot(struct unit_test_state *uts) +{ + ofnode src, dst; + oftree otree = get_other_oftree(uts); + + src = ofnode_path("/b-test"); + dst = oftree_path(otree, "/node/subnode2"); + ut_assertok(check_copy_props(uts, src, dst)); + return 0; } -DM_TEST(dm_test_ofnode_u32, - UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT | UT_TESTF_LIVE_OR_FLAT); +DM_TEST(dm_test_ofnode_copy_props_ot, UT_TESTF_SCAN_FDT | UT_TESTF_OTHER_FDT); diff --git a/test/dm/ofread.c b/test/dm/ofread.c index 8c7dd82513..3523860d2b 100644 --- a/test/dm/ofread.c +++ b/test/dm/ofread.c @@ -5,7 +5,7 @@ #include <dm/test.h> #include <test/ut.h> -static int dm_test_ofnode_get_property_by_prop(struct unit_test_state *uts) +static int dm_test_ofprop_get_property(struct unit_test_state *uts) { ofnode node; struct ofprop prop; @@ -14,10 +14,10 @@ static int dm_test_ofnode_get_property_by_prop(struct unit_test_state *uts) int res, len, count = 0; node = ofnode_path("/cros-ec/flash"); - for (res = ofnode_get_first_property(node, &prop); + for (res = ofnode_first_property(node, &prop); !res; - res = ofnode_get_next_property(&prop)) { - value = ofnode_get_property_by_prop(&prop, &propname, &len); + res = ofnode_next_property(&prop)) { + value = ofprop_get_property(&prop, &propname, &len); ut_assertnonnull(value); switch (count) { case 0: @@ -46,5 +46,4 @@ static int dm_test_ofnode_get_property_by_prop(struct unit_test_state *uts) return 0; } -DM_TEST(dm_test_ofnode_get_property_by_prop, - UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); +DM_TEST(dm_test_ofprop_get_property, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/test/image/spl_load.c b/test/image/spl_load.c index df389e26f9..4e27ff460a 100644 --- a/test/image/spl_load.c +++ b/test/image/spl_load.c @@ -49,7 +49,7 @@ int board_fit_config_name_match(const char *name) return 0; } -struct image_header *spl_get_load_buffer(ssize_t offset, size_t size) +struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size) { return map_sysmem(0x100000, 0); } @@ -57,7 +57,7 @@ struct image_header *spl_get_load_buffer(ssize_t offset, size_t size) static int spl_test_load(struct unit_test_state *uts) { struct spl_image_info image; - struct image_header *header; + struct legacy_img_hdr *header; struct text_ctx text_ctx; struct spl_load_info load; char fname[256]; diff --git a/test/test-main.c b/test/test-main.c index ae34002a3d..d74df297c4 100644 --- a/test/test-main.c +++ b/test/test-main.c @@ -9,14 +9,53 @@ #include <cyclic.h> #include <dm.h> #include <event.h> +#include <of_live.h> +#include <os.h> +#include <dm/ofnode.h> #include <dm/root.h> #include <dm/test.h> #include <dm/uclass-internal.h> #include <test/test.h> #include <test/ut.h> +#include <u-boot/crc.h> DECLARE_GLOBAL_DATA_PTR; +/** + * enum fdtchk_t - what to do with the device tree (gd->fdt_blob) + * + * This affects what happens with the device tree before and after a test + * + * @FDTCHK_NONE: Do nothing + * @FDTCHK_CHECKSUM: Take a checksum of the FDT before the test runs and + * compare it afterwards to detect any changes + * @FDTCHK_COPY: Make a copy of the FDT and restore it afterwards + */ +enum fdtchk_t { + FDTCHK_NONE, + FDTCHK_CHECKSUM, + FDTCHK_COPY, +}; + +/** + * fdt_action() - get the required action for the FDT + * + * @return the action that should be taken for this build + */ +static enum fdtchk_t fdt_action(void) +{ + /* Do a copy for sandbox (but only the U-Boot build, not SPL) */ + if (CONFIG_IS_ENABLED(SANDBOX)) + return FDTCHK_COPY; + + /* For sandbox SPL builds, do nothing */ + if (IS_ENABLED(CONFIG_SANDBOX)) + return FDTCHK_NONE; + + /* For all other boards, do a checksum */ + return FDTCHK_CHECKSUM; +} + /* This is valid when a test is running, NULL otherwise */ static struct unit_test_state *cur_test_state; @@ -42,17 +81,26 @@ static int dm_test_pre_run(struct unit_test_state *uts) { bool of_live = uts->of_live; + if (of_live && (gd->flags & GD_FLG_FDT_CHANGED)) { + printf("Cannot run live tree test as device tree changed\n"); + return -EFAULT; + } uts->root = NULL; uts->testdev = NULL; uts->force_fail_alloc = false; uts->skip_post_probe = false; + if (fdt_action() == FDTCHK_CHECKSUM) + uts->fdt_chksum = crc8(0, gd->fdt_blob, + fdt_totalsize(gd->fdt_blob)); gd->dm_root = NULL; + malloc_disable_testing(); if (CONFIG_IS_ENABLED(UT_DM) && !CONFIG_IS_ENABLED(OF_PLATDATA)) memset(dm_testdrv_op_count, '\0', sizeof(dm_testdrv_op_count)); arch_reset_for_test(); /* Determine whether to make the live tree available */ gd_set_of_root(of_live ? uts->of_root : NULL); + oftree_reset(); ut_assertok(dm_init(of_live)); uts->root = dm_root(); @@ -63,6 +111,33 @@ static int dm_test_post_run(struct unit_test_state *uts) { int id; + if (gd->fdt_blob) { + switch (fdt_action()) { + case FDTCHK_COPY: + memcpy((void *)gd->fdt_blob, uts->fdt_copy, uts->fdt_size); + break; + case FDTCHK_CHECKSUM: { + uint chksum; + + chksum = crc8(0, gd->fdt_blob, fdt_totalsize(gd->fdt_blob)); + if (chksum != uts->fdt_chksum) { + /* + * We cannot run any more tests that need the + * live tree, since its strings point into the + * flat tree, which has changed. This likely + * means that at least some of the pointers from + * the live tree point to different things + */ + printf("Device tree changed: cannot run live tree tests\n"); + gd->flags |= GD_FLG_FDT_CHANGED; + } + break; + } + case FDTCHK_NONE: + break; + } + } + /* * With of-platdata-inst the uclasses are created at build time. If we * destroy them we cannot get them back since uclass_add() is not @@ -242,6 +317,20 @@ static int test_pre_run(struct unit_test_state *uts, struct unit_test *test) (test->flags & UT_TESTF_SCAN_FDT)) ut_assertok(dm_extended_scan(false)); + if (IS_ENABLED(CONFIG_SANDBOX) && (test->flags & UT_TESTF_OTHER_FDT)) { + /* make sure the other FDT is available */ + ut_assertok(test_load_other_fdt(uts)); + + /* + * create a new live tree with it for every test, in case a + * test modifies the tree + */ + if (of_live_active()) { + ut_assertok(unflatten_device_tree(uts->other_fdt, + &uts->of_other)); + } + } + if (test->flags & UT_TESTF_CONSOLE_REC) { int ret = console_record_reset_enable(); @@ -270,6 +359,9 @@ static int test_post_run(struct unit_test_state *uts, struct unit_test *test) ut_assertok(cyclic_uninit()); ut_assertok(event_uninit()); + free(uts->of_other); + uts->of_other = NULL; + return 0; } @@ -340,11 +432,13 @@ static int ut_run_test_live_flat(struct unit_test_state *uts, { int runs; + if ((test->flags & UT_TESTF_OTHER_FDT) && !IS_ENABLED(CONFIG_SANDBOX)) + return -EAGAIN; + /* Run with the live tree if possible */ runs = 0; if (CONFIG_IS_ENABLED(OF_LIVE)) { - if (!(test->flags & - (UT_TESTF_FLAT_TREE | UT_TESTF_LIVE_OR_FLAT))) { + if (!(test->flags & UT_TESTF_FLAT_TREE)) { uts->of_live = true; ut_assertok(ut_run_test(uts, test, test->name)); runs++; @@ -352,11 +446,22 @@ static int ut_run_test_live_flat(struct unit_test_state *uts, } /* - * Run with the flat tree if we couldn't run it with live tree, - * or it is a core test. + * Run with the flat tree if: + * - it is not marked for live tree only + * - it doesn't require the 'other' FDT when OFNODE_MULTI_TREE_MAX is + * not enabled (since flat tree can only support a single FDT in that + * case + * - we couldn't run it with live tree, + * - it is a core test (dm tests except video) + * - the FDT is still valid and has not been updated by an earlier test + * (for sandbox we handle this by copying the tree, but not for other + * boards) */ if (!(test->flags & UT_TESTF_LIVE_TREE) && - (!runs || ut_test_run_on_flattree(test))) { + (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) || + !(test->flags & UT_TESTF_OTHER_FDT)) && + (!runs || ut_test_run_on_flattree(test)) && + !(gd->flags & GD_FLG_FDT_CHANGED)) { uts->of_live = false; ut_assertok(ut_run_test(uts, test, test->name)); runs++; @@ -443,8 +548,25 @@ int ut_run_list(const char *category, const char *prefix, uts.of_root = gd_of_root(); uts.runs_per_test = runs_per_test; + if (fdt_action() == FDTCHK_COPY && gd->fdt_blob) { + uts.fdt_size = fdt_totalsize(gd->fdt_blob); + uts.fdt_copy = os_malloc(uts.fdt_size); + if (!uts.fdt_copy) { + printf("Out of memory for device tree copy\n"); + return -ENOMEM; + } + memcpy(uts.fdt_copy, gd->fdt_blob, uts.fdt_size); + } ret = ut_run_tests(&uts, prefix, tests, count, select_name); + /* Best efforts only...ignore errors */ + if (has_dm_tests) + dm_test_restore(uts.of_root); + if (IS_ENABLED(CONFIG_SANDBOX)) { + os_free(uts.fdt_copy); + os_free(uts.other_fdt); + } + if (ret == -ENOENT) printf("Test '%s' not found\n", select_name); else diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index ecb3595603..261107b335 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -5782,7 +5782,7 @@ fdt fdtmap Extract the devicetree blob from the fdtmap # Check that the data appears in the file somewhere self.assertIn(U_BOOT_SPL_DATA, data) - # Get struct image_header -> ih_name + # Get struct legacy_img_hdr -> ih_name name = data[0x20:0x40] # Build the filename that we expect to be placed in there, by virtue of @@ -5799,7 +5799,7 @@ fdt fdtmap Extract the devicetree blob from the fdtmap # Check that the data appears in the file somewhere self.assertIn(U_BOOT_SPL_DATA, data) - # Get struct image_header -> ih_name + # Get struct legacy_img_hdr -> ih_name name = data[0x20:0x40] # Build the filename that we expect to be placed in there, by virtue of diff --git a/tools/default_image.c b/tools/default_image.c index e164c0c27d..4a067e6586 100644 --- a/tools/default_image.c +++ b/tools/default_image.c @@ -22,7 +22,7 @@ #include <u-boot/crc.h> #include <imximage.h> -static image_header_t header; +static struct legacy_img_hdr header; static int image_check_image_types(uint8_t type) { @@ -46,15 +46,15 @@ static int image_verify_header(unsigned char *ptr, int image_size, uint32_t len; const unsigned char *data; uint32_t checksum; - image_header_t header; - image_header_t *hdr = &header; + struct legacy_img_hdr header; + struct legacy_img_hdr *hdr = &header; /* * create copy of header so that we can blank out the * checksum field for checking - this can't be done * on the PROT_READ mapped data. */ - memcpy(hdr, ptr, sizeof(image_header_t)); + memcpy(hdr, ptr, sizeof(struct legacy_img_hdr)); if (be32_to_cpu(hdr->ih_magic) != IH_MAGIC) { debug("%s: Bad Magic Number: \"%s\" is no valid image\n", @@ -63,7 +63,7 @@ static int image_verify_header(unsigned char *ptr, int image_size, } data = (const unsigned char *)hdr; - len = sizeof(image_header_t); + len = sizeof(struct legacy_img_hdr); checksum = be32_to_cpu(hdr->ih_hcrc); hdr->ih_hcrc = cpu_to_be32(0); /* clear for re-calculation */ @@ -74,8 +74,8 @@ static int image_verify_header(unsigned char *ptr, int image_size, return -FDT_ERR_BADSTATE; } - data = (const unsigned char *)ptr + sizeof(image_header_t); - len = image_size - sizeof(image_header_t) ; + data = (const unsigned char *)ptr + sizeof(struct legacy_img_hdr); + len = image_size - sizeof(struct legacy_img_hdr); checksum = be32_to_cpu(hdr->ih_dcrc); if (crc32(0, data, len) != checksum) { @@ -94,13 +94,12 @@ static void image_set_header(void *ptr, struct stat *sbuf, int ifd, uint32_t imagesize; uint32_t ep; uint32_t addr; - - image_header_t * hdr = (image_header_t *)ptr; + struct legacy_img_hdr *hdr = (struct legacy_img_hdr *)ptr; checksum = crc32(0, (const unsigned char *)(ptr + - sizeof(image_header_t)), - sbuf->st_size - sizeof(image_header_t)); + sizeof(struct legacy_img_hdr)), + sbuf->st_size - sizeof(struct legacy_img_hdr)); time = imagetool_get_source_date(params->cmdname, sbuf->st_mtime); ep = params->ep; @@ -108,11 +107,11 @@ static void image_set_header(void *ptr, struct stat *sbuf, int ifd, if (params->type == IH_TYPE_FIRMWARE_IVT) /* Add size of CSF minus IVT */ - imagesize = sbuf->st_size - sizeof(image_header_t) + imagesize = sbuf->st_size - sizeof(struct legacy_img_hdr) + 0x2060 - sizeof(flash_header_v2_t); else - imagesize = sbuf->st_size - sizeof(image_header_t); + imagesize = sbuf->st_size - sizeof(struct legacy_img_hdr); if (params->os == IH_OS_TEE) { addr = optee_image_get_load_addr(hdr); @@ -134,14 +133,14 @@ static void image_set_header(void *ptr, struct stat *sbuf, int ifd, image_set_name(hdr, params->imagename); checksum = crc32(0, (const unsigned char *)hdr, - sizeof(image_header_t)); + sizeof(struct legacy_img_hdr)); image_set_hcrc(hdr, checksum); } static int image_extract_subimage(void *ptr, struct image_tool_params *params) { - const image_header_t *hdr = (const image_header_t *)ptr; + const struct legacy_img_hdr *hdr = (const struct legacy_img_hdr *)ptr; ulong file_data; ulong file_len; @@ -175,7 +174,7 @@ static int image_extract_subimage(void *ptr, struct image_tool_params *params) U_BOOT_IMAGE_TYPE( defimage, "Default Image support", - sizeof(image_header_t), + sizeof(struct legacy_img_hdr), (void *)&header, image_check_params, image_verify_header, diff --git a/tools/fit_image.c b/tools/fit_image.c index 979f2411ee..923a9755b7 100644 --- a/tools/fit_image.c +++ b/tools/fit_image.c @@ -22,7 +22,7 @@ #include <version.h> #include <u-boot/crc.h> -static image_header_t header; +static struct legacy_img_hdr header; static int fit_add_file_data(struct image_tool_params *params, size_t size_inc, const char *tmpfile) @@ -915,7 +915,7 @@ static int fit_check_params(struct image_tool_params *params) U_BOOT_IMAGE_TYPE( fitimage, "FIT Image support", - sizeof(image_header_t), + sizeof(struct legacy_img_hdr), (void *)&header, fit_check_params, fit_verify_header, diff --git a/tools/imx8mimage.c b/tools/imx8mimage.c index a4699decf9..35d0a92bfd 100644 --- a/tools/imx8mimage.c +++ b/tools/imx8mimage.c @@ -318,7 +318,7 @@ err_mmap: static int generate_ivt_for_fit(int fd, int fit_offset, uint32_t ep, uint32_t *fit_load_addr) { - image_header_t image_header; + struct legacy_img_hdr image_header; int ret; uint32_t fit_size, load_addr; @@ -330,8 +330,8 @@ static int generate_ivt_for_fit(int fd, int fit_offset, uint32_t ep, exit(EXIT_FAILURE); } - if (read(fd, (char *)&image_header, sizeof(image_header_t)) != - sizeof(image_header_t)) { + if (read(fd, (char *)&image_header, sizeof(struct legacy_img_hdr)) != + sizeof(struct legacy_img_hdr)) { fprintf(stderr, "generate_ivt_for_fit read failed: %s\n", strerror(errno)); exit(EXIT_FAILURE); @@ -600,7 +600,7 @@ void build_image(int ofd) close(sld_fd); file_off = sld_header_off; - file_off += sbuf.st_size + sizeof(image_header_t); + file_off += sbuf.st_size + sizeof(struct legacy_img_hdr); } } diff --git a/tools/mkimage.c b/tools/mkimage.c index 597cb3a5ce..30c6df7708 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -845,7 +845,7 @@ copy_file (int ifd, const char *datafile, int pad) if (params.xflag) { unsigned char *p = NULL; /* - * XIP: do not append the image_header_t at the + * XIP: do not append the struct legacy_img_hdr at the * beginning of the file, but consume the space * reserved for it. */ diff --git a/tools/mtk_image.c b/tools/mtk_image.c index 9b3136afa3..5ef9334163 100644 --- a/tools/mtk_image.c +++ b/tools/mtk_image.c @@ -427,10 +427,10 @@ static uint32_t crc32be_cal(const void *data, size_t length) static int mtk_image_verify_mt7621_header(const uint8_t *ptr, int print) { - const image_header_t *hdr = (const image_header_t *)ptr; + const struct legacy_img_hdr *hdr = (const struct legacy_img_hdr *)ptr; struct mt7621_nand_header *nhdr; uint32_t spl_size, crcval; - image_header_t header; + struct legacy_img_hdr header; int ret; spl_size = image_get_size(hdr); @@ -490,7 +490,7 @@ static int mtk_image_verify_mt7621_header(const uint8_t *ptr, int print) static int mtk_image_verify_header(unsigned char *ptr, int image_size, struct image_tool_params *params) { - image_header_t *hdr = (image_header_t *)ptr; + struct legacy_img_hdr *hdr = (struct legacy_img_hdr *)ptr; union lk_hdr *lk = (union lk_hdr *)ptr; /* nothing to verify for LK image header */ @@ -512,7 +512,7 @@ static int mtk_image_verify_header(unsigned char *ptr, int image_size, static void mtk_image_print_header(const void *ptr) { - image_header_t *hdr = (image_header_t *)ptr; + struct legacy_img_hdr *hdr = (struct legacy_img_hdr *)ptr; union lk_hdr *lk = (union lk_hdr *)ptr; if (le32_to_cpu(lk->magic) == LK_PART_MAGIC) { @@ -691,7 +691,7 @@ static void mtk_image_set_nand_header(void *ptr, off_t filesize, static void mtk_image_set_mt7621_header(void *ptr, off_t filesize, uint32_t loadaddr) { - image_header_t *hdr = (image_header_t *)ptr; + struct legacy_img_hdr *hdr = (struct legacy_img_hdr *)ptr; struct mt7621_stage1_header *shdr; struct mt7621_nand_header *nhdr; uint32_t datasize, crcval; |