From patchwork Sat Feb 4 10:22:43 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefano Babic X-Patchwork-Id: 139575 X-Patchwork-Delegate: trini@ti.com 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 98CEBB71CA for ; Sat, 4 Feb 2012 21:25:01 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 682DB280F8; Sat, 4 Feb 2012 11:24:21 +0100 (CET) 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 tqc0AOn7Ih29; Sat, 4 Feb 2012 11:24:21 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id B93202811E; Sat, 4 Feb 2012 11:23:39 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 75E30280E8 for ; Sat, 4 Feb 2012 11:23:31 +0100 (CET) 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 oW6uIIV7G6l4 for ; Sat, 4 Feb 2012 11:23:30 +0100 (CET) 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 smtpi4.ngi.it (smtpi4.ngi.it [88.149.128.104]) by theia.denx.de (Postfix) with ESMTP id B4CBA280FF for ; Sat, 4 Feb 2012 11:23:13 +0100 (CET) Received: from paperina.lan (unknown [88.149.182.160]) by smtpi4.ngi.it (Postfix) with ESMTP id 0133E4240C; Sat, 4 Feb 2012 11:23:13 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by paperina.lan (Postfix) with ESMTP id BFBCA140A09E; Sat, 4 Feb 2012 11:23:12 +0100 (CET) Received: from paperina.lan ([127.0.0.1]) by localhost (paperina.lan [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id o73ODnrYLuu6; Sat, 4 Feb 2012 11:23:09 +0100 (CET) Received: from papero.lan (papero.lan [192.168.2.247]) by paperina.lan (Postfix) with ESMTP id 06AF8140A14C; Sat, 4 Feb 2012 11:22:49 +0100 (CET) From: Stefano Babic To: u-boot@lists.denx.de Date: Sat, 4 Feb 2012 11:22:43 +0100 Message-Id: <1328350963-30989-13-git-send-email-sbabic@denx.de> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1328350963-30989-1-git-send-email-sbabic@denx.de> References: <1324049833-18143-1-git-send-email-sbabic@denx.de> <1328350963-30989-1-git-send-email-sbabic@denx.de> Cc: Simon Schwarz Subject: [U-Boot] [PATCH V13 12/12] arm: Add Prep subcommand support to bootm X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 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 From: Simon Schwarz 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 Acked-by: Stefano Babic Tested-by: Stefano Babic --- arch/arm/include/asm/bootm.h | 26 ++++ arch/arm/lib/bootm.c | 341 ++++++++++++++++++++++-------------------- 2 files changed, 202 insertions(+), 165 deletions(-) create mode 100644 arch/arm/include/asm/bootm.h diff --git a/arch/arm/include/asm/bootm.h b/arch/arm/include/asm/bootm.h new file mode 100644 index 0000000..db2ff94 --- /dev/null +++ b/arch/arm/include/asm/bootm.h @@ -0,0 +1,26 @@ +/* Copyright (C) 2011 + * Corscience GmbH & Co. KG - Simon Schwarz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef ARM_BOOTM_H +#define ARM_BOOTM_H + +#ifdef CONFIG_USB_DEVICE +extern void udc_disconnect(void); +#endif + +#endif diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index afa0093..03c25e9 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 @@ -29,35 +33,26 @@ #include #include #include +#include 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); - +#if defined(CONFIG_SETUP_MEMORY_TAGS) || \ + defined(CONFIG_CMDLINE_TAG) || \ + defined(CONFIG_INITRD_TAG) || \ + defined(CONFIG_SERIAL_TAG) || \ + defined(CONFIG_REVISION_TAG) 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) { ulong sp; @@ -80,85 +75,7 @@ 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; @@ -173,60 +90,26 @@ static int fixup_memory_node(void *blob) return fdt_fixup_memory_banks(blob, start, size, CONFIG_NR_DRAM_BANKS); } +#endif -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_fixup_ethernet(*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) +#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,10 +120,10 @@ static void setup_start_tag (bd_t *bd) params = tag_next (params); } - +#endif #ifdef CONFIG_SETUP_MEMORY_TAGS -static void setup_memory_tags (bd_t *bd) +static void setup_memory_tags(bd_t *bd) { int i; @@ -254,10 +137,10 @@ static void setup_memory_tags (bd_t *bd) params = tag_next (params); } } -#endif /* CONFIG_SETUP_MEMORY_TAGS */ - +#endif -static void setup_commandline_tag (bd_t *bd, char *commandline) +#ifdef CONFIG_CMDLINE_TAG +static void setup_commandline_tag(bd_t *bd, char *commandline) { char *p; @@ -281,10 +164,10 @@ static void setup_commandline_tag (bd_t *bd, char *commandline) params = tag_next (params); } - +#endif #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. @@ -297,10 +180,10 @@ static void setup_initrd_tag (bd_t *bd, ulong initrd_start, ulong initrd_end) params = tag_next (params); } -#endif /* CONFIG_INITRD_TAG */ +#endif #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; @@ -328,19 +211,147 @@ void setup_revision_tag(struct tag **in_params) params->u.revision.rev = rev; params = tag_next (params); } -#endif /* CONFIG_REVISION_TAG */ +#endif -static void setup_end_tag (bd_t *bd) +#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_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 */ +#endif -static ulong get_sp(void) +#ifdef CONFIG_OF_LIBFDT +static int create_fdt(bootm_headers_t *images) { - ulong ret; + 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; - asm("mov %0, sp" : "=r"(ret) : ); - return 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; +} +#endif + +/* Subcommand: PREP */ +static void boot_prep_linux(bootm_headers_t *images) +{ +#ifdef CONFIG_CMDLINE_TAG + char *commandline = getenv("bootargs"); +#endif + +#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"); + setup_start_tag(gd->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(gd->bd); +#endif +#ifdef CONFIG_INITRD_TAG + if (images->rd_start && images->rd_end) + setup_initrd_tag(gd->bd, images->rd_start, + images->rd_end); +#endif + setup_end_tag(gd->bd); +#else /* all tags */ + printf("FDT and ATAGS support not compiled in - hanging\n"); + hang(); +#endif /* all tags */ + } +} + +/* 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; }