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

myan miao.yan at windriver.com
Thu Nov 28 10:51:38 CET 2013


From: Miao Yan <miao.yan at 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 at 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
-- 
1.7.9.5



More information about the U-Boot mailing list