[U-Boot] [PATCH] arm: Adds saving of Kernel boot args to NAND flash

Adds the saving of either ATAGS or FDT kernel argument image to NAND flash. This image then can be used in SPL boot.
This adds two CONFIG_ paramter to board configuration (in this RFC as example added to devkit8000.h): CONFIG_SAVE_BOOT_ARGS makes the feature active CONFIG_BOOT_ARGS_NAND_OFS defines the offset in NAND flash where the image is saved
For OMAP34XX the image is saved with hw-ecc.
Signed-off-by: Simon Schwarz simonschwarzcor@gmail.com --- This is an RFC on how this can be done.
What I don't like here is the omap specific hw ecc switch. But the nand-spl has just hw-ecc yet - at least afaik.
Belonging discussion: http://marc.info/?t=130942998000003
Regards Simon
arch/arm/lib/bootm.c | 64 ++++++++++++++++++++++++++++++++++++++++++ include/configs/devkit8000.h | 4 ++ 2 files changed, 68 insertions(+), 0 deletions(-)
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 802e833..57e08d3 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -5,6 +5,10 @@ * * Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) * + * Copyright (C) 2011 + * Corscience GmbH & Co. KG - Simon Schwarz schwarz@corscience.de + * - added saving of kernel-parameter-image to NAND flash + * * 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 @@ -30,6 +34,14 @@ #include <libfdt.h> #include <fdt_support.h>
+#ifdef CONFIG_SAVE_BOOT_ARGS +#include <nand.h> +#include <asm/setup.h> +#ifdef CONFIG_OMAP34XX +#include <asm/arch/sys_proto.h> +#endif +#endif + DECLARE_GLOBAL_DATA_PTR;
#if defined (CONFIG_SETUP_MEMORY_TAGS) || \ @@ -58,6 +70,38 @@ static ulong get_sp(void); static int bootm_linux_fdt(int machid, bootm_headers_t *images); #endif
+#ifdef CONFIG_SAVE_BOOT_ARGS +/* This function writes given bootparams to NAND flash + * adr: Start adress of Kernel parameter image (ATAGS, FDT) + * length: length of the image in byte + * + * borrowd heavily from common/cmd_nand.c + */ +void boot_params_to_nand(u_char *adr, size_t length) { + nand_info_t *nand = &nand_info[nand_curr_device]; /* use current dev */ + loff_t off = CONFIG_BOOT_ARGS_NAND_OFS; + nand_erase_options_t opts; + +#ifdef CONFIG_OMAP34XX + omap_nand_switch_ecc(1); /* use hw ecc on omap for SPL compat */ +#endif + /* erase */ + memset(&opts, 0, sizeof(opts)); + opts.offset = off; + opts.length = length; + opts.quiet = 1; + opts.spread = 1; + nand_erase_opts(nand,&opts); + + /* write */ + if(nand_write_skip_bad(nand, off, &length, adr, 0)) + printf("FAILED!\n"); + + printf("Written to offset 0x%llX, size: %d bytes\n", + off, length); +} +#endif /* CONFIG_SAVE_BOOT_ARGS */ + void arch_lmb_reserve(struct lmb *lmb) { ulong sp; @@ -104,6 +148,10 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) char *commandline = getenv ("bootargs"); #endif
+#ifdef CONFIG_SAVE_BOOT_ARGS + struct tag *t; + size_t size=0; +#endif if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) return 1;
@@ -150,6 +198,17 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) setup_end_tag(bd); #endif
+#ifdef CONFIG_SAVE_BOOT_ARGS + printf("write ATAGS to NAND...\n"); + + /* get size of atags */ + for_each_tag(t, (struct tag *)(bd->bi_boot_params)) + size += t->hdr.size; + size += 2; /* ATAG_NONE has size 0 */ + size *= 4; /* words -> byte! */ + boot_params_to_nand((u_char *)bd->bi_boot_params, size); +#endif + announce_and_cleanup();
kernel_entry(0, machid, bd->bi_boot_params); @@ -208,6 +267,11 @@ static int bootm_linux_fdt(int machid, bootm_headers_t *images)
fdt_initrd(*of_flat_tree, *initrd_start, *initrd_end, 1);
+#ifdef CONFIG_SAVE_BOOT_ARGS + printf("write FDT to NAND...\n"); + boot_params_to_nand((u_char *)(*of_flat_tree),of_size); +#endif + announce_and_cleanup();
kernel_entry(0, machid, *of_flat_tree); diff --git a/include/configs/devkit8000.h b/include/configs/devkit8000.h index 1bf6bea..3061fc2 100644 --- a/include/configs/devkit8000.h +++ b/include/configs/devkit8000.h @@ -345,4 +345,8 @@ CONFIG_SYS_INIT_RAM_SIZE - \ GENERATED_GBL_DATA_SIZE)
+/* Direct OS boot options */ +#define CONFIG_SAVE_BOOT_ARGS +#define CONFIG_BOOT_ARGS_NAND_OFS 0x700000 + #endif /* __CONFIG_H */

