[klibc] ARM: create /arch.cmd commands from firmware tags ARM communicates with its firmware with a tagged data structure. This takes appropriate chunks of the tagged data structure and converts it to /arch.cmd options for kinit. Bug report and initial patch by Thomas Gleixner , significantly modified by me. Signed-off-by: H. Peter Anvin --- commit 154c0ca675048a41a3f2ca5d3c0800b07bbc1d77 tree 5cfa889055f3ae37f46830edf61a0b2cac832d2e parent 12c13caa9889babd6e305caead3038dd4218b45d author H. Peter Anvin Fri, 30 Jun 2006 16:03:47 -0700 committer H. Peter Anvin Sun, 02 Jul 2006 12:26:19 -0700 arch/arm/kernel/setup.c | 80 ++++++++++++++++++++++++++++++++++++++--------- 1 files changed, 64 insertions(+), 16 deletions(-) diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 7447a19..3797582 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -56,7 +56,6 @@ #endif extern void paging_init(struct meminfo *, struct machine_desc *desc); extern void reboot_setup(char *str); -extern int root_mountflags; extern void _stext, _text, _etext, __data_start, _edata, _end; unsigned int processor_id; @@ -517,20 +516,31 @@ static void __init parse_cmdline(char ** *cmdline_p = command_line; } -static void __init -setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz) +/* + * Generate /arch.cmd, which contains command-line equivalent options + * for kinit. We do this in two steps: save into a buffer, and then + * write out the file, since the first step will typically be done + * very early, and the second step needs to be done after rootfs is fully + * operational. + */ +static char __initdata arch_cmd_buffer[256]; +static int __initdata arch_cmd_len; + +static int __init write_arch_init_command(void) { -#ifdef CONFIG_BLK_DEV_RAM - extern int rd_size, rd_image_start, rd_prompt, rd_doload; + int fd; - rd_image_start = image_start; - rd_prompt = prompt; - rd_doload = doload; + fd = sys_open("/arch.cmd", O_WRONLY|O_CREAT|O_APPEND, 0666); + if (fd < 0) + return fd; - if (rd_sz) - rd_size = rd_sz; -#endif + sys_write(fd, arch_cmd_buffer, arch_cmd_len); + sys_close(fd); + + return 0; } + +late_initcall(write_arch_init_command); static void __init request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc) @@ -596,13 +606,27 @@ request_standard_resources(struct meminf * a param_struct). The list is terminated with a zero-length tag (this tag * is not parsed in any way). */ + + static int __init parse_tag_core(const struct tag *tag) { + char *buf = arch_cmd_buffer + arch_cmd_len; + char *end = arch_cmd_buffer + sizeof arch_cmd_buffer; + + if (end-buf <= 3) + return -ENOMEM; + + *buf++ = 'r'; + *buf = 'o'; if (tag->hdr.size > 2) { if ((tag->u.core.flags & 1) == 0) - root_mountflags &= ~MS_RDONLY; + *buf = 'w'; ROOT_DEV = old_decode_dev(tag->u.core.rootdev); } + buf++; + *buf++ = '\n'; + + arch_cmd_len = end-buf; return 0; } @@ -651,11 +675,35 @@ #endif static int __init parse_tag_ramdisk(const struct tag *tag) { - setup_ramdisk((tag->u.ramdisk.flags & 1) == 0, - (tag->u.ramdisk.flags & 2) == 0, - tag->u.ramdisk.start, tag->u.ramdisk.size); +#ifdef CONFIG_BLK_DEV_RAM + char *buf = arch_cmd_buffer + arch_cmd_len; + char *end = arch_cmd_buffer + sizeof arch_cmd_buffer; + int len; + + len = snprintf(buf, end-buf, + "ramdisk_start=%u\n" + "load_ramdisk=%d\n" + "prompt_ramdisk=%d\n", + tag->u.ramdisk.start, + tag->u.ramdisk.flags & 1 ? 0 : 1, + tag->u.ramdisk.flags & 2 ? 0 : 1); + if (len >= end-buf) + return -ENOMEM; + buf += len; + + if (tag->u.ramdisk.size) { + len = snprintf(buf, end-buf, + "ramdisk_size=%u\n", + tag->u.ramdisk.size); + if (len >= end-buf) + return -ENOMEM; + buf += len; + } + + arch_cmd_len = end-buf; +#endif return 0; -} +} __tagtable(ATAG_RAMDISK, parse_tag_ramdisk);