[U-Boot] [PATCH 0/5] Add device tree support for VxWorks

Hello Wolfgang and All,
The next release of VxWorks will adopt device tree as its hardware description mechanism (for PowerPC and ARM), thus requiring boot interface changes for these two architechtures. And we would like to better support U-Boot with our operating system, because almost all the PowerPC and ARM boards that we support come with U-Boot pre-flashed and we would like to create better experience for our users.
Currently, U-Boot provides a 'bootvx' command (bootm internally uses bootvx) to load and run VxWorks image (for both ELF format or raw binary), for example:
bootvx 0x1000000
or just:
bootvx
if the environmental variable 'loadaddr' is set. The 'bootvx' will setup bootline and jump to the VxWorks entry using the following calling convention:
(void)(*entry)(int arg /* 0 */)
With the new VxWorks, the kernel entry interface for PowerPC is going to be changed to conform to the ePAPR standard, and for ARM, we need deivce tree's physical address to be passed to the kernel like this:
(void)(*entry)(void *fdt_addr)
And VxWorks bootline will be saved into deivce tree's 'bootargs' node as specified by the ePAPR (for both PowerPC and ARM).
The 'bootvx' commnad stays unchaged, and is still avalaible under the configuration option CONFIG_CMD_ELF for older kernels. A new option CONFIG_BOOTM_VXWORKS is added for bootm to align with other bootm supported operating systems.
So the do_bootm_vxworks will work as below:
#if (libfdt && (ppc || arm)) if (using device tree) boot_vxworks_with_device_tree else #endif bootvx(...);
The following patches are rebased on today's master branch (commit 6856254fc05d67f874d08a534724c842f93a605f).
Thanks,
Miao Yan (5): common/cmd_bootm.c: seperate do_bootm_vxworks related code from CONFIG_CMD_ELF. common/config_defaults.h: make CONFIG_BOOTM_VXWORKS default configuration common/cmd_bootm: extend do_bootm_vxworks to support the new VxWorks boot interface. common/fdt_support.c: avoid unintended return from fdt_fixup_memory_banks() doc/README.vxworks: add a document describing the new VxWorks boot interface
arch/arm/lib/bootm.c | 21 +++++++++++ arch/powerpc/lib/bootm.c | 52 ++++++++++++++++++++++++++ common/cmd_bootm.c | 90 +++++++++++++++++++++++++++++++++++++++++---- common/fdt_support.c | 5 ++- doc/README.vxworks | 34 +++++++++++++++++ include/common.h | 4 ++ include/config_defaults.h | 1 + include/vxworks.h | 2 + 8 files changed, 200 insertions(+), 9 deletions(-) create mode 100644 doc/README.vxworks

do_bootm_vxworks now is available under the configuration option CONFIG_BOOTM_VXWORKS, thus aligned with other operating systems that supported by bootm command. The bootvx command still depneds on CONFIG_CMD_ELF.
Signed-off-by: Miao Yan miao.yan@windriver.com --- common/cmd_bootm.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index b07b0f4..973c9f5 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -120,8 +120,10 @@ static boot_os_fn do_bootm_ose; #if defined(CONFIG_BOOTM_PLAN9) static boot_os_fn do_bootm_plan9; #endif -#if defined(CONFIG_CMD_ELF) +#if defined(CONFIG_BOOTM_VXWORKS) static boot_os_fn do_bootm_vxworks; +#endif +#if defined(CONFIG_CMD_ELF) static boot_os_fn do_bootm_qnxelf; int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); @@ -149,8 +151,10 @@ static boot_os_fn *boot_os[] = { #if defined(CONFIG_BOOTM_PLAN9) [IH_OS_PLAN9] = do_bootm_plan9, #endif -#if defined(CONFIG_CMD_ELF) +#if defined(CONFIG_BOOTM_VXWORKS) [IH_OS_VXWORKS] = do_bootm_vxworks, +#endif +#if defined(CONFIG_CMD_ELF) [IH_OS_QNX] = do_bootm_qnxelf, #endif #ifdef CONFIG_INTEGRITY @@ -1683,7 +1687,7 @@ static int do_bootm_plan9(int flag, int argc, char * const argv[], } #endif /* CONFIG_BOOTM_PLAN9 */
-#if defined(CONFIG_CMD_ELF) +#if defined(CONFIG_BOOTM_VXWORKS) static int do_bootm_vxworks(int flag, int argc, char * const argv[], bootm_headers_t *images) { @@ -1703,11 +1707,16 @@ static int do_bootm_vxworks(int flag, int argc, char * const argv[],
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
return 1; } +#endif
+#if defined(CONFIG_CMD_ELF) static int do_bootm_qnxelf(int flag, int argc, char * const argv[], bootm_headers_t *images) {