On Tue, 5 Jul 2011 15:20:39 +0200 Simon Schwarz simonschwarzcor@googlemail.com wrote:
+#ifdef CONFIG_SAVE_BOOT_ARGS +/* This function writes given bootparams to NAND flash
- adr: Start adress of Kernel parameter image (ATAGS, FDT)
- length: length of the image in byte
- borrowd heavily from common/cmd_nand.c
- */
+void boot_params_to_nand(u_char *adr, size_t length) {
Brace on its own line for functions
- /* write */
- if(nand_write_skip_bad(nand, off, &length, adr, 0))
printf("FAILED!\n");
Space after "if"
+#ifdef CONFIG_SAVE_BOOT_ARGS
- struct tag *t;
- size_t size=0;
+#endif
Spaces around =
if ((flag != 0) && (flag != BOOTM_STATE_OS_GO)) return 1;
@@ -150,6 +198,17 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) setup_end_tag(bd); #endif
+#ifdef CONFIG_SAVE_BOOT_ARGS
- printf("write ATAGS to NAND...\n");
- /* get size of atags */
- for_each_tag(t, (struct tag *)(bd->bi_boot_params))
size += t->hdr.size;
- size += 2; /* ATAG_NONE has size 0 */
- size *= 4; /* words -> byte! */
- boot_params_to_nand((u_char *)bd->bi_boot_params, size);
+#endif
announce_and_cleanup();
kernel_entry(0, machid, bd->bi_boot_params);
@@ -208,6 +267,11 @@ static int bootm_linux_fdt(int machid, bootm_headers_t *images)
fdt_initrd(*of_flat_tree, *initrd_start, *initrd_end, 1);
+#ifdef CONFIG_SAVE_BOOT_ARGS
- printf("write FDT to NAND...\n");
- boot_params_to_nand((u_char *)(*of_flat_tree),of_size);
+#endif
Why are you writing to NAND as part of bootm?
If you just want access to the results of the FDT/ATAG preparation that bootm does, consider using the bootm subcommands to prepare them, then normal U-Boot commands to write to NAND.
-Scott

Hi,
thanks for your feedback!
I will address the style problems - didn't run checkpatch for the RFC - sorry my fault.
Why are you writing to NAND as part of bootm?
If you just want access to the results of the FDT/ATAG preparation that bootm does, consider using the bootm subcommands to prepare them, then normal U-Boot commands to write to NAND.
Hm thats a point. I see this as a feature as it saves new settings without the need of special commands - you start the same configuration either with u-boot or the SPL. But you are right - an extra command would also be nice. I will add this.
Regards Simon

On Wed, 6 Jul 2011 09:42:52 +0200 Simon Schwarz simonschwarzcor@googlemail.com wrote:
Hi,
thanks for your feedback!
I will address the style problems - didn't run checkpatch for the RFC
- sorry my fault.
Why are you writing to NAND as part of bootm?
If you just want access to the results of the FDT/ATAG preparation that bootm does, consider using the bootm subcommands to prepare them, then normal U-Boot commands to write to NAND.
Hm thats a point. I see this as a feature as it saves new settings without the need of special commands
But that's not what bootm is for. If you're doing something new, it should be in a new command -- or in a script of existing commands.
-Scott

But that's not what bootm is for. If you're doing something new, it should be in a new command -- or in a script of existing commands.
True. The upper patch was the quickest way to do this.
I implemented a first test for a command. This is a bit ugly because I have to rip apart bootm. For now I heavily used extern and removed static keywords from bootm - this is ok for the testing but not to get it into mainline...
I'am not sure how i can handle this to get it into mainline. The main problem is in arch/arm/lib/bootm.c implementation: static void setup_start_tag (bd_t *bd); static void setup_memory_tags (bd_t *bd); static void setup_commandline_tag (bd_t *bd, char *commandline); static void setup_initrd_tag (bd_t *bd, ulong initrd_start, ulong initrd_end); static void setup_end_tag (bd_t *bd); static struct tag *params; static ulong get_sp(void); static int bootm_linux_fdt(int machid, bootm_headers_t *images);
These function i need to build the atags. But they are defined static and not really meant to be used from the outside. What comes to my mind here is to create a new setup_atags.c in the same directory + a header in include. Is this the right place for this? Maybe another solution?
Regards Simon

