在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);
}