Signed-off-by: Miao Yan miao.yan@windriver.com --- include/config_defaults.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/include/config_defaults.h b/include/config_defaults.h index 567b46c..ad08c1d 100644 --- a/include/config_defaults.h +++ b/include/config_defaults.h @@ -14,6 +14,7 @@ #define CONFIG_BOOTM_NETBSD 1 #define CONFIG_BOOTM_PLAN9 1 #define CONFIG_BOOTM_RTEMS 1 +#define CONFIG_BOOTM_VXWORKS 1
#define CONFIG_GZIP 1 #define CONFIG_ZLIB 1

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.yan@windriver.com --- arch/arm/lib/bootm.c | 21 +++++++++++++ arch/powerpc/lib/bootm.c | 52 ++++++++++++++++++++++++++++++++ common/cmd_bootm.c | 75 +++++++++++++++++++++++++++++++++++++++++++--- include/common.h | 4 +++ include/vxworks.h | 2 ++ 5 files changed, 150 insertions(+), 4 deletions(-)
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index eefb456..da432c6 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -308,3 +308,24 @@ int bootz_setup(ulong image, ulong *start, ulong *end) }
#endif /* CONFIG_CMD_BOOTZ */ + +#if defined(CONFIG_BOOTM_VXWORKS) && defined(CONFIG_OF_LIBFDT) +void boot_prep_vxworks(bootm_headers_t *images) +{ + int off; + + assert(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"); + } + 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..ebd42b5 100644 --- a/arch/powerpc/lib/bootm.c +++ b/arch/powerpc/lib/bootm.c @@ -277,3 +277,55 @@ static void set_clocks_in_mhz (bd_t *kbd) #endif /* CONFIG_MPC5xxx */ } } + +#if defined(CONFIG_BOOTM_VXWORKS) && defined(CONFIG_OF_LIBFDT) +void boot_prep_vxworks(bootm_headers_t *images) +{ + int off; + u64 base, size; + + assert(images->ft_addr); + + 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 +} + +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..245c0c9 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -23,6 +23,10 @@ #include <asm/io.h> #include <linux/compiler.h>
+#if defined(CONFIG_BOOTM_VXWORKS) +#include <vxworks.h> +#endif + #if defined(CONFIG_CMD_USB) #include <usb.h> #endif @@ -337,7 +341,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;
@@ -1688,10 +1693,61 @@ static int do_bootm_plan9(int flag, int argc, char * const argv[], #endif /* CONFIG_BOOTM_PLAN9 */
#if defined(CONFIG_BOOTM_VXWORKS) + +#if defined(CONFIG_OF_LIBFDT) && (defined(CONFIG_PPC) || defined(CONFIG_ARM)) +void do_bootvx_fdt(bootm_headers_t *images) +{ + int ret; + char *bootline; + ulong of_size = images->ft_len; + char **of_flat_tree = &images->ft_addr; + struct lmb *lmb = &images->lmb; + + assert(*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; + } + + 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"); +} +#endif + static int do_bootm_vxworks(int flag, int argc, char * const argv[], bootm_headers_t *images) { +#if defined(CONFIG_CMD_ELF) char str[80]; +#endif
if (flag & BOOTM_STATE_OS_PREP) return 0; @@ -1705,11 +1761,22 @@ 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_OF_LIBFDT) && (defined(CONFIG_PPC) || defined(CONFIG_ARM)) + if (images->ft_addr) { + do_bootvx_fdt(images); + } else { +#endif
#if defined(CONFIG_CMD_ELF) - do_bootvx(NULL, 0, 0, NULL); + /* write entry-point into string */ + sprintf(str, "%lx", images->ep); + setenv("loadaddr", str); + + do_bootvx(NULL, 0, 0, NULL); +#endif + +#if defined(CONFIG_OF_LIBFDT) && (defined(CONFIG_PPC) || defined(CONFIG_ARM)) + } #endif
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..e70865a 100644 --- a/include/vxworks.h +++ b/include/vxworks.h @@ -9,6 +9,8 @@ #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);
/* * Use bootaddr to find the location in memory that VxWorks

fdt_fixup_memory_banks() will add and update /memory node in device tree blob. In the case that /memory node doesn't exist, after adding a new one, this function returns error.
The correct behavior should be continuing to update its properties.
Signed-off-by: Miao Yan miao.yan@windriver.com --- common/fdt_support.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/common/fdt_support.c b/common/fdt_support.c index b034c98..a97a705 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -400,10 +400,11 @@ int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks) nodeoffset = fdt_path_offset(blob, "/memory"); if (nodeoffset < 0) { nodeoffset = fdt_add_subnode(blob, 0, "memory"); - if (nodeoffset < 0) + if (nodeoffset < 0) { printf("WARNING: could not create /memory: %s.\n", fdt_strerror(nodeoffset)); - return nodeoffset; + return nodeoffset; + } } err = fdt_setprop(blob, nodeoffset, "device_type", "memory", sizeof("memory"));

Signed-off-by: Miao Yan miao.yan@windriver.com --- doc/README.vxworks | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 doc/README.vxworks
diff --git a/doc/README.vxworks b/doc/README.vxworks new file mode 100644 index 0000000..08c3813 --- /dev/null +++ b/doc/README.vxworks @@ -0,0 +1,34 @@ +From VxWorks 6.9+ (not include 6.9), VxWorks starts adopting device tree as its hardware +decription mechansim (for PowerPC and ARM), thus requiring boot interface changes. +This section will describe the new interface. + +For PowerPC, the calling convention of the new VxWorks entry point conforms to the ePAPR standard[1], +which is shown below (see ePAPR for more details): + + void (*kernel_entry)(ulong fdt_addr, + ulong r4 /* 0 */, ulong r5 /* 0 */, + ulong r6 /* EPAPR_MAGIC */ + ulong r7 /* boot IMA */, + ulong r8 /* 0 */, ulong r9 /* 0 */) + +For ARM, the calling convention is show below: + + void (*kernel_entry)(void *fdt_addr) + +When booting new VxWorks kernel (uImage format), the parameters passed to bootm is like below: + + bootm <kernel image address> - <device tree address> + +for example, booting p2020rdb kernel: (kernel is placed at address 0x1000000 and device tree blob +is places at address 0xf000000) + + setenv bootargs "gei(0,0)....." + tftp 0x1000000 vxWorks.uboot + tftp 0xf000000 p2020rdb.dtb + bootm 0x1000000 - 0xf000000 + +The second parameter to bootm is always '-' for VxWorks (VxWorks kernel doesn't make use of initrd) + +The bootvx command still works as it was for older kernels. + +[1] www.power.org

Dear Miao Yan,
In message 1379325490-3462-1-git-send-email-miao.yan@windriver.com you wrote:
The 'bootvx' commnad stays unchaged, and is still avalaible under the configuration option CONFIG_CMD_ELF for older kernels. A new option CONFIG_BOOTM_VXWORKS is added for bootm to align with other bootm supported operating systems.
So the do_bootm_vxworks will work as below:
#if (libfdt && (ppc || arm)) if (using device tree) boot_vxworks_with_device_tree else #endif bootvx(...);
I'm not sure I understand what this means. Please correct if my interpretation is incorrect or incomplete:
You intend to 1) just keep the existing 'bootvx' command for compatibility with older VxWorks versions, and 2) use plain 'bootm' for new versions, like we do for other OSes?
That sounds good to me.
Best regards,
Wolfgang Denk