On Thu, 7 Jul 2011 17:50:12 +0200 Simon Schwarz simonschwarzcor@googlemail.com wrote:
But that's not what bootm is for. If you're doing something new, it should be in a new command -- or in a script of existing commands.
True. The upper patch was the quickest way to do this.
I implemented a first test for a command. This is a bit ugly because I have to rip apart bootm. For now I heavily used extern and removed static keywords from bootm - this is ok for the testing but not to get it into mainline...
I'am not sure how i can handle this to get it into mainline. The main problem is in arch/arm/lib/bootm.c implementation: static void setup_start_tag (bd_t *bd); static void setup_memory_tags (bd_t *bd); static void setup_commandline_tag (bd_t *bd, char *commandline); static void setup_initrd_tag (bd_t *bd, ulong initrd_start, ulong initrd_end); static void setup_end_tag (bd_t *bd); static struct tag *params; static ulong get_sp(void); static int bootm_linux_fdt(int machid, bootm_headers_t *images);
These function i need to build the atags. But they are defined static and not really meant to be used from the outside. What comes to my mind here is to create a new setup_atags.c in the same directory + a header in include. Is this the right place for this? Maybe another solution?
Look at bootm subcommands to run just the portion of the existing bootm functionality that you need. Type "help bootm" for details.
-Scott

Look at bootm subcommands to run just the portion of the existing bootm functionality that you need. Type "help bootm" for details.
Of course I could implement a subcommand - actually this seems to be the best method.
IMHO "prep" would be the right one to use? correct?
Regards Simon

On Fri, 8 Jul 2011 09:53:46 +0200 Simon Schwarz simonschwarzcor@googlemail.com wrote:
Look at bootm subcommands to run just the portion of the existing bootm functionality that you need. Type "help bootm" for details.
Of course I could implement a subcommand - actually this seems to be the best method.
IMHO "prep" would be the right one to use? correct?
Probably.
-Scott

If you just want access to the results of the FDT/ATAG preparation that bootm does, consider using the bootm subcommands to prepare them, then normal U-Boot commands to write to NAND.
Me again. I rethought and the problem with bootm is that the subfunctions (bootm_linux_fdt/do_bootm_linux) are directly boot the kernel. That means either I copy almost the whole function and delete the kernel_entry-call. Or I move the tag/fdt creation out of bootm-command and create a extra function.
The first way I consider bad because of code duplication - therefore I would take the second path. Any Objections?
Regards Simon

