gpio: pxa: Fix return value of pxa_gpio_probe()
[linux-2.6-microblaze.git] / init / main.c
index a48617f..0337197 100644 (file)
@@ -257,6 +257,47 @@ static int __init loglevel(char *str)
 
 early_param("loglevel", loglevel);
 
+#ifdef CONFIG_BLK_DEV_INITRD
+static void * __init get_boot_config_from_initrd(u32 *_size, u32 *_csum)
+{
+       u32 size, csum;
+       char *data;
+       u32 *hdr;
+
+       if (!initrd_end)
+               return NULL;
+
+       data = (char *)initrd_end - BOOTCONFIG_MAGIC_LEN;
+       if (memcmp(data, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN))
+               return NULL;
+
+       hdr = (u32 *)(data - 8);
+       size = hdr[0];
+       csum = hdr[1];
+
+       data = ((void *)hdr) - size;
+       if ((unsigned long)data < initrd_start) {
+               pr_err("bootconfig size %d is greater than initrd size %ld\n",
+                       size, initrd_end - initrd_start);
+               return NULL;
+       }
+
+       /* Remove bootconfig from initramfs/initrd */
+       initrd_end = (unsigned long)data;
+       if (_size)
+               *_size = size;
+       if (_csum)
+               *_csum = csum;
+
+       return data;
+}
+#else
+static void * __init get_boot_config_from_initrd(u32 *_size, u32 *_csum)
+{
+       return NULL;
+}
+#endif
+
 #ifdef CONFIG_BOOT_CONFIG
 
 char xbc_namebuf[XBC_KEYLEN_MAX] __initdata;
@@ -357,9 +398,11 @@ static void __init setup_boot_config(const char *cmdline)
        int pos;
        u32 size, csum;
        char *data, *copy;
-       u32 *hdr;
        int ret;
 
+       /* Cut out the bootconfig data even if we have no bootconfig option */
+       data = get_boot_config_from_initrd(&size, &csum);
+
        strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
        parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL,
                   bootconfig_params);
@@ -367,16 +410,10 @@ static void __init setup_boot_config(const char *cmdline)
        if (!bootconfig_found)
                return;
 
-       if (!initrd_end)
-               goto not_found;
-
-       data = (char *)initrd_end - BOOTCONFIG_MAGIC_LEN;
-       if (memcmp(data, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN))
-               goto not_found;
-
-       hdr = (u32 *)(data - 8);
-       size = hdr[0];
-       csum = hdr[1];
+       if (!data) {
+               pr_err("'bootconfig' found on command line, but no bootconfig found\n");
+               return;
+       }
 
        if (size >= XBC_DATA_MAX) {
                pr_err("bootconfig size %d greater than max size %d\n",
@@ -384,10 +421,6 @@ static void __init setup_boot_config(const char *cmdline)
                return;
        }
 
-       data = ((void *)hdr) - size;
-       if ((unsigned long)data < initrd_start)
-               goto not_found;
-
        if (boot_config_checksum((unsigned char *)data, size) != csum) {
                pr_err("bootconfig checksum failed\n");
                return;
@@ -417,11 +450,15 @@ static void __init setup_boot_config(const char *cmdline)
                extra_init_args = xbc_make_cmdline("init");
        }
        return;
-not_found:
-       pr_err("'bootconfig' found on command line, but no bootconfig found\n");
 }
+
 #else
-#define setup_boot_config(cmdline)     do { } while (0)
+
+static void __init setup_boot_config(const char *cmdline)
+{
+       /* Remove bootconfig data from initrd */
+       get_boot_config_from_initrd(NULL, NULL);
+}
 
 static int __init warn_bootconfig(char *str)
 {
@@ -1001,6 +1038,8 @@ asmlinkage __visible void __init start_kernel(void)
 
        /* Do the rest non-__init'ed, we're now alive */
        arch_call_rest_init();
+
+       prevent_tail_call_optimization();
 }
 
 /* Call all constructor functions linked into the kernel. */