1#include <linux/slab.h> 2#include <linux/proc_fs.h> 3#include <asm/setup.h> 4#include <asm/types.h> 5#include <asm/page.h> 6 7struct buffer { 8 size_t size; 9 char data[]; 10}; 11 12static int 13read_buffer(char* page, char** start, off_t off, int count, 14 int* eof, void* data) 15{ 16 struct buffer *buffer = (struct buffer *)data; 17 18 if (off >= buffer->size) { 19 *eof = 1; 20 return 0; 21 } 22 23 count = min((int) (buffer->size - off), count); 24 25 memcpy(page, &buffer->data[off], count); 26 27 return count; 28} 29 30#define BOOT_PARAMS_SIZE 1536 31static char __initdata atags_copy[BOOT_PARAMS_SIZE]; 32 33void __init save_atags(const struct tag *tags) 34{ 35 memcpy(atags_copy, tags, sizeof(atags_copy)); 36} 37 38static int __init init_atags_procfs(void) 39{ 40 /* 41 * This cannot go into save_atags() because kmalloc and proc don't work 42 * yet when it is called. 43 */ 44 struct proc_dir_entry *tags_entry; 45 struct tag *tag = (struct tag *)atags_copy; 46 struct buffer *b; 47 size_t size; 48 49 if (tag->hdr.tag != ATAG_CORE) { 50 printk(KERN_INFO "No ATAGs?"); 51 return -EINVAL; 52 } 53 54 for (; tag->hdr.size; tag = tag_next(tag)) 55 ; 56 57 /* include the terminating ATAG_NONE */ 58 size = (char *)tag - atags_copy + sizeof(struct tag_header); 59 60 WARN_ON(tag->hdr.tag != ATAG_NONE); 61 62 b = kmalloc(sizeof(*b) + size, GFP_KERNEL); 63 if (!b) 64 goto nomem; 65 66 b->size = size; 67 memcpy(b->data, atags_copy, size); 68 69 tags_entry = create_proc_read_entry("atags", 0400, 70 NULL, read_buffer, b); 71 72 if (!tags_entry) 73 goto nomem; 74 75 return 0; 76 77nomem: 78 kfree(b); 79 printk(KERN_ERR "Exporting ATAGs: not enough memory\n"); 80 81 return -ENOMEM; 82} 83arch_initcall(init_atags_procfs); 84