Adds prep subcommand to bootm implementation of ARM. When bootm is called prep the function stops right after ATAGS creation and before announce_and_cleanup.
This is used in savebp command
Signed-off-by: Simon Schwarz simonschwarzcor@gmail.com --- Ok second RFC!
I know that there are many style problems - but I don't have the time before weekend/at the weekend to fix them.
So please no close inspection just a comment on the way how the patch is done.
I will address the styleproblems on Monday!
Thanks, and have a nive weekend! Simon
--- arch/arm/lib/bootm.c | 107 +++++++++++++++++++++++++++----------------------- 1 files changed, 58 insertions(+), 49 deletions(-)
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 802e833..58334a2 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -1,4 +1,7 @@ -/* +/* Copyright (C) 2011 + * Corscience GmbH & Co. KG - Simon Schwarz schwarz@corscience.de + * - Added prep subcommand support + * * (C) Copyright 2002 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> * Marius Groeger mgroeger@sysgo.de @@ -55,7 +58,7 @@ static struct tag *params;
static ulong get_sp(void); #if defined(CONFIG_OF_LIBFDT) -static int bootm_linux_fdt(int machid, bootm_headers_t *images); +static int bootm_linux_fdt(int machid, bootm_headers_t *images, int flag); #endif
void arch_lmb_reserve(struct lmb *lmb) @@ -104,57 +107,61 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) 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); - } + if ((flag != 0) && (flag != BOOTM_STATE_OS_GO || + flag != BOOTM_STATE_OS_PREP)) + return 1; /* subcommand not implemented */ + else + if((flag == 0) || flag == BOOTM_STATE_OS_PREP) { + s = getenv ("machid"); + if (s) { + machid = simple_strtoul (s, NULL, 16); + printf ("Using machid 0x%x from environment\n", machid); + }
- show_boot_progress (15); + show_boot_progress (15);
#ifdef CONFIG_OF_LIBFDT - if (images->ft_len) - return bootm_linux_fdt(machid, images); + if (images->ft_len) + return bootm_linux_fdt(machid, images, flag); #endif
- kernel_entry = (void (*)(int, int, uint))images->ep; + kernel_entry = (void (*)(int, int, uint))images->ep;
- debug ("## Transferring control to Linux (at address %08lx) ...\n", - (ulong) kernel_entry); + 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); + setup_start_tag (bd); #ifdef CONFIG_SERIAL_TAG - setup_serial_tag (¶ms); + setup_serial_tag (¶ms); #endif #ifdef CONFIG_REVISION_TAG - setup_revision_tag (¶ms); + setup_revision_tag (¶ms); #endif #ifdef CONFIG_SETUP_MEMORY_TAGS - setup_memory_tags (bd); + setup_memory_tags (bd); #endif #ifdef CONFIG_CMDLINE_TAG - setup_commandline_tag (bd, commandline); + 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); + if (images->rd_start && images->rd_end) + setup_initrd_tag (bd, images->rd_start, images->rd_end); #endif - setup_end_tag(bd); + setup_end_tag(bd); #endif + }
- announce_and_cleanup(); - - kernel_entry(0, machid, bd->bi_boot_params); - /* does not return */ + if(flag == 0 || flag == BOOTM_STATE_OS_GO) { + announce_and_cleanup();
+ kernel_entry(0, machid, bd->bi_boot_params); + /* does not return */ + } return 1; }
@@ -174,7 +181,7 @@ 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 int bootm_linux_fdt(int machid, bootm_headers_t *images, int flag) { ulong rd_len; void (*kernel_entry)(int zero, int dt_machid, void *dtblob); @@ -185,34 +192,36 @@ static int bootm_linux_fdt(int machid, bootm_headers_t *images) 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; + if((flag == 0) || flag == BOOTM_STATE_OS_PREP) { + kernel_entry = (void (*)(int, int, void *))images->ep;
- ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size); - if (ret) - return ret; + boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree);
- debug("## Transferring control to Linux (at address %08lx) ...\n", - (ulong) kernel_entry); + 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;
- fdt_chosen(*of_flat_tree, 1); + ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size); + if (ret) + return ret;
- fixup_memory_node(*of_flat_tree); + debug("## Transferring control to Linux (at address %08lx) ...\n", + (ulong) kernel_entry);
- fdt_initrd(*of_flat_tree, *initrd_start, *initrd_end, 1); + fdt_chosen(*of_flat_tree, 1);
- announce_and_cleanup(); + fixup_memory_node(*of_flat_tree);
- kernel_entry(0, machid, *of_flat_tree); - /* does not return */ + fdt_initrd(*of_flat_tree, *initrd_start, *initrd_end, 1); + } + if(flag == 0 || flag == BOOTM_STATE_OS_GO) { + announce_and_cleanup();
+ kernel_entry(0, machid, *of_flat_tree); + /* does not return */ + } return 1; } #endif