Hello Wolfgang,
You intend to 1) just keep the existing 'bootvx' command for compatibility with older VxWorks versions, and 2) use plain 'bootm' for new versions, like we do for other OSes?
Yes, this is what I intended to implement, sorry for not being more clear. The pesdo-code is like this:
int do_bootm_vxworks(bootm_headers_t *images) { if (images->ft_addr) do_bootvx_fdt(images); else do_bootvx(NULL, 0, 0, NULL); }
So 'bootm' works with new versions of VxWorks if device tree blob is provided, otherwise it falls back to 'bootvx'.
The original idea was to separate 'bootvx' from 'bootm' entirely, but I am not sure how many users out there that depend on the old behavior, so I am inclined to keep it and not break anyone.
Could you help review the patches ? Thank you very much.
Miao

Dear Myan,
In message 5237BB0B.1000309@windriver.com you wrote:
Hello Wolfgang,
You intend to 1) just keep the existing 'bootvx' command for compatibility with older VxWorks versions, and 2) use plain 'bootm' for new versions, like we do for other OSes?
Yes, this is what I intended to implement, sorry for not being more clear. The pesdo-code is like this:
int do_bootm_vxworks(bootm_headers_t *images) { if (images->ft_addr) do_bootvx_fdt(images); else do_bootvx(NULL, 0, 0, NULL); }
So 'bootm' works with new versions of VxWorks if device tree blob is provided, otherwise it falls back to 'bootvx'.
I think this is not a good idea, for two reasons.
First, it means the behaviour of the "bootm" command is not consistent - with FDT address passed as argument it behaves one way, without it behaves different.
Second, You may want to support images that have the FDT attached or embedded or similar - maybe not now, but I bet such requests will pop up. You cannot do this in your code.
The original idea was to separate 'bootvx' from 'bootm' entirely, but I am not sure how many users out there that depend on the old behavior, so I am inclined to keep it and not break anyone.
If there is no way to inquire from the image itself wether it is one with FDT support or not (we might even assign a new IH_OS_ type for the new ones?), then it would probably be better to make "bootm" support only the new FDT aware images, and keep "bootvx" as compatibility command to boot older images.
On the other hand - what exactly is the difference between both boot ways to start an image? Does the additional address passed for the FDT really hurt old style images, so do we need the differentiation at all?
Best regards,
Wolfgang Denk

