diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-14 23:06:58 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-14 23:06:58 (GMT) |
commit | 85082fd7cbe3173198aac0eb5e85ab1edcc6352c (patch) | |
tree | edbc09b7945994f78668d218fa02e991c3b3b365 /arch/arm/kernel/atags.c | |
parent | 666484f0250db2e016948d63b3ef33e202e3b8d0 (diff) | |
parent | 53ffe3b440aa85af6fc4eda09b2d44bcdd312d4d (diff) | |
download | linux-85082fd7cbe3173198aac0eb5e85ab1edcc6352c.tar.xz |
Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm: (241 commits)
[ARM] 5171/1: ep93xx: fix compilation of modules using clocks
[ARM] 5133/2: at91sam9g20 defconfig file
[ARM] 5130/4: Support for the at91sam9g20
[ARM] 5160/1: IOP3XX: gpio/gpiolib support
[ARM] at91: Fix NAND FLASH timings for at91sam9x evaluation kits.
[ARM] 5084/1: zylonite: Register AC97 device
[ARM] 5085/2: PXA: Move AC97 over to the new central device declaration model
[ARM] 5120/1: pxa: correct platform driver names for PXA25x and PXA27x UDC drivers
[ARM] 5147/1: pxaficp_ir: drop pxa_gpio_mode calls, as pin setting
[ARM] 5145/1: PXA2xx: provide api to control IrDA pins state
[ARM] 5144/1: pxaficp_ir: cleanup includes
[ARM] pxa: remove pxa_set_cken()
[ARM] pxa: allow clk aliases
[ARM] Feroceon: don't disable BPU on boot
[ARM] Orion: LED support for HP mv2120
[ARM] Orion: add RD88F5181L-FXO support
[ARM] Orion: add RD88F5181L-GE support
[ARM] Orion: add Netgear WNR854T support
[ARM] s3c2410_defconfig: update for current build
[ARM] Acer n30: Minor style and indentation fixes.
...
Diffstat (limited to 'arch/arm/kernel/atags.c')
-rw-r--r-- | arch/arm/kernel/atags.c | 83 |
1 files changed, 40 insertions, 43 deletions
diff --git a/arch/arm/kernel/atags.c b/arch/arm/kernel/atags.c index 64c4208..42a1a14 100644 --- a/arch/arm/kernel/atags.c +++ b/arch/arm/kernel/atags.c @@ -1,5 +1,4 @@ #include <linux/slab.h> -#include <linux/kexec.h> #include <linux/proc_fs.h> #include <asm/setup.h> #include <asm/types.h> @@ -7,9 +6,8 @@ struct buffer { size_t size; - char *data; + char data[]; }; -static struct buffer tags_buffer; static int read_buffer(char* page, char** start, off_t off, int count, @@ -29,58 +27,57 @@ read_buffer(char* page, char** start, off_t off, int count, return count; } - -static int -create_proc_entries(void) -{ - struct proc_dir_entry* tags_entry; - - tags_entry = create_proc_read_entry("atags", 0400, NULL, read_buffer, &tags_buffer); - if (!tags_entry) - return -ENOMEM; - - return 0; -} - - -static char __initdata atags_copy_buf[KEXEC_BOOT_PARAMS_SIZE]; -static char __initdata *atags_copy; +#define BOOT_PARAMS_SIZE 1536 +static char __initdata atags_copy[BOOT_PARAMS_SIZE]; void __init save_atags(const struct tag *tags) { - atags_copy = atags_copy_buf; - memcpy(atags_copy, tags, KEXEC_BOOT_PARAMS_SIZE); + memcpy(atags_copy, tags, sizeof(atags_copy)); } - static int __init init_atags_procfs(void) { - struct tag *tag; - int error; + /* + * This cannot go into save_atags() because kmalloc and proc don't work + * yet when it is called. + */ + struct proc_dir_entry *tags_entry; + struct tag *tag = (struct tag *)atags_copy; + struct buffer *b; + size_t size; - if (!atags_copy) { - printk(KERN_WARNING "Exporting ATAGs: No saved tags found\n"); - return -EIO; + if (tag->hdr.tag != ATAG_CORE) { + printk(KERN_INFO "No ATAGs?"); + return -EINVAL; } - for (tag = (struct tag *) atags_copy; tag->hdr.size; tag = tag_next(tag)) + for (; tag->hdr.size; tag = tag_next(tag)) ; - tags_buffer.size = ((char *) tag - atags_copy) + sizeof(tag->hdr); - tags_buffer.data = kmalloc(tags_buffer.size, GFP_KERNEL); - if (tags_buffer.data == NULL) - return -ENOMEM; - memcpy(tags_buffer.data, atags_copy, tags_buffer.size); - - error = create_proc_entries(); - if (error) { - printk(KERN_ERR "Exporting ATAGs: not enough memory\n"); - kfree(tags_buffer.data); - tags_buffer.size = 0; - tags_buffer.data = NULL; - } + /* include the terminating ATAG_NONE */ + size = (char *)tag - atags_copy + sizeof(struct tag_header); - return error; -} + WARN_ON(tag->hdr.tag != ATAG_NONE); + + b = kmalloc(sizeof(*b) + size, GFP_KERNEL); + if (!b) + goto nomem; + b->size = size; + memcpy(b->data, atags_copy, size); + + tags_entry = create_proc_read_entry("atags", 0400, + NULL, read_buffer, b); + + if (!tags_entry) + goto nomem; + + return 0; + +nomem: + kfree(b); + printk(KERN_ERR "Exporting ATAGs: not enough memory\n"); + + return -ENOMEM; +} arch_initcall(init_atags_procfs); |