Adds the saving of either ATAGS or FDT kernel argument image to NAND flash This image then can be used in SPL boot.
Command savebp is added to achieve this. This inits a partial run of bootm utilizing subcommands. The result then is saved to NAND flash.
This adds the following defines to board configuration: CONFIG_CMD_SAVEBP activates the command CONFIG_CMD_SAVEBP_ARGS_NAND_OFS defines the offset in NAND flash where the image is saved
For OMAP34XX the image is saved with hw-ecc.
--- For RFC: the FDT implementation is todo
Signed-off-by: Simon Schwarz simonschwarzcor@gmail.com --- arch/arm/lib/Makefile | 1 + arch/arm/lib/savebp.c | 100 ++++++++++++++++++++++++++++++++++++++++++ common/Makefile | 2 +- common/cmd_savebp.c | 97 ++++++++++++++++++++++++++++++++++++++++ include/configs/devkit8000.h | 4 ++ 5 files changed, 203 insertions(+), 1 deletions(-) create mode 100644 arch/arm/lib/savebp.c create mode 100644 common/cmd_savebp.c
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index 03b1b5e..ccaae4f 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -44,6 +44,7 @@ COBJS-y += cache-cp15.o endif COBJS-y += interrupts.o COBJS-y += reset.o +COBJS-$(CONFIG_CMD_SAVEBP) += savebp.o SOBJS-$(CONFIG_USE_ARCH_MEMSET) += memset.o SOBJS-$(CONFIG_USE_ARCH_MEMCPY) += memcpy.o
diff --git a/arch/arm/lib/savebp.c b/arch/arm/lib/savebp.c new file mode 100644 index 0000000..8394994 --- /dev/null +++ b/arch/arm/lib/savebp.c @@ -0,0 +1,100 @@ +/* Copyright (C) 2011 + * Corscience GmbH & Co. KG - Simon Schwarz schwarz@corscience.de + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +#include <common.h> +#include <command.h> +/*#include <fdt.h>*/ +/*#include <libfdt.h>*/ +/*#include <fdt_support.h>*/ + +#ifdef CONFIG_CMD_SAVEBP +#include <nand.h> +#ifdef CONFIG_OMAP34XX +#include <asm/arch/sys_proto.h> +#endif +#endif + +DECLARE_GLOBAL_DATA_PTR; +extern bootm_headers_t images; /* Struct of the Image header */ + +/* This function writes given bootparams to NAND flash + * adr: Start adress of Kernel parameter image (ATAGS, FDT) + * length: length of the image in byte + * off: offset in NAND flash + * + * borrowd heavily from common/cmd_nand.c + */ +void boot_params_to_nand(u_char *adr, size_t length, loff_t off) +{ + nand_info_t *nand = &nand_info[nand_curr_device]; /* use current dev */ + nand_erase_options_t opts; + +#ifdef CONFIG_OMAP34XX + omap_nand_switch_ecc(1); /* use hw ecc on omap for SPL compat */ +#endif + /* erase */ + memset(&opts, 0, sizeof(opts)); + opts.offset = off; + opts.length = length; + opts.quiet = 1; + opts.spread = 1; + nand_erase_opts(nand, &opts); + + /* write */ + if (nand_write_skip_bad(nand, off, &length, adr, 0)) + printf("FAILED!\n"); + + printf("Written to offset 0x%llX, size: %d bytes\n", + off, length); +} + +/* Saves FDT to NAND */ +int do_savebp_fdt(loff_t offset) +{ + printf(">>>do_save_params_fdt()"); + printf("NOT IMPLEMENTED YET!"); + printf("<<<do_save_params_fdt()"); + return 0; +} + + +/* Saves ATAGS to NAND */ +int do_savebp_atags(loff_t offset, bootm_headers_t *images) +{ + /* Vars */ + struct tag *t; + size_t size = 0; + bd_t *bd = gd->bd; + + printf("write ATAGS to NAND...\n"); + + /* get size of atags */ + for_each_tag(t, (struct tag *)(bd->bi_boot_params)) + size += t->hdr.size; + size += 2; /* ATAG_NONE has size 0 */ + size *= 4; /* words -> byte! */ + + /* save em */ + boot_params_to_nand((u_char *)bd->bi_boot_params, size, offset); + + return 0; +} diff --git a/common/Makefile b/common/Makefile index 224b7cc..d7719bc 100644 --- a/common/Makefile +++ b/common/Makefile @@ -160,6 +160,7 @@ COBJS-$(CONFIG_USB_STORAGE) += usb_storage.o endif COBJS-$(CONFIG_CMD_XIMG) += cmd_ximg.o COBJS-$(CONFIG_YAFFS2) += cmd_yaffs2.o +COBJS-$(CONFIG_CMD_SAVEBP) += cmd_savebp.o
# others COBJS-$(CONFIG_DDR_SPD) += ddr_spd.o @@ -174,7 +175,6 @@ COBJS-$(CONFIG_MODEM_SUPPORT) += modem.o COBJS-$(CONFIG_UPDATE_TFTP) += update.o COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
- COBJS := $(sort $(COBJS-y)) XCOBJS := $(sort $(XCOBJS-y)) SRCS := $(COBJS:.o=.c) $(XCOBJS:.o=.c) diff --git a/common/cmd_savebp.c b/common/cmd_savebp.c new file mode 100644 index 0000000..b8233f8 --- /dev/null +++ b/common/cmd_savebp.c @@ -0,0 +1,97 @@ +/* Copyright (C) 2011 + * Corscience GmbH & Co. KG - Simon Schwarz schwarz@corscience.de + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +#include <common.h> +#include <command.h> + +#define TYPE_FDT 0 +#define TYPE_ATAGS 1 + +extern bootm_headers_t images; + +static inline int str2off(const char *p, loff_t *num) +{ + char *endptr; + + *num = simple_strtoull(p, &endptr, 16); + return *p != '\0' && *endptr == '\0'; +} + +int do_savebp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + loff_t offset; + char * bootm_argsv[] = {"do_bootm","xxxxxxx"}; + + /* - Validate args - */ + if (argc == 2) { + if (!str2off(argv[2], &offset)) { + printf("'%s' is not a number\n",argv[2]); + return cmd_usage(cmdtp); + } + } else if (argc == 1) { + offset = (loff_t)CONFIG_CMD_SAVEBP_NAND_OFS; + printf("using standard destination at: 0x%x\n", (uint32_t)offset); + } else + return cmd_usage(cmdtp); + + /* - do the work - */ + /* exec bootm_start as subcommand of do_bootm to init the images + * data structure */ + bootm_argsv[1] = "start"; + if(do_bootm(find_cmd("do_bootm"),0,2,bootm_argsv)) + printf("ERROR: subcommand start of bootm failed\n"); + + bootm_argsv[1] = "loados"; + if(do_bootm(find_cmd("do_bootm"),0,2,bootm_argsv)) + printf("ERROR: subcommand loados of bootm failed\n"); + +#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH + bootm_argsv[1] = "ramdisk"; + if(do_bootm(find_cmd("do_bootm"),0,2,bootm_argsv)) + printf("ERROR: subcommand ramdisk of bootm failed\n"); +#endif + +#ifdef CONFIG_OF_LIBFDT + bootm_argsv[1] = "fdt"; + if(do_bootm(find_cmd("do_bootm"),0,2,bootm_argsv)) + printf("ERROR: subcommand fdt of bootm failed\n"); +#endif + + /*subcommand cmdline and bdt are not implemented*/ + + bootm_argsv[1] = "prep"; + if(do_bootm(find_cmd("do_bootm"),0,2,bootm_argsv)) + printf("ERROR: subcommand prep of bootm failed\n"); + + /* call arch specific handlers */ +#ifdef CONFIG_OF_LIBFDT + /*do_savebp_fdt(offset);*/ +#else + do_savebp_atags(offset, &images); +#endif + return 0; +} + +U_BOOT_CMD( + savebp,3,1,do_savebp,"save boot params to NAND flash", + "[nand_offset] saves the parameter image to NAND. \ + Kernel image has to be in RAM!"); diff --git a/include/configs/devkit8000.h b/include/configs/devkit8000.h index 1bf6bea..ff6d750 100644 --- a/include/configs/devkit8000.h +++ b/include/configs/devkit8000.h @@ -194,6 +194,7 @@ #define CONFIG_CMD_MTDPARTS /* Enable MTD parts commands */ #define CONFIG_CMD_NAND /* NAND support */ #define CONFIG_CMD_NAND_LOCK_UNLOCK /* nand (un)lock commands */ +#define CONFIG_CMD_SAVEBP /* Save kernel params command */
#undef CONFIG_CMD_FPGA /* FPGA configuration Support */ #undef CONFIG_CMD_IMI /* iminfo */ @@ -345,4 +346,7 @@ CONFIG_SYS_INIT_RAM_SIZE - \ GENERATED_GBL_DATA_SIZE)
+/* Direct OS boot options */ +#define CONFIG_CMD_SAVEBP_NAND_OFS 0x700000 + #endif /* __CONFIG_H */

