From: Rusty Russell <rusty@rustcorp.com.au>

On Thu, 2004-04-01 at 12:42, Andrew Morton wrote:
> Tom Rini <trini@kernel.crashing.org> wrote:
> >
> >  On Thu, Apr 01, 2004 at 11:51:41AM +1000, Rusty Russell wrote:
> >  > On Thu, 2004-04-01 at 02:13, Tom Rini wrote:
> >  > > My first concern is can parse_args & co really be run so very early on ?
> >  > 
> >  > If you can run normal C code, yes.  It doesn't require any
> >  > initialization.
> > 
> >  No malloc'ing, etc?  OK.  Then yes, please create some sort of merged
> >  patchset (I don't know how Andrew wants to handle it, maybe just replace
> >  the core patch?)
> 
> I guess a diff against
> 
> http://www.zip.com.au/~akpm/linux/patches/stuff/x.gz
> 
> would suit.  That's a diff against rc3 which is all of current mm up to an
> including all the early-param patches.  

Here 'tis.  Reverts much of the previous patch.

1) setup_arch doesn't return a cmdline pointer any more.  It should set
   up saved_command_line (if it's not already), then call
   parse_early_options().

2) __early_param() works like module_param(), rather than __setup():
   the parser splits the '=' sign if any, and hands the value off to
   the function (or NULL if no '=').  Partial matches aren't possible,
   so __early_param("foo") won't match "foobar".  One difference is
   that it returns void: if it wants to panic or warn it should do so.
   Also, __early_param must not keep a refernce to the string (it's
   __initdata).

3) archs changed to use strlcpy(..., COMMAND_LINE_SIZE) if they didn't
   already, instead of memcpy or strlcpy(...sizeof(saved_command_line))
   because sizeof() will give an erorr if the prototype is "char
   saved_command_line[]".

4) Parsers make their own working copies of saved_command_line, rather
   than having the arch supply one.

Boots here...
Rusty.



---

 25-akpm/arch/alpha/kernel/setup.c                  |    5 -
 25-akpm/arch/alpha/kernel/vmlinux.lds.S            |    5 -
 25-akpm/arch/arm/kernel/setup.c                    |   24 +++--
 25-akpm/arch/arm/kernel/vmlinux.lds.S              |    3 
 25-akpm/arch/arm/mm/mm-armv.c                      |   23 ++---
 25-akpm/arch/arm26/kernel/setup.c                  |   15 +--
 25-akpm/arch/arm26/kernel/vmlinux-arm26-xip.lds.in |    3 
 25-akpm/arch/arm26/kernel/vmlinux-arm26.lds.in     |    3 
 25-akpm/arch/cris/kernel/setup.c                   |    7 -
 25-akpm/arch/h8300/kernel/setup.c                  |    7 -
 25-akpm/arch/h8300/kernel/vmlinux.lds.S            |    5 -
 25-akpm/arch/i386/kernel/apic.c                    |    3 
 25-akpm/arch/i386/kernel/head.S                    |    1 
 25-akpm/arch/i386/kernel/setup.c                   |   70 ++++++++---------
 25-akpm/arch/i386/kernel/vmlinux.lds.S             |    3 
 25-akpm/arch/i386/mach-generic/probe.c             |   12 +-
 25-akpm/arch/ia64/kernel/efi.c                     |    9 +-
 25-akpm/arch/ia64/kernel/setup.c                   |    7 -
 25-akpm/arch/ia64/kernel/vmlinux.lds.S             |    6 -
 25-akpm/arch/m68k/atari/config.c                   |    9 +-
 25-akpm/arch/m68k/kernel/setup.c                   |   19 +---
 25-akpm/arch/m68k/kernel/vmlinux-std.lds           |    3 
 25-akpm/arch/m68k/kernel/vmlinux-sun3.lds          |    3 
 25-akpm/arch/m68knommu/kernel/setup.c              |    6 -
 25-akpm/arch/m68knommu/kernel/vmlinux.lds.S        |    3 
 25-akpm/arch/mips/kernel/setup.c                   |   15 +--
 25-akpm/arch/mips/kernel/vmlinux.lds.S             |    3 
 25-akpm/arch/parisc/kernel/setup.c                 |   18 ++--
 25-akpm/arch/parisc/kernel/vmlinux.lds.S           |    3 
 25-akpm/arch/parisc/mm/init.c                      |    9 +-
 25-akpm/arch/ppc/kernel/ppc-stub.c                 |    2 
 25-akpm/arch/ppc/kernel/setup.c                    |   11 +-
 25-akpm/arch/ppc/kernel/vmlinux.lds.S              |    3 
 25-akpm/arch/ppc/xmon/xmon.c                       |    2 
 25-akpm/arch/ppc64/kernel/setup.c                  |    7 -
 25-akpm/arch/ppc64/kernel/vmlinux.lds.S            |    5 -
 25-akpm/arch/s390/kernel/setup.c                   |    8 +
 25-akpm/arch/s390/kernel/vmlinux.lds.S             |    3 
 25-akpm/arch/sh/kernel/setup.c                     |   18 ++--
 25-akpm/arch/sh/kernel/vmlinux.lds.S               |    3 
 25-akpm/arch/sparc/kernel/setup.c                  |    6 -
 25-akpm/arch/sparc/kernel/vmlinux.lds.S            |    3 
 25-akpm/arch/sparc64/kernel/setup.c                |    6 -
 25-akpm/arch/sparc64/kernel/vmlinux.lds.S          |    3 
 25-akpm/arch/um/kernel/um_arch.c                   |    6 -
 25-akpm/arch/v850/kernel/setup.c                   |    6 -
 25-akpm/arch/v850/kernel/vmlinux.lds.S             |    5 -
 25-akpm/arch/x86_64/kernel/e820.c                  |    7 -
 25-akpm/arch/x86_64/kernel/early_printk.c          |   11 +-
 25-akpm/arch/x86_64/kernel/mpparse.c               |    8 -
 25-akpm/arch/x86_64/kernel/pci-gart.c              |    8 +
 25-akpm/arch/x86_64/kernel/setup.c                 |   55 +++++--------
 25-akpm/arch/x86_64/kernel/vmlinux.lds.S           |    3 
 25-akpm/arch/x86_64/mm/numa.c                      |    9 --
 25-akpm/drivers/pci/pci.c                          |    5 -
 25-akpm/include/asm-i386/param.h                   |    1 
 25-akpm/include/asm-i386/setup.h                   |    1 
 25-akpm/include/asm-um/common.lds.S                |    4 
 25-akpm/include/linux/init.h                       |   62 +++++++--------
 25-akpm/init/do_mounts.c                           |    1 
 25-akpm/init/main.c                                |   86 ++++++++-------------
 25-akpm/kernel/printk.c                            |    8 +
 62 files changed, 281 insertions(+), 387 deletions(-)

diff -puN arch/alpha/kernel/setup.c~early-param-rusty arch/alpha/kernel/setup.c
--- 25/arch/alpha/kernel/setup.c~early-param-rusty	2004-04-04 17:01:39.167677856 -0700
+++ 25-akpm/arch/alpha/kernel/setup.c	2004-04-04 17:01:39.261663568 -0700
@@ -480,7 +480,7 @@ page_is_ram(unsigned long pfn)
 #undef PFN_MAX
 
 void __init
-setup_arch(char **cmdline_p)
+setup_arch(void)
 {
 	extern char _end[];
 
@@ -534,8 +534,7 @@ setup_arch(char **cmdline_p)
 	} else {
 		strlcpy(command_line, COMMAND_LINE, sizeof command_line);
 	}
-	*cmdline_p = command_line;
-	parse_early_options(cmdline_p);
+	parse_early_options();
 
 	/* 
 	 * Process command-line arguments.
diff -puN arch/alpha/kernel/vmlinux.lds.S~early-param-rusty arch/alpha/kernel/vmlinux.lds.S
--- 25/arch/alpha/kernel/vmlinux.lds.S~early-param-rusty	2004-04-04 17:01:39.169677552 -0700
+++ 25-akpm/arch/alpha/kernel/vmlinux.lds.S	2004-04-04 17:01:39.261663568 -0700
@@ -46,11 +46,6 @@ SECTIONS
   __setup_end = .;
 
   . = ALIGN(8);
-  __early_begin = .;
-  __early_param : { *(__early_param) }
-  __early_end = .;
-
-  . = ALIGN(8);
   __start___param = .;
   __param : { *(__param) }
   __stop___param = .;
diff -puN arch/arm26/kernel/setup.c~early-param-rusty arch/arm26/kernel/setup.c
--- 25/arch/arm26/kernel/setup.c~early-param-rusty	2004-04-04 17:01:39.170677400 -0700
+++ 25-akpm/arch/arm26/kernel/setup.c	2004-04-04 17:01:39.262663416 -0700
@@ -156,11 +156,14 @@ static void __init setup_processor(void)
  * Pick out the memory size.  We look for mem=size@start,
  * where start and size are "size[KkMm]"
  */
