From patchwork Mon Sep 5 14:53:11 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Schwarz X-Patchwork-Id: 113380 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 9CF9AB6F7D for ; Tue, 6 Sep 2011 00:53:44 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 4F5992814E; Mon, 5 Sep 2011 16:53:42 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 6obfxmrwGJ0k; Mon, 5 Sep 2011 16:53:42 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 231932814F; Mon, 5 Sep 2011 16:53:41 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 53D992814F for ; Mon, 5 Sep 2011 16:53:39 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id cHBokSEDLOnb for ; Mon, 5 Sep 2011 16:53:37 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-fx0-f44.google.com (mail-fx0-f44.google.com [209.85.161.44]) by theia.denx.de (Postfix) with ESMTPS id 99A1D2814E for ; Mon, 5 Sep 2011 16:53:35 +0200 (CEST) Received: by fxe6 with SMTP id 6so3680947fxe.3 for ; Mon, 05 Sep 2011 07:53:35 -0700 (PDT) Received: by 10.223.6.91 with SMTP id 27mr133729fay.145.1315234415572; Mon, 05 Sep 2011 07:53:35 -0700 (PDT) Received: from localhost.localdomain (DSL01.212.114.252.242.ip-pool.NEFkom.net [212.114.252.242]) by mx.google.com with ESMTPS id g1sm1258716fad.24.2011.09.05.07.53.33 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 05 Sep 2011 07:53:34 -0700 (PDT) From: Simon Schwarz To: u-boot@lists.denx.de Date: Mon, 5 Sep 2011 16:53:11 +0200 Message-Id: <1315234391-26951-1-git-send-email-simonschwarzcor@gmail.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1314634093-8494-1-git-send-email-simonschwarzcor@gmail.com> References: <1314634093-8494-1-git-send-email-simonschwarzcor@gmail.com> Organization: Corscience GmbH & Co. KG Cc: scottwood@freescale.com Subject: [U-Boot] [PATCH V2] arm: Add Prep subcommand support to bootm X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.9 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Adds prep subcommand to bootm implementation of ARM. When bootm is called with the subcommand prep the function stops right after ATAGS creation and before announce_and_cleanup. This is used in command "cmd_spl export" Signed-off-by: Simon Schwarz --- V2 changes: nothing V3 changes: nothing changes after slicing this from patch http://article.gmane.org/gmane.comp.boot-loaders.u-boot/106422: DEL Prototype declaration - not necessary if reordered DEL Most #ifdefs - relying on -ffunction-sections and --gc-sections to handle unused CHG reorganized bootm. powerpc implementation was the model ADD get_board_serial fake implementation - this is needed if setup_serial_tag is compiled but the board doesn't support it - tradeoff for removing #ifdefs CHG changed back to former not checking for zero approach V2 changes (after split): CHG wrong comment using old savebp DEL file-wide kernel-entry forward-defintion (moved to funciton using it) DEL get_board_serial added #ifdef CONFIG_SERIAL_TAG to setup_serial_tag instead DEL boot_bd_t_linux and boot_cmdline_linux, do_bootm_linux returns -1 if they are called CHG boot_prep_linux: error text emitted CHG some typos and style problems CHG logic in do_bootm_linux to do it exactly like ppc no == 0 DEL extern from udc_disconnect - gc should do it squash! 7d85f60647af20c52e40a8422cdb8eb91a94d0a2 --- arch/arm/lib/bootm.c | 320 ++++++++++++++++++++++++-------------------------- 1 files changed, 154 insertions(+), 166 deletions(-) diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 802e833..e5afc7e 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -1,4 +1,8 @@ -/* +/* Copyright (C) 2011 + * Corscience GmbH & Co. KG - Simon Schwarz + * - Added prep subcommand support + * - Reorganized source - modeled after powerpc version + * * (C) Copyright 2002 * Sysgo Real-Time Solutions, GmbH * Marius Groeger @@ -32,31 +36,15 @@ DECLARE_GLOBAL_DATA_PTR; -#if defined (CONFIG_SETUP_MEMORY_TAGS) || \ - defined (CONFIG_CMDLINE_TAG) || \ - defined (CONFIG_INITRD_TAG) || \ - defined (CONFIG_SERIAL_TAG) || \ - defined (CONFIG_REVISION_TAG) -static void setup_start_tag (bd_t *bd); - -# ifdef CONFIG_SETUP_MEMORY_TAGS -static void setup_memory_tags (bd_t *bd); -# endif -static void setup_commandline_tag (bd_t *bd, char *commandline); - -# ifdef CONFIG_INITRD_TAG -static void setup_initrd_tag (bd_t *bd, ulong initrd_start, - ulong initrd_end); -# endif -static void setup_end_tag (bd_t *bd); - static struct tag *params; -#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */ -static ulong get_sp(void); -#if defined(CONFIG_OF_LIBFDT) -static int bootm_linux_fdt(int machid, bootm_headers_t *images); -#endif +static ulong get_sp(void) +{ + ulong ret; + + asm("mov %0, sp" : "=r"(ret) : ); + return ret; +} void arch_lmb_reserve(struct lmb *lmb) { @@ -80,85 +68,6 @@ void arch_lmb_reserve(struct lmb *lmb) gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size - sp); } -static void announce_and_cleanup(void) -{ - printf("\nStarting kernel ...\n\n"); - -#ifdef CONFIG_USB_DEVICE - { - extern void udc_disconnect(void); - udc_disconnect(); - } -#endif - cleanup_before_linux(); -} - -int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) -{ - bd_t *bd = gd->bd; - char *s; - int machid = bd->bi_arch_number; - void (*kernel_entry)(int zero, int arch, uint params); - -#ifdef CONFIG_CMDLINE_TAG - char *commandline = getenv ("bootargs"); -#endif - - if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) - return 1; - - s = getenv ("machid"); - if (s) { - machid = simple_strtoul (s, NULL, 16); - printf ("Using machid 0x%x from environment\n", machid); - } - - show_boot_progress (15); - -#ifdef CONFIG_OF_LIBFDT - if (images->ft_len) - return bootm_linux_fdt(machid, images); -#endif - - kernel_entry = (void (*)(int, int, uint))images->ep; - - debug ("## Transferring control to Linux (at address %08lx) ...\n", - (ulong) kernel_entry); - -#if defined (CONFIG_SETUP_MEMORY_TAGS) || \ - defined (CONFIG_CMDLINE_TAG) || \ - defined (CONFIG_INITRD_TAG) || \ - defined (CONFIG_SERIAL_TAG) || \ - defined (CONFIG_REVISION_TAG) - setup_start_tag (bd); -#ifdef CONFIG_SERIAL_TAG - setup_serial_tag (¶ms); -#endif -#ifdef CONFIG_REVISION_TAG - setup_revision_tag (¶ms); -#endif -#ifdef CONFIG_SETUP_MEMORY_TAGS - setup_memory_tags (bd); -#endif -#ifdef CONFIG_CMDLINE_TAG - setup_commandline_tag (bd, commandline); -#endif -#ifdef CONFIG_INITRD_TAG - if (images->rd_start && images->rd_end) - setup_initrd_tag (bd, images->rd_start, images->rd_end); -#endif - setup_end_tag(bd); -#endif - - announce_and_cleanup(); - - kernel_entry(0, machid, bd->bi_boot_params); - /* does not return */ - - return 1; -} - -#if defined(CONFIG_OF_LIBFDT) static int fixup_memory_node(void *blob) { bd_t *bd = gd->bd; @@ -174,57 +83,21 @@ static int fixup_memory_node(void *blob) return fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS); } -static int bootm_linux_fdt(int machid, bootm_headers_t *images) +static void announce_and_cleanup(void) { - ulong rd_len; - void (*kernel_entry)(int zero, int dt_machid, void *dtblob); - ulong of_size = images->ft_len; - char **of_flat_tree = &images->ft_addr; - ulong *initrd_start = &images->initrd_start; - ulong *initrd_end = &images->initrd_end; - struct lmb *lmb = &images->lmb; - int ret; - - kernel_entry = (void (*)(int, int, void *))images->ep; - - boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree); - - rd_len = images->rd_end - images->rd_start; - ret = boot_ramdisk_high(lmb, images->rd_start, rd_len, - initrd_start, initrd_end); - if (ret) - return ret; - - ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size); - if (ret) - return ret; - - debug("## Transferring control to Linux (at address %08lx) ...\n", - (ulong) kernel_entry); - - fdt_chosen(*of_flat_tree, 1); - - fixup_memory_node(*of_flat_tree); - - fdt_initrd(*of_flat_tree, *initrd_start, *initrd_end, 1); - - announce_and_cleanup(); - - kernel_entry(0, machid, *of_flat_tree); - /* does not return */ + printf("\nStarting kernel ...\n\n"); - return 1; -} +#ifdef CONFIG_USB_DEVICE + { + udc_disconnect(); + } #endif + cleanup_before_linux(); +} -#if defined (CONFIG_SETUP_MEMORY_TAGS) || \ - defined (CONFIG_CMDLINE_TAG) || \ - defined (CONFIG_INITRD_TAG) || \ - defined (CONFIG_SERIAL_TAG) || \ - defined (CONFIG_REVISION_TAG) static void setup_start_tag (bd_t *bd) { - params = (struct tag *) bd->bi_boot_params; + params = (struct tag *)bd->bi_boot_params; params->hdr.tag = ATAG_CORE; params->hdr.size = tag_size (tag_core); @@ -237,8 +110,7 @@ static void setup_start_tag (bd_t *bd) } -#ifdef CONFIG_SETUP_MEMORY_TAGS -static void setup_memory_tags (bd_t *bd) +static void setup_memory_tags(bd_t *bd) { int i; @@ -252,10 +124,8 @@ static void setup_memory_tags (bd_t *bd) params = tag_next (params); } } -#endif /* CONFIG_SETUP_MEMORY_TAGS */ - -static void setup_commandline_tag (bd_t *bd, char *commandline) +static void setup_commandline_tag(bd_t *bd, char *commandline) { char *p; @@ -280,9 +150,7 @@ static void setup_commandline_tag (bd_t *bd, char *commandline) params = tag_next (params); } - -#ifdef CONFIG_INITRD_TAG -static void setup_initrd_tag (bd_t *bd, ulong initrd_start, ulong initrd_end) +static void setup_initrd_tag(bd_t *bd, ulong initrd_start, ulong initrd_end) { /* an ATAG_INITRD node tells the kernel where the compressed * ramdisk can be found. ATAG_RDIMG is a better name, actually. @@ -295,10 +163,9 @@ static void setup_initrd_tag (bd_t *bd, ulong initrd_start, ulong initrd_end) params = tag_next (params); } -#endif /* CONFIG_INITRD_TAG */ #ifdef CONFIG_SERIAL_TAG -void setup_serial_tag (struct tag **tmp) +void setup_serial_tag(struct tag **tmp) { struct tag *params = *tmp; struct tag_serialnr serialnr; @@ -314,7 +181,6 @@ void setup_serial_tag (struct tag **tmp) } #endif -#ifdef CONFIG_REVISION_TAG void setup_revision_tag(struct tag **in_params) { u32 rev = 0; @@ -326,19 +192,141 @@ void setup_revision_tag(struct tag **in_params) params->u.revision.rev = rev; params = tag_next (params); } -#endif /* CONFIG_REVISION_TAG */ -static void setup_end_tag (bd_t *bd) +static void setup_end_tag(bd_t *bd) { params->hdr.tag = ATAG_NONE; params->hdr.size = 0; } -#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */ -static ulong get_sp(void) +static void create_atags(bootm_headers_t *images) { - ulong ret; + bd_t *bd = gd->bd; + char *commandline = getenv("bootargs"); - asm("mov %0, sp" : "=r"(ret) : ); - return ret; + setup_start_tag(bd); +#ifdef CONFIG_SERIAL_TAG + setup_serial_tag(¶ms); +#endif +#ifdef CONFIG_CMDLINE_TAG + setup_commandline_tag(gd->bd, commandline); +#endif +#ifdef CONFIG_REVISION_TAG + setup_revision_tag(¶ms); +#endif +#ifdef CONFIG_SETUP_MEMORY_TAGS + setup_memory_tags(bd); +#endif +#ifdef CONFIG_INITRD_TAG + if (images->rd_start && images->rd_end) + setup_initrd_tag(bd, images->rd_start, images->rd_end); +#endif + setup_end_tag(bd); +} + +static int create_fdt(bootm_headers_t *images) +{ + ulong of_size = images->ft_len; + char **of_flat_tree = &images->ft_addr; + ulong *initrd_start = &images->initrd_start; + ulong *initrd_end = &images->initrd_end; + struct lmb *lmb = &images->lmb; + ulong rd_len; + int ret; + + debug("using: FDT\n"); + + boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree); + + rd_len = images->rd_end - images->rd_start; + ret = boot_ramdisk_high(lmb, images->rd_start, rd_len, + initrd_start, initrd_end); + if (ret) + return ret; + + ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size); + if (ret) + return ret; + + fdt_chosen(*of_flat_tree, 1); + fixup_memory_node(*of_flat_tree); + fdt_initrd(*of_flat_tree, *initrd_start, *initrd_end, 1); + + return 0; +} + +/* Subcommand: PREP */ +static void boot_prep_linux(bootm_headers_t *images) +{ +#ifdef CONFIG_OF_LIBFDT + if (images->ft_len) { + debug("using: FDT\n"); + if (create_fdt(images)) { + printf("FDT creation failed! hanging..."); + hang(); + } + } else +#endif + { +#if defined(CONFIG_SETUP_MEMORY_TAGS) || \ + defined(CONFIG_CMDLINE_TAG) || \ + defined(CONFIG_INITRD_TAG) || \ + defined(CONFIG_SERIAL_TAG) || \ + defined(CONFIG_REVISION_TAG) + debug("using: ATAGS\n"); + create_atags(images); +#else + printf("FDT and ATAGS support not compiled in - hanging\n"); + hang(); +#endif + } +} + +/* Subcommand: GO */ +static void boot_jump_linux(bootm_headers_t *images) +{ + int machid = gd->bd->bi_arch_number; + char *s; + void (*kernel_entry)(int zero, int arch, uint params); + + kernel_entry = (void (*)(int, int, uint))images->ep; + + s = getenv("machid"); + if (s) { + strict_strtoul(s, 16, (long unsigned int *) &machid); + printf("Using machid 0x%x from environment\n", machid); + } + + debug("## Transferring control to Linux (at address %08lx)" \ + "...\n", (ulong) kernel_entry); + show_boot_progress(15); + announce_and_cleanup(); + kernel_entry(0, machid, gd->bd->bi_boot_params); +} + +/* Main Entry point for arm bootm implementation + * + * Modeled after the powerpc implementation + * DIFFERENCE: Instead of calling prep and go at the end + * they are called if subcommand is equal 0. + */ +int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) +{ + /* No need for those on ARM */ + if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE) + return -1; + + if (flag & BOOTM_STATE_OS_PREP) { + boot_prep_linux(images); + return 0; + } + + if (flag & BOOTM_STATE_OS_GO) { + boot_jump_linux(images); + return 0; + } + + boot_prep_linux(images); + boot_jump_linux(images); + return 0; }