root/arch/arm/kernel/atags_parse.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. parse_tag_core
  2. parse_tag_mem32
  3. parse_tag_videotext
  4. parse_tag_ramdisk
  5. parse_tag_serialnr
  6. parse_tag_revision
  7. parse_tag_cmdline
  8. parse_tag
  9. parse_tags
  10. squash_mem_tags
  11. setup_machine_tags

   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 
  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 
  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 {
  93         rd_image_start = tag->u.ramdisk.start;
  94         rd_doload = (tag->u.ramdisk.flags & 1) == 0;
  95         rd_prompt = (tag->u.ramdisk.flags & 2) == 0;
  96 
  97         if (tag->u.ramdisk.size)
  98                 rd_size = tag->u.ramdisk.size;
  99 
 100         return 0;
 101 }
 102 
 103 __tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
 104 #endif
 105 
 106 static int __init parse_tag_serialnr(const struct tag *tag)
 107 {
 108         system_serial_low = tag->u.serialnr.low;
 109         system_serial_high = tag->u.serialnr.high;
 110         return 0;
 111 }
 112 
 113 __tagtable(ATAG_SERIAL, parse_tag_serialnr);
 114 
 115 static int __init parse_tag_revision(const struct tag *tag)
 116 {
 117         system_rev = tag->u.revision.rev;
 118         return 0;
 119 }
 120 
 121 __tagtable(ATAG_REVISION, parse_tag_revision);
 122 
 123 static int __init parse_tag_cmdline(const struct tag *tag)
 124 {
 125 #if defined(CONFIG_CMDLINE_EXTEND)
 126         strlcat(default_command_line, " ", COMMAND_LINE_SIZE);
 127         strlcat(default_command_line, tag->u.cmdline.cmdline,
 128                 COMMAND_LINE_SIZE);
 129 #elif defined(CONFIG_CMDLINE_FORCE)
 130         pr_warn("Ignoring tag cmdline (using the default kernel command line)\n");
 131 #else
 132         strlcpy(default_command_line, tag->u.cmdline.cmdline,
 133                 COMMAND_LINE_SIZE);
 134 #endif
 135         return 0;
 136 }
 137 
 138 __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
 139 
 140 /*
 141  * Scan the tag table for this tag, and call its parse function.
 142  * The tag table is built by the linker from all the __tagtable
 143  * declarations.
 144  */
 145 static int __init parse_tag(const struct tag *tag)
 146 {
 147         extern struct tagtable __tagtable_begin, __tagtable_end;
 148         struct tagtable *t;
 149 
 150         for (t = &__tagtable_begin; t < &__tagtable_end; t++)
 151                 if (tag->hdr.tag == t->tag) {
 152                         t->parse(tag);
 153                         break;
 154                 }
 155 
 156         return t < &__tagtable_end;
 157 }
 158 
 159 /*
 160  * Parse all tags in the list, checking both the global and architecture
 161  * specific tag tables.
 162  */
 163 static void __init parse_tags(const struct tag *t)
 164 {
 165         for (; t->hdr.size; t = tag_next(t))
 166                 if (!parse_tag(t))
 167                         pr_warn("Ignoring unrecognised tag 0x%08x\n",
 168                                 t->hdr.tag);
 169 }
 170 
 171 static void __init squash_mem_tags(struct tag *tag)
 172 {
 173         for (; tag->hdr.size; tag = tag_next(tag))
 174                 if (tag->hdr.tag == ATAG_MEM)
 175                         tag->hdr.tag = ATAG_NONE;
 176 }
 177 
 178 const struct machine_desc * __init
 179 setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr)
 180 {
 181         struct tag *tags = (struct tag *)&default_tags;
 182         const struct machine_desc *mdesc = NULL, *p;
 183         char *from = default_command_line;
 184 
 185         default_tags.mem.start = PHYS_OFFSET;
 186 
 187         /*
 188          * locate machine in the list of supported machines.
 189          */
 190         for_each_machine_desc(p)
 191                 if (machine_nr == p->nr) {
 192                         pr_info("Machine: %s\n", p->name);
 193                         mdesc = p;
 194                         break;
 195                 }
 196 
 197         if (!mdesc)
 198                 return NULL;
 199 
 200         if (__atags_pointer)
 201                 tags = phys_to_virt(__atags_pointer);
 202         else if (mdesc->atag_offset)
 203                 tags = (void *)(PAGE_OFFSET + mdesc->atag_offset);
 204 
 205 #if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
 206         /*
 207          * If we have the old style parameters, convert them to
 208          * a tag list.
 209          */
 210         if (tags->hdr.tag != ATAG_CORE)
 211                 convert_to_tag_list(tags);
 212 #endif
 213         if (tags->hdr.tag != ATAG_CORE) {
 214                 early_print("Warning: Neither atags nor dtb found\n");
 215                 tags = (struct tag *)&default_tags;
 216         }
 217 
 218         if (mdesc->fixup)
 219                 mdesc->fixup(tags, &from);
 220 
 221         if (tags->hdr.tag == ATAG_CORE) {
 222                 if (memblock_phys_mem_size())
 223                         squash_mem_tags(tags);
 224                 save_atags(tags);
 225                 parse_tags(tags);
 226         }
 227 
 228         /* parse_early_param needs a boot_command_line */
 229         strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
 230 
 231         return mdesc;
 232 }

/* [<][>][^][v][top][bottom][index][help] */