zoukankan      html  css  js  c++  java
  • Bootloader与Kernel间参数传递机制 taglist【转】

    本文转载自:http://blog.csdn.net/tommy_wxie/article/details/9187821

    Tag list被用来在bootloader和Linux kernel 之间传递参数,这里分析一下相关的数据结构,主要包括两个部分:Tag list 和Tag parser list。

    先来看Tag list:

    这个list是在bootloader中填充的,其数据结构定义在bootloader和linux kernel中均有定义,是一致的。我们来看linux kernel中的定义:


    top/arch/arm/include/asm/setup.h
    struct tag {
        struct tag_header hdr;
        union {
            struct tag_core        core;
            struct tag_mem32    mem;
            struct tag_videotext    videotext;
            struct tag_ramdisk    ramdisk;
            struct tag_initrd    initrd;
            struct tag_serialnr    serialnr;
            struct tag_revision    revision;
            struct tag_videolfb    videolfb;
            struct tag_cmdline    cmdline;
            /*
             * Acorn specific
             */
            struct tag_acorn    acorn;
            /*
             * DC21285 specific
             */
            struct tag_memclk    memclk;
        } u;
    };
    struct tag_header {
        __u32 size;
        __u32 tag;
    };

    其中tag的取值如下,暂且称之为tagtype:


    #define ATAG_CORE            0x54410001
    #define ATAG_MEM            0x54410002
    #define ATAG_VIDEOTEXT        0x54410003
    #define ATAG_RAMDISK        0x54410004
    #define ATAG_INITRD            0x54410005
    #define ATAG_INITRD2        0x54420005
    #define ATAG_SERIAL            0x54410006
    #define ATAG_REVISION        0x54410007
    #define ATAG_VIDEOLFB        0x54410008
    #define ATAG_CMDLINE        0x54410009
    #define ATAG_ACORN            0x41000101
    #define ATAG_MEMCLK        0x41000402


    其数据结构用图形表示就是:

    其实就是一个链表,通过Tagsize以及当前tag的位置来定位下一个tag的位置。而且第一个tag的类型必然是ATAG_CORE。

    参数就是按照这个结构进行传递的,那么kernel是如何进行解析的呢?

    我们来看tag parserlist:

    同样是在top/arch/arm/include/asm/setup.h,有如下定义:


    top/arch/arm/include/asm/setup.h

    struct tagtable{
        __u32 tag;
        int (*parse)(conststruct tag *);
    };
    #define __tag __used __attribute__((__section__(".taglist.init")))
    #define __tagtable(tag, fn) /
    static struct tagtable __tagtable_##fn __tag={ tag, fn}


    从上面知道,tag parser list存在于.taglist.init段,他们的定义将通过宏__tagtable(tag, fn)的形式给出,比如在 top/arch/arm/kernel/setup.c中:

    top/arch/arm/kernel/setup.c

    __tagtable(ATAG_CORE, parse_tag_core);
    __tagtable(ATAG_MEM, parse_tag_mem32);
    __tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
    __tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
    __tagtable(ATAG_SERIAL, parse_tag_serialnr);
    __tagtable(ATAG_REVISION, parse_tag_revision);
    __tagtable(ATAG_CMDLINE, parse_tag_cmdline);


    通过这样的定义,每个tag table的表项就自动连接在了一起,而且存在于同一个段中。如图所示:

    可以看到,所有支持的tag parser都列在这里了。

    在kernel中,将针对taglist中的每一项在这个tag parser list中进行查找,如果有对应的处理项,则调用解析函数,于是就完成了参数的传递以及解析!

    注意:

    在top/arch/arm/kernel/head-common.s中会对从bootloader传递过来的tag list进行合法性判断:

    以标号__vet_atags开始的一段处理就要是判断tag list的第一项是否是ATAG_CORE,同时判断长度是否越界!

    setup.c 中cmdline的获取就是采用taglist的方式:

    static int __init parse_tag_serialnr(const struct tag *tag)
    {
        system_serial_low = tag->u.serialnr.low;
        system_serial_high = tag->u.serialnr.high;
        return 0;
    }

    __tagtable(ATAG_SERIAL, parse_tag_serialnr);

    static int __init parse_tag_revision(const struct tag *tag)
    {
        system_rev = tag->u.revision.rev;
        return 0;
    }

    __tagtable(ATAG_REVISION, parse_tag_revision);

    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_warning("Ignoring tag cmdline (using the default kernel command line) ");
    #else
        strlcpy(default_command_line, tag->u.cmdline.cmdline,
            COMMAND_LINE_SIZE);
    #endif
        return 0;
    }

    __tagtable(ATAG_CMDLINE, parse_tag_cmdline);

    由__tagtable 申明的放在vmlinux.lds的taglist section中

    使用时bootloader中也要申明 taglist,地址相同即可传递。。。。。 参考 cmdline实现方式

  • 相关阅读:
    MD代码块指定语言类型
    spring通过bean名称,方法名,反射调用服务。
    h5魔塔开坑记
    意识流CSP2021游记
    Android开发byte version = 0x80错误: 不兼容的类型: 从int转换到byte可能会有损失
    Installed Build Tools revision 31.0.0 is corrupted. Remove and install again using the SDK Manager解决方法
    Android开发androidstudio调试smali代码
    Android开发修改手机ro.debuggable=1便于调试应用程序
    window环境下载Android系统源代码的方法
    android开发jni开发遍历文件夹下的文件以及目录
  • 原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/6994898.html
Copyright © 2011-2022 走看看