Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
atags_parse.c
Go to the documentation of this file.
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>
25 
26 #include <asm/setup.h>
27 #include <asm/system_info.h>
28 #include <asm/page.h>
29 #include <asm/mach/arch.h>
30 
31 #include "atags.h"
32 
33 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
34 
35 #ifndef MEM_SIZE
36 #define MEM_SIZE (16*1024*1024)
37 #endif
38 
39 static struct {
40  struct tag_header hdr1;
41  struct tag_core core;
42  struct tag_header hdr2;
43  struct tag_mem32 mem;
44  struct tag_header hdr3;
45 } default_tags __initdata = {
47  { 1, PAGE_SIZE, 0xff },
49  { MEM_SIZE },
50  { 0, ATAG_NONE }
51 };
52 
53 static int __init parse_tag_core(const struct tag *tag)
54 {
55  if (tag->hdr.size > 2) {
56  if ((tag->u.core.flags & 1) == 0)
58  ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
59  }
60  return 0;
61 }
62 
63 __tagtable(ATAG_CORE, parse_tag_core);
64 
65 static int __init parse_tag_mem32(const struct tag *tag)
66 {
67  return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
68 }
69 
70 __tagtable(ATAG_MEM, parse_tag_mem32);
71 
72 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
73 static int __init parse_tag_videotext(const struct tag *tag)
74 {
75  screen_info.orig_x = tag->u.videotext.x;
76  screen_info.orig_y = tag->u.videotext.y;
77  screen_info.orig_video_page = tag->u.videotext.video_page;
78  screen_info.orig_video_mode = tag->u.videotext.video_mode;
79  screen_info.orig_video_cols = tag->u.videotext.video_cols;
80  screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
81  screen_info.orig_video_lines = tag->u.videotext.video_lines;
82  screen_info.orig_video_isVGA = tag->u.videotext.video_isvga;
83  screen_info.orig_video_points = tag->u.videotext.video_points;
84  return 0;
85 }
86 
87 __tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
88 #endif
89 
90 #ifdef CONFIG_BLK_DEV_RAM
91 static int __init parse_tag_ramdisk(const struct tag *tag)
92 {
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 
108 static 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 
117 static 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 
125 static 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,
131 #elif defined(CONFIG_CMDLINE_FORCE)
132  pr_warning("Ignoring tag cmdline (using the default kernel command line)\n");
133 #else
134  strlcpy(default_command_line, tag->u.cmdline.cmdline,
136 #endif
137  return 0;
138 }
139 
140 __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
141 
142 /*
143  * Scan the tag table for this tag, and call its parse function.
144  * The tag table is built by the linker from all the __tagtable
145  * declarations.
146  */
147 static 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  * Parse all tags in the list, checking both the global and architecture
163  * specific tag tables.
164  */
165 static void __init parse_tags(const struct tag *t)
166 {
167  for (; t->hdr.size; t = tag_next(t))
168  if (!parse_tag(t))
170  "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 
182  unsigned int machine_nr)
183 {
184  struct tag *tags = (struct tag *)&default_tags;
185  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  */
194  if (machine_nr == p->nr) {
195  printk("Machine: %s\n", p->name);
196  mdesc = p;
197  break;
198  }
199 
200  if (!mdesc) {
201  early_print("\nError: unrecognized/unsupported machine ID"
202  " (r1 = 0x%08x).\n\n", machine_nr);
203  dump_machine_table(); /* does not return */
204  }
205 
206  if (__atags_pointer)
207  tags = phys_to_virt(__atags_pointer);
208  else if (mdesc->atag_offset)
209  tags = (void *)(PAGE_OFFSET + mdesc->atag_offset);
210 
211 #if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
212  /*
213  * If we have the old style parameters, convert them to
214  * a tag list.
215  */
216  if (tags->hdr.tag != ATAG_CORE)
217  convert_to_tag_list(tags);
218 #endif
219  if (tags->hdr.tag != ATAG_CORE) {
220  early_print("Warning: Neither atags nor dtb found\n");
221  tags = (struct tag *)&default_tags;
222  }
223 
224  if (mdesc->fixup)
225  mdesc->fixup(tags, &from, &meminfo);
226 
227  if (tags->hdr.tag == ATAG_CORE) {
228  if (meminfo.nr_banks != 0)
229  squash_mem_tags(tags);
230  save_atags(tags);
231  parse_tags(tags);
232  }
233 
234  /* parse_early_param needs a boot_command_line */
236 
237  return mdesc;
238 }