[POWERPC] Clean up zImage handling of the command line
authorDavid Gibson <david@gibson.dropbear.id.au>
Thu, 22 Mar 2007 06:02:21 +0000 (17:02 +1100)
committerPaul Mackerras <paulus@samba.org>
Thu, 12 Apr 2007 17:55:14 +0000 (03:55 +1000)
This cleans up how the zImage code manipulates the kernel
command line.  Notable improvements from the old handling:
- Command line manipulation is consolidated into a new
prep_cmdline() function, rather than being scattered across start()
and some helper functions
- Less stack space use: we use just a single global command
line buffer, which can be initialized by an external tool as before,
we no longer need another command line sized buffer on the stack.
- Easier to support platforms whose firmware passes a
commandline, but not a device tree.  Platform code can now point new
loader_info fields to the firmware's command line, rather than having
to do early manipulation of the /chosen bootargs property which may
then be rewritten again by the core.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Paul Mackerras <paulus@samba.org>
arch/powerpc/boot/main.c
arch/powerpc/boot/ops.h

index ab9dfe2b38f192a0d45eb65b69c896d5cba2e736..03c0ccaecf29169f93bf873bdcb9531d4c1dc519 100644 (file)
@@ -205,31 +205,22 @@ static struct addr_range prep_initrd(struct addr_range vmlinux, void *chosen,
  * edit the command line passed to vmlinux (by setting /chosen/bootargs).
  * The buffer is put in it's own section so that tools may locate it easier.
  */
-static char builtin_cmdline[COMMAND_LINE_SIZE]
+static char cmdline[COMMAND_LINE_SIZE]
        __attribute__((__section__("__builtin_cmdline")));
 
-static void get_cmdline(char *buf, int size)
+static void prep_cmdline(void *chosen)
 {
-       void *devp;
-       int len = strlen(builtin_cmdline);
+       if (cmdline[0] == '\0')
+               getprop(chosen, "bootargs", cmdline, COMMAND_LINE_SIZE-1);
 
-       buf[0] = '\0';
+       printf("\n\rLinux/PowerPC load: %s", cmdline);
+       /* If possible, edit the command line */
+       if (console_ops.edit_cmdline)
+               console_ops.edit_cmdline(cmdline, COMMAND_LINE_SIZE);
+       printf("\n\r");
 
-       if (len > 0) { /* builtin_cmdline overrides dt's /chosen/bootargs */
-               len = min(len, size-1);
-               strncpy(buf, builtin_cmdline, len);
-               buf[len] = '\0';
-       }
-       else if ((devp = finddevice("/chosen")))
-               getprop(devp, "bootargs", buf, size);
-}
-
-static void set_cmdline(char *buf)
-{
-       void *devp;
-
-       if ((devp = finddevice("/chosen")))
-               setprop(devp, "bootargs", buf, strlen(buf) + 1);
+       /* Put the command line back into the devtree for the kernel */
+       setprop_str(chosen, "bootargs", cmdline);
 }
 
 struct platform_ops platform_ops;
@@ -241,10 +232,16 @@ void start(void)
 {
        struct addr_range vmlinux, initrd;
        kernel_entry_t kentry;
-       char cmdline[COMMAND_LINE_SIZE];
        unsigned long ft_addr = 0;
        void *chosen;
 
+       /* Do this first, because malloc() could clobber the loader's
+        * command line.  Only use the loader command line if a
+        * built-in command line wasn't set by an external tool */
+       if ((loader_info.cmdline_len > 0) && (cmdline[0] == '\0'))
+               memmove(cmdline, loader_info.cmdline,
+                       min(loader_info.cmdline_len, COMMAND_LINE_SIZE-1));
+
        if (console_ops.open && (console_ops.open() < 0))
                exit();
        if (platform_ops.fixups)
@@ -261,18 +258,7 @@ void start(void)
        vmlinux = prep_kernel();
        initrd = prep_initrd(vmlinux, chosen,
                             loader_info.initrd_addr, loader_info.initrd_size);
-
-       /* If cmdline came from zimage wrapper or if we can edit the one
-        * in the dt, print it out and edit it, if possible.
-        */
-       if ((strlen(builtin_cmdline) > 0) || console_ops.edit_cmdline) {
-               get_cmdline(cmdline, COMMAND_LINE_SIZE);
-               printf("\n\rLinux/PowerPC load: %s", cmdline);
-               if (console_ops.edit_cmdline)
-                       console_ops.edit_cmdline(cmdline, COMMAND_LINE_SIZE);
-               printf("\n\r");
-               set_cmdline(cmdline);
-       }
+       prep_cmdline(chosen);
 
        printf("Finalizing device tree...");
        if (dt_ops.finalize)
index cc191e8e147f3e2cc75052cfa0e0433c1e4649c8..8008d612402e4f49b06829769bf64eae14b0bfb0 100644 (file)
@@ -70,6 +70,8 @@ struct serial_console_data {
 struct loader_info {
        void *promptr;
        unsigned long initrd_addr, initrd_size;
+       char *cmdline;
+       int cmdline_len;
 };
 extern struct loader_info loader_info;