[PATCH] boot an arm linux kernel direct from nand_spl code

Heiko Schocher hs at denx.de
Mon May 30 08:26:10 CEST 2011


you need 2 images in Flash:

- Linux image @CONFIG_SYS_NAND_LINUX_OFFS
- ATAG image @CONFIG_SYS_NAND_ATAG_OFFS

ATAG image is just a copy from the ATAG info u-boot
created, before booting an arm linux kernel ...

ToDo/suggestions:

- we should define a struct, which contains the 3 values
  offset, size, destination, so we can create a "nand_load_list"
  which can contain n entries, that could be processed in
  a while loop ... so no need for the CONFIG_SYS_BOOT_LINUX
  define ;-)

  For example:
  {
	{CONFIG_SYS_NAND_LINUX_OFFS,
	 CONFIG_SYS_NAND_LINUX_SIZE,
	 CONFIG_SYS_NAND_LINUX_DST},
	{CONFIG_SYS_NAND_ATAG_OFFS,
	 CONFIG_SYS_NAND_ATAG_SIZE,
	 CONFIG_SYS_NAND_ATAG_DST},
	{}
  } nand_load_list_linux;

  {
	{CONFIG_SYS_NAND_U_BOOT_OFFS,
	 CONFIG_SYS_NAND_U_BOOT_SIZE,
	 CONFIG_SYS_NAND_U_BOOT_DST},
#ifdef CONFIG_NAND_ENV_DST
	{CONFIG_ENV_OFFSET,
	 CONFIG_ENV_SIZE,
	 CONFIG_NAND_ENV_DST},
#ifdef CONFIG_ENV_OFFSET_REDUND
	{CONFIG_ENV_OFFSET_REDUND,
	 CONFIG_ENV_SIZE,
	CONFIG_NAND_ENV_DST + CONFIG_ENV_SIZE},
#endif
#endif
	{}
  }nand_load_list_uboot;

  in nand_boot() we can now for example get the state from a GPIO
  pin, and boot "linux/atag" or the "u-boot/env/env-red" case, or
  others (for example "powerpclinux/dtb")

  if (gpio == bootlinux)
	  nand_list = &nand_load_list_linux;
  else
	nand_list = &nand_load_list_uboot
  while (nand_list) {
	nand_load((&nand_info,
		nand_list->off,
		nand_list->size,
		nand_list->dest);
  }

Signed-off-by: Heiko Schocher <hs at denx.de>
---
diff --git a/include/configs/board_config.h b/include/configs/board_config.h
index fed8ac1..6f304f5 100644
--- a/include/configs/board_config.h
+++ b/include/configs/board_config.h
@@ -342,6 +342,19 @@ was ist das?
 					 * and in nand_spl mode cpu setup is
 					 * done in board_init_f from c code.
 					 */
+#define CONFIG_SYS_BOOT_LINUX
+#if defined(CONFIG_SYS_BOOT_LINUX)
+#define CONFIG_SYS_NAND_LINUX_OFFS	0x400000
+#define CONFIG_SYS_NAND_LINUX_SIZE	0x240000
+#define CONFIG_SYS_NAND_LINUX_DST	0x80008000
+
+#define CONFIG_SYS_NAND_ATAG_OFFS	(CONFIG_SYS_NAND_LINUX_OFFS + CONFIG_SYS_NAND_LINUX_SIZE)
+#define CONFIG_SYS_NAND_ATAG_SIZE	(CONFIG_SYS_NAND_PAGE_SIZE)
+#define CONFIG_SYS_NAND_ATAG_DST	(0x80000100)
+
+#define CONFIG_SYS_NAND_SPL_MACHID	MACH_TYPE_DAVINCI_DM365_EVM
+#endif
+

 /* for UBL header */

diff --git a/nand_spl/nand_boot.c b/nand_spl/nand_boot.c
index c0e56e7..f78b39d 100644
--- a/nand_spl/nand_boot.c
+++ b/nand_spl/nand_boot.c
@@ -242,6 +239,8 @@ static int nand_load(struct mtd_info *mtd, unsigned int offs,
 				nand_read_page(mtd, block, page, dst);
 				dst += CONFIG_SYS_NAND_PAGE_SIZE;
 				page++;
+				if (uboot_size == CONFIG_SYS_NAND_PAGE_SIZE)
+				break;
 			}

 			page = 0;
@@ -280,6 +279,30 @@ void nand_boot(void)
 	if (nand_chip.select_chip)
 		nand_chip.select_chip(&nand_info, 0);

+#if defined(CONFIG_SYS_BOOT_LINUX)
+	{
+	__attribute__((noreturn)) void (*kernel_entry)(int zero, int arch, uint params);
+
+	kernel_entry = (void (*)(int, int, uint))CONFIG_SYS_NAND_LINUX_DST;
+	/*
+	 * Load Linux image from NAND into RAM
+	 */
+	puts("load Linux image ...\n");
+	ret = nand_load(&nand_info, CONFIG_SYS_NAND_LINUX_OFFS, CONFIG_SYS_NAND_LINUX_SIZE,
+			(uchar *)CONFIG_SYS_NAND_LINUX_DST);
+	/*
+	 * Load ATAG image from NAND into RAM
+	 */
+	puts("load ATAG image ...\n");
+	ret = nand_load(&nand_info, CONFIG_SYS_NAND_ATAG_OFFS, CONFIG_SYS_NAND_ATAG_SIZE,
+			(uchar *)CONFIG_SYS_NAND_ATAG_DST);
+
+
+	puts("booting Linux ....\n");
+	(kernel_entry)(0, CONFIG_SYS_NAND_SPL_MACHID, CONFIG_SYS_NAND_ATAG_DST);
+	}
+#else
+
 	/*
 	 * Load U-Boot image from NAND into RAM
 	 */
@@ -304,4 +327,5 @@ void nand_boot(void)
 	 */
 	uboot = (void *)CONFIG_SYS_NAND_U_BOOT_START;
 	(*uboot)();
+#endif
 }
-- 
1.7.4.4

bye,
Heiko
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany


More information about the U-Boot mailing list