Sorry, this was meant in-reply to this message: [PATCH] arm: Adds saving of Kernel boot args to NAND flash
2011/7/8 Simon Schwarz simonschwarzcor@googlemail.com:
Adds prep subcommand to bootm implementation of ARM. When bootm is called prep the function stops right after ATAGS creation and before announce_and_cleanup.
This is used in savebp command
Signed-off-by: Simon Schwarz simonschwarzcor@gmail.com
Ok second RFC!
I know that there are many style problems - but I don't have the time before weekend/at the weekend to fix them.
So please no close inspection just a comment on the way how the patch is done.
I will address the styleproblems on Monday!
Thanks, and have a nive weekend! Simon
arch/arm/lib/bootm.c | 107 +++++++++++++++++++++++++++----------------------- 1 files changed, 58 insertions(+), 49 deletions(-)
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 802e833..58334a2 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -1,4 +1,7 @@ -/* +/* Copyright (C) 2011
- Corscience GmbH & Co. KG - Simon Schwarz schwarz@corscience.de
- - Added prep subcommand support
* (C) Copyright 2002 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> * Marius Groeger mgroeger@sysgo.de @@ -55,7 +58,7 @@ static struct tag *params;
static ulong get_sp(void); #if defined(CONFIG_OF_LIBFDT) -static int bootm_linux_fdt(int machid, bootm_headers_t *images); +static int bootm_linux_fdt(int machid, bootm_headers_t *images, int flag); #endif
void arch_lmb_reserve(struct lmb *lmb) @@ -104,57 +107,61 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) 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);
- }
- if ((flag != 0) && (flag != BOOTM_STATE_OS_GO ||
- flag != BOOTM_STATE_OS_PREP))
- return 1; /* subcommand not implemented */
- else
- if((flag == 0) || flag == BOOTM_STATE_OS_PREP) {
- s = getenv ("machid");
- if (s) {
- machid = simple_strtoul (s, NULL, 16);
- printf ("Using machid 0x%x from environment\n", machid);
- }
- show_boot_progress (15);
- show_boot_progress (15);
#ifdef CONFIG_OF_LIBFDT
- if (images->ft_len)
- return bootm_linux_fdt(machid, images);
- if (images->ft_len)
- return bootm_linux_fdt(machid, images, flag);
#endif
- kernel_entry = (void (*)(int, int, uint))images->ep;
- kernel_entry = (void (*)(int, int, uint))images->ep;
- debug ("## Transferring control to Linux (at address %08lx) ...\n",
- (ulong) kernel_entry);
- 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);
- setup_start_tag (bd);
#ifdef CONFIG_SERIAL_TAG
- setup_serial_tag (¶ms);
- setup_serial_tag (¶ms);
#endif #ifdef CONFIG_REVISION_TAG
- setup_revision_tag (¶ms);
- setup_revision_tag (¶ms);
#endif #ifdef CONFIG_SETUP_MEMORY_TAGS
- setup_memory_tags (bd);
- setup_memory_tags (bd);
#endif #ifdef CONFIG_CMDLINE_TAG
- setup_commandline_tag (bd, commandline);
- 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);
- if (images->rd_start && images->rd_end)
- setup_initrd_tag (bd, images->rd_start, images->rd_end);
#endif
- setup_end_tag(bd);
- setup_end_tag(bd);
#endif
- }
- announce_and_cleanup();
- kernel_entry(0, machid, bd->bi_boot_params);
- /* does not return */
if(flag == 0 || flag == BOOTM_STATE_OS_GO) {
announce_and_cleanup();
kernel_entry(0, machid, bd->bi_boot_params);
/* does not return */
}
return 1; }
@@ -174,7 +181,7 @@ 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 int bootm_linux_fdt(int machid, bootm_headers_t *images, int flag) { ulong rd_len; void (*kernel_entry)(int zero, int dt_machid, void *dtblob); @@ -185,34 +192,36 @@ static int bootm_linux_fdt(int machid, bootm_headers_t *images) 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;
- if((flag == 0) || flag == BOOTM_STATE_OS_PREP) {
- kernel_entry = (void (*)(int, int, void *))images->ep;
- ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size);
- if (ret)
- return ret;
- boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree);
- debug("## Transferring control to Linux (at address %08lx) ...\n",
- (ulong) kernel_entry);
- 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;
- fdt_chosen(*of_flat_tree, 1);
- ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size);
- if (ret)
- return ret;
- fixup_memory_node(*of_flat_tree);
- debug("## Transferring control to Linux (at address %08lx) ...\n",
- (ulong) kernel_entry);
- fdt_initrd(*of_flat_tree, *initrd_start, *initrd_end, 1);
- fdt_chosen(*of_flat_tree, 1);
- announce_and_cleanup();
- fixup_memory_node(*of_flat_tree);
- kernel_entry(0, machid, *of_flat_tree);
- /* does not return */
fdt_initrd(*of_flat_tree, *initrd_start, *initrd_end, 1);
}
if(flag == 0 || flag == BOOTM_STATE_OS_GO) {
announce_and_cleanup();
kernel_entry(0, machid, *of_flat_tree);
/* does not return */
}
return 1; } #endif -- 1.7.4.1