-static int __init early_mem(char *p)
+static void __init early_mem(char *p)
 {
 	static int usermem __initdata = 0;
 	unsigned long size, start;
 
+	if (!p)
+		return;
+
 	/*
 	 * The user has specified the memory size for the first time,
 	 * so we blow away any automatically generated size.
@@ -181,10 +184,8 @@ static int __init early_mem(char *p)
 	mi->bank[mi->nr_banks].size  = size;
 	mi->bank[mi->nr_banks].node  = PHYS_TO_NID(start);
 	mi->nr_banks += 1;
-
-	return 0;
 }
-__early_param("mem=", early_mem);
+__early_param("mem", early_mem);
 
 static void __init
 setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
@@ -436,7 +437,7 @@ static struct init_tags {
 	{ 0, ATAG_NONE }
 };
 
-void __init setup_arch(char **cmdline_p)
+void __init setup_arch(void)
 {
 	struct tag *tags = (struct tag *)&init_tags;
 	char *from = default_command_line;
@@ -479,8 +480,8 @@ void __init setup_arch(char **cmdline_p)
 	init_mm.end_data   = (unsigned long) &_edata;
 	init_mm.brk	   = (unsigned long) &_end;
 
-	*cmdline_p = from;
-	parse_early_options(cmdline_p);
+	strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
+	parse_early_options();
 	bootmem_init(&meminfo);
 	paging_init(&meminfo);
 	request_standard_resources(&meminfo);
diff -puN arch/arm26/kernel/vmlinux-arm26.lds.in~early-param-rusty arch/arm26/kernel/vmlinux-arm26.lds.in
--- 25/arch/arm26/kernel/vmlinux-arm26.lds.in~early-param-rusty	2004-04-04 17:01:39.172677096 -0700
+++ 25-akpm/arch/arm26/kernel/vmlinux-arm26.lds.in	2004-04-04 17:01:39.263663264 -0700
@@ -32,9 +32,6 @@ SECTIONS
 		__setup_start = .;
 			*(.init.setup)
 		__setup_end = .;
-		__early_begin = .;
-			*(__early_param)
-		__early_end = .;
 		__start___param = .;
 			*(__param)
 		__stop___param = .;
diff -puN arch/arm26/kernel/vmlinux-arm26-xip.lds.in~early-param-rusty arch/arm26/kernel/vmlinux-arm26-xip.lds.in
--- 25/arch/arm26/kernel/vmlinux-arm26-xip.lds.in~early-param-rusty	2004-04-04 17:01:39.173676944 -0700
+++ 25-akpm/arch/arm26/kernel/vmlinux-arm26-xip.lds.in	2004-04-04 17:01:39.263663264 -0700
@@ -31,9 +31,6 @@ SECTIONS
 		__setup_start = .;
 			*(.init.setup)
 		__setup_end = .;
-		__early_begin = .;
-			*(__early_param)
-		__early_end = .;
 		__start___param = .;
 			*(__param)
 		__stop___param = .;
diff -puN arch/arm/kernel/setup.c~early-param-rusty arch/arm/kernel/setup.c
--- 25/arch/arm/kernel/setup.c~early-param-rusty	2004-04-04 17:01:39.175676640 -0700
+++ 25-akpm/arch/arm/kernel/setup.c	2004-04-04 17:01:39.264663112 -0700
@@ -329,10 +329,13 @@ static struct machine_desc * __init setu
 	return list;
 }
 
-static int __init early_initrd(char *p)
+static void __init early_initrd(char *p)
 {
 	unsigned long start, size;
 
+	if (!p)
+		return;
+
 	start = memparse(p, &p);
 	if (*p == ',') {
 		size = memparse(p++, &p);
@@ -340,20 +343,21 @@ static int __init early_initrd(char *p)
 		phys_initrd_start = start;
 		phys_initrd_size = size;
 	}
-
-	return 0;
 }
-__early_param("initrd=", early_initrd);
+__early_param("initrd", early_initrd);
 
 /*
  * Pick out the memory size.  We look for mem=size@start,
  * where start and size are "size[KkMm]"
  */
-static int __init early_mem(char *p)
+static void __init early_mem(char *p)
 {
 	static int usermem __initdata = 0;
 	unsigned long size, start;
 
+	if (!p)
+		return;
+
 	/*
 	 * The user has specified the memory size for the first time,
 	 * so we blow away any automatically generated size.
@@ -372,10 +376,8 @@ static int __init early_mem(char *p)
 	meminfo.bank[meminfo.nr_banks].size  = size;
 	meminfo.bank[meminfo.nr_banks].node  = PHYS_TO_NID(start);
 	meminfo.nr_banks += 1;
-
-	return 0;
 }
-__early_param("mem=", early_mem);
+__early_param("mem", early_mem);
 
 static void __init
 setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
@@ -628,7 +630,7 @@ static int __init customize_machine(void
 }
 arch_initcall(customize_machine);
 
-void __init setup_arch(char **cmdline_p)
+void __init setup_arch(void)
 {
 	struct tag *tags = (struct tag *)&init_tags;
 	struct machine_desc *mdesc;
@@ -667,8 +669,8 @@ void __init setup_arch(char **cmdline_p)
 	init_mm.end_data   = (unsigned long) &_edata;
 	init_mm.brk	   = (unsigned long) &_end;
 
-	*cmdline_p = from;
-	parse_early_options(cmdline_p);
+	strlcpy(saved_command_line, from, COMMAND_LINE_SIZE);
+	parse_early_options();
 	bootmem_init(&meminfo);
 	paging_init(&meminfo, mdesc);
 	request_standard_resources(&meminfo, mdesc);
diff -puN arch/arm/kernel/vmlinux.lds.S~early-param-rusty arch/arm/kernel/vmlinux.lds.S
--- 25/arch/arm/kernel/vmlinux.lds.S~early-param-rusty	2004-04-04 17:01:39.176676488 -0700
+++ 25-akpm/arch/arm/kernel/vmlinux.lds.S	2004-04-04 17:01:39.264663112 -0700
@@ -35,9 +35,6 @@ SECTIONS
 		__setup_start = .;
 			*(.init.setup)
 		__setup_end = .;
-		__early_begin = .;
-			*(__early_param)
-		__early_end = .;
 		__start___param = .;
 			*(__param)
 		__stop___param = .;
diff -puN arch/arm/mm/mm-armv.c~early-param-rusty arch/arm/mm/mm-armv.c
--- 25/arch/arm/mm/mm-armv.c~early-param-rusty	2004-04-04 17:01:39.177676336 -0700
+++ 25-akpm/arch/arm/mm/mm-armv.c	2004-04-04 17:01:39.265662960 -0700
@@ -84,6 +84,9 @@ static int __init early_cachepolicy(char
 {
 	int i;
 
+	if (!p)
+		p = "FAIL";
+
 	for (i = 0; i < ARRAY_SIZE(cache_policies); i++) {
 		int len = strlen(cache_policies[i].policy);
 
@@ -99,42 +102,34 @@ static int __init early_cachepolicy(char
 		printk(KERN_ERR "ERROR: unknown or unsupported cache policy\n");
 	flush_cache_all();
 	set_cr(cr_alignment);
-
-	return 0;
 }
 
-static int __init early_nocache(char *__unused)
+static void __init early_nocache(char *__unused)
 {
 	char *p = "buffered";
 	printk(KERN_WARNING "nocache is deprecated; use cachepolicy=%s\n", p);
 	early_cachepolicy(p);
-
-	return 0;
 }
 
-static int __init early_nowrite(char *__unused)
+static void __init early_nowrite(char *__unused)
 {
 	char *p = "uncached";
 	printk(KERN_WARNING "nowb is deprecated; use cachepolicy=%s\n", p);
 	early_cachepolicy(p);
-
-	return 0;
 }
 
-static int __init early_ecc(char *p)
+static void __init early_ecc(char *p)
 {
-	if (memcmp(p, "on", 2) == 0)
+	if (!p || memcmp(p, "on", 2) == 0)
 		ecc_mask = PMD_PROTECTION;
 	else if (memcmp(p, "off", 3) == 0)
 		ecc_mask = 0;
-
-	return 0;
 }
 
 __early_param("nocache", early_nocache);
 __early_param("nowb", early_nowrite);
-__early_param("cachepolicy=", early_cachepolicy);
-__early_param("ecc=", early_ecc);
+__early_param("cachepolicy", early_cachepolicy);
+__early_param("ecc", early_ecc);
 
 static int __init noalign_setup(char *__unused)
 {
diff -puN arch/cris/kernel/setup.c~early-param-rusty arch/cris/kernel/setup.c
--- 25/arch/cris/kernel/setup.c~early-param-rusty	2004-04-04 17:01:39.178676184 -0700
+++ 25-akpm/arch/cris/kernel/setup.c	2004-04-04 17:01:39.266662808 -0700
@@ -53,7 +53,7 @@ extern unsigned long romfs_start, romfs_
  */
 
 void __init 
-setup_arch(char **cmdline_p)
+setup_arch(void)
 {
 	extern void init_etrax_debug(void);
 	unsigned long bootmap_size;
@@ -148,8 +148,6 @@ setup_arch(char **cmdline_p)
 	/* We don't use a command line yet, so just re-initialize it without
 	   saving anything that might be there.  */
 
-	*cmdline_p = command_line;
-
 #ifdef CONFIG_ETRAX_CMDLINE
 	strlcpy(command_line, CONFIG_ETRAX_CMDLINE, sizeof(command_line));
 #elif defined(CONFIG_ETRAX_ROOT_DEVICE)
@@ -158,7 +156,8 @@ setup_arch(char **cmdline_p)
 		sizeof(command_line));
 #endif
 	command_line[COMMAND_LINE_SIZE - 1] = '\0';
-	parse_early_options(cmdline_p);
+	strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
+	parse_early_options();
 
 	/* give credit for the CRIS port */
 
diff -puN arch/h8300/kernel/setup.c~early-param-rusty arch/h8300/kernel/setup.c
--- 25/arch/h8300/kernel/setup.c~early-param-rusty	2004-04-04 17:01:39.180675880 -0700
+++ 25-akpm/arch/h8300/kernel/setup.c	2004-04-04 17:01:39.266662808 -0700
@@ -100,7 +100,7 @@ static const struct console gdb_console 
 };
 #endif
 
-void __init setup_arch(char **cmdline_p)
+void __init setup_arch(void)
 {
 	int bootmap_size;
 
@@ -164,9 +164,8 @@ void __init setup_arch(char **cmdline_p)
 	if (*command_line == '\0')
 		strcpy(command_line,CONFIG_KERNEL_COMMAND);
 #endif
-	/* Keep a copy of command line */
-	*cmdline_p = &command_line[0];
-	parse_early_options(cmdline_p);
+	strlcpy(saved_command_line, command_line, sizeof(saved_command_line));
+	parse_early_options();
 
 #ifdef DEBUG
 	if (strlen(*cmdline_p)) 
diff -puN arch/h8300/kernel/vmlinux.lds.S~early-param-rusty arch/h8300/kernel/vmlinux.lds.S
--- 25/arch/h8300/kernel/vmlinux.lds.S~early-param-rusty	2004-04-04 17:01:39.181675728 -0700
+++ 25-akpm/arch/h8300/kernel/vmlinux.lds.S	2004-04-04 17:01:39.267662656 -0700
@@ -132,11 +132,6 @@ SECTIONS
 		*(.init.setup)
 	. = ALIGN(0x4) ;
 	___setup_end = .;
-
-	__early_begin = .;
-		*(__early_param)
-	__early_end = .;
-
 	___start___param = .;
 		*(__param)
 	___stop___param = .;
diff -puN arch/i386/kernel/apic.c~early-param-rusty arch/i386/kernel/apic.c
--- 25/arch/i386/kernel/apic.c~early-param-rusty	2004-04-04 17:01:39.183675424 -0700
+++ 25-akpm/arch/i386/kernel/apic.c	2004-04-04 17:01:39.268662504 -0700
@@ -610,11 +610,10 @@ static void apic_pm_activate(void) { }
  */
 int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
 
-static int __init lapic_disable(char *str)
+static void __init lapic_disable(char *str)
 {
 	enable_local_apic = -1;
 	clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
-	return 0;
 }
 __early_param("nolapic", lapic_disable);
 
diff -puN arch/i386/kernel/head.S~early-param-rusty arch/i386/kernel/head.S
--- 25/arch/i386/kernel/head.S~early-param-rusty	2004-04-04 17:01:39.184675272 -0700
+++ 25-akpm/arch/i386/kernel/head.S	2004-04-04 17:01:39.268662504 -0700
@@ -19,6 +19,7 @@
 #include <asm/thread_info.h>
 #include <asm/asm_offsets.h>
 #include <asm/setup.h>
+#include <asm/param.h>
 
 /*
  * References to members of the new_cpu_data structure.
diff -puN arch/i386/kernel/setup.c~early-param-rusty arch/i386/kernel/setup.c
--- 25/arch/i386/kernel/setup.c~early-param-rusty	2004-04-04 17:01:39.186674968 -0700
+++ 25-akpm/arch/i386/kernel/setup.c	2004-04-04 17:01:39.270662200 -0700
@@ -489,8 +489,11 @@ static void __init setup_memory_region(v
  * HPA tells me bootloaders need to parse mem=, so no new
  * option should be mem=  [also see Documentation/i386/boot.txt]
  */
-static int __init early_mem(char *from)
+static void __init early_mem(char *from)
 {
+	if (!from)
+		return;
+
 	if (!memcmp(from, "nopentium", 9)) {
 		clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
 		disable_pse = 1;
@@ -508,19 +511,20 @@ static int __init early_mem(char *from)
 		printk(KERN_INFO "user-defined physical RAM map:\n");
 		print_memory_map("user");
 	}
-
-	return 0;
 }
-__early_param("mem=", early_mem);
+__early_param("mem", early_mem);
 
 /*
  * "memmap=XXX[KkmM][@#$]XXX[KkmM]" defines a memory region from
  * <start> to <start>+<mem>, overriding the bios size.
  */
-static int __init early_memmap(char *from)
+static void __init early_memmap(char *from)
 {
 	int userdef = 0;
 
+	if (!from)
+		return;
+
 	if (!memcmp(from, "exactmap", 8)) {
 		e820.nr_map = 0;
 		userdef = 1;
@@ -552,31 +556,31 @@ static int __init early_memmap(char *fro
 		printk(KERN_INFO "user-defined physical RAM map:\n");
 		print_memory_map("user");
 	}
-
-	return 0;
 }
-__early_param("memmap=", early_memmap);
+__early_param("memmap", early_memmap);
 
 #ifdef  CONFIG_X86_SMP
 /*
  * If the BIOS enumerates physical processors before logical,
  * maxcpus=N at enumeration-time can be used to disable HT.
  */
-static int __init early_maxcpus(char *from)
+static void __init early_maxcpus(char *from)
 {
 	extern unsigned int maxcpus;
 
-	maxcpus = simple_strtoul(from, NULL, 0);
-
-	return 0;
+	if (from)
+		maxcpus = simple_strtoul(from, NULL, 0);
 }
-__early_param("maxcpus=", early_maxcpus);
+__early_param("maxcpus", early_maxcpus);
 #endif
 
 
 #ifdef CONFIG_ACPI_BOOT
-static int __init early_acpi(char *from)
+static void __init early_acpi(char *from)
 {
+	if (!from)
+		return;
+
 	/* "off" disables both ACPI table parsing and interpreter */
 	if (!memcmp(from, "off", 3))
 		disable_acpi();
@@ -598,21 +602,21 @@ static int __init early_acpi(char *from)
 			disable_acpi();
 		acpi_ht = 1;
 	}
-
-	return 0;
 }
-__early_param("acpi=", early_acpi);
+__early_param("acpi", early_acpi);
 
-static int __init early_pci_noacpi(char *ign)
+static void __init early_pci_noacpi(char *val)
 {
-	acpi_noirq_set();
-
-	return 0;
+	if (val && strcmp(val, "noacpi") == 0)
+		acpi_noirq_set();
 }
-__early_param("pci=noacpi", early_pci_noacpi);
+__early_param("pci", early_pci_noacpi);
 
-static int __init early_acpi_sci(char *from)
+static void __init early_acpi_sci(char *from)
 {
+	if (!from)
+		return;
+
 	if (!memcmp(from, "edge", 4))
 		acpi_sci_flags.trigger =  1;
 
@@ -624,17 +628,13 @@ static int __init early_acpi_sci(char *f
 
 	else if (!memcmp(from, "low", 3))
 		acpi_sci_flags.polarity = 3;
-
-	return 0;
 }
-__early_param("acpi_sci=", early_acpi_sci);
+__early_param("acpi_sci", early_acpi_sci);
 #ifdef CONFIG_X86_LOCAL_APIC
 /* Disable IO-APIC. */
-static int __init early_disable_ioapic(char *from)
+static void __init early_disable_ioapic(char *from)
 {
 	disable_ioapic_setup();
-
-	return 0;
 }
 __early_param("noapic", early_disable_ioapic);
 #endif /* CONFIG_X86_LOCAL_APIC */
@@ -645,13 +645,11 @@ __early_param("noapic", early_disable_io
  * This works even on boxes that have no highmem otherwise.
  * This also works to reduce highmem size on bigger boxes.
  */
-static int __init early_highmem_size(char *from)
+static void __init early_highmem_size(char *from)
 {
 	highmem_pages = memparse(from, &from) >> PAGE_SHIFT;
-
-	return 0;
 }
-__early_param("highmem=", early_highmem_size);
+__early_param("highmem", early_highmem_size);
 
 /*
  * Callback for efi_memory_walk.
@@ -1094,9 +1092,8 @@ __setup("noreplacement", noreplacement_s
  * global efi_enabled. This allows the same kernel image to be used on existing
  * systems (with a traditional BIOS) as well as on EFI systems.
  */
-void __init setup_arch(char **cmdline_p)
+void __init setup_arch(void)
 {
-	extern char saved_command_line[];
 	unsigned long max_low_pfn;
 
 	memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
@@ -1156,8 +1153,7 @@ void __init setup_arch(char **cmdline_p)
 	data_resource.end = virt_to_phys(_edata)-1;
 
 	/* We have the original cmdline stored here already. */
-	*cmdline_p = saved_command_line;
-	parse_early_options(cmdline_p);
+	parse_early_options();
 	max_low_pfn = setup_memory();
 
 	/*
diff -puN arch/i386/kernel/vmlinux.lds.S~early-param-rusty arch/i386/kernel/vmlinux.lds.S
--- 25/arch/i386/kernel/vmlinux.lds.S~early-param-rusty	2004-04-04 17:01:39.187674816 -0700
+++ 25-akpm/arch/i386/kernel/vmlinux.lds.S	2004-04-04 17:01:39.270662200 -0700
@@ -66,9 +66,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __early_begin = .;
-  __early_param : { *(__early_param) }
-  __early_end = .;
   __start___param = .;
   __param : { *(__param) }
   __stop___param = .;
diff -puN arch/i386/mach-generic/probe.c~early-param-rusty arch/i386/mach-generic/probe.c
--- 25/arch/i386/mach-generic/probe.c~early-param-rusty	2004-04-04 17:01:39.188674664 -0700
+++ 25-akpm/arch/i386/mach-generic/probe.c	2004-04-04 17:01:39.271662048 -0700
@@ -28,13 +28,17 @@ struct genapic *apic_probe[] __initdata 
 	NULL,
 };
 
-static int __init generic_apic_probe(char *command_line)
+static void __init generic_apic_probe(char *command_line)
 {
 	char *s = command_line;
 	int i;
 	int changed = 0;
+	char *p;
 
-	char *p = strchr(s, ' '), old;
+	if (!command_line)
+		return;
+
+	p = strchr(s, ' '), old;
 	if (!p)
 		p = strchr(s, '\0');
 	old = *p;
@@ -60,10 +64,8 @@ static int __init generic_apic_probe(cha
 		panic("Didn't find an APIC driver");
 
 	printk(KERN_INFO "Using APIC driver %s\n", genapic->name);
-
-	return 0;
 }
-__early_param("apic=", generic_apic_probe);
+__early_param("apic", generic_apic_probe);
 
 /* These functions can switch the APIC even after the initial ->probe() */
 
diff -puN arch/ia64/kernel/efi.c~early-param-rusty arch/ia64/kernel/efi.c
--- 25/arch/ia64/kernel/efi.c~early-param-rusty	2004-04-04 17:01:39.189674512 -0700
+++ 25-akpm/arch/ia64/kernel/efi.c	2004-04-04 17:01:39.272661896 -0700
@@ -469,18 +469,19 @@ efi_map_pal_code (void)
 	}
 }
 
-static int __init
+static void __init
 early_mem(char *cp)
 {
+	if (!cp)
+		return;
+
 	mem_limit = memparse(cp, &cp) - 1;
 
 	if (mem_limit != ~0UL)
 		printk(KERN_INFO "Ignoring memory above %luMB\n",
 				mem_limit >> 20);
-
-	return 0;
 }
-__early_param("mem=", early_mem);
+__early_param("mem", early_mem);
 
 void __init
 efi_init (void)
diff -puN arch/ia64/kernel/setup.c~early-param-rusty arch/ia64/kernel/setup.c
--- 25/arch/ia64/kernel/setup.c~early-param-rusty	2004-04-04 17:01:39.191674208 -0700
+++ 25-akpm/arch/ia64/kernel/setup.c	2004-04-04 17:01:39.273661744 -0700
@@ -277,14 +277,15 @@ setup_serial_legacy (void)
 #endif
 
 void __init
-setup_arch (char **cmdline_p)
+setup_arch (void)
 {
 	unw_init();
 
 	ia64_patch_vtop((u64) __start___vtop_patchlist, (u64) __end___vtop_patchlist);
 
-	*cmdline_p = __va(ia64_boot_param->command_line);
-	parse_early_options(cmdline_p);
+	strlcpy(saved_command_line, __va(ia64_boot_param->command_line),
+		COMMAND_LINE_SIZE);
+	parse_early_options();
 
 	efi_init();
 	io_port_init();
diff -puN arch/ia64/kernel/vmlinux.lds.S~early-param-rusty arch/ia64/kernel/vmlinux.lds.S
--- 25/arch/ia64/kernel/vmlinux.lds.S~early-param-rusty	2004-04-04 17:01:39.192674056 -0700
+++ 25-akpm/arch/ia64/kernel/vmlinux.lds.S	2004-04-04 17:01:39.273661744 -0700
@@ -135,12 +135,6 @@ SECTIONS
 	  *(.init.setup)
 	  __setup_end = .;
 	}
-  __early_param : AT(ADDR(__early_param) - LOAD_OFFSET)
-	{
-	  __early_begin = .;
-	  *(__early_param)
-	  __early_end = .;
-	}
   __param : AT(ADDR(__param) - LOAD_OFFSET)
         {
 	  __start___param = .;
diff -puN arch/m68k/atari/config.c~early-param-rusty arch/m68k/atari/config.c
--- 25/arch/m68k/atari/config.c~early-param-rusty	2004-04-04 17:01:39.193673904 -0700
+++ 25-akpm/arch/m68k/atari/config.c	2004-04-04 17:01:39.274661592 -0700
@@ -217,16 +217,17 @@ static void __init atari_switches_setup(
     }
 }
 
-static int __init early_switches(char *p)
+static void __init early_switches(char *p)
 {
 	char *q;
 
+	if (!p)
+		return;
+
 	atari_switches_setup(p, (q = strchr(p, ' ' )) ?
 				           (q - p) : strlen(p));
-
-	return 0;
 }
-__early_param("switches=", early_switches);
+__early_param("switches", early_switches);
 
 
     /*
diff -puN arch/m68k/kernel/setup.c~early-param-rusty arch/m68k/kernel/setup.c
--- 25/arch/m68k/kernel/setup.c~early-param-rusty	2004-04-04 17:01:39.195673600 -0700
+++ 25-akpm/arch/m68k/kernel/setup.c	2004-04-04 17:01:39.275661440 -0700
@@ -199,19 +199,14 @@ static void __init m68k_parse_bootinfo(c
  * "debug=xxx" will enable printing certain kernel messages to some
  * machine-specific device.
  */
-static int __init early_debug(char *p)
+static void __init early_debug(char *p)
 {
-	strlcpy(m68k_debug_device, p, sizeof(m68k_debug_device));
-
-	/* Terminate the arg. */
-	if ((p = strchr(m68k_debug_device, ' ' )))
-		*p = 0;
-
-	return 0;
+	if (p)
+		strlcpy(m68k_debug_device, p, sizeof(m68k_debug_device));
 }
-__early_param("debug=", early_debug);
+__early_param("debug", early_debug);
 
-void __init setup_arch(char **cmdline_p)
+void __init setup_arch(void)
 {
 	extern int _etext, _edata, _end;
 #ifndef CONFIG_SUN3
@@ -257,8 +252,8 @@ void __init setup_arch(char **cmdline_p)
 	init_mm.end_data = (unsigned long) &_edata;
 	init_mm.brk = (unsigned long) &_end;
 
-	*cmdline_p = m68k_command_line;
-	parse_early_options(cmdline_p);
+	strlcpy(saved_command_line, m68k_command_line, COMMAND_LINE_SIZE);
+	parse_early_options();
 
 	switch (m68k_machtype) {
 #ifdef CONFIG_AMIGA
diff -puN arch/m68k/kernel/vmlinux-std.lds~early-param-rusty arch/m68k/kernel/vmlinux-std.lds
--- 25/arch/m68k/kernel/vmlinux-std.lds~early-param-rusty	2004-04-04 17:01:39.197673296 -0700
+++ 25-akpm/arch/m68k/kernel/vmlinux-std.lds	2004-04-04 17:01:39.275661440 -0700
@@ -51,9 +51,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __early_begin = .;
-  __early_param : { *(__early_param) }
-  __early_end = .;
   __start___param = .;
   __param : { *(__param) }
   __stop___param = .;
diff -puN arch/m68k/kernel/vmlinux-sun3.lds~early-param-rusty arch/m68k/kernel/vmlinux-sun3.lds
--- 25/arch/m68k/kernel/vmlinux-sun3.lds~early-param-rusty	2004-04-04 17:01:39.199672992 -0700
+++ 25-akpm/arch/m68k/kernel/vmlinux-sun3.lds	2004-04-04 17:01:39.275661440 -0700
@@ -45,9 +45,6 @@ __init_begin = .;
 	__setup_start = .;
 	.init.setup : { *(.init.setup) }
 	__setup_end = .;
-	__early_begin = .;
-	__early_param : { *(__early_param) }
-	__early_end = .;
 	__start___param = .;
 	__param : { *(__param) }
 	__stop___param = .;
diff -puN arch/m68knommu/kernel/setup.c~early-param-rusty arch/m68knommu/kernel/setup.c
--- 25/arch/m68knommu/kernel/setup.c~early-param-rusty	2004-04-04 17:01:39.201672688 -0700
+++ 25-akpm/arch/m68knommu/kernel/setup.c	2004-04-04 17:01:39.276661288 -0700
@@ -141,7 +141,7 @@ void (*mach_power_off)( void ) = NULL;
 extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
 extern int _ramstart, _ramend;
 
-void setup_arch(char **cmdline_p)
+void setup_arch(void)
 {
 	int bootmap_size;
 
@@ -223,8 +223,8 @@ void setup_arch(char **cmdline_p)
 		(int) memory_end, (int) _ramend);
 #endif
 
-	*cmdline_p = &command_line[0];
-	parse_early_options(cmdline_p);
+	strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
+	parse_early_options();
 
 #ifdef DEBUG
 	if (strlen(*cmdline_p)) 
diff -puN arch/m68knommu/kernel/vmlinux.lds.S~early-param-rusty arch/m68knommu/kernel/vmlinux.lds.S
--- 25/arch/m68knommu/kernel/vmlinux.lds.S~early-param-rusty	2004-04-04 17:01:39.202672536 -0700
+++ 25-akpm/arch/m68knommu/kernel/vmlinux.lds.S	2004-04-04 17:01:39.276661288 -0700
@@ -263,9 +263,6 @@ SECTIONS {
 		__setup_start = .;
 		*(.init.setup)
 		__setup_end = .;
-		__early_begin = .;
-		__early_param : { *(__early_param) }
-		__early_end = .;
 		__start___param = .;
 		*(__param)
 		__stop___param = .;
diff -puN arch/mips/kernel/setup.c~early-param-rusty arch/mips/kernel/setup.c
--- 25/arch/mips/kernel/setup.c~early-param-rusty	2004-04-04 17:01:39.204672232 -0700
+++ 25-akpm/arch/mips/kernel/setup.c	2004-04-04 17:01:39.277661136 -0700
@@ -147,11 +147,14 @@ static void __init print_memory_map(void
  * the determined size. "mem=XXX[KkmM]@YYY[KkmM]" defines a memory region
  * from <YYY> to <YYY>+<XXX>, overriding the determined size.
  */
-static int __init early_mem(char *from)
+static void __init early_mem(char *from)
 {
 	unsigned long start_at, mem_size;
 	int len = 0;
 
+	if (!from)
+		return;
+
 	/*
 	 * The user has specified the memory size, so we blow away any
 	 * automatically generated size.
@@ -169,10 +172,8 @@ static int __init early_mem(char *from)
 
 	printk("User-defined physical RAM map:\n");
 	print_memory_map();
-
-	return 0;
 }
-__early_param("mem=", early_mem);
+__early_param("mem", early_mem);
 
 #define PFN_UP(x)	(((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)
 #define PFN_DOWN(x)	((x) >> PAGE_SHIFT)
@@ -430,7 +431,7 @@ static void __init do_earlyinitcalls(voi
 	}
 }
 
-void __init setup_arch(char **cmdline_p)
+void __init setup_arch(void)
 {
 	cpu_probe();
 	prom_init();
@@ -463,12 +464,12 @@ void __init setup_arch(char **cmdline_p)
 	do_earlyinitcalls();
 
 	strlcpy(command_line, arcs_cmdline, sizeof(command_line));
+	strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
 
 	printk("Determined physical RAM map:\n");
 	print_memory_map();
 
-	*cmdline_p = command_line;
-	parse_early_options(cmdline_p);
+	parse_early_options();
 
 	bootmem_init();
 	paging_init();
diff -puN arch/mips/kernel/vmlinux.lds.S~early-param-rusty arch/mips/kernel/vmlinux.lds.S
--- 25/arch/mips/kernel/vmlinux.lds.S~early-param-rusty	2004-04-04 17:01:39.205672080 -0700
+++ 25-akpm/arch/mips/kernel/vmlinux.lds.S	2004-04-04 17:01:39.278660984 -0700
@@ -96,9 +96,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __early_begin = .;
-  __early_param : { *(__early_param) }
-  __early_end = .;
   __start___param = .;
   __param : { *(__param) }
   __stop___param = .;
diff -puN arch/parisc/kernel/setup.c~early-param-rusty arch/parisc/kernel/setup.c
--- 25/arch/parisc/kernel/setup.c~early-param-rusty	2004-04-04 17:01:39.206671928 -0700
+++ 25-akpm/arch/parisc/kernel/setup.c	2004-04-04 17:01:39.279660832 -0700
@@ -52,15 +52,19 @@ char	command_line[COMMAND_LINE_SIZE];
 struct proc_dir_entry * proc_runway_root = NULL;
 struct proc_dir_entry * proc_gsc_root = NULL;
 
-void __init setup_cmdline(char **cmdline_p)
+static void __init setup_cmdline(void)
 {
 	extern unsigned int boot_args[];
 
 	/* Collect stuff passed in from the boot loader */
 
 	/* boot_args[0] is free-mem start, boot_args[1] is ptr to command line */
-	if (boot_args[0] > 64) {
-		strcpy(command_line, (char *)__va(boot_args[1]));
+	if (boot_args[0] < 64) {
+		/* called from hpux boot loader */
+		saved_command_line[0] = '\0';
+	} else {
+		strlcpy(saved_command_line, (char *)__va(boot_args[1]),
+			COMMAND_LINE_SIZE);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 		if (boot_args[2] != 0) /* did palo pass us a ramdisk? */
@@ -71,8 +75,8 @@ void __init setup_cmdline(char **cmdline
 #endif
 	}
 
-	*cmdline_p = command_line;
-	parse_early_options(cmdline_p);
+	strcpy(command_line, saved_command_line);
+	parse_early_options();
 }
 
 #ifdef CONFIG_PA11
@@ -105,7 +109,7 @@ void __init dma_ops_init(void)
 extern int init_per_cpu(int cpuid);
 extern void collect_boot_cpu_data(void);
 
-void __init setup_arch(char **cmdline_p)
+void __init setup_arch(void)
 {
 	init_per_cpu(smp_processor_id());	/* Set Modes & Enable FP */
 
@@ -121,7 +125,7 @@ void __init setup_arch(char **cmdline_p)
 	printk(KERN_INFO "Kernel is using PDC in 32-bit mode.\n");
 #endif
 	setup_pdc();
-	setup_cmdline(cmdline_p);
+	setup_cmdline();
 	collect_boot_cpu_data();
 	do_memory_inventory();  /* probe for physical memory */
 	parisc_cache_init();
diff -puN arch/parisc/kernel/vmlinux.lds.S~early-param-rusty arch/parisc/kernel/vmlinux.lds.S
--- 25/arch/parisc/kernel/vmlinux.lds.S~early-param-rusty	2004-04-04 17:01:39.208671624 -0700
+++ 25-akpm/arch/parisc/kernel/vmlinux.lds.S	2004-04-04 17:01:39.280660680 -0700
@@ -117,9 +117,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __early_begin = .;
-  __early_param : { *(__early_param) }
-  __early_end = .;
   __start___param = .;
   __param : { *(__param) }
   __stop___param = .;
diff -puN arch/parisc/mm/init.c~early-param-rusty arch/parisc/mm/init.c
--- 25/arch/parisc/mm/init.c~early-param-rusty	2004-04-04 17:01:39.210671320 -0700
+++ 25-akpm/arch/parisc/mm/init.c	2004-04-04 17:01:39.280660680 -0700
@@ -74,18 +74,19 @@ int npmem_ranges;
 
 static unsigned long mem_limit = MAX_MEM;
 
-static int __init mem_limit_func(char *cp)
+static void __init mem_limit_func(char *cp)
 {
 	unsigned long limit;
 
+	if (!cp)
+		return;
+
 	limit = memparse(cp, &cp);
 
 	if (limit < mem_limit)
 		mem_limit = limit;
-
-	return 0;
 }
-__early_param("mem=", mem_limit_func);
+__early_param("mem", mem_limit_func);
 
 #define MAX_GAP (0x40000000UL >> PAGE_SHIFT)
 
diff -puN arch/ppc64/kernel/setup.c~early-param-rusty arch/ppc64/kernel/setup.c
--- 25/arch/ppc64/kernel/setup.c~early-param-rusty	2004-04-04 17:01:39.211671168 -0700
+++ 25-akpm/arch/ppc64/kernel/setup.c	2004-04-04 17:01:39.281660528 -0700
@@ -570,7 +570,7 @@ extern void (*calibrate_delay)(void);
  * Initializes bootmem, which is unsed to manage page allocation until
  * mem_init is called.
  */
-void __init setup_arch(char **cmdline_p)
+void __init setup_arch(void)
 {
 	extern int panic_timeout;
 	extern void do_init_bootmem(void);
@@ -603,8 +603,9 @@ void __init setup_arch(char **cmdline_p)
 	init_mm.end_data = (unsigned long) _edata;
 	init_mm.brk = klimit;
 	
-	*cmdline_p = cmd_line;
-	parse_early_options(cmdline_p);
+	/* Save unparsed command line copy for /proc/cmdline */
+	strlcpy(saved_command_line, cmd_line, sizeof(saved_command_line));
+	parse_early_options();
 
 	/* set up the bootmem stuff with available memory */
 	do_init_bootmem();
diff -puN arch/ppc64/kernel/vmlinux.lds.S~early-param-rusty arch/ppc64/kernel/vmlinux.lds.S
--- 25/arch/ppc64/kernel/vmlinux.lds.S~early-param-rusty	2004-04-04 17:01:39.213670864 -0700
+++ 25-akpm/arch/ppc64/kernel/vmlinux.lds.S	2004-04-04 17:01:39.282660376 -0700
@@ -60,11 +60,6 @@ SECTIONS
 	*(.init.setup)
 	__setup_end = .;
 	}
-  __early_param : {
-	__early_begin = .;
-	*(__early_param)
-	__early_end = .;
-	}
 
   __param : {
 	__start___param = .;
diff -puN arch/ppc/kernel/ppc-stub.c~early-param-rusty arch/ppc/kernel/ppc-stub.c
--- 25/arch/ppc/kernel/ppc-stub.c~early-param-rusty	2004-04-04 17:01:39.214670712 -0700
+++ 25-akpm/arch/ppc/kernel/ppc-stub.c	2004-04-04 17:01:39.283660224 -0700
@@ -836,7 +836,7 @@ breakpoint(void)
 }
 
 /* Give us an early hook in. */
-static void __init early_kgdb(char **ign)
+static void __init early_kgdb(char *ign)
 {
 	if (ppc_md.kgdb_map_scc)
 		ppc_md.kgdb_map_scc();
diff -puN arch/ppc/kernel/setup.c~early-param-rusty arch/ppc/kernel/setup.c
--- 25/arch/ppc/kernel/setup.c~early-param-rusty	2004-04-04 17:01:39.215670560 -0700
+++ 25-akpm/arch/ppc/kernel/setup.c	2004-04-04 17:01:39.283660224 -0700
@@ -470,11 +470,10 @@ platform_init(unsigned long r3, unsigned
 
 #ifdef CONFIG_ADB
 /* Allow us to say that ADB probing will be done synchronously. */
-static int __init early_adb_sync(char *ign)
+static void __init early_adb_sync(char *ign)
 {
 	extern int __adb_probe_sync;
 	__adb_probe_sync = 1;
-	return 0;
 }
 __early_param("adb_sync", early_adb_sync);
 #endif /* CONFIG_ADB */
@@ -623,7 +622,7 @@ int __init ppc_init(void)
 arch_initcall(ppc_init);
 
 /* Warning, IO base is not yet inited */
-void __init setup_arch(char **cmdline_p)
+void __init setup_arch(void)
 {
 	extern int panic_timeout;
 	extern char *klimit;
@@ -683,8 +682,10 @@ void __init setup_arch(char **cmdline_p)
 	init_mm.end_code = (unsigned long) _etext;
 	init_mm.end_data = (unsigned long) _edata;
 	init_mm.brk = (unsigned long) klimit;
-	*cmdline_p = cmd_line;
-	parse_early_options(cmdline_p);
+
+	/* Save unparsed command line copy for /proc/cmdline */
+	strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
+	parse_early_options();
 
 	/* set up the bootmem stuff with available memory */
 	do_init_bootmem();
diff -puN arch/ppc/kernel/vmlinux.lds.S~early-param-rusty arch/ppc/kernel/vmlinux.lds.S
--- 25/arch/ppc/kernel/vmlinux.lds.S~early-param-rusty	2004-04-04 17:01:39.217670256 -0700
+++ 25-akpm/arch/ppc/kernel/vmlinux.lds.S	2004-04-04 17:01:39.284660072 -0700
@@ -102,9 +102,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __early_begin = .;
-  __early_param : { *(__early_param) }
-  __early_end = .;
   __start___param = .;
   __param : { *(__param) }
   __stop___param = .;
diff -puN arch/ppc/xmon/xmon.c~early-param-rusty arch/ppc/xmon/xmon.c
--- 25/arch/ppc/xmon/xmon.c~early-param-rusty	2004-04-04 17:01:39.218670104 -0700
+++ 25-akpm/arch/ppc/xmon/xmon.c	2004-04-04 17:01:39.285659920 -0700
@@ -264,7 +264,7 @@ xmon(struct pt_regs *excp)
 }
 
 /* Allow us a hook to drop in early. */
-static void __init early_xmon(char **ign)
+static void __init early_xmon(char *ign)
 {
 	xmon(0);
 }
diff -puN arch/s390/kernel/setup.c~early-param-rusty arch/s390/kernel/setup.c
--- 25/arch/s390/kernel/setup.c~early-param-rusty	2004-04-04 17:01:39.220669800 -0700
+++ 25-akpm/arch/s390/kernel/setup.c	2004-04-04 17:01:39.286659768 -0700
@@ -316,7 +316,7 @@ EXPORT_SYMBOL(machine_power_off);
  */
 extern char _pstart, _pend, _stext;
 
-void __init setup_arch(char **cmdline_p)
+void __init setup_arch(void)
 {
         unsigned long bootmap_size;
         unsigned long memory_start, memory_end;
@@ -372,6 +372,9 @@ void __init setup_arch(char **cmdline_p)
 	data_resource.start = (unsigned long) &_etext;
 	data_resource.end = (unsigned long) &_edata - 1;
 
+        /* Save unparsed command line copy for /proc/cmdline */
+        strlcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
+
         for (;;) {
                 /*
                  * "mem=XXX[kKmM]" sets memsize 
@@ -417,8 +420,7 @@ void __init setup_arch(char **cmdline_p)
         }
         if (c == ' ' && to > command_line) to--;
         *to = '\0';
-        *cmdline_p = command_line;
-	parse_early_options(cmdline_p);
+	parse_early_options();
 
 	/*
 	 * partially used pages are not usable - thus
diff -puN arch/s390/kernel/vmlinux.lds.S~early-param-rusty arch/s390/kernel/vmlinux.lds.S
--- 25/arch/s390/kernel/vmlinux.lds.S~early-param-rusty	2004-04-04 17:01:39.221669648 -0700
+++ 25-akpm/arch/s390/kernel/vmlinux.lds.S	2004-04-04 17:01:39.286659768 -0700
@@ -78,9 +78,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __early_begin = .;
-  __early_param : { *(__early_param) }
-  __early_end = .;
   __start___param = .;
   __param : { *(__param) }
   __stop___param = .;
diff -puN arch/sh/kernel/setup.c~early-param-rusty arch/sh/kernel/setup.c
--- 25/arch/sh/kernel/setup.c~early-param-rusty	2004-04-04 17:01:39.223669344 -0700
+++ 25-akpm/arch/sh/kernel/setup.c	2004-04-04 17:01:39.288659464 -0700
@@ -243,7 +243,7 @@ void sh_console_unregister(void)
 
 #endif
 
-static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
+static inline void parse_cmdline (char mv_name[MV_NAME_SIZE],
 				  struct sh_machine_vector** mvp,
 				  unsigned long *mv_io_base,
 				  int *mv_mmio_enable)
@@ -251,6 +251,9 @@ static inline void parse_cmdline (char *
 	char c = ' ', *to = command_line, *from = COMMAND_LINE;
 	int len = 0;
 
+	/* Save unparsed command line copy for /proc/cmdline */
+	strlcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
+
 	memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START;
 	memory_end = memory_start + __MEMORY_SIZE;
 
@@ -305,10 +308,9 @@ static inline void parse_cmdline (char *
 		*(to++) = c;
 	}
 	*to = '\0';
-	*cmdline_p = command_line;
 }
 
-static int __init sh_mv_setup(char **cmdline_p)
+static int __init sh_mv_setup(void)
 {
 #if defined(CONFIG_SH_UNKNOWN)
 	extern struct sh_machine_vector mv_unknown;
@@ -318,10 +320,10 @@ static int __init sh_mv_setup(char **cmd
 	unsigned long mv_io_base = 0;
 	int mv_mmio_enable = 0;
 
-	parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base, &mv_mmio_enable);
+	parse_cmdline(mv_name, &mv, &mv_io_base, &mv_mmio_enable);
 
 #ifdef CONFIG_CMDLINE_BOOL
-        sprintf(*cmdline_p, CONFIG_CMDLINE);
+        sprintf(command_line, CONFIG_CMDLINE);
 #endif
 
 #ifdef CONFIG_SH_GENERIC
@@ -372,7 +374,7 @@ static int __init sh_mv_setup(char **cmd
 	return 0;
 }
 
-void __init setup_arch(char **cmdline_p)
+void __init setup_arch(void)
 {
 	unsigned long bootmap_size;
 	unsigned long start_pfn, max_pfn, max_low_pfn;
@@ -405,8 +407,8 @@ void __init setup_arch(char **cmdline_p)
 	data_resource.start = virt_to_bus(_etext);
 	data_resource.end = virt_to_bus(_edata)-1;
 
-	sh_mv_setup(cmdline_p);
-	parse_early_options(cmdline_p);
+	sh_mv_setup();
+	parse_early_options();
 
 #define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
 #define PFN_DOWN(x)	((x) >> PAGE_SHIFT)
diff -puN arch/sh/kernel/vmlinux.lds.S~early-param-rusty arch/sh/kernel/vmlinux.lds.S
--- 25/arch/sh/kernel/vmlinux.lds.S~early-param-rusty	2004-04-04 17:01:39.225669040 -0700
+++ 25-akpm/arch/sh/kernel/vmlinux.lds.S	2004-04-04 17:01:39.288659464 -0700
@@ -67,9 +67,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __early_begin = .;
-  __early_param : { *(__early_param) }
-  __early_end = .;
   __start___param = .;
   __param : { *(__param) }
   __stop___param = .;
diff -puN arch/sparc64/kernel/setup.c~early-param-rusty arch/sparc64/kernel/setup.c
--- 25/arch/sparc64/kernel/setup.c~early-param-rusty	2004-04-04 17:01:39.226668888 -0700
+++ 25-akpm/arch/sparc64/kernel/setup.c	2004-04-04 17:01:39.289659312 -0700
@@ -469,14 +469,14 @@ void register_prom_callbacks(void)
 
 extern void paging_init(void);
 
-void __init setup_arch(char **cmdline_p)
+void __init setup_arch(void)
 {
 	unsigned long highest_paddr;
 	int i;
 
 	/* Initialize PROM console and command line. */
-	*cmdline_p = prom_getbootargs();
-	parse_early_options(cmdline_p);
+	strlcpy(saved_command_line, prom_getbootargs(), COMMAND_LINE_SIZE);
+	parse_early_options();
 
 	printk("ARCH: SUN4U\n");
 
diff -puN arch/sparc64/kernel/vmlinux.lds.S~early-param-rusty arch/sparc64/kernel/vmlinux.lds.S
--- 25/arch/sparc64/kernel/vmlinux.lds.S~early-param-rusty	2004-04-04 17:01:39.228668584 -0700
+++ 25-akpm/arch/sparc64/kernel/vmlinux.lds.S	2004-04-04 17:01:39.289659312 -0700
@@ -52,9 +52,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __early_begin = .;
-  __early_param : { *(__early_param) }
-  __early_end = .;
   __start___param = .;
   __param : { *(__param) }
   __stop___param = .;
diff -puN arch/sparc/kernel/setup.c~early-param-rusty arch/sparc/kernel/setup.c
--- 25/arch/sparc/kernel/setup.c~early-param-rusty	2004-04-04 17:01:39.229668432 -0700
+++ 25-akpm/arch/sparc/kernel/setup.c	2004-04-04 17:01:39.290659160 -0700
@@ -254,7 +254,7 @@ struct pt_regs fake_swapper_regs;
 
 extern void paging_init(void);
 
-void __init setup_arch(char **cmdline_p)
+void __init setup_arch(void)
 {
 	int i;
 	unsigned long highest_paddr;
@@ -262,8 +262,8 @@ void __init setup_arch(char **cmdline_p)
 	sparc_ttable = (struct tt_entry *) &start;
 
 	/* Initialize PROM console and command line. */
-	*cmdline_p = prom_getbootargs();
-	parse_early_options(cmdline_p);
+	strlcpy(saved_command_line, prom_getbootargs(), COMMAND_LINE_SIZE);
+	parse_early_options();
 
 	/* Set sparc_cpu_model */
 	sparc_cpu_model = sun_unknown;
diff -puN arch/sparc/kernel/vmlinux.lds.S~early-param-rusty arch/sparc/kernel/vmlinux.lds.S
--- 25/arch/sparc/kernel/vmlinux.lds.S~early-param-rusty	2004-04-04 17:01:39.231668128 -0700
+++ 25-akpm/arch/sparc/kernel/vmlinux.lds.S	2004-04-04 17:01:39.290659160 -0700
@@ -46,9 +46,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __early_begin = .;
-  __early_param : { *(__early_param) }
-  __early_end = .;
   __start___param = .;
   __param : { *(__param) }
   __stop___param = .;
diff -puN arch/um/kernel/um_arch.c~early-param-rusty arch/um/kernel/um_arch.c
--- 25/arch/um/kernel/um_arch.c~early-param-rusty	2004-04-04 17:01:39.232667976 -0700
+++ 25-akpm/arch/um/kernel/um_arch.c	2004-04-04 17:01:39.291659008 -0700
@@ -389,13 +389,11 @@ static struct notifier_block panic_exit_
 	.priority 		= 0
 };
 
-void __init setup_arch(char **cmdline_p)
+void __init setup_arch(void)
 {
 	notifier_chain_register(&panic_notifier_list, &panic_exit_notifier);
 	paging_init();
- 	strcpy(command_line, saved_command_line);
- 	*cmdline_p = command_line;
-	parse_early_options(cmdline_p);
+	parse_early_options();
 	setup_hostinfo();
 }
 
diff -puN arch/v850/kernel/setup.c~early-param-rusty arch/v850/kernel/setup.c
--- 25/arch/v850/kernel/setup.c~early-param-rusty	2004-04-04 17:01:39.234667672 -0700
+++ 25-akpm/arch/v850/kernel/setup.c	2004-04-04 17:01:39.291659008 -0700
@@ -58,10 +58,10 @@ static void init_mem_alloc (unsigned lon
 void set_mem_root (void *addr, size_t len, char *cmd_line);
 
 
-void __init setup_arch (char **cmdline)
+void __init setup_arch (void)
 {
-	*cmdline = command_line;
-	parse_early_options(cmdline_p);
+	strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
+	parse_early_options();
 
 	console_verbose ();
 
diff -puN arch/v850/kernel/vmlinux.lds.S~early-param-rusty arch/v850/kernel/vmlinux.lds.S
--- 25/arch/v850/kernel/vmlinux.lds.S~early-param-rusty	2004-04-04 17:01:39.235667520 -0700
+++ 25-akpm/arch/v850/kernel/vmlinux.lds.S	2004-04-04 17:01:39.292658856 -0700
@@ -110,11 +110,6 @@
 			*(.init.setup)	/* 2.5 convention */		      \
 			*(.setup.init)	/* 2.4 convention */		      \
 		___setup_end = . ;					      \
-
-		__early_begin = .;
-			*(__early_param)
-		__early_end = .;
-
 		___start___param = . ;					      \
 			*(__param)					      \
 		___stop___param = . ;					      \
diff -puN arch/x86_64/kernel/e820.c~early-param-rusty arch/x86_64/kernel/e820.c
--- 25/arch/x86_64/kernel/e820.c~early-param-rusty	2004-04-04 17:01:39.236667368 -0700
+++ 25-akpm/arch/x86_64/kernel/e820.c	2004-04-04 17:01:39.293658704 -0700
@@ -505,7 +505,7 @@ void __init setup_memory_region(void)
 	e820_print_map(who);
 }
 
-static int __init parse_memopt(char *s)
+static void __init parse_memopt(char *s)
 { 
 	/*
 	 * mem=XXX[kKmM] limits kernel memory to XXX+1MB
@@ -521,9 +521,10 @@ static int __init parse_memopt(char *s)
 	 *
 	 * -AK
 	 */
+	if (!s)
+		return;
 	end_user_pfn = memparse(s, &s) + HIGH_MEMORY;
 	end_user_pfn >>= PAGE_SHIFT;	
-	return 0;
 } 
-__early_param("mem=",parse_memopt);
+__early_param("mem", parse_memopt);
 
diff -puN arch/x86_64/kernel/early_printk.c~early-param-rusty arch/x86_64/kernel/early_printk.c
--- 25/arch/x86_64/kernel/early_printk.c~early-param-rusty	2004-04-04 17:01:39.238667064 -0700
+++ 25-akpm/arch/x86_64/kernel/early_printk.c	2004-04-04 17:01:39.293658704 -0700
@@ -171,13 +171,13 @@ void early_printk(const char *fmt, ...)
 
 static int keep_early; 
 
-int __init setup_early_printk(char *opt) 
+void __init setup_early_printk(char *opt)
 {  
 	char *space;
 	char buf[256]; 
 
-	if (early_console_initialized)
-		return -1;
+	if (early_console_initialized || !opt)
+		return;
 
 	opt = strchr(opt, '=') + 1;
 
@@ -199,11 +199,10 @@ int __init setup_early_printk(char *opt)
 		early_console = &early_vga_console; 
 	} else {
 		early_console = NULL; 		
-		return -1; 
+		return;
 	}
 	early_console_initialized = 1;
 	register_console(early_console);       
-	return 0;
 }
 
 void __init disable_early_printk(void)
@@ -219,4 +218,4 @@ void __init disable_early_printk(void)
 	}
 } 
 
-__early_param("earlyprintk=", setup_early_printk);
+__early_param("earlyprintk", setup_early_printk);
diff -puN arch/x86_64/kernel/mpparse.c~early-param-rusty arch/x86_64/kernel/mpparse.c
--- 25/arch/x86_64/kernel/mpparse.c~early-param-rusty	2004-04-04 17:01:39.240666760 -0700
+++ 25-akpm/arch/x86_64/kernel/mpparse.c	2004-04-04 17:01:39.294658552 -0700
@@ -977,9 +977,9 @@ void __init mp_parse_prt (void)
 
 #endif /*CONFIG_ACPI_BOOT*/
 
-static __init int early_maxcpus(char *s)
+static __init void early_maxcpus(char *s)
 {
-	maxcpus = simple_strtoul(s, NULL, 0);
-	return 0;
+	if (s)
+		maxcpus = simple_strtoul(s, NULL, 0);
 }
-__early_param("maxcpus=", early_maxcpus);
+__early_param("maxcpus", early_maxcpus);
diff -puN arch/x86_64/kernel/pci-gart.c~early-param-rusty arch/x86_64/kernel/pci-gart.c
--- 25/arch/x86_64/kernel/pci-gart.c~early-param-rusty	2004-04-04 17:01:39.241666608 -0700
+++ 25-akpm/arch/x86_64/kernel/pci-gart.c	2004-04-04 17:01:39.295658400 -0700
@@ -857,6 +857,9 @@ static __init int iommu_setup(char *opt)
 { 
     int arg;
     char *p = opt;
+
+    if (!opt)
+	    return;
     
     for (;;) { 
 	    if (!memcmp(p,"noagp", 5))
@@ -910,9 +913,8 @@ static __init int iommu_setup(char *opt)
 		    iommu_size = arg;
 	    do {
 		    if (*p == ' ' || *p == 0) 
-			    return 0; 
+			    return;
 	    } while (*p++ != ','); 
     }
-    return 0;
 } 
-__early_param("iommu=",iommu_setup);
+__early_param("iommu", iommu_setup);
diff -puN arch/x86_64/kernel/setup.c~early-param-rusty arch/x86_64/kernel/setup.c
--- 25/arch/x86_64/kernel/setup.c~early-param-rusty	2004-04-04 17:01:39.242666456 -0700
+++ 25-akpm/arch/x86_64/kernel/setup.c	2004-04-04 17:01:39.296658248 -0700
@@ -193,8 +193,11 @@ static void __init probe_roms(void)
 
 #ifdef CONFIG_ACPI_BOOT
 /* should be moved elsewhere */
-static __init int early_acpi(char *s)
+static __init void early_acpi(char *s)
 {
+	if (!s)
+		return;
+
 	/* "acpi=off" disables both ACPI table parsing and interpreter init */
 	if (!strcmp(s, "off"))
 		acpi_disabled = 1;
@@ -213,15 +216,13 @@ static __init int early_acpi(char *s)
 	/* acpi=strict disables out-of-spec workarounds */
 	else if (!strcmp(s, "strict"))
 		acpi_strict = 1;
-	else
-		return -1;
-
-	return 0;
 }
 __early_param("acpi=", early_acpi);
 
-static __init int early_acpi_sci(char *s)
+static __init void early_acpi_sci(char *s)
 {
+	if (!s)
+		return;
 	if (!strcmp(s, "edge"))
 		acpi_sci_flags.trigger =  1;
 	else if (!strcmp(s, "level"))
@@ -230,37 +231,24 @@ static __init int early_acpi_sci(char *s
 		acpi_sci_flags.polarity = 1;
 	else if (!strcmp(s, "low"))
 		acpi_sci_flags.polarity = 3;
-	else
-		return -1;
-	return 0;
 }
-__early_param("acpi_sci=", early_acpi_sci);
+__early_param("acpi_sci", early_acpi_sci);
 
-static __init int early_pci(char *s)
+static __init void early_pci(char *s)
 {
-	if (!strcmp(s, "noacpi"))
+	if (s && !strcmp(s, "noacpi"))
 		acpi_noirq_set();
-	else
-		return -1;
-	return 0;
 }
-__early_param("pci=", early_pci);
+__early_param("pci", early_pci);
 #endif
 
-static __init int early_nolapic(char *s)
+static __init void early_nolapic(char *s)
 {
 	disable_apic = 1;
-	return 0;
 }
 __early_param("nolapic", early_nolapic);
-
 /* alias for compatibility */
-static __init int early_disableapic(char *s)
-{
-	disable_apic = 1;
-	return 0;
-}
-__early_param("disableapic", early_disableapic);
+__early_param("disableapic", early_nolapic);
 
 static __init int early_no_ioapic(char *s)
 {
@@ -269,20 +257,19 @@ static __init int early_no_ioapic(char *
 }
 __early_param("noapic", early_no_ioapic);
 
-static __init int early_apic(char *s)
+static __init void early_apic(char *s)
 {
 	skip_ioapic_setup = 0;
 	ioapic_force = 1;
-	return 0;
 }
 __early_param("apic", early_apic);
 
-static __init int early_oopspanic(char *s)
+static __init void early_oopspanic(char *s)
 {
-	panic_on_oops = 1;
-	return 0;
+	if (s && strcmp(s, "panic") == 0)
+		panic_on_oops = 1;
 }
-__early_param("oops=panic", early_oopspanic);
+__early_param("oops", early_oopspanic);
 
 
 #ifndef CONFIG_DISCONTIGMEM
@@ -389,7 +376,7 @@ static inline void copy_edd(void)
 #define copy_edd() do {} while (0)
 #endif
 
-void __init setup_arch(char **cmdline_p)
+void __init setup_arch(void)
 {
 	unsigned long low_mem_size;
 	unsigned long kernel_end;
@@ -421,8 +408,8 @@ void __init setup_arch(char **cmdline_p)
 	data_resource.start = virt_to_phys(&_etext);
 	data_resource.end = virt_to_phys(&_edata)-1;
 
-	*cmdline_p = early_command_line;
-	parse_early_options(cmdline_p);
+	strlcpy(saved_command_line, early_command_line, COMMAND_LINE_SIZE);
+	parse_early_options();
 
 	/*
 	 * partially used pages are not usable - thus
diff -puN arch/x86_64/kernel/vmlinux.lds.S~early-param-rusty arch/x86_64/kernel/vmlinux.lds.S
--- 25/arch/x86_64/kernel/vmlinux.lds.S~early-param-rusty	2004-04-04 17:01:39.244666152 -0700
+++ 25-akpm/arch/x86_64/kernel/vmlinux.lds.S	2004-04-04 17:01:39.297658096 -0700
@@ -90,9 +90,6 @@ SECTIONS
   __setup_start = .;
   .init.setup : { *(.init.setup) }
   __setup_end = .;
-  __early_begin = .;
-  __early_param : { *(__early_param) }
-  __early_end = .;
   __start___param = .;
   __param : { *(__param) }
   __stop___param = .;
diff -puN arch/x86_64/mm/numa.c~early-param-rusty arch/x86_64/mm/numa.c
--- 25/arch/x86_64/mm/numa.c~early-param-rusty	2004-04-04 17:01:39.245666000 -0700
+++ 25-akpm/arch/x86_64/mm/numa.c	2004-04-04 17:01:39.297658096 -0700
@@ -178,13 +178,10 @@ void __init paging_init(void)
 } 
 
 /* [numa=off] */
-static __init int numa_setup(char *opt)
+static __init void numa_setup(char *opt)
 { 
-	if (!strcmp(opt,"off"))
+	if (opt && !strcmp(opt,"off"))
 		numa_off = 1;
-	else
-		return -1;
-	return 0;
 } 
-__early_param("numa=", numa_setup);
+__early_param("numa", numa_setup);
 
diff -puN drivers/pci/pci.c~early-param-rusty drivers/pci/pci.c
--- 25/drivers/pci/pci.c~early-param-rusty	2004-04-04 17:01:39.246665848 -0700
+++ 25-akpm/drivers/pci/pci.c	2004-04-04 17:01:39.298657944 -0700
@@ -750,7 +750,7 @@ static int __devinit pci_init(void)
 	return 0;
 }
 
-static int __devinit pci_setup(char *str)
+static void __init pci_setup(char *str)
 {
 	while (str) {
 		char *k = strchr(str, ',');
@@ -762,12 +762,11 @@ static int __devinit pci_setup(char *str
 		}
 		str = k;
 	}
-	return 1;
 }
 
 device_initcall(pci_init);
 
-__early_param("pci=", pci_setup);
+__early_param("pci", pci_setup);
 
 #if defined(CONFIG_ISA) || defined(CONFIG_EISA)
 /* FIXME: Some boxes have multiple ISA bridges! */
diff -puN include/asm-i386/param.h~early-param-rusty include/asm-i386/param.h
--- 25/include/asm-i386/param.h~early-param-rusty	2004-04-04 17:01:39.248665544 -0700
+++ 25-akpm/include/asm-i386/param.h	2004-04-04 17:01:39.299657792 -0700
@@ -20,5 +20,6 @@
 #endif
 
 #define MAXHOSTNAMELEN	64	/* max length of hostname */
+#define COMMAND_LINE_SIZE 256
 
 #endif
diff -puN include/asm-i386/setup.h~early-param-rusty include/asm-i386/setup.h
--- 25/include/asm-i386/setup.h~early-param-rusty	2004-04-04 17:01:39.249665392 -0700
+++ 25-akpm/include/asm-i386/setup.h	2004-04-04 17:01:39.299657792 -0700
@@ -17,7 +17,6 @@
 #define MAX_NONPAE_PFN	(1 << 20)
 
 #define PARAM_SIZE 2048
-#define COMMAND_LINE_SIZE 256
 
 #define OLD_CL_MAGIC_ADDR	0x90020
 #define OLD_CL_MAGIC		0xA33F
diff -puN include/asm-um/common.lds.S~early-param-rusty include/asm-um/common.lds.S
--- 25/include/asm-um/common.lds.S~early-param-rusty	2004-04-04 17:01:39.250665240 -0700
+++ 25-akpm/include/asm-um/common.lds.S	2004-04-04 17:01:39.299657792 -0700
@@ -46,10 +46,6 @@
   .init.setup : { *(.init.setup) }
   __setup_end = .;
 
-  __early_begin = .;
-  __early_param : { *(__early_param) }
-  __early_end = .;
-
   __start___param = .;
   __param : { *(__param) }
   __stop___param = .;
diff -puN include/linux/init.h~early-param-rusty include/linux/init.h
--- 25/include/linux/init.h~early-param-rusty	2004-04-04 17:01:39.251665088 -0700
+++ 25-akpm/include/linux/init.h	2004-04-04 17:01:39.300657640 -0700
@@ -68,23 +68,6 @@ typedef void (*exitcall_t)(void);
 
 extern initcall_t __con_initcall_start, __con_initcall_end;
 extern initcall_t __security_initcall_start, __security_initcall_end;
-
-/*
- * Early command line parameters.  We do not allow for spaces in
- * our arguments.  Functions are allowed to fail (negative return
- * value) but must ensure the arg is unchanged, and can only splice
- * the arg up, and not rewrite it.
- */
-struct early_params {
-	const char *arg;
-	int (*fn)(char *p);
-};
-extern struct early_params __early_begin, __early_end;
-extern void parse_early_options(char **cmdline_p);
-
-#define __early_param(name,fn)					\
-static struct early_params __early_##fn __attribute_used__	\
-__attribute__((__section__("__early_param"))) = { name, fn }
 #endif
   
 #ifndef MODULE
@@ -125,26 +108,43 @@ __attribute__((__section__("__early_para
 
 struct obs_kernel_param {
 	const char *str;
-	int (*setup_func)(char *);
+	union {
+		int (*setup_func)(char *);
+		void (*param_func)(char *);
+	} u;
+	int early;
 };
 
-/* OBSOLETE: see moduleparam.h for the right way. */
-#define __setup_param(str, unique_id, fn)			\
-	static char __setup_str_##unique_id[] __initdata = str;	\
-	static struct obs_kernel_param __setup_##unique_id	\
-		 __attribute_used__				\
-		 __attribute__((__section__(".init.setup")))	\
-		= { __setup_str_##unique_id, fn }
+/* These only when builtin: see moduleparam.h for the normal way. */
+/* Called if str matches prefix: fn returns 1 if we're the right one. */
+#define __setup(prefix, fn)					\
+	__setup_param(prefix, fn, {.setup_func = fn}, 0)
+
+/* Called v. early on when option matches str: fn gets string after =,
+ * or NULL. */
+#define __early_param(str, fn)					\
+	__setup_param(str, __LINE__, {.param_func = fn}, 1)
 
-#define __setup_null_param(str, unique_id)			\
-	__setup_param(str, unique_id, NULL)
+/* Does nothing, but will warn user if it's used. */
+#define __obsolete_setup(str)					\
+	__setup_param(str, __LINE__, {.setup_func = NULL}, 0)
 
-#define __setup(str, fn)					\
-	__setup_param(str, fn, fn)
+/* Indirection req'd to expand __LINE__. */
+#define __setup_param(str, line, fn_init, early)		\
+	__setup_param2(str, line, fn_init, early)
+
+#define __setup_param2(str, line, fn_init, early)		\
+	static char __setup_str_##line[] __initdata = str;	\
+	static struct obs_kernel_param __setup_##line		\
+		 __attribute_used__				\
+		 __attribute__((__section__(".init.setup")))	\
+		= { __setup_str_##line, fn_init, early }
 
-#define __obsolete_setup(str)					\
-	__setup_null_param(str, __LINE__)
+/* Arch provides */
+extern void setup_arch(void);
 
+/* Relies on saved_command_line being set */
+void __init parse_early_options(void);
 #endif /* __ASSEMBLY__ */
 
 /**
diff -puN init/do_mounts.c~early-param-rusty init/do_mounts.c
--- 25/init/do_mounts.c~early-param-rusty	2004-04-04 17:01:39.253664784 -0700
+++ 25-akpm/init/do_mounts.c	2004-04-04 17:01:39.301657488 -0700
@@ -387,6 +387,7 @@ void __init prepare_namespace(void)
 	md_run_setup();
 
 	if (saved_root_name[0]) {
+		printk("Saved root name %s\n", saved_root_name);
 		root_device_name = saved_root_name;
 		ROOT_DEV = name_to_dev_t(root_device_name);
 		if (strncmp(root_device_name, "/dev/", 5) == 0)
diff -puN init/main.c~early-param-rusty init/main.c
--- 25/init/main.c~early-param-rusty	2004-04-04 17:01:39.254664632 -0700
+++ 25-akpm/init/main.c	2004-04-04 17:01:39.302657336 -0700
@@ -110,7 +110,6 @@ extern void softirq_init(void);
 
 /* Stuff for the command line. */
 char saved_command_line[COMMAND_LINE_SIZE];		/* For /proc */
-static char tmp_command_line[COMMAND_LINE_SIZE];	/* Parsed. */
 
 static char *execute_command;
 
@@ -158,10 +157,13 @@ static int __init obsolete_checksetup(ch
 	do {
 		int n = strlen(p->str);
 		if (!strncmp(line, p->str, n)) {
-			if (!p->setup_func) {
+			/* Already done in handle_early_option? */
+			if (p->early)
+				return 1;
+			if (!p->u.setup_func) {
 				printk(KERN_WARNING "Parameter %s is obsolete, ignored\n", p->str);
 				return 1;
-			} else if (p->setup_func(line + n))
+			} else if (p->u.setup_func(line + n))
 				return 1;
 		}
 		p++;
@@ -304,7 +306,6 @@ static int __init init_setup(char *str)
 }
 __setup("init=", init_setup);
 
-extern void setup_arch(char **);
 extern void cpu_idle(void);
 
 #ifndef CONFIG_SMP
@@ -394,53 +395,30 @@ static void noinline rest_init(void)
 	kernel_thread(init, NULL, CLONE_FS | CLONE_SIGHAND);
 	unlock_kernel();
  	cpu_idle();
-} 
+}
 
-/*
- * Initial parsing of the command line.  We destructivly
- * scan the pointer, and take out any params for which we have
- * an early handler for.
- */
-void __init parse_early_options(char **cmdline_p)
+/* Check for early options. */
+static int __init early_option(char *param, char *val)
 {
-	char *from = *cmdline_p;	/* Original. */
-	char c = ' ', *to = tmp_command_line;	/* Parsed. */
-	int len = 0;
-
-	/* Save it, if we need to. */
-	if (*cmdline_p != saved_command_line)
-		memcpy(saved_command_line, *cmdline_p, COMMAND_LINE_SIZE);
-	saved_command_line[COMMAND_LINE_SIZE - 1] = '\0';
-
-	for (;;) {
-		if (c == ' ') {
-			struct early_params *p;
-
-			for (p = &__early_begin; p < &__early_end; p++) {
-				int len = strlen(p->arg);
-
-				if (memcmp(from, p->arg, len) == 0) {
-					if (to != *cmdline_p)
-						to -= 1;
-					from += len;
-					p->fn(from);
-
-					while (*from != ' ' && *from != '\0')
-						from++;
-					break;
-				}
-			}
-		}
-		c = *from++;
-		if (!c)
-			break;
-		if (COMMAND_LINE_SIZE <= ++len)
-			break;
-		*to++ = c;
-	}
+	struct obs_kernel_param *p;
+	extern struct obs_kernel_param __setup_start, __setup_end;
+
+	for (p = &__setup_start; p < &__setup_end; p++)
+		if (p->early && strcmp(param, p->str) == 0)
+			p->u.param_func(val);
 
-	*to = '\0';
-	*cmdline_p = tmp_command_line;
+	/* We accept everything at this stage. */
+	return 0;
+}
+
+/* Arch code calls this early on. */
+void __init parse_early_options(void)
+{
+	static __initdata char tmp_cmdline[COMMAND_LINE_SIZE];
+
+	/* All fall through to early_option. */
+	strlcpy(tmp_cmdline, saved_command_line, COMMAND_LINE_SIZE);
+	parse_args("early options", tmp_cmdline, NULL, 0, early_option);
 }
 
 /*
@@ -449,7 +427,8 @@ void __init parse_early_options(char **c
 
 asmlinkage void __init start_kernel(void)
 {
-	char * command_line;
+	/* init options and env stay in here, so can't be __init */
+	static char parsed_cmdline[COMMAND_LINE_SIZE];
 	extern struct kernel_param __start___param[], __stop___param[];
 /*
  * Interrupts are still disabled. Do necessary setups, then
@@ -458,7 +437,7 @@ asmlinkage void __init start_kernel(void
 	lock_kernel();
 	page_address_init();
 	printk(linux_banner);
-	setup_arch(&command_line);
+	setup_arch();
 	setup_per_cpu_areas();
 
 	/*
@@ -478,7 +457,8 @@ asmlinkage void __init start_kernel(void
 	page_alloc_init();
 	trap_init();
 	printk("Kernel command line: %s\n", saved_command_line);
-	parse_args("Booting kernel", command_line, __start___param,
+	strlcpy(parsed_cmdline, saved_command_line, COMMAND_LINE_SIZE);
+	parse_args("Booting kernel", parsed_cmdline, __start___param,
 		   __stop___param - __start___param,
 		   &unknown_bootoption);
 	sort_main_extable();
@@ -663,7 +643,7 @@ static int init(void * unused)
         * let it do all the work
         */
        if (sys_access("/init", 0) == 0)
-               execute_command = "/init";
+	       execute_command = "/init";
        else
 	prepare_namespace();
 
@@ -681,7 +661,7 @@ static int init(void * unused)
 
 	(void) sys_dup(0);
 	(void) sys_dup(0);
-	
+
 	/*
 	 * We try each of these until one succeeds.
 	 *
diff -puN kernel/printk.c~early-param-rusty kernel/printk.c
--- 25/kernel/printk.c~early-param-rusty	2004-04-04 17:01:39.255664480 -0700
+++ 25-akpm/kernel/printk.c	2004-04-04 17:01:39.303657184 -0700
@@ -116,12 +116,15 @@ static int console_may_schedule;
 /*
  *	Setup a list of consoles. Called from init/main.c
  */
-static int __init console_setup(char *str)
+static void __init console_setup(char *str)
 {
 	char name[sizeof(console_cmdline[0].name)];
 	char *s, *options;
 	int idx;
 
+	if (!str)
+		return;
+
 	/*
 	 *	Decode str into name, index, options, ensure name and
 	 *	options are NUL-terminated.
@@ -150,10 +153,9 @@ static int __init console_setup(char *st
 	*s = 0;
 
 	add_preferred_console(name, idx, options);
-	return 1;
 }
 
-__early_param("console=", console_setup);
+__early_param("console", console_setup);
 
 /**
  * add_preferred_console - add a device to the list of preferred consoles.

_