From patchwork Mon Aug 29 16:08:13 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Schwarz X-Patchwork-Id: 112105 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 6CBA2B6F71 for ; Tue, 30 Aug 2011 02:08:31 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id CFA3D28102; Mon, 29 Aug 2011 18:08:29 +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 02zVK1myIWJi; Mon, 29 Aug 2011 18:08:29 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id C229F28103; Mon, 29 Aug 2011 18:08:27 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id C32C628103 for ; Mon, 29 Aug 2011 18:08:24 +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 16uGlYerfkEf for ; Mon, 29 Aug 2011 18:08:22 +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 A5B4628102 for ; Mon, 29 Aug 2011 18:08:21 +0200 (CEST) Received: by fxe6 with SMTP id 6so4310862fxe.3 for ; Mon, 29 Aug 2011 09:08:20 -0700 (PDT) Received: by 10.223.56.17 with SMTP id w17mr7328381fag.142.1314634100708; Mon, 29 Aug 2011 09:08:20 -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 c4sm3683090fac.11.2011.08.29.09.08.18 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 29 Aug 2011 09:08:19 -0700 (PDT) From: Simon Schwarz To: u-boot@lists.denx.de Date: Mon, 29 Aug 2011 18:08:13 +0200 Message-Id: <1314634093-8494-1-git-send-email-simonschwarzcor@gmail.com> X-Mailer: git-send-email 1.7.4.1 Organization: Corscience GmbH & Co. KG Cc: scottwood@freescale.com Subject: [U-Boot] [PATCH] 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 savebp command 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 --- arch/arm/lib/bootm.c | 330 +++++++++++++++++++++++++------------------------ 1 files changed, 168 insertions(+), 162 deletions(-) diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 802e833..5f112e2 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,16 @@ 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 void (*kernel_entry)(int zero, int arch, uint params); 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 +69,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,54 +84,19 @@ 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 + { + extern void udc_disconnect(void); + 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; @@ -237,7 +112,6 @@ static void setup_start_tag (bd_t *bd) } -#ifdef CONFIG_SETUP_MEMORY_TAGS static void setup_memory_tags (bd_t *bd) { int i; @@ -252,8 +126,6 @@ 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) { @@ -280,8 +152,6 @@ 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) { /* an ATAG_INITRD node tells the kernel where the compressed @@ -295,9 +165,18 @@ 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 +/* This is a workaround - if boards don't implement + * get_board_serial */ +__attribute__((weak)) +void get_board_serial(struct tag_serialnr *serialnr) +{ + printf("This board does not implement get_board_serial() \ + but calls it serialnr is filled with junk!\n"); + serialnr->high = 0xABCDF; + serialnr->low = 0xABCDF; +} + void setup_serial_tag (struct tag **tmp) { struct tag *params = *tmp; @@ -312,9 +191,7 @@ void setup_serial_tag (struct tag **tmp) params = tag_next (params); *tmp = params; } -#endif -#ifdef CONFIG_REVISION_TAG void setup_revision_tag(struct tag **in_params) { u32 rev = 0; @@ -326,19 +203,148 @@ 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) { 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: CMDLINE */ +static int boot_cmdline_linux(bootm_headers_t *images) +{ + return -1; /* not implemented */ +} + +/* Subcommand: BDT */ +static int boot_bd_t_linux(bootm_headers_t *images) +{ + return -1; /* not implemented */ +} + +/* 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 failed - hanging\n"); + hang(); +#endif + } + + kernel_entry = (void (*)(int, int, uint))images->ep; +} + +/* Subcommand: GO */ +static void boot_jump_linux(bootm_headers_t *images) +{ + int machid = gd->bd->bi_arch_number; + char *s; + s = getenv("machid"); + if (s) { + strict_strtoul(s, 16, (long unsigned int *) &machid); + debug("Using machid 0x%x from environment\n", machid); + } + + debug("Using machid 0x%x from bd\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 subommand is equal 0. + */ +int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) +{ + if (flag & BOOTM_STATE_OS_CMDLINE) + boot_cmdline_linux(images); + + if (flag & BOOTM_STATE_OS_BD_T) + boot_bd_t_linux(images); + + if (flag & BOOTM_STATE_OS_PREP || flag == 0) + boot_prep_linux(images); + + if (flag & BOOTM_STATE_OS_GO || flag == 0) + boot_jump_linux(images); + + return 0; }