1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
28#include <asm/setup.h>
29#include <asm/system_info.h>
30#include <asm/page.h>
31#include <asm/mach/arch.h>
32
33#include "atags.h"
34
35static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
36
37#ifndef MEM_SIZE
38#define MEM_SIZE (16*1024*1024)
39#endif
40
41static struct {
42 struct tag_header hdr1;
43 struct tag_core core;
44 struct tag_header hdr2;
45 struct tag_mem32 mem;
46 struct tag_header hdr3;
47} default_tags __initdata = {
48 { tag_size(tag_core), ATAG_CORE },
49 { 1, PAGE_SIZE, 0xff },
50 { tag_size(tag_mem32), ATAG_MEM },
51 { MEM_SIZE },
52 { 0, ATAG_NONE }
53};
54
55static int __init parse_tag_core(const struct tag *tag)
56{
57 if (tag->hdr.size > 2) {
58 if ((tag->u.core.flags & 1) == 0)
59 root_mountflags &= ~MS_RDONLY;
60 ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
61 }
62 return 0;
63}
64
65__tagtable(ATAG_CORE, parse_tag_core);
66
67static int __init parse_tag_mem32(const struct tag *tag)
68{
69 return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
70}
71
72__tagtable(ATAG_MEM, parse_tag_mem32);
73
74#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
75static int __init parse_tag_videotext(const struct tag *tag)
76{
77 screen_info.orig_x = tag->u.videotext.x;
78 screen_info.orig_y = tag->u.videotext.y;
79 screen_info.orig_video_page = tag->u.videotext.video_page;
80 screen_info.orig_video_mode = tag->u.videotext.video_mode;
81 screen_info.orig_video_cols = tag->u.videotext.video_cols;
82 screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
83 screen_info.orig_video_lines = tag->u.videotext.video_lines;
84 screen_info.orig_video_isVGA = tag->u.videotext.video_isvga;
85 screen_info.orig_video_points = tag->u.videotext.video_points;
86 return 0;
87}
88
89__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
90#endif
91
92#ifdef CONFIG_BLK_DEV_RAM
93static int __init parse_tag_ramdisk(const struct tag *tag)
94{
95 rd_image_start = tag->u.ramdisk.start;
96 rd_doload = (tag->u.ramdisk.flags & 1) == 0;
97 rd_prompt = (tag->u.ramdisk.flags & 2) == 0;
98
99 if (tag->u.ramdisk.size)
100 rd_size = tag->u.ramdisk.size;
101
102 return 0;
103}
104
105__tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
106#endif
107
108static int __init parse_tag_serialnr(const struct tag *tag)
109{
110 system_serial_low = tag->u.serialnr.low;
111 system_serial_high = tag->u.serialnr.high;
112 return 0;
113}
114
115__tagtable(ATAG_SERIAL, parse_tag_serialnr);
116
117static int __init parse_tag_revision(const struct tag *tag)
118{
119 system_rev = tag->u.revision.rev;
120 return 0;
121}
122
123__tagtable(ATAG_REVISION, parse_tag_revision);
124
125static int __init parse_tag_cmdline(const struct tag *tag)
126{
127#if defined(CONFIG_CMDLINE_EXTEND)
128 strlcat(default_command_line, " ", COMMAND_LINE_SIZE);
129 strlcat(default_command_line, tag->u.cmdline.cmdline,
130 COMMAND_LINE_SIZE);
131#elif defined(CONFIG_CMDLINE_FORCE)
132 pr_warn("Ignoring tag cmdline (using the default kernel command line)\n");
133#else
134 strlcpy(default_command_line, tag->u.cmdline.cmdline,
135 COMMAND_LINE_SIZE);
136#endif
137 return 0;
138}
139
140__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
141
142
143
144
145
146
147static int __init parse_tag(const struct tag *tag)
148{
149 extern struct tagtable __tagtable_begin, __tagtable_end;
150 struct tagtable *t;
151
152 for (t = &__tagtable_begin; t < &__tagtable_end; t++)
153 if (tag->hdr.tag == t->tag) {
154 t->parse(tag);
155 break;
156 }
157
158 return t < &__tagtable_end;
159}
160
161
162
163
164
165static void __init parse_tags(const struct tag *t)
166{
167 for (; t->hdr.size; t = tag_next(t))
168 if (!parse_tag(t))
169 pr_warn("Ignoring unrecognised tag 0x%08x\n",
170 t->hdr.tag);
171}
172
173static void __init squash_mem_tags(struct tag *tag)
174{
175 for (; tag->hdr.size; tag = tag_next(tag))
176 if (tag->hdr.tag == ATAG_MEM)
177 tag->hdr.tag = ATAG_NONE;
178}
179
180const struct machine_desc * __init
181setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr)
182{
183 struct tag *tags = (struct tag *)&default_tags;
184 const struct machine_desc *mdesc = NULL, *p;
185 char *from = default_command_line;
186
187 default_tags.mem.start = PHYS_OFFSET;
188
189
190
191
192 for_each_machine_desc(p)
193 if (machine_nr == p->nr) {
194 pr_info("Machine: %s\n", p->name);
195 mdesc = p;
196 break;
197 }
198
199 if (!mdesc)
200 return NULL;
201
202 if (__atags_pointer)
203 tags = phys_to_virt(__atags_pointer);
204 else if (mdesc->atag_offset)
205 tags = (void *)(PAGE_OFFSET + mdesc->atag_offset);
206
207#if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
208
209
210
211
212 if (tags->hdr.tag != ATAG_CORE)
213 convert_to_tag_list(tags);
214#endif
215 if (tags->hdr.tag != ATAG_CORE) {
216 early_print("Warning: Neither atags nor dtb found\n");
217 tags = (struct tag *)&default_tags;
218 }
219
220 if (mdesc->fixup)
221 mdesc->fixup(tags, &from);
222
223 if (tags->hdr.tag == ATAG_CORE) {
224 if (memblock_phys_mem_size())
225 squash_mem_tags(tags);
226 save_atags(tags);
227 parse_tags(tags);
228 }
229
230
231 strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
232
233 return mdesc;
234}
235