diff options
author | Hervé Fache <h-fache@ti.com> | 2012-03-13 19:07:53 +0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2012-03-27 03:57:11 +0400 |
commit | b2a2a84d35e0f42ad26e326ec4258f6a8b8eecbe (patch) | |
tree | 12407708dfdab40e0bf4107db15f780f46e933de /drivers/mtd/devices/phram.c | |
parent | 09ef90d965fff295da8d5359ac21e54c02236dba (diff) | |
download | linux-b2a2a84d35e0f42ad26e326ec4258f6a8b8eecbe.tar.xz |
mtd: phram: dot not crash when built-in and passing boot param
This patch is based on Ville Herva's similar patch to block2mtd.
Trying to pass a parameter through the kernel command line when built-in would
crash the kernel, as phram_setup() was called so early that kmalloc() was not
functional yet.
This patch only saves the parameter string at the early boot stage, and parses
it later when init_phram() is called. The same happens in both module and
built-in cases.
With this patch, I can boot with a statically-compiled phram, and mount a
ext2 root fs from physical RAM, without the need for a initrd.
This has been tested in built-in and module cases, with and without a
parameter string.
Artem: amended comments a bit
Signed-off-by: Hervé Fache <h-fache@ti.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/devices/phram.c')
-rw-r--r-- | drivers/mtd/devices/phram.c | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c index 9d2bf1741fb2..3d91ace1ee4c 100644 --- a/drivers/mtd/devices/phram.c +++ b/drivers/mtd/devices/phram.c @@ -39,7 +39,8 @@ static int phram_erase(struct mtd_info *mtd, struct erase_info *instr) memset(start + instr->addr, 0xff, instr->len); - /* This'll catch a few races. Free the thing before returning :) + /* + * This'll catch a few races. Free the thing before returning :) * I don't feel at all ashamed. This kind of thing is possible anyway * with flash, but unlikely. */ @@ -204,7 +205,17 @@ static inline void kill_final_newline(char *str) return 1; \ } while (0) -static int phram_setup(const char *val, struct kernel_param *kp) +/* + * This shall contain the module parameter if any. It is of the form: + * - phram=<device>,<address>,<size> for module case + * - phram.phram=<device>,<address>,<size> for built-in case + * We leave 64 bytes for the device name, 12 for the address and 12 for the + * size. + * Example: phram.phram=rootfs,0xa0000000,512Mi + */ +static __initdata char phram_paramline[64+12+12]; + +static int phram_setup(const char *val) { char buf[64+12+12], *str = buf; char *token[3]; @@ -253,12 +264,28 @@ static int phram_setup(const char *val, struct kernel_param *kp) return ret; } -module_param_call(phram, phram_setup, NULL, NULL, 000); +static int __init phram_param_call(const char *val, struct kernel_param *kp) +{ + /* + * This function is always called before 'init_phram()', whether + * built-in or module. + */ + if (strlen(val) >= sizeof(phram_paramline)) + return -ENOSPC; + strcpy(phram_paramline, val); + + return 0; +} + +module_param_call(phram, phram_param_call, NULL, NULL, 000); MODULE_PARM_DESC(phram, "Memory region to map. \"phram=<name>,<start>,<length>\""); static int __init init_phram(void) { + if (phram_paramline[0]) + return phram_setup(phram_paramline); + return 0; } |