The next version VxWorks adopts device tree (for PowerPC and ARM) as its hardware description mechanism. For PowerPC, the boot interface conforms to the ePAPR standard, which is:
void (*kernel_entry)(ulong fdt_addr, ulong r4 /* 0 */, ulong r5 /* 0 */, ulong r6 /* EPAPR_MAGIC */, ulong r7 /* IMA size */, ulong r8 /* 0 */, ulong r9 /* 0 */) For ARM, the boot interface is: void (*kernel_entry)(void *fdt_addr) Signed-off-by: Miao Yan <miao....@windriver.com> --- Changes for v2: 1) remove legacy do_bootvx code from do_bootm_vxworks, thus making do_bootm_vxworks work only with new kernels, old kernels can still use 'bootvx' 2) minor fixes to make code more clear arch/arm/lib/bootm.c | 23 ++++++++++++++ arch/powerpc/lib/bootm.c | 55 +++++++++++++++++++++++++++++++++ common/cmd_bootm.c | 77 ++++++++++++++++++++++++++++++++++++++-------- include/common.h | 4 +++ include/vxworks.h | 3 ++ 5 files changed, 150 insertions(+), 12 deletions(-) diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index eefb456..6b8a951 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -308,3 +308,26 @@ int bootz_setup(ulong image, ulong *start, ulong *end) } #endif /* CONFIG_CMD_BOOTZ */ + +#if defined(CONFIG_BOOTM_VXWORKS) +void boot_prep_vxworks(bootm_headers_t *images) +{ +#if defined(CONFIG_OF_LIBFDT) + int off; + + if (images->ft_addr) { + off = fdt_path_offset(images->ft_addr, "/memory"); + if (off < 0) { + if (arch_fixup_memory_node(images->ft_addr)) + puts("## WARNING: fixup memory failed!\n"); + } + } +#endif + cleanup_before_linux(); +} +void boot_jump_vxworks(bootm_headers_t *images) +{ + /* ARM VxWorks requires device tree physical address to be passed */ + ((void (*)(void *))images->ep)(images->ft_addr); +} +#endif diff --git a/arch/powerpc/lib/bootm.c b/arch/powerpc/lib/bootm.c index e7153b0..5398092 100644 --- a/arch/powerpc/lib/bootm.c +++ b/arch/powerpc/lib/bootm.c @@ -277,3 +277,58 @@ static void set_clocks_in_mhz (bd_t *kbd) #endif /* CONFIG_MPC5xxx */ } } + +#if defined(CONFIG_BOOTM_VXWORKS) +void boot_prep_vxworks(bootm_headers_t *images) +{ +#if defined(CONFIG_OF_LIBFDT) + int off; + u64 base, size; + + if (!images->ft_addr) + return; + + base = (u64)gd->bd->bi_memstart; + size = (u64)gd->bd->bi_memsize; + + off = fdt_path_offset(images->ft_addr, "/memory"); + if (off < 0) + fdt_fixup_memory(images->ft_addr, base, size); + +#if defined(CONFIG_MP) +#if defined(CONFIG_MPC85xx) + ft_fixup_cpu(images->ft_addr, base + size); + ft_fixup_num_cores(images->ft_addr); +#elif defined(CONFIG_MPC86xx) + off = fdt_add_mem_rsv(images->ft_addr, + determin_mp_bootpg(NULL), (u64)4096); + if (off < 0) + printf("## WARNING %s: %s\n", __func__, fdt_strerror(off)); + ft_fixup_num_cores(images->ft_addr); +#endif + flush_cache((unsigned long)images->ft_addr, images->ft_len); +#endif +#endif +} + +void boot_jump_vxworks(bootm_headers_t *images) +{ + /* PowerPC VxWorks boot interface conforms to the ePAPR standard + * general purpuse registers: + * + * r3: Effective address of the device tree image + * r4: 0 + * r5: 0 + * r6: ePAPR magic value + * r7: shall be the size of the boot IMA in bytes + * r8: 0 + * r9: 0 + * TCR: WRC = 0, no watchdog timer reset will occur + */ + WATCHDOG_RESET(); + + ((void (*)(void *, ulong, ulong, ulong, + ulong, ulong, ulong))images->ep)(images->ft_addr, + 0, 0, EPAPR_MAGIC, getenv_bootm_mapsize(), 0, 0); +} +#endif diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 973c9f5..cf712c2 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -23,6 +23,11 @@ #include <asm/io.h> #include <linux/compiler.h> +#if defined(CONFIG_BOOTM_VXWORKS) && \ + (defined(CONFIG_PPC) || defined(CONFIG_ARM)) +#include <vxworks.h> +#endif + #if defined(CONFIG_CMD_USB) #include <usb.h> #endif @@ -120,7 +125,8 @@ static boot_os_fn do_bootm_ose; #if defined(CONFIG_BOOTM_PLAN9) static boot_os_fn do_bootm_plan9; #endif -#if defined(CONFIG_BOOTM_VXWORKS) +#if defined(CONFIG_BOOTM_VXWORKS) && \ + (defined(CONFIG_PPC) || defined(CONFIG_ARM)) static boot_os_fn do_bootm_vxworks; #endif #if defined(CONFIG_CMD_ELF) @@ -151,7 +157,8 @@ static boot_os_fn *boot_os[] = { #if defined(CONFIG_BOOTM_PLAN9) [IH_OS_PLAN9] = do_bootm_plan9, #endif -#if defined(CONFIG_BOOTM_VXWORKS) +#if defined(CONFIG_BOOTM_VXWORKS) && \ + (defined(CONFIG_PPC) || defined(CONFIG_ARM)) [IH_OS_VXWORKS] = do_bootm_vxworks, #endif #if defined(CONFIG_CMD_ELF) @@ -337,7 +344,8 @@ static int bootm_find_other(cmd_tbl_t *cmdtp, int flag, int argc, if (((images.os.type == IH_TYPE_KERNEL) || (images.os.type == IH_TYPE_KERNEL_NOLOAD) || (images.os.type == IH_TYPE_MULTI)) && - (images.os.os == IH_OS_LINUX)) { + (images.os.os == IH_OS_LINUX || + images.os.os == IH_OS_VXWORKS)) { if (bootm_find_ramdisk(flag, argc, argv)) return 1; @@ -1687,12 +1695,62 @@ static int do_bootm_plan9(int flag, int argc, char * const argv[], } #endif /* CONFIG_BOOTM_PLAN9 */ -#if defined(CONFIG_BOOTM_VXWORKS) +#if defined(CONFIG_BOOTM_VXWORKS) && \ + (defined(CONFIG_PPC) || defined(CONFIG_ARM)) + +void do_bootvx_fdt(bootm_headers_t *images) +{ +#if defined(CONFIG_OF_LIBFDT) + int ret; + char *bootline; + ulong of_size = images->ft_len; + char **of_flat_tree = &images->ft_addr; + struct lmb *lmb = &images->lmb; + + if (*of_flat_tree) { + boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree); + + ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size); + if (ret) + return; + + ret = fdt_add_subnode(*of_flat_tree, 0, "chosen"); + if ((ret >= 0 || ret == -FDT_ERR_EXISTS)) { + bootline = getenv("bootargs"); + if (bootline) { + ret = fdt_find_and_setprop(*of_flat_tree, + "/chosen", "bootargs", + bootline, + strlen(bootline) + 1, 1); + if (ret < 0) { + printf("## ERROR: %s : %s\n", __func__, + fdt_strerror(ret)); + return; + } + } + } else { + printf("## ERROR: %s : %s\n", __func__, + fdt_strerror(ret)); + return; + } + } +#endif + + boot_prep_vxworks(images); + + bootstage_mark(BOOTSTAGE_ID_RUN_OS); + + printf("## Starting vxWorks at 0x%08lx, device tree at 0x%08lx ...\n", + (ulong)images->ep, (ulong)*of_flat_tree); + + boot_jump_vxworks(images); + + puts("## vxWorks terminated\n"); +} + static int do_bootm_vxworks(int flag, int argc, char * const argv[], bootm_headers_t *images) { - char str[80]; - if (flag & BOOTM_STATE_OS_PREP) return 0; if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) @@ -1705,12 +1763,7 @@ static int do_bootm_vxworks(int flag, int argc, char * const argv[], } #endif - sprintf(str, "%lx", images->ep); /* write entry-point into string */ - setenv("loadaddr", str); - -#if defined(CONFIG_CMD_ELF) - do_bootvx(NULL, 0, 0, NULL); -#endif + do_bootvx_fdt(images); return 1; } diff --git a/include/common.h b/include/common.h index 8addf43..e05f7a2 100644 --- a/include/common.h +++ b/include/common.h @@ -690,6 +690,10 @@ ulong get_ddr_freq(ulong); #if defined(CONFIG_MPC85xx) typedef MPC85xx_SYS_INFO sys_info_t; void get_sys_info ( sys_info_t * ); +# if defined(CONFIG_OF_LIBFDT) + void ft_fixup_cpu(void *, u64); + void ft_fixup_num_cores(void *); +# endif #endif #if defined(CONFIG_MPC86xx) typedef MPC86xx_SYS_INFO sys_info_t; diff --git a/include/vxworks.h b/include/vxworks.h index c5d1577..122043c 100644 --- a/include/vxworks.h +++ b/include/vxworks.h @@ -9,6 +9,9 @@ #define _VXWORKS_H_ int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); +void boot_prep_vxworks(bootm_headers_t *images); +void boot_jump_vxworks(bootm_headers_t *images); +void do_bootvx_fdt(bootm_headers_t *images); /* * Use bootaddr to find the location in memory that VxWorks -- 1.7.9.5 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot