Linux- 启动参数Tag解析

在Tags  parse 库的开头归纳了Tag 的特征如下:

 * This is the traditional way of passing data to the kernel at boot time.  Rather
 * than passing a fixed inflexible structure to the kernel, we pass a list
 
* of variable-sized tags to the kernel.  The first tag must be a ATAG_CORE
 * tag for the list to be recognised (to distinguish the tagged list from
 * a param_struct).  The list is terminated with a zero-length tag (this tag
 * is not parsed in any way).

总结下来如下:

  • 这是一个长度可变对象的列表
  • 第一个Tag的类型为ATAG_CORE
  • 最后一个Tag的长度为0

整个方案依赖如下:

  • 数据结构的设计
  • 解析函数的注册
  • 解析调用

数据结构

根据Tags Parse的描述知道识别一个Tag对象需要知道其类型及针对具体类型的转换,故只需通过设计一个Tag头对象以及实际数据类型即可以解决,在steup.h中有如下定义:

struct tag_header {  #tag头对象数据结构
    __u32 size;      #该Tag的长度
    __u32 tag;        #该Tag的类型
};

/* The list must start with an ATAG_CORE node */
#define ATAG_CORE    0x54410001            #Tag类型

struct tag_core {    #具体Tag类型定义
    __u32 flags;        /* bit 0 = read-only */
    __u32 pagesize;
    __u32 rootdev;
};

----------------------

struct tag {   #具体Tag定义  由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;
};
 

解析函数注册

注册函数针对具体的Tag类型进行处理,函数管理类如下:

struct tagtable {
    __u32 tag;  # Tag类型
    int (*parse)(const struct tag *);  #解析函数
};

注册函数示例如下:

static int __init parse_tag_core(const struct tag *tag)
{
    if (tag->hdr.size > 2) {
        if ((tag->u.core.flags & 1) == 0)
            root_mountflags &= ~MS_RDONLY;
        ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
    }
    return 0;
}

__tagtable(ATAG_CORE, parse_tag_core);

宏__tagtable定义如下:

#define __tag __used __section(".taglist.init")
#define __tagtable(tag, fn) \
static const struct tagtable __tagtable_##fn __tag = { tag, fn }

则示例可以转换如下:

static const struct tagtable  __tagtable_parse_tag_core __used __section(".taglist.init")={ATAG_CORE, parse_tag_core)}

而section 定义如下:

    .init.tagtable : {
        __tagtable_begin = .;
        *(.taglist.init)
        __tagtable_end = .;
    }

解析调用

由Tag定义可知只需循环遍历所有Tag对象然后匹配Tag对应函数即可完成解析

/*
 * Scan the tag table for this tag, and call its parse function.
 * The tag table is built by the linker from all the __tagtable
 * declarations.
 */
static int __init parse_tag(const struct tag *tag)
{
    extern struct tagtable __tagtable_begin, __tagtable_end;
    struct tagtable *t;

    for (t = &__tagtable_begin; t < &__tagtable_end; t++)
        if (tag->hdr.tag == t->tag) {

            t->parse(tag);
            break;
        }

    return t < &__tagtable_end;
}

/*
 * Parse all tags in the list, checking both the global and architecture
 * specific tag tables.
 */
static void __init parse_tags(const struct tag *t)
{
    for (; t->hdr.size; t = tag_next(t))
        if (!parse_tag(t))
            pr_warn("Ignoring unrecognised tag 0x%08x\n",
                t->hdr.tag);
}

  • 27
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值