Merge tag 'for-linus-20141102' of git://git.infradead.org/linux-mtd
[deliverable/linux.git] / arch / arm / kernel / atags_parse.c
CommitLineData
aa783b6f
NP
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/kernel.h>
22#include <linux/fs.h>
23#include <linux/root_dev.h>
24#include <linux/screen_info.h>
1c2f87c2 25#include <linux/memblock.h>
aa783b6f
NP
26
27#include <asm/setup.h>
28#include <asm/system_info.h>
29#include <asm/page.h>
30#include <asm/mach/arch.h>
31
32#include "atags.h"
33
34static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
35
36#ifndef MEM_SIZE
37#define MEM_SIZE (16*1024*1024)
38#endif
39
40static struct {
41 struct tag_header hdr1;
42 struct tag_core core;
43 struct tag_header hdr2;
44 struct tag_mem32 mem;
45 struct tag_header hdr3;
46} default_tags __initdata = {
47 { tag_size(tag_core), ATAG_CORE },
48 { 1, PAGE_SIZE, 0xff },
49 { tag_size(tag_mem32), ATAG_MEM },
50 { MEM_SIZE },
51 { 0, ATAG_NONE }
52};
53
54static int __init parse_tag_core(const struct tag *tag)
55{
56 if (tag->hdr.size > 2) {
57 if ((tag->u.core.flags & 1) == 0)
58 root_mountflags &= ~MS_RDONLY;
59 ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
60 }
61 return 0;
62}
63
64__tagtable(ATAG_CORE, parse_tag_core);
65
66static int __init parse_tag_mem32(const struct tag *tag)
67{
68 return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
69}
70
71__tagtable(ATAG_MEM, parse_tag_mem32);
72
73#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
74static int __init parse_tag_videotext(const struct tag *tag)
75{
76 screen_info.orig_x = tag->u.videotext.x;
77 screen_info.orig_y = tag->u.videotext.y;
78 screen_info.orig_video_page = tag->u.videotext.video_page;
79 screen_info.orig_video_mode = tag->u.videotext.video_mode;
80 screen_info.orig_video_cols = tag->u.videotext.video_cols;
81 screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
82 screen_info.orig_video_lines = tag->u.videotext.video_lines;
83 screen_info.orig_video_isVGA = tag->u.videotext.video_isvga;
84 screen_info.orig_video_points = tag->u.videotext.video_points;
85 return 0;
86}
87
88__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
89#endif
90
91#ifdef CONFIG_BLK_DEV_RAM
92static int __init parse_tag_ramdisk(const struct tag *tag)
93{
94 extern int rd_size, rd_image_start, rd_prompt, rd_doload;
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
109static 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
118static 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
126static 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)
8b521cb2 133 pr_warn("Ignoring tag cmdline (using the default kernel command line)\n");
aa783b6f
NP
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 */
148static 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 */
166static void __init parse_tags(const struct tag *t)
167{
168 for (; t->hdr.size; t = tag_next(t))
169 if (!parse_tag(t))
170 printk(KERN_WARNING
171 "Ignoring unrecognised tag 0x%08x\n",
172 t->hdr.tag);
173}
174
175static void __init squash_mem_tags(struct tag *tag)
176{
177 for (; tag->hdr.size; tag = tag_next(tag))
178 if (tag->hdr.tag == ATAG_MEM)
179 tag->hdr.tag = ATAG_NONE;
180}
181
ff69a4c8
RK
182const struct machine_desc * __init
183setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr)
aa783b6f
NP
184{
185 struct tag *tags = (struct tag *)&default_tags;
ff69a4c8 186 const struct machine_desc *mdesc = NULL, *p;
aa783b6f
NP
187 char *from = default_command_line;
188
189 default_tags.mem.start = PHYS_OFFSET;
190
191 /*
192 * locate machine in the list of supported machines.
193 */
194 for_each_machine_desc(p)
195 if (machine_nr == p->nr) {
196 printk("Machine: %s\n", p->name);
197 mdesc = p;
198 break;
199 }
200
201 if (!mdesc) {
202 early_print("\nError: unrecognized/unsupported machine ID"
203 " (r1 = 0x%08x).\n\n", machine_nr);
204 dump_machine_table(); /* does not return */
205 }
206
207 if (__atags_pointer)
208 tags = phys_to_virt(__atags_pointer);
209 else if (mdesc->atag_offset)
210 tags = (void *)(PAGE_OFFSET + mdesc->atag_offset);
211
212#if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
213 /*
214 * If we have the old style parameters, convert them to
215 * a tag list.
216 */
217 if (tags->hdr.tag != ATAG_CORE)
218 convert_to_tag_list(tags);
219#endif
220 if (tags->hdr.tag != ATAG_CORE) {
221 early_print("Warning: Neither atags nor dtb found\n");
222 tags = (struct tag *)&default_tags;
223 }
224
225 if (mdesc->fixup)
1c2f87c2 226 mdesc->fixup(tags, &from);
aa783b6f
NP
227
228 if (tags->hdr.tag == ATAG_CORE) {
1c2f87c2 229 if (memblock_phys_mem_size())
aa783b6f
NP
230 squash_mem_tags(tags);
231 save_atags(tags);
232 parse_tags(tags);
233 }
234
235 /* parse_early_param needs a boot_command_line */
236 strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
237
238 return mdesc;
239}
This page took 0.139828 seconds and 5 git commands to generate.