1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (C) 1995-2001 Russell King
9 * This is the traditional way of passing data to the kernel at boot time. Rather
10 * than passing a fixed inflexible structure to the kernel, we pass a list
11 * of variable-sized tags to the kernel. The first tag must be a ATAG_CORE
12 * tag for the list to be recognised (to distinguish the tagged list from
13 * a param_struct). The list is terminated with a zero-length tag (this tag
14 * is not parsed in any way).
17 #include <linux/init.h>
18 #include <linux/initrd.h>
19 #include <linux/kernel.h>
21 #include <linux/root_dev.h>
22 #include <linux/screen_info.h>
23 #include <linux/memblock.h>
24 #include <uapi/linux/mount.h>
26 #include <asm/setup.h>
27 #include <asm/system_info.h>
29 #include <asm/mach/arch.h>
33 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
36 #define MEM_SIZE (16*1024*1024)
40 struct tag_header hdr1;
42 struct tag_header hdr2;
44 struct tag_header hdr3;
45 } default_tags __initdata = {
46 { tag_size(tag_core), ATAG_CORE },
47 { 1, PAGE_SIZE, 0xff },
48 { tag_size(tag_mem32), ATAG_MEM },
53 static int __init parse_tag_core(const struct tag *tag)
55 if (tag->hdr.size > 2) {
56 if ((tag->u.core.flags & 1) == 0)
57 root_mountflags &= ~MS_RDONLY;
58 ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
63 __tagtable(ATAG_CORE, parse_tag_core);
65 static int __init parse_tag_mem32(const struct tag *tag)
67 return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
70 __tagtable(ATAG_MEM, parse_tag_mem32);
72 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
73 static int __init parse_tag_videotext(const struct tag *tag)
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;
87 __tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
90 #ifdef CONFIG_BLK_DEV_RAM
91 static int __init parse_tag_ramdisk(const struct tag *tag)
93 rd_image_start = tag->u.ramdisk.start;
95 if (tag->u.ramdisk.size)
96 rd_size = tag->u.ramdisk.size;
101 __tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
104 static int __init parse_tag_serialnr(const struct tag *tag)
106 system_serial_low = tag->u.serialnr.low;
107 system_serial_high = tag->u.serialnr.high;
111 __tagtable(ATAG_SERIAL, parse_tag_serialnr);
113 static int __init parse_tag_revision(const struct tag *tag)
115 system_rev = tag->u.revision.rev;
119 __tagtable(ATAG_REVISION, parse_tag_revision);
121 static int __init parse_tag_cmdline(const struct tag *tag)
123 #if defined(CONFIG_CMDLINE_EXTEND)
124 strlcat(default_command_line, " ", COMMAND_LINE_SIZE);
125 strlcat(default_command_line, tag->u.cmdline.cmdline,
127 #elif defined(CONFIG_CMDLINE_FORCE)
128 pr_warn("Ignoring tag cmdline (using the default kernel command line)\n");
130 strlcpy(default_command_line, tag->u.cmdline.cmdline,
136 __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
139 * Scan the tag table for this tag, and call its parse function.
140 * The tag table is built by the linker from all the __tagtable
143 static int __init parse_tag(const struct tag *tag)
145 extern struct tagtable __tagtable_begin, __tagtable_end;
148 for (t = &__tagtable_begin; t < &__tagtable_end; t++)
149 if (tag->hdr.tag == t->tag) {
154 return t < &__tagtable_end;
158 * Parse all tags in the list, checking both the global and architecture
159 * specific tag tables.
161 static void __init parse_tags(const struct tag *t)
163 for (; t->hdr.size; t = tag_next(t))
165 pr_warn("Ignoring unrecognised tag 0x%08x\n",
169 static void __init squash_mem_tags(struct tag *tag)
171 for (; tag->hdr.size; tag = tag_next(tag))
172 if (tag->hdr.tag == ATAG_MEM)
173 tag->hdr.tag = ATAG_NONE;
176 const struct machine_desc * __init
177 setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr)
179 struct tag *tags = (struct tag *)&default_tags;
180 const struct machine_desc *mdesc = NULL, *p;
181 char *from = default_command_line;
183 default_tags.mem.start = PHYS_OFFSET;
186 * locate machine in the list of supported machines.
188 for_each_machine_desc(p)
189 if (machine_nr == p->nr) {
190 pr_info("Machine: %s\n", p->name);
199 tags = phys_to_virt(__atags_pointer);
200 else if (mdesc->atag_offset)
201 tags = (void *)(PAGE_OFFSET + mdesc->atag_offset);
203 #if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
205 * If we have the old style parameters, convert them to
208 if (tags->hdr.tag != ATAG_CORE)
209 convert_to_tag_list(tags);
211 if (tags->hdr.tag != ATAG_CORE) {
212 early_print("Warning: Neither atags nor dtb found\n");
213 tags = (struct tag *)&default_tags;
217 mdesc->fixup(tags, &from);
219 if (tags->hdr.tag == ATAG_CORE) {
220 if (memblock_phys_mem_size())
221 squash_mem_tags(tags);
226 /* parse_early_param needs a boot_command_line */
227 strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);