__atags_pointer

               arch/arm/kernel/head-common.S
                /* Determine validity of the r2 atags pointer.  The heuristic requires
                 * that the pointer be aligned, in the first 16k of physical RAM and
                 * that the ATAG_CORE marker is first and present.  If CONFIG_OF_FLATTREE
                 * is selected, then it will also accept a dtb pointer.  Future revisions
                 * of this function may be more lenient with the physical address and
                 * may also be able to move the ATAGS block if necessary.
                 *
                 * Returns:
                 *  r2 either valid atags pointer, valid dtb pointer, or zero
                 *  r5, r6 corrupted
                 */
                __vet_atags:
                        tst     r2, #0x3                        @ aligned?
                        bne     1f
                
                        ldr     r5, [r2, #0]
                #ifdef CONFIG_OF_FLATTREE
                        ldr     r6, =OF_DT_MAGIC                @ is it a DTB?
                        cmp     r5, r6
                        beq     2f
                #endif
                        cmp     r5, #ATAG_CORE_SIZE             @ is first tag ATAG_CORE?
                        cmpne   r5, #ATAG_CORE_SIZE_EMPTY
                        bne     1f
                        ldr     r5, [r2, #4]
                        ldr     r6, =ATAG_CORE
                        cmp     r5, r6
                        bne     1f
                
                2:      ret     lr                              @ atag/dtb pointer is ok
                
                1:      mov     r2, #0
                        ret     lr
                ENDPROC(__vet_atags)
                /*
                 * The following fragment of code is executed with the MMU on in MMU mode,
                 * and uses absolute addresses; this is not position independent.
                 *
                 *  r0  = cp#15 control register
                 *  r1  = machine ID
                 *  r2  = atags/dtb pointer
                 *  r9  = processor ID
                 */
                        __INIT
                __mmap_switched:
                        adr     r3, __mmap_switched_data
                
                        ldmia   r3!, {r4, r5, r6, r7}
                        cmp     r4, r5                          @ Copy data segment if needed
                1:      cmpne   r5, r6
                        ldrne   fp, [r4], #4
                        strne   fp, [r5], #4
                        bne     1b
                
                        mov     fp, #0                          @ Clear BSS (and zero fp)
                1:      cmp     r6, r7
                        strcc   fp, [r6],#4
                        bcc     1b
                
                 ARM(   ldmia   r3, {r4, r5, r6, r7, sp})
                 THUMB( ldmia   r3, {r4, r5, r6, r7}    )
                 THUMB( ldr     sp, [r3, #16]           )
                        str     r9, [r4]                        @ Save processor ID
                        str     r1, [r5]                        @ Save machine type
                        str     r2, [r6]                        @ Save atags pointer
                        cmp     r7, #0
                        strne   r0, [r7]                        @ Save control register values
                        b       start_kernel
                ENDPROC(__mmap_switched)
                
                        .align  2
                        .type   __mmap_switched_data, %object
                __mmap_switched_data:
                        .long   __data_loc                      @ r4
                        .long   _sdata                          @ r5
                        .long   __bss_start                     @ r6
                        .long   _end                            @ r7
                        .long   processor_id                    @ r4
                        .long   __machine_arch_type             @ r5
                        .long   __atags_pointer                 @ r6
                #ifdef CONFIG_CPU_CP15
                        .long   cr_alignment                    @ r7
                #else
                        .long   0                               @ r7
                #endif
                        .long   init_thread_union + THREAD_START_SP @ sp
                        .size   __mmap_switched_data, . - __mmap_switched_data
            
            
            arch/arm/kernel/setup.c
            unsigned int __atags_pointer __initdata;
            
            void __init setup_arch(char **cmdline_p)
            {
                    const struct machine_desc *mdesc;
            
                    setup_processor();
                    mdesc = setup_machine_fdt(__atags_pointer);
                    if (!mdesc)
                            mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type);
                    machine_desc = mdesc;
                    machine_name = mdesc->name;
                    dump_stack_set_arch_desc("%s", mdesc->name);
            
                    if (mdesc->reboot_mode != REBOOT_HARD)
                            reboot_mode = mdesc->reboot_mode;
            
                    init_mm.start_code = (unsigned long) _text;
                    init_mm.end_code   = (unsigned long) _etext;
                    init_mm.end_data   = (unsigned long) _edata;
                    init_mm.brk        = (unsigned long) _end;
            
                    /* populate cmd_line too for later use, preserving boot_command_line */
                    strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
                    *cmdline_p = cmd_line;
            
                    early_fixmap_init();
                    early_ioremap_init();
            
                    parse_early_param();
            ...
            }
            
            /**
             * setup_machine_fdt - Machine setup when an dtb was passed to the kernel
             * @dt:         virtual address pointer to dt blob
             *      
             * If a dtb was passed to the kernel, then use it to choose the correct
             * machine_desc and to setup the system.
             */     
            const struct machine_desc * __init setup_machine_fdt(void *dt)
            {
                    const struct machine_desc *mdesc;
                    unsigned long dt_root;
            
                    if (!early_init_dt_scan(dt))
                            return NULL;
            
                    mdesc = of_flat_dt_match_machine(NULL, arch_get_next_mach);
                    if (!mdesc)
                            machine_halt();
            
                    dt_root = of_get_flat_dt_root();
                    arc_set_early_base_baud(dt_root);
            
                    return mdesc;
            }
            bool __init early_init_dt_scan(void *params)
            {
                    bool status;
            
                    status = early_init_dt_verify(params);
                    if (!status)
                            return false;
                    
                    early_init_dt_scan_nodes();
                    return true;
            }
            bool __init early_init_dt_verify(void *params)
            {
                    if (!params)
                            return false;
            
                    /* check device tree validity */
                    if (fdt_check_header(params))
                            return false;
            
                    /* Setup flat device-tree pointer */
                    initial_boot_params = params;
                    of_fdt_crc32 = crc32_be(~0, initial_boot_params,
                                            fdt_totalsize(initial_boot_params));
                    return true;
            }
            
            int fdt_check_header(const void *fdt)
            {
                    if (fdt_magic(fdt) == FDT_MAGIC) {
                            /* Complete tree */
                            if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
                                    return -FDT_ERR_BADVERSION;
                            if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
                                    return -FDT_ERR_BADVERSION;
                    } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
                            /* Unfinished sequential-write blob */
                            if (fdt_size_dt_struct(fdt) == 0)
                                    return -FDT_ERR_BADSTATE;
                    } else {
                            return -FDT_ERR_BADMAGIC;
                    }
            
                    return 0;
            }
            
            arch/arm/kernel/atags.h
            
            #ifdef CONFIG_ATAGS
            const struct machine_desc *setup_machine_tags(phys_addr_t __atags_pointer,
                    unsigned int machine_nr);
            #else   
            static inline const struct machine_desc *
            setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr)
            {               
                    early_print("no ATAGS support: can't continue\n");
                    while (true);
                    unreachable();
            }       
            #endif
            
            arch/arm/kernel/atags_parse.c
    static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
    
    static int __init parse_tag_cmdline(const struct tag *tag)
    {
    #if defined(CONFIG_CMDLINE_EXTEND)
            strlcat(default_command_line, " ", COMMAND_LINE_SIZE);
            strlcat(default_command_line, tag->u.cmdline.cmdline,
                    COMMAND_LINE_SIZE);
    #elif defined(CONFIG_CMDLINE_FORCE)
            pr_warn("Ignoring tag cmdline (using the default kernel command line)\n");
    #else
            strlcpy(default_command_line, tag->u.cmdline.cmdline,
                    COMMAND_LINE_SIZE);
    #endif
            return 0;
    }
    
    __tagtable(ATAG_CMDLINE, parse_tag_cmdline);
    
    
        static struct {
                struct tag_header hdr1;
                struct tag_core   core;
                struct tag_header hdr2;
                struct tag_mem32  mem;
                struct tag_header hdr3;
        } default_tags __initdata = {
                { tag_size(tag_core), ATAG_CORE },
                { 1, PAGE_SIZE, 0xff },
                { tag_size(tag_mem32), ATAG_MEM },
                { MEM_SIZE },
                { 0, ATAG_NONE }
        };    
        
            const struct machine_desc * __init
            setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr)
            {
                    struct tag *tags = (struct tag *)&default_tags;
                    const struct machine_desc *mdesc = NULL, *p;
                    char *from = default_command_line;
            
                    default_tags.mem.start = PHYS_OFFSET;
            
                    /*
                     * locate machine in the list of supported machines.
                     */
                    for_each_machine_desc(p)
                            if (machine_nr == p->nr) {
                                    pr_info("Machine: %s\n", p->name);
                                    mdesc = p;
                                    break;
                            }
            
                    if (!mdesc) {
                            early_print("\nError: unrecognized/unsupported machine ID"
                                        " (r1 = 0x%08x).\n\n", machine_nr);
                            dump_machine_table(); /* does not return */
                    }
            
                    if (__atags_pointer)
                            tags = phys_to_virt(__atags_pointer);
                    else if (mdesc->atag_offset)
                            tags = (void *)(PAGE_OFFSET + mdesc->atag_offset);
            
            #if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
                    /*
                     * If we have the old style parameters, convert them to
                     * a tag list.
                     */
                    if (tags->hdr.tag != ATAG_CORE)
                            convert_to_tag_list(tags);
            #endif
                    if (tags->hdr.tag != ATAG_CORE) {
                            early_print("Warning: Neither atags nor dtb found\n");
                            tags = (struct tag *)&default_tags;
                    }
            
                    if (mdesc->fixup)
                            mdesc->fixup(tags, &from);
            
                    if (tags->hdr.tag == ATAG_CORE) {
                            if (memblock_phys_mem_size())
                                    squash_mem_tags(tags);
                            save_atags(tags);
                            parse_tags(tags);
                    }
            
                    /* parse_early_param needs a boot_command_line */
                    strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
            
                    return mdesc;
            }
        
        arch/arm/mach-s3c24xx/mach-smdk2440.c
        MACHINE_START(S3C2440, "SMDK2440")
                /* Maintainer: Ben Dooks <[email protected]> */
                .atag_offset    = 0x100,
        
                .init_irq       = s3c2440_init_irq,
                .map_io         = smdk2440_map_io,
                .init_machine   = smdk2440_machine_init,
                .init_time      = smdk2440_init_time,
        MACHINE_END
    
    init/main.c
    
    /* Untouched command line saved by arch-specific code. */
    char __initdata boot_command_line[COMMAND_LINE_SIZE];
    /* Untouched saved command line (eg. for /proc) */
    char *saved_command_line;
    /* Command line for parameter parsing */
    static char *static_command_line;
    /* Command line for per-initcall parameter parsing */
    static char *initcall_command_line;
    
    static char *execute_command;
    static char *ramdisk_execute_command;
    
    /*
     * We need to store the untouched command line for future reference.
     * We also need to store the touched command line since the parameter
     * parsing is performed in place, and we should allow a component to
     * store reference of name/value for future reference.
     */
    static void __init setup_command_line(char *command_line)
    {
            saved_command_line =
                    memblock_virt_alloc(strlen(boot_command_line) + 1, 0);
            initcall_command_line =
                    memblock_virt_alloc(strlen(boot_command_line) + 1, 0);
            static_command_line = memblock_virt_alloc(strlen(command_line) + 1, 0);
            strcpy(saved_command_line, boot_command_line);
            strcpy(static_command_line, command_line);
    }
    /* Arch code calls this early on, or if not, just before other parsing. */
    void __init parse_early_param(void)
    {
            static int done __initdata;
            static char tmp_cmdline[COMMAND_LINE_SIZE] __initdata;
    
            if (done)
                    return;
    
            /* All fall through to do_early_param. */
            strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
            parse_early_options(tmp_cmdline);
            done = 1;
    }
    asmlinkage __visible void __init start_kernel(void)
    {
	char *command_line;
	...
	setup_arch(&command_line);
	...
	setup_command_line(command_line);
	...
    	pr_notice("Kernel command line: %s\n", boot_command_line);
       parse_early_param();
       after_dashes = parse_args("Booting kernel",
                                 static_command_line, __start___param,
                                 __stop___param - __start___param,
                                 -1, -1, NULL, &unknown_bootoption);
       if (!IS_ERR_OR_NULL(after_dashes))
               parse_args("Setting init args", after_dashes, NULL, 0, -1, -1,
                          NULL, set_init_arg);
    	
    	...
    }
    extern initcall_t __initcall_start[];
    extern initcall_t __initcall0_start[];
    extern initcall_t __initcall1_start[];
    extern initcall_t __initcall2_start[];
    extern initcall_t __initcall3_start[];
    extern initcall_t __initcall4_start[];
    extern initcall_t __initcall5_start[];
    extern initcall_t __initcall6_start[];
    extern initcall_t __initcall7_start[];
    extern initcall_t __initcall_end[];
    
    static initcall_t *initcall_levels[] __initdata = {
            __initcall0_start,
            __initcall1_start,
            __initcall2_start,
            __initcall3_start,
            __initcall4_start,
            __initcall5_start,
            __initcall6_start,
            __initcall7_start,
            __initcall_end,
    };
    /* Keep these in sync with initcalls in include/linux/init.h */
    static char *initcall_level_names[] __initdata = {
            "early",
            "core",
            "postcore",
            "arch",
            "subsys",
            "fs",
            "device",
            "late",
    };
    
    static void __init do_initcall_level(int level)
    {
            initcall_t *fn;
    
            strcpy(initcall_command_line, saved_command_line);
            parse_args(initcall_level_names[level],
                       initcall_command_line, __start___param,
                       __stop___param - __start___param,
                       level, level,
                       NULL, &repair_env_string);
    
            for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)
                    do_one_initcall(*fn);
    }
    
    static void __init do_initcalls(void)
    {
            int level;
    
            for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)
                    do_initcall_level(level);
    }


arch/alpha/kernel/setup.c

static char __initdata command_line[COMMAND_LINE_SIZE];

void __init
setup_arch(char **cmdline_p)
{ 
...
        /* 
         * Locate the command line.
         */
        /* Hack for Jensen... since we're restricted to 8 or 16 chars for
           boot flags depending on the boot mode, we need some shorthand.
           This should do for installation.  */
        if (strcmp(COMMAND_LINE, "INSTALL") == 0) {
                strlcpy(command_line, "root=/dev/fd0 load_ramdisk=1", sizeof command_line);
        } else {
                strlcpy(command_line, COMMAND_LINE, sizeof command_line);
        }
        strcpy(boot_command_line, command_line);
        *cmdline_p = command_line;
...
        /* Replace the command line, now that we've killed it with strsep.  */
        strcpy(command_line, boot_command_line);
...
}

猜你喜欢

转载自blog.csdn.net/hbcbgcx/article/details/84970596