Hello Simon,

Simon Schwarz wrote:
> for my bachelor thesis I will implement a direct Linux boot from U-Boot SPL.
> My current plan is to utilize do_bootm_[OS].
> 
> Simplest solution is to direct boot Linux/other OS and just boot
> u-boot when a key is pressed. In addition i will also have some tests
> (header check/CRC) - if they fail start u-boot.
> 
> IMHO this may also be of interest for the new SPL architecture.
> 
> Are there already implementations I am not aware of? Any comments on
> what I should also add? Problems I may not see?

I tried this on an davinci dm368 based board (not in mainline yet,
but patches for the board support coming soon), with the following
patch:

>From 684cb207b14585f9d83f2c4c6f72b5b8bd4fd1a0 Mon Sep 17 00:00:00 2001
From: Heiko Schocher <h...@denx.de>
Date: Mon, 30 May 2011 08:26:10 +0200
Subject: [PATCH] boot an arm linux kernel direct from nand_spl code

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 <h...@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
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to