[U-Boot] [PATCH 3/5] common/cmd_bootm: extend do_bootm_vxworks to support the new VxWorks boot interface.

Miao Yan
2013-09-16T09:58:08Z

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@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
--
1.7.9.5