Hello Wolfgang,
I think this is not a good idea, for two reasons.
First, it means the behaviour of the "bootm" command is not consistent - with FDT address passed as argument it behaves one way, without it behaves different.
Second, You may want to support images that have the FDT attached or embedded or similar - maybe not now, but I bet such requests will pop up. You cannot do this in your code.
I understand this. The only reason that I did this way is that I am afraid of breaking existing 'bootm' users, but I just searched the mailing, seems that VxWorks volume is rather low, maybe it's OK to separate the two without hurting anyone.
If there is no way to inquire from the image itself wether it is one with FDT support or not (we might even assign a new IH_OS_ type for the new ones?), then it would probably be better to make "bootm" support only the new FDT aware images, and keep "bootvx" as compatibility command to boot older images.
I don't prefer to add a new OS type. It is still VxWorks after all, and with the fact that I am not allowed to disclose any information of the new version (not GA yet) makes it harder to come up with a meaningful name like IH_OS_VXWORKS_xxx. I would prefer to do it as you said, just making 'bootm' work with new versions and keeping 'bootvx' for the older ones. This makes things a lot easier.
On the other hand - what exactly is the difference between both boot ways to start an image? Does the additional address passed for the FDT really hurt old style images, so do we need the differentiation at all?
90% of the 'do_bootvx' function is about bootline setup (storing bootline to random memory locations that totally depend on individual BSP), which doesn't apply to the new kernel (in fact, if not doing right, it will likely result in memory corruption and hang the board). And I don't see a reliable way to distinguish the new and old kernels at runtime. Mixing them would make the code hard to maintain. I'd rather see them separated so we could focus on supporting the new one.
Miao

Hello Wolfgang and All,
The next release of VxWorks will adopt device tree as its hardware description mechanism (for PowerPC and ARM), thus requiring boot interface changes for these two architechtures. And we would like to better support U-Boot with our operating system, because almost all the PowerPC and ARM boards that we support come with U-Boot pre-flashed and we would like to create better experience for our users.
Currently, U-Boot provides a 'bootvx' command (bootm internally uses bootvx) to load and run VxWorks image (for both ELF format or raw binary), for example:
bootvx 0x1000000
or just:
bootvx
if the environmental variable 'loadaddr' is set. The 'bootvx' will setup bootline and jump to the VxWorks entry using the following calling convention:
(void)(*entry)(int arg /* 0 */)
With the new VxWorks, the kernel entry interface for PowerPC is going to be changed to conform to the ePAPR standard, and for ARM, we need deivce tree's physical address to be passed to the kernel like this:
(void)(*entry)(void *fdt_addr)
And VxWorks bootline will be saved into deivce tree's 'bootargs' node as specified by the ePAPR (for both PowerPC and ARM).
The 'bootvx' commnad stays unchaged, and is still avalaible under the configuration option CONFIG_CMD_ELF for older kernels. A new option CONFIG_BOOTM_VXWORKS is added for bootm to align with other bootm supported operating systems.
So the do_bootm_vxworks will work wit new versions of VxWorks which need device tree support, and do_bootvx will work with older VxWorks kernels as before.
Thanks,
Changes for v2: 1) seperating legacy do_bootvx code from do_bootm_vxworks, thus making do_bootm_vxworks only work with new kernels, old kernels can still use 'bootvx' 2) minor fixes to make code more clear
Miao Yan (5): common/cmd_bootm.c: seperate do_bootm_vxworks related code from CONFIG_CMD_ELF. common/config_defaults.h: make CONFIG_BOOTM_VXWORKS default configuration common/cmd_bootm: extend do_bootm_vxworks to support the new VxWorks boot interface. common/fdt_support.c: avoid unintended return from fdt_fixup_memory_banks() doc/README.vxworks: add a document describing the new VxWorks boot interface
arch/arm/lib/bootm.c | 23 +++++++++++++ arch/powerpc/lib/bootm.c | 55 +++++++++++++++++++++++++++++++ common/cmd_bootm.c | 80 ++++++++++++++++++++++++++++++++++++++++----- common/fdt_support.c | 5 +-- doc/README.vxworks | 34 +++++++++++++++++++ include/common.h | 4 +++ include/config_defaults.h | 1 + include/vxworks.h | 3 ++ 8 files changed, 194 insertions(+), 11 deletions(-) create mode 100644 doc/README.vxworks

