当前位置: 首页 > news >正文

Linux启动之__vet_atags

本文基于: linux-4.19 + ARMv7
介绍Linux启动之__vet_atags函数分析。

head.S启动代码:

ENTRY(stext)
 ARM_BE8(setend	be )			@ ensure we are in BE8 mode

 THUMB(	badr	r9, 1f		)	@ Kernel is always entered in ARM.
 THUMB(	bx	r9		)	@ If this is a Thumb-2 kernel,
 THUMB(	.thumb			)	@ switch to Thumb now.
 THUMB(1:			)

#ifdef CONFIG_ARM_VIRT_EXT
	bl	__hyp_stub_install
#endif
	@ ensure svc mode and all interrupts masked
	safe_svcmode_maskall r9

	mrc	p15, 0, r9, c0, c0		@ get processor id
	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid
    ......
	/*
	 * r1 = machine no, r2 = atags or dtb,
	 * r8 = phys_offset, r9 = cpuid, r10 = procinfo
	 */
	bl	__vet_atags

__vet_atags代码实现位于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)

  1. 核心功能概述
    __vet_atags函数用于验证启动时传入的 r2 寄存器值是否符合 ATAGS(ARM Tagged List)或 DTB(Device Tree Blob)的合法性要求,确保内核能正确解析硬件参数。若验证失败,r2 会被清零。

  1. 验证条件分解
    (1) 对齐检查(Alignment Check)
tst	r2, #0x3			@ 检查r2是否4字节对齐 
bne	1f				    @ 若未对齐,跳转到标签1(返回r2=0
  • 意义:ATAGS/DTB的起始地址必须按4字节对齐,否则视为非法。

(2) DTB合法性检查

#ifdef CONFIG_OF_FLATTREE		@ 若启用设备树(DTB)支持 
ldr	r6, =OF_DT_MAGIC	 	    @ 加载DTB魔数(0xd00dfeed)
cmp	r5, r6				        @ 比较r5(r2[0])与DTB魔数 
beq	2f				            @ 相等则跳转到标签2(返回有效r2)
#endif 
  • 逻辑:若内核配置了设备树支持(CONFIG_OF_FLATTREE),则检查 r2[0] 是否为DTB魔数 0xd00dfeed

(3) ATAGS合法性检查

cmp	r5, #ATAG_CORE_SIZE		        @ 检查r2[0]是否为ATAG_CORE_SIZE(5| #define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
cmpne	r5, #ATAG_CORE_SIZE_EMPTY	@ 或ATAG_CORE_SIZE_EMPTY(2| #define ATAG_CORE_SIZE_EMPTY ((2*4) >> 2)
bne	1f				                @ 若不匹配,跳转到标签1(返回r2=0)
ldr	r5, [r2, #4]	  		        @ 加载r2[1](ATAG_CORE标记)
ldr	r6, =ATAG_CORE                  @ 加载标准ATAG_CORE值(0x54410001| #define ATAG_CORE 0x54410001
cmp	r5, r6				            @ 比较标记是否合法 
bne	1f				                @ 不匹配则返回r2=0 
  • ATAG_CORE规范:
    • r2[0] 必须为 ATAG_CORE_SIZE(5)或 ATAG_CORE_SIZE_EMPTY(2)。
    • r2[1] 必须为 ATAG_CORE 标记(0x54410001)。

(4) 返回结果

  • 标签2(有效):直接返回,保留 r2 原始值。
  • 标签1(无效):将 r2 清零后返回。

  1. 技术背景与设计意图
  2. 物理地址限制:
    • 注释提到ATAGS需位于 物理RAM前16KB,但代码未显式检查(可能由调用方保证)。
  3. 兼容性设计:
    • 同时支持传统ATAGS和现代DTB,适应不同启动协议(如U-Boot传递DTB时无需ATAGS)。
  4. 安全性扩展:
    • 未来可能放宽物理地址限制或动态调整ATAGS位置(当前版本仅静态验证)。

  1. 代码流程图解
               +----------------+
               | 输入: r2        |
               +----------------+
                        |
                        v 
               +----------------+
               | 对齐检查(r2&3)  |-- 未对齐 --> 清零r2并返回 
               +----------------+
                        |
                        v 
        +-------------------------------+
        | 读取r2[0]到r5                  |
        +-------------------------------+
                        |
                        v 
        +-------------------------------+
        | 检查是否为DTB魔数?             |-- 是 --> 返回有效r2 
        +-------------------------------+  
                        |
                        v 
        +-------------------------------+
        | 检查r2[0]是否为ATAG_CORE_SIZE |-- 否 --> 清零r2并返回 
        +-------------------------------+
                        |
                        v 
        +-------------------------------+
        | 检查r2[1]是否为ATAG_CORE标记  |-- 否 --> 清零r2并返回 
        +-------------------------------+
                        |
                        v 
               +----------------+
               | 返回有效r2      |
               +----------------+

  1. 应用场景与影响
  • 启动阶段:在Linux内核启动初期(start_kernel之前),用于校验Bootloader传递的参数合法性。
  • 错误处理:若校验失败,内核可能拒绝启动或回退到默认硬件配置。
  • 硬件兼容:确保不同厂商的Bootloader(如U-Boot、RedBoot)遵循ARM启动协议。

总结
__vet_atags 是ARM Linux启动流程中的关键验证环节,通过严格的指针检查保障内核稳定启动。其设计平衡了传统ATAGS与现代DTB的兼容性,同时为未来安全性和灵活性扩展预留空间。

相关文章:

  • 23种设计模式-外观(Facade)设计模式
  • unix网络编程
  • annoy编译安装问题及解决
  • 嵌入式八股文学习笔记——C++学习笔记面向对象相关
  • Python第九章节——异常,模块与包
  • leetcode128.最长连续序列
  • Objects.equals() 和 Object.equals() 的区别:
  • 信号处理中的窗
  • 《Python实战进阶》第30集:Scikit-learn 入门:分类与回归模型
  • Pytest的参数化测试
  • Xamarin.Android实现本地化部署DeepSeek的对话功能
  • 【docker】安装SQLServer
  • DrRacket是一款专为Scheme和Racket编程语言设计的集成开发环境(IDE)
  • 重温Docker 构建
  • 3110. 字符串的分数
  • java版嘎嘎快充玉阳软件互联互通中电联云快充协议充电桩铁塔协议汽车单车一体充电系统源码uniapp
  • Thinkphp(TP)漏洞攻略
  • python基础语法中的内置函数与拆包
  • 我的创作纪念日暨六年编程路的回顾
  • Select多路转接
  • 德雷克海峡发生6.4级地震,震源深度10千米
  • 国际观察|韩国在政局多重不确定性中迎接总统选举
  • 港股5月迎开门红,恒生科指涨3%,欧股开盘全线上扬
  • 停电催生商机,中国品牌 “照亮” 西班牙
  • 比黄油年糕热量还高,这个火爆全网的甜品劝你慎吃
  • 向总书记汇报具身智能发展的“稚辉君”:从期待到兴奋再到备受鼓舞