Adds prep subcommand to bootm implementation of ARM. When bootm is called prep the function stops right after ATAGS creation and before announce_and_cleanup.
This is used in savebp command
Signed-off-by: Simon Schwarz simonschwarzcor@gmail.com --- Ok second RFC!
I know that there are many style problems - but I don't have the time before weekend/at the weekend to fix them.
So please no close inspection just a comment on the way how the patch is done.
I will address the styleproblems on Monday!
Thanks, and have a nive weekend! Simon
--- arch/arm/lib/bootm.c | 107 +++++++++++++++++++++++++++----------------------- 1 files changed, 58 insertions(+), 49 deletions(-)
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 802e833..58334a2 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -1,4 +1,7 @@ -/* +/* Copyright (C) 2011 + * Corscience GmbH & Co. KG - Simon Schwarz schwarz@corscience.de + * - Added prep subcommand support + * * (C) Copyright 2002 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> * Marius Groeger mgroeger@sysgo.de @@ -55,7 +58,7 @@ static struct tag *params;
static ulong get_sp(void); #if defined(CONFIG_OF_LIBFDT) -static int bootm_linux_fdt(int machid, bootm_headers_t *images); +static int bootm_linux_fdt(int machid, bootm_headers_t *images, int flag); #endif
void arch_lmb_reserve(struct lmb *lmb) @@ -104,57 +107,61 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) 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); - } + if ((flag != 0) && (flag != BOOTM_STATE_OS_GO || + flag != BOOTM_STATE_OS_PREP)) + return 1; /* subcommand not implemented */ + else + if((flag == 0) || flag == BOOTM_STATE_OS_PREP) { + s = getenv ("machid"); + if (s) { + machid = simple_strtoul (s, NULL, 16); + printf ("Using machid 0x%x from environment\n", machid); + }
- show_boot_progress (15); + show_boot_progress (15);
#ifdef CONFIG_OF_LIBFDT - if (images->ft_len) - return bootm_linux_fdt(machid, images); + if (images->ft_len) + return bootm_linux_fdt(machid, images, flag); #endif
- kernel_entry = (void (*)(int, int, uint))images->ep; + kernel_entry = (void (*)(int, int, uint))images->ep;
- debug ("## Transferring control to Linux (at address %08lx) ...\n", - (ulong) kernel_entry); + 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); + setup_start_tag (bd); #ifdef CONFIG_SERIAL_TAG - setup_serial_tag (¶ms); + setup_serial_tag (¶ms); #endif #ifdef CONFIG_REVISION_TAG - setup_revision_tag (¶ms); + setup_revision_tag (¶ms); #endif #ifdef CONFIG_SETUP_MEMORY_TAGS - setup_memory_tags (bd); + setup_memory_tags (bd); #endif #ifdef CONFIG_CMDLINE_TAG - setup_commandline_tag (bd, commandline); + 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); + if (images->rd_start && images->rd_end) + setup_initrd_tag (bd, images->rd_start, images->rd_end); #endif - setup_end_tag(bd); + setup_end_tag(bd); #endif + }
- announce_and_cleanup(); - - kernel_entry(0, machid, bd->bi_boot_params); - /* does not return */ + if(flag == 0 || flag == BOOTM_STATE_OS_GO) { + announce_and_cleanup();
+ kernel_entry(0, machid, bd->bi_boot_params); + /* does not return */ + } return 1; }
@@ -174,7 +181,7 @@ 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 int bootm_linux_fdt(int machid, bootm_headers_t *images, int flag) { ulong rd_len; void (*kernel_entry)(int zero, int dt_machid, void *dtblob); @@ -185,34 +192,36 @@ static int bootm_linux_fdt(int machid, bootm_headers_t *images) 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; + if((flag == 0) || flag == BOOTM_STATE_OS_PREP) { + kernel_entry = (void (*)(int, int, void *))images->ep;
- ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size); - if (ret) - return ret; + boot_fdt_add_mem_rsv_regions(lmb, *of_flat_tree);
- debug("## Transferring control to Linux (at address %08lx) ...\n", - (ulong) kernel_entry); + 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;
- fdt_chosen(*of_flat_tree, 1); + ret = boot_relocate_fdt(lmb, of_flat_tree, &of_size); + if (ret) + return ret;
- fixup_memory_node(*of_flat_tree); + debug("## Transferring control to Linux (at address %08lx) ...\n", + (ulong) kernel_entry);
- fdt_initrd(*of_flat_tree, *initrd_start, *initrd_end, 1); + fdt_chosen(*of_flat_tree, 1);
- announce_and_cleanup(); + fixup_memory_node(*of_flat_tree);
- kernel_entry(0, machid, *of_flat_tree); - /* does not return */ + fdt_initrd(*of_flat_tree, *initrd_start, *initrd_end, 1); + } + if(flag == 0 || flag == BOOTM_STATE_OS_GO) { + announce_and_cleanup();
+ kernel_entry(0, machid, *of_flat_tree); + /* does not return */ + } return 1; } #endif

Dear Simon Schwarz,
In message 1310125056-11643-1-git-send-email-simonschwarzcor@gmail.com you wrote:
Adds prep subcommand to bootm implementation of ARM. When bootm is called prep the function stops right after ATAGS creation and before announce_and_cleanup.
This is used in savebp command
Signed-off-by: Simon Schwarz simonschwarzcor@gmail.com
Ok second RFC!
Grrrrrghhh!!!
Can you PLEASE follow the rules for posting new patch versions?
You are supposed to mark them in the Subject:, and you are supposed to provide a desciption what you changed.
See http://www.denx.de/wiki/view/U-Boot/Patches#Sending_updated_patch_versions
Message ignored.
Wolfgang Denk
participants (4)
-
Albert ARIBAUD
-
Scott Wood
-
Simon Schwarz
-
Wolfgang Denk