IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 内核中对uboot传参tags的校验 -> 正文阅读

[C++知识库]内核中对uboot传参tags的校验

前言

此篇博客介绍的是内核如何解析uboot传递的tag参数。

uboot给内核传tag参数

参考博客:《uboot以tag方式给内核传参》

* (taglist.init)段

······
  __tagtable_begin = .;
   *(.taglist.init)
  __tagtable_end = .;
·······

上面是摘抄自内核的链接脚本,__tagtable_begin和__tagtable_end表示taglist.init段在链接地址的起始和结束,在内核处理tag传参时需要用到。。

struct tagtable结构体

struct tagtable {
	__u32 tag;
	int (*parse)(const struct tag *);
};

struct tagtable结构体由一个整形数tag和函数指针parse构成,其中tag代表不同类型的tag参数,函数指针就是该类型tag参数的处理函数。此结构体就是对每种类型的tag参数绑定一个处理函数。

__tagtable宏

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

static int __init parse_tag_cmdline(const struct tag *tag)
{
	strlcpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
	return 0;
}
__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
//将宏展开:
static struct tagtable __tagtable_parse_tag_cmdline __used __attribute__((__section__(".taglist.init"))) = \
{ATAG_CMDLINE, parse_tag_cmdline}

_tagtable宏的作用:
1.定义一个静态局部变量,类型是struct tagtable,名字是__tagtable
##fn,并赋值;
2.对定义的结构体赋予".taglist.init"的段属性,链接的时候用__tagtable宏定义的结构体会被链接到一起,类型与一个结构体数组。

struct tag结构体

struct tag_header {
		u32 size;	//结构体的大小
		u32 tag;	//结构体的类型
	};

struct tag {
       struct tag_header hdr;
		union { 	//此枚举体包含了uboot传给内核参数的所有类型
				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;
				
				struct tag_mtdpart      mtdpart_info;
		} u;
};

struct tag结构体定义在arch/arm/include/asm/setup.h中。参考博客:《uboot以tag方式给内核传参》

内核汇编阶段对tag参数的校验

__vet_atags:
	tst	r2, #0x3							@ 检查tag参数所在地址是否对齐
	bne	1f									@上一句代码的结果不相等则跳转到标号1处,校验失败

	ldr	r5, [r2, #0]					@r2中保存的是第一个tag参数的地址,此句相当于r5=r2->hdr.size
	cmp	r5, #ATAG_CORE_SIZE		@比较r5和ATAG_CORE_SIZE是否相等,
	cmpne	r5, #ATAG_CORE_SIZE_EMPTY	@如果上一句不相等,则比较r5和ATAG_CORE_SIZE_EMPTY是否相等
	bne	1f									@上一句代码的结果不相等则跳转到标号1处,校验失败
	ldr	r5, [r2, #4]					@此句相当于r5=r2->hdr.tag
	ldr	r6, =ATAG_CORE				@将ATAG_CORE赋值给r6
	cmp	r5, r6								@判断r5是否等于ATAG_CORE	
	bne	1f									@上一句代码的结果不相等则跳转到标号1处,校验失败

	mov	pc, lr								@校验成功,函数返回

1:	mov	r2, #0
	mov	pc, lr
ENDPROC(__vet_atags)

1.ATAG_CORE_SIZE:ATAG_CORE类型tag结构体的大小;
2.ATAG_CORE_SIZE_EMPTY:第一个tag类型为空,代表uboot没有给内核传tag;
3.ATAG_CORE:这是tag的类型,tag参数的第一个必须是此类型;
4.整个校验的思路:
查看uboot传的第一个tag结构体是不是ATAG_CORE类型;

内核C语言阶段对tag参数的校验

调用的函数

//init/main.c
void __init start_kernel(void)
	void __init setup_arch(char **cmdline_p)
		mdesc = setup_machine(machine_arch_type);
		tags = phys_to_virt(mdesc->boot_params);
			parse_tags(tags)
				parse_tag(t)
					t->parse(tag)

setup_arch函数

void __init setup_arch(char **cmdline_p)
{
	struct tag *tags = (struct tag *)&init_tags;
	struct machine_desc *mdesc;

	setup_processor();
	mdesc = setup_machine(machine_arch_type);
	machine_name = mdesc->name;

	if (mdesc->soft_reboot)
		reboot_setup("s");

	if (__atags_pointer)
	{
		tags = phys_to_virt(__atags_pointer);
		printk("@@@@@@@ atags_pointer not null\n");
		
	}
	else if (mdesc->boot_params)
	{
		tags = phys_to_virt(mdesc->boot_params);
		printk("@@@@@@@ boot params not null\n");
	}

	if (tags->hdr.tag == ATAG_CORE) {
		if (meminfo.nr_banks != 0)
			squash_mem_tags(tags);
		save_atags(tags);
		parse_tags(tags);
	}
}

parse_tags函数

static void __init parse_tags(const struct tag *t)
{
	for (; t->hdr.size; t = tag_next(t))
		if (!parse_tag(t))
			printk(KERN_WARNING
				"Ignoring unrecognised tag 0x%08x\n",
				t->hdr.tag);
}

parse_tag函数

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;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-28 22:43:27  更:2021-12-28 22:43:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:01:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码