aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2006-06-30 16:03:47 -0700
committerH. Peter Anvin <hpa@zytor.com>2006-07-02 12:26:19 -0700
commit154c0ca675048a41a3f2ca5d3c0800b07bbc1d77 (patch)
tree5cfa889055f3ae37f46830edf61a0b2cac832d2e
parent12c13caa9889babd6e305caead3038dd4218b45d (diff)
downloadlinux-2.6-klibc-clean-154c0ca675048a41a3f2ca5d3c0800b07bbc1d77.tar.gz
[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 <tglx@linuxtronix.de>, significantly modified by me. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--arch/arm/kernel/setup.c80
1 files changed, 64 insertions, 16 deletions
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 7447a198732297..3797582e9a6c9d 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -56,7 +56,6 @@ __setup("fpe=", fpe_setup);
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, char *from)
*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 meminfo *mi, struct machine_desc *mdesc)
* 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 @@ __tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
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);