do_bootm_vxworks now is available under the configuration option CONFIG_BOOTM_VXWORKS, thus aligned with other operating systems that supported by bootm command. The bootvx command still depneds on CONFIG_CMD_ELF.
Signed-off-by: Miao Yan miao.yan@windriver.com --- Changes for v2: none
common/cmd_bootm.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index b07b0f4..973c9f5 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -120,8 +120,10 @@ static boot_os_fn do_bootm_ose; #if defined(CONFIG_BOOTM_PLAN9) static boot_os_fn do_bootm_plan9; #endif -#if defined(CONFIG_CMD_ELF) +#if defined(CONFIG_BOOTM_VXWORKS) static boot_os_fn do_bootm_vxworks; +#endif +#if defined(CONFIG_CMD_ELF) static boot_os_fn do_bootm_qnxelf; int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); @@ -149,8 +151,10 @@ static boot_os_fn *boot_os[] = { #if defined(CONFIG_BOOTM_PLAN9) [IH_OS_PLAN9] = do_bootm_plan9, #endif -#if defined(CONFIG_CMD_ELF) +#if defined(CONFIG_BOOTM_VXWORKS) [IH_OS_VXWORKS] = do_bootm_vxworks, +#endif +#if defined(CONFIG_CMD_ELF) [IH_OS_QNX] = do_bootm_qnxelf, #endif #ifdef CONFIG_INTEGRITY @@ -1683,7 +1687,7 @@ static int do_bootm_plan9(int flag, int argc, char * const argv[], } #endif /* CONFIG_BOOTM_PLAN9 */
-#if defined(CONFIG_CMD_ELF) +#if defined(CONFIG_BOOTM_VXWORKS) static int do_bootm_vxworks(int flag, int argc, char * const argv[], bootm_headers_t *images) { @@ -1703,11 +1707,16 @@ static int do_bootm_vxworks(int flag, int argc, char * const argv[],
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
return 1; } +#endif
+#if defined(CONFIG_CMD_ELF) static int do_bootm_qnxelf(int flag, int argc, char * const argv[], bootm_headers_t *images) {

From: Miao Yan miao.yan@windriver.com
do_bootm_vxworks now is available under the configuration option CONFIG_BOOTM_VXWORKS, thus aligned with other operating systems that supported by bootm command. The bootvx command still depneds on CONFIG_CMD_ELF.
Signed-off-by: Miao Yan miao.yan@windriver.com --- Changes: v2->v3: rebase to master: d19ad726bcd5d9106f7ba9c750462fcc369f1020 v1->v2: none
common/cmd_bootm.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index ba73f57..881370d 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -120,8 +120,10 @@ static boot_os_fn do_bootm_ose; #if defined(CONFIG_BOOTM_PLAN9) static boot_os_fn do_bootm_plan9; #endif -#if defined(CONFIG_CMD_ELF) +#if defined(CONFIG_BOOTM_VXWORKS) static boot_os_fn do_bootm_vxworks; +#endif +#if defined(CONFIG_CMD_ELF) static boot_os_fn do_bootm_qnxelf; int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); int do_bootelf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); @@ -149,8 +151,10 @@ static boot_os_fn *boot_os[] = { #if defined(CONFIG_BOOTM_PLAN9) [IH_OS_PLAN9] = do_bootm_plan9, #endif -#if defined(CONFIG_CMD_ELF) +#if defined(CONFIG_BOOTM_VXWORKS) [IH_OS_VXWORKS] = do_bootm_vxworks, +#endif +#if defined(CONFIG_CMD_ELF) [IH_OS_QNX] = do_bootm_qnxelf, #endif #ifdef CONFIG_INTEGRITY @@ -1678,7 +1682,7 @@ static int do_bootm_plan9(int flag, int argc, char * const argv[], } #endif /* CONFIG_BOOTM_PLAN9 */
-#if defined(CONFIG_CMD_ELF) +#if defined(CONFIG_BOOTM_VXWORKS) static int do_bootm_vxworks(int flag, int argc, char * const argv[], bootm_headers_t *images) { @@ -1696,11 +1700,16 @@ static int do_bootm_vxworks(int flag, int argc, char * const argv[],
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
return 1; } +#endif
+#if defined(CONFIG_CMD_ELF) static int do_bootm_qnxelf(int flag, int argc, char * const argv[], bootm_headers_t *images) {

