vfs: Suppress MS_* flag defs within the kernel unless explicitly enabled
[linux-2.6-block.git] / arch / arm / kernel / atags_parse.c
1 /*
2  * Tag parsing.
3  *
4  * Copyright (C) 1995-2001 Russell King
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10
11 /*
12  * This is the traditional way of passing data to the kernel at boot time.  Rather
13  * than passing a fixed inflexible structure to the kernel, we pass a list
14  * of variable-sized tags to the kernel.  The first tag must be a ATAG_CORE
15  * tag for the list to be recognised (to distinguish the tagged list from
16  * a param_struct).  The list is terminated with a zero-length tag (this tag
17  * is not parsed in any way).
18  */
19
20 #include <linux/init.h>
21 #include <linux/initrd.h>
22 #include <linux/kernel.h>
23 #include <linux/fs.h>
24 #include <linux/root_dev.h>
25 #include <linux/screen_info.h>
26 #include <linux/memblock.h>
27 #include <uapi/linux/mount.h>
28
29 #include <asm/setup.h>
30 #include <asm/system_info.h>
31 #include <asm/page.h>
32 #include <asm/mach/arch.h>
33
34 #include "atags.h"
35
36 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
37
38 #ifndef MEM_SIZE
39 #define MEM_SIZE        (16*1024*1024)
40 #endif
41
42 static struct {
43         struct tag_header hdr1;
44         struct tag_core   core;
45         struct tag_header hdr2;
46         struct tag_mem32  mem;
47         struct tag_header hdr3;
48 } default_tags __initdata = {
49         { tag_size(tag_core), ATAG_CORE },
50         { 1, PAGE_SIZE, 0xff },
51         { tag_size(tag_mem32), ATAG_MEM },
52         { MEM_SIZE },
53         { 0, ATAG_NONE }
54 };
55
56 static int __init parse_tag_core(const struct tag *tag)
57 {
58         if (tag->hdr.size > 2) {
59                 if ((tag->u.core.flags & 1) == 0)
60                         root_mountflags &= ~MS_RDONLY;
61                 ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
62         }
63         return 0;
64 }
65
66 __tagtable(ATAG_CORE, parse_tag_core);
67
68 static int __init parse_tag_mem32(const struct tag *tag)
69 {
70         return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
71 }
72
73 __tagtable(ATAG_MEM, parse_tag_mem32);
74
75 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
76 static int __init parse_tag_videotext(const struct tag *tag)
77 {
78         screen_info.orig_x            = tag->u.videotext.x;
79         screen_info.orig_y            = tag->u.videotext.y;
80         screen_info.orig_video_page   = tag->u.videotext.video_page;
81         screen_info.orig_video_mode   = tag->u.videotext.video_mode;
82         screen_info.orig_video_cols   = tag->u.videotext.video_cols;
83         screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
84         screen_info.orig_video_lines  = tag->u.videotext.video_lines;
85         screen_info.orig_video_isVGA  = tag->u.videotext.video_isvga;
86         screen_info.orig_video_points = tag->u.videotext.video_points;
87         return 0;
88 }
89
90 __tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
91 #endif
92
93 #ifdef CONFIG_BLK_DEV_RAM
94 static int __init parse_tag_ramdisk(const struct tag *tag)
95 {
96         rd_image_start = tag->u.ramdisk.start;
97         rd_doload = (tag->u.ramdisk.flags & 1) == 0;
98         rd_prompt = (tag->u.ramdisk.flags & 2) == 0;
99
100         if (tag->u.ramdisk.size)
101                 rd_size = tag->u.ramdisk.size;
102
103         return 0;
104 }
105
106 __tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
107 #endif
108
109 static int __init parse_tag_serialnr(const struct tag *tag)
110 {
111         system_serial_low = tag->u.serialnr.low;
112         system_serial_high = tag->u.serialnr.high;
113         return 0;
114 }
115
116 __tagtable(ATAG_SERIAL, parse_tag_serialnr);
117
118 static int __init parse_tag_revision(const struct tag *tag)
119 {
120         system_rev = tag->u.revision.rev;
121         return 0;
122 }
123
124 __tagtable(ATAG_REVISION, parse_tag_revision);
125
126 static int __init parse_tag_cmdline(const struct tag *tag)
127 {
128 #if defined(CONFIG_CMDLINE_EXTEND)
129         strlcat(default_command_line, " ", COMMAND_LINE_SIZE);
130         strlcat(default_command_line, tag->u.cmdline.cmdline,
131                 COMMAND_LINE_SIZE);
132 #elif defined(CONFIG_CMDLINE_FORCE)
133         pr_warn("Ignoring tag cmdline (using the default kernel command line)\n");
134 #else
135         strlcpy(default_command_line, tag->u.cmdline.cmdline,
136                 COMMAND_LINE_SIZE);
137 #endif
138         return 0;
139 }
140
141 __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
142
143 /*
144  * Scan the tag table for this tag, and call its parse function.
145  * The tag table is built by the linker from all the __tagtable
146  * declarations.
147  */
148 static int __init parse_tag(const struct tag *tag)
149 {
150         extern struct tagtable __tagtable_begin, __tagtable_end;
151         struct tagtable *t;
152
153         for (t = &__tagtable_begin; t < &__tagtable_end; t++)
154                 if (tag->hdr.tag == t->tag) {
155                         t->parse(tag);
156                         break;
157                 }
158
159         return t < &__tagtable_end;
160 }
161
162 /*
163  * Parse all tags in the list, checking both the global and architecture
164  * specific tag tables.
165  */
166 static void __init parse_tags(const struct tag *t)
167 {
168         for (; t->hdr.size; t = tag_next(t))
169                 if (!parse_tag(t))
170                         pr_warn("Ignoring unrecognised tag 0x%08x\n",
171                                 t->hdr.tag);
172 }
173
174 static void __init squash_mem_tags(struct tag *tag)
175 {
176         for (; tag->hdr.size; tag = tag_next(tag))
177                 if (tag->hdr.tag == ATAG_MEM)
178                         tag->hdr.tag = ATAG_NONE;
179 }
180
181 const struct machine_desc * __init
182 setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr)
183 {
184         struct tag *tags = (struct tag *)&default_tags;
185         const struct machine_desc *mdesc = NULL, *p;
186         char *from = default_command_line;
187
188         default_tags.mem.start = PHYS_OFFSET;
189
190         /*
191          * locate machine in the list of supported machines.
192          */
193         for_each_machine_desc(p)
194                 if (machine_nr == p->nr) {
195                         pr_info("Machine: %s\n", p->name);
196                         mdesc = p;
197                         break;
198                 }
199
200         if (!mdesc)
201                 return NULL;
202
203         if (__atags_pointer)
204                 tags = phys_to_virt(__atags_pointer);
205         else if (mdesc->atag_offset)
206                 tags = (void *)(PAGE_OFFSET + mdesc->atag_offset);
207
208 #if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
209         /*
210          * If we have the old style parameters, convert them to
211          * a tag list.
212          */
213         if (tags->hdr.tag != ATAG_CORE)
214                 convert_to_tag_list(tags);
215 #endif
216         if (tags->hdr.tag != ATAG_CORE) {
217                 early_print("Warning: Neither atags nor dtb found\n");
218                 tags = (struct tag *)&default_tags;
219         }
220
221         if (mdesc->fixup)
222                 mdesc->fixup(tags, &from);
223
224         if (tags->hdr.tag == ATAG_CORE) {
225                 if (memblock_phys_mem_size())
226                         squash_mem_tags(tags);
227                 save_atags(tags);
228                 parse_tags(tags);
229         }
230
231         /* parse_early_param needs a boot_command_line */
232         strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
233
234         return mdesc;
235 }