1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Tag parsing. 4 * 5 * Copyright (C) 1995-2001 Russell King 6 */ 7 8 /* 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). 15 */ 16 17 #include <linux/init.h> 18 #include <linux/initrd.h> 19 #include <linux/kernel.h> 20 #include <linux/fs.h> 21 #include <linux/root_dev.h> 22 #include <linux/screen_info.h> 23 #include <linux/memblock.h> 24 #include <uapi/linux/mount.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 = { 46 { tag_size(tag_core), ATAG_CORE }, 47 { 1, PAGE_SIZE, 0xff }, 48 { tag_size(tag_mem32), ATAG_MEM }, 49 { MEM_SIZE }, 50 { 0, ATAG_NONE } 51 }; 52 parse_tag_core(const struct tag * tag)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) 57 root_mountflags &= ~MS_RDONLY; 58 ROOT_DEV = old_decode_dev(tag->u.core.rootdev); 59 } 60 return 0; 61 } 62 63 __tagtable(ATAG_CORE, parse_tag_core); 64 parse_tag_mem32(const struct tag * tag)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_ARCH_FOOTBRIDGE) && defined(CONFIG_VGA_CONSOLE) parse_tag_videotext(const struct tag * tag)73 static int __init parse_tag_videotext(const struct tag *tag) 74 { 75 vgacon_screen_info.orig_x = tag->u.videotext.x; 76 vgacon_screen_info.orig_y = tag->u.videotext.y; 77 vgacon_screen_info.orig_video_page = tag->u.videotext.video_page; 78 vgacon_screen_info.orig_video_mode = tag->u.videotext.video_mode; 79 vgacon_screen_info.orig_video_cols = tag->u.videotext.video_cols; 80 vgacon_screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx; 81 vgacon_screen_info.orig_video_lines = tag->u.videotext.video_lines; 82 vgacon_screen_info.orig_video_isVGA = tag->u.videotext.video_isvga; 83 vgacon_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 parse_tag_ramdisk(const struct tag * tag)91 static int __init parse_tag_ramdisk(const struct tag *tag) 92 { 93 rd_image_start = tag->u.ramdisk.start; 94 95 if (tag->u.ramdisk.size) 96 rd_size = tag->u.ramdisk.size; 97 98 return 0; 99 } 100 101 __tagtable(ATAG_RAMDISK, parse_tag_ramdisk); 102 #endif 103 parse_tag_serialnr(const struct tag * tag)104 static int __init parse_tag_serialnr(const struct tag *tag) 105 { 106 system_serial_low = tag->u.serialnr.low; 107 system_serial_high = tag->u.serialnr.high; 108 return 0; 109 } 110 111 __tagtable(ATAG_SERIAL, parse_tag_serialnr); 112 parse_tag_revision(const struct tag * tag)113 static int __init parse_tag_revision(const struct tag *tag) 114 { 115 system_rev = tag->u.revision.rev; 116 return 0; 117 } 118 119 __tagtable(ATAG_REVISION, parse_tag_revision); 120 parse_tag_cmdline(const struct tag * tag)121 static int __init parse_tag_cmdline(const struct tag *tag) 122 { 123 #if defined(CONFIG_CMDLINE_EXTEND) 124 strlcat(default_command_line, " ", COMMAND_LINE_SIZE); 125 strlcat(default_command_line, tag->u.cmdline.cmdline, 126 COMMAND_LINE_SIZE); 127 #elif defined(CONFIG_CMDLINE_FORCE) 128 pr_warn("Ignoring tag cmdline (using the default kernel command line)\n"); 129 #else 130 strscpy(default_command_line, tag->u.cmdline.cmdline, 131 COMMAND_LINE_SIZE); 132 #endif 133 return 0; 134 } 135 136 __tagtable(ATAG_CMDLINE, parse_tag_cmdline); 137 138 /* 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 141 * declarations. 142 */ parse_tag(const struct tag * tag)143 static int __init parse_tag(const struct tag *tag) 144 { 145 extern struct tagtable __tagtable_begin, __tagtable_end; 146 struct tagtable *t; 147 148 for (t = &__tagtable_begin; t < &__tagtable_end; t++) 149 if (tag->hdr.tag == t->tag) { 150 t->parse(tag); 151 break; 152 } 153 154 return t < &__tagtable_end; 155 } 156 157 /* 158 * Parse all tags in the list, checking both the global and architecture 159 * specific tag tables. 160 */ parse_tags(const struct tag * t)161 static void __init parse_tags(const struct tag *t) 162 { 163 for (; t->hdr.size; t = tag_next(t)) 164 if (!parse_tag(t)) 165 pr_warn("Ignoring unrecognised tag 0x%08x\n", 166 t->hdr.tag); 167 } 168 squash_mem_tags(struct tag * tag)169 static void __init squash_mem_tags(struct tag *tag) 170 { 171 for (; tag->hdr.size; tag = tag_next(tag)) 172 if (tag->hdr.tag == ATAG_MEM) 173 tag->hdr.tag = ATAG_NONE; 174 } 175 176 const struct machine_desc * __init setup_machine_tags(void * atags_vaddr,unsigned int machine_nr)177 setup_machine_tags(void *atags_vaddr, unsigned int machine_nr) 178 { 179 struct tag *tags = (struct tag *)&default_tags; 180 const struct machine_desc *mdesc = NULL, *p; 181 char *from = default_command_line; 182 183 default_tags.mem.start = PHYS_OFFSET; 184 185 /* 186 * locate machine in the list of supported machines. 187 */ 188 for_each_machine_desc(p) 189 if (machine_nr == p->nr) { 190 pr_info("Machine: %s\n", p->name); 191 mdesc = p; 192 break; 193 } 194 195 if (!mdesc) 196 return NULL; 197 198 if (atags_vaddr) 199 tags = atags_vaddr; 200 else if (mdesc->atag_offset) 201 tags = (void *)(PAGE_OFFSET + mdesc->atag_offset); 202 203 #if defined(CONFIG_DEPRECATED_PARAM_STRUCT) 204 /* 205 * If we have the old style parameters, convert them to 206 * a tag list. 207 */ 208 if (tags->hdr.tag != ATAG_CORE) 209 convert_to_tag_list(tags); 210 #endif 211 if (tags->hdr.tag != ATAG_CORE) { 212 early_print("Warning: Neither atags nor dtb found\n"); 213 tags = (struct tag *)&default_tags; 214 } 215 216 if (mdesc->fixup) 217 mdesc->fixup(tags, &from); 218 219 if (tags->hdr.tag == ATAG_CORE) { 220 if (memblock_phys_mem_size()) 221 squash_mem_tags(tags); 222 save_atags(tags); 223 parse_tags(tags); 224 } 225 226 /* parse_early_param needs a boot_command_line */ 227 strscpy(boot_command_line, from, COMMAND_LINE_SIZE); 228 229 return mdesc; 230 } 231