From: Miao Yan miao.yan@windriver.com
Signed-off-by: Miao Yan miao.yan@windriver.com --- Changes: v2->v3: rebase to master: d19ad726bcd5d9106f7ba9c750462fcc369f1020 v1->v2: none
include/config_defaults.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/include/config_defaults.h b/include/config_defaults.h index 567b46c..ad08c1d 100644 --- a/include/config_defaults.h +++ b/include/config_defaults.h @@ -14,6 +14,7 @@ #define CONFIG_BOOTM_NETBSD 1 #define CONFIG_BOOTM_PLAN9 1 #define CONFIG_BOOTM_RTEMS 1 +#define CONFIG_BOOTM_VXWORKS 1
#define CONFIG_GZIP 1 #define CONFIG_ZLIB 1

On Thu, Nov 28, 2013 at 05:51:37PM +0800, miao.yan@windriver.com wrote:
From: Miao Yan miao.yan@windriver.com
Signed-off-by: Miao Yan miao.yan@windriver.com
Applied to u-boot/master, thanks!

From: Miao Yan miao.yan@windriver.com
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.yan@windriver.com --- Changes: v2->v3: rebase to master d19ad726bcd5d9106f7ba9c750462fcc369f1020 v1->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 f476a89..dff10ba 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -326,3 +326,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 881370d..cf60b41 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;
@@ -1682,12 +1690,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_GO) return 0;
@@ -1698,12 +1756,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 8ca67f6..d49c514 100644 --- a/include/common.h +++ b/include/common.h @@ -698,6 +698,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

On Thu, Nov 28, 2013 at 05:51:38PM +0800, miao.yan@windriver.com wrote:
From: Miao Yan miao.yan@windriver.com
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.yan@windriver.com
Applied to u-boot/master, thanks!

From: Miao Yan miao.yan@windriver.com
fdt_fixup_memory_banks() will add and update /memory node in device tree blob. In the case that /memory node doesn't exist, after adding a new one, this function returns error.
The correct behavior should be continuing to update its properties.
Signed-off-by: Miao Yan miao.yan@windriver.com --- changes: v2->v3: rebase to master: d19ad726bcd5d9106f7ba9c750462fcc369f1020 v1->v2: none
common/fdt_support.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/common/fdt_support.c b/common/fdt_support.c index 1f0d8f5..4e32b02 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -400,10 +400,11 @@ int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks) nodeoffset = fdt_path_offset(blob, "/memory"); if (nodeoffset < 0) { nodeoffset = fdt_add_subnode(blob, 0, "memory"); - if (nodeoffset < 0) + if (nodeoffset < 0) { printf("WARNING: could not create /memory: %s.\n", fdt_strerror(nodeoffset)); - return nodeoffset; + return nodeoffset; + } } err = fdt_setprop(blob, nodeoffset, "device_type", "memory", sizeof("memory"));

On Thu, Nov 28, 2013 at 05:51:39PM +0800, miao.yan@windriver.com wrote:
From: Miao Yan miao.yan@windriver.com
fdt_fixup_memory_banks() will add and update /memory node in device tree blob. In the case that /memory node doesn't exist, after adding a new one, this function returns error.
The correct behavior should be continuing to update its properties.
Signed-off-by: Miao Yan miao.yan@windriver.com
Applied to u-boot/master, thanks!

From: Miao Yan miao.yan@windriver.com
Signed-off-by: Miao Yan miao.yan@windriver.com --- changes:
v2->v3: rebase to master: d19ad726bcd5d9106f7ba9c750462fcc369f1020 v1->v2: none
doc/README.vxworks | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 doc/README.vxworks
diff --git a/doc/README.vxworks b/doc/README.vxworks new file mode 100644 index 0000000..4cb302e --- /dev/null +++ b/doc/README.vxworks @@ -0,0 +1,19 @@ +From VxWorks 6.9+ (not include 6.9), VxWorks starts adopting device tree as its hardware +decription mechansim (for PowerPC and ARM), thus requiring boot interface changes. +This section will describe the new interface. + +For PowerPC, the calling convention of the new VxWorks entry point conforms to the ePAPR standard, +which is shown below (see ePAPR for more details): + + void (*kernel_entry)(fdt_addr, + 0, 0, EPAPR_MAGIC, boot_IMA, 0, 0) + +For ARM, the calling convention is show below: + + void (*kernel_entry)(void *fdt_addr) + +When booting new VxWorks kernel (uImage format), the parameters passed to bootm is like below: + + bootm <kernel image address> - <device tree address> + +The do_bootvx command still works as it was for older VxWorks kernels.

On Thu, Nov 28, 2013 at 05:51:40PM +0800, miao.yan@windriver.com wrote:
From: Miao Yan miao.yan@windriver.com
Signed-off-by: Miao Yan miao.yan@windriver.com
Applied to u-boot/master, thanks!

On Thu, Nov 28, 2013 at 05:51:36PM +0800, miao.yan@windriver.com wrote:
From: Miao Yan miao.yan@windriver.com
do_bootm_vxworks now is available under the configuration option CONFIG_BOOTM_VXWORKS, thus aligned with other operating systems that supported by bootm command. The bootvx command still depneds on CONFIG_CMD_ELF.
Signed-off-by: Miao Yan miao.yan@windriver.com
Applied to u-boot/master, thanks!

Signed-off-by: Miao Yan miao.yan@windriver.com --- Changes for v2: none
include/config_defaults.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/include/config_defaults.h b/include/config_defaults.h index 567b46c..ad08c1d 100644 --- a/include/config_defaults.h +++ b/include/config_defaults.h @@ -14,6 +14,7 @@ #define CONFIG_BOOTM_NETBSD 1 #define CONFIG_BOOTM_PLAN9 1 #define CONFIG_BOOTM_RTEMS 1 +#define CONFIG_BOOTM_VXWORKS 1
#define CONFIG_GZIP 1 #define CONFIG_ZLIB 1

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.yan@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

fdt_fixup_memory_banks() will add and update /memory node in device tree blob. In the case that /memory node doesn't exist, after adding a new one, this function returns error.
The correct behavior should be continuing to update its properties.
Signed-off-by: Miao Yan miao.yan@windriver.com --- Changes for v2: none
common/fdt_support.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/common/fdt_support.c b/common/fdt_support.c index b034c98..a97a705 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -400,10 +400,11 @@ int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks) nodeoffset = fdt_path_offset(blob, "/memory"); if (nodeoffset < 0) { nodeoffset = fdt_add_subnode(blob, 0, "memory"); - if (nodeoffset < 0) + if (nodeoffset < 0) { printf("WARNING: could not create /memory: %s.\n", fdt_strerror(nodeoffset)); - return nodeoffset; + return nodeoffset; + } } err = fdt_setprop(blob, nodeoffset, "device_type", "memory", sizeof("memory"));

Signed-off-by: Miao Yan miao.yan@windriver.com --- Changes for v2: none
doc/README.vxworks | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 doc/README.vxworks
diff --git a/doc/README.vxworks b/doc/README.vxworks new file mode 100644 index 0000000..08c3813 --- /dev/null +++ b/doc/README.vxworks @@ -0,0 +1,34 @@ +From VxWorks 6.9+ (not include 6.9), VxWorks starts adopting device tree as its hardware +decription mechansim (for PowerPC and ARM), thus requiring boot interface changes. +This section will describe the new interface. + +For PowerPC, the calling convention of the new VxWorks entry point conforms to the ePAPR standard[1], +which is shown below (see ePAPR for more details): + + void (*kernel_entry)(ulong fdt_addr, + ulong r4 /* 0 */, ulong r5 /* 0 */, + ulong r6 /* EPAPR_MAGIC */ + ulong r7 /* boot IMA */, + ulong r8 /* 0 */, ulong r9 /* 0 */) + +For ARM, the calling convention is show below: + + void (*kernel_entry)(void *fdt_addr) + +When booting new VxWorks kernel (uImage format), the parameters passed to bootm is like below: + + bootm <kernel image address> - <device tree address> + +for example, booting p2020rdb kernel: (kernel is placed at address 0x1000000 and device tree blob +is places at address 0xf000000) + + setenv bootargs "gei(0,0)....." + tftp 0x1000000 vxWorks.uboot + tftp 0xf000000 p2020rdb.dtb + bootm 0x1000000 - 0xf000000 + +The second parameter to bootm is always '-' for VxWorks (VxWorks kernel doesn't make use of initrd) + +The bootvx command still works as it was for older kernels. + +[1] www.power.org

Hi Wolfgang,
Changes for v2: 1) separating legacy do_bootvx code from do_bootm_vxworks, thus making do_bootm_vxworks only work with new kernels, old kernels can still use 'bootvx' 2) minor fixes to make code more clear
I've posted the v2 patches, how do you think of them ? Thanks.
Miao

Hi Tom,
I posted some patches to add device tree support for VxWorks several days ago. Wolfgang provided me with some very useful feedback, and I sent v2 patches. The discussion and patches are recorded here:
http://u-boot.10912.n7.nabble.com/PATCH-0-5-Add-device-tree-support-for-VxWo...
I see you are the master branch custodian, so do you think these patches are OK to be integrated or more discussions are needed ? What else should I do to make this upstream ? Thank you.
Miao

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 09/21/2013 10:57 PM, myan wrote:
Hi Tom,
I posted some patches to add device tree support for VxWorks several days ago. Wolfgang provided me with some very useful feedback, and I sent v2 patches. The discussion and patches are recorded here:
http://u-boot.10912.n7.nabble.com/PATCH-0-5-Add-device-tree-support-for-VxWo...
I see you are the master branch custodian, so do you think these patches are OK to be integrated or more discussions are needed ? What else should I do to make this upstream ? Thank you.
I think things look OK, but as they were posted after the merge window closed, they won't go in to master until after the v2013.10 release, thanks!
- -- Tom

Hi Tom,
On 09/24/2013 07:27 AM, Tom Rini wrote:
I think things look OK, but as they were posted after the merge window closed, they won't go in to master until after the v2013.10 release, thanks!
Will this go into master in this merge window ?
And I noticed there are some changes to common do_bootm, which reqiures adjustment to vxworks subcommand handling code, do I need to rebase and resend the patches ? Thanks.
Miao

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 10/31/2013 05:56 AM, myan wrote:
Hi Tom,
On 09/24/2013 07:27 AM, Tom Rini wrote:
I think things look OK, but as they were posted after the merge window closed, they won't go in to master until after the v2013.10 release, thanks!
Will this go into master in this merge window ?
And I noticed there are some changes to common do_bootm, which reqiures adjustment to vxworks subcommand handling code, do I need to rebase and resend the patches ? Thanks.
Yes, it can come in, I just have been a bit busy and getting behind on collecting up patches. If you can re-base and re-test things I'd appreciate it, thanks!
- -- Tom

Hi Tom,
On 10/31/2013 07:31 PM, Tom Rini wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 10/31/2013 05:56 AM, myan wrote:
Will this go into master in this merge window ?
And I noticed there are some changes to common do_bootm, which reqiures adjustment to vxworks subcommand handling code, do I need to rebase and resend the patches ? Thanks.
Yes, it can come in, I just have been a bit busy and getting behind on collecting up patches. If you can re-base and re-test things I'd appreciate it, thanks!
I re-tested against master but found a problem. In commit "5c427e4: use BOOTM_STATE_OS_CMDLINE flag for plain bootm" and "3d187b3: Only pass BOOTM_STATE_OS_CMDLINE on PowerPC/MIPS", BOOTM_STATE_OS_CMLINE was added to do_bootm for PowerPC and MIPS. This breaks other OSes (vxworks, netbsd, plan9,...) that don't support subcommand processing, e.g. they all contain the following code in their do_bootm_xxx():
if (flag & BOOTM_STATE_OS_PREP) return 0; if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) return 1;
which will result a "subcommand not supported" error. IMO, the above code should be converted to something like this:
/* if not go command, pretend everything to be OK */ if (flag != BOOTM_STATE_OS_GO) return 0;
And if you are OK with it, I could send patches to clean them up. Thanks.
Miao

On Fri, Nov 01, 2013 at 03:44:10PM +0800, myan wrote:
Hi Tom,
On 10/31/2013 07:31 PM, Tom Rini wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 10/31/2013 05:56 AM, myan wrote:
Will this go into master in this merge window ?
And I noticed there are some changes to common do_bootm, which reqiures adjustment to vxworks subcommand handling code, do I need to rebase and resend the patches ? Thanks.
Yes, it can come in, I just have been a bit busy and getting behind on collecting up patches. If you can re-base and re-test things I'd appreciate it, thanks!
I re-tested against master but found a problem. In commit "5c427e4: use BOOTM_STATE_OS_CMDLINE flag for plain bootm" and "3d187b3: Only pass BOOTM_STATE_OS_CMDLINE on PowerPC/MIPS", BOOTM_STATE_OS_CMLINE was added to do_bootm for PowerPC and MIPS. This breaks other OSes (vxworks, netbsd, plan9,...) that don't support subcommand processing, e.g. they all contain the following code in their do_bootm_xxx():
if (flag & BOOTM_STATE_OS_PREP) return 0; if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) return 1;
which will result a "subcommand not supported" error. IMO, the above code should be converted to something like this:
/* if not go command, pretend everything to be OK */ if (flag != BOOTM_STATE_OS_GO) return 0;
And if you are OK with it, I could send patches to clean them up. Thanks.
OK, reading over all of the other OS bootm functions, yeah, I think you're on the right path here. Thanks!
participants (4)
-
Miao Yan
-
myan
-
Tom Rini
-
Wolfgang Denk