head.s分析(1):保存u-boot传递过来的指针

 

快乐虾

http://blog.youkuaiyun.com/lights_joy/

lights@hb165.com

 

本文适用于

ADI bf561 DSP

uclinux-2008r1.5-rc3 (移植到vdsp5)

Visual DSP++ 5.0(update 5)

 

欢迎转载,但请保留作者信息

 

linux-2.6.x/arch/blackfin/mach-bf561/head.Suclinux的入口点,uclinux的第一条语句就是从__start这个入口开始执行的,本文分析的就是head.s这个文件。

1.1    保存u-boot传递过来的指针

     /* R0: argument of command line string, passed from uboot, save it */

     R7 = R0;

这一行看起来很简单,实际上涉及到很多内容。

首先要知道的是R0保存的是什么东西。由于uclinux是由u-boot这类的bootloader进行引导的,这类程序通常需要将内核解压缩到一个指定的地址,然后通过一个函数调用将控制权交给内核,通常还要传递一个”console=/dev/ttyBF0”之类的字符串给内核,R0就保存了这个字符串的头指针,因此这行代码先把这个指针保存起来。

下面的代码来自于u-boot-1.1.6-2008R1.5/lib_blackfin/boot.c,从中可以看出这个参数的传递过程:

void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],

             ulong addr, ulong *len_ptr, int verify)

{

     int (*appl) (char *cmdline);

     char *cmdline;

 

#ifdef SHARED_RESOURCES

     swap_to(FLASH);

#endif

 

     appl = (int (*)(char *))ntohl(header.ih_ep);

     printf("Starting Kernel at = %x/n", appl);

     cmdline = make_command_line();

     if (icache_status())

         icache_disable();

     if (dcache_status())

         dcache_disable();

     (*appl) (cmdline);

}

全局变量header中存放了压缩的uClinux映象文件的信息(参见《u-boot引导uclinux》一文),ip_ep这个成员存放的就是uClinux解压后的入口点的地址,所以在此直接将它赋给appl作为函数指针。而cmdline这个变量存放的就是要传递给uClinux的参数,它是一个字符串。

关键的调用是由(*appl)(cmdline);来完成的,看看它的汇编代码:

R0 = [FP – 4];

P1 = [FP – 8];

CALL(P1);

[FP-4]存放的就是cmdline这个局部变量的值,而[FP-8]存放的则是app1这个局部变量的值。也就是说,编译器是将要传递的字符串参数指针放在R0中的。

在保存了这个指针之后,uclinux在下面还要将这个指针指向的内容复制到uclinux自己的数据段中。

 

 

 

<think>嗯,用户现在想了解关于boot.S文件的信息,包括它的内容、作用以及解析。根据之前的对话历史,用户之前询问了Linux下查看系统核心数量的命令,我给出了详细的回答和相关问题。现在用户的问题转向了boot.S文件,这可能与系统启动过程或嵌入式开发有关。 首先,我需要回顾用户提供的引用内容。引用[1]提到了U-Boot的start.S文件,作为整个U-Boot的入口,负责初始化硬件和跳转到C语言环境。引用[3]则讨论了FreeNOS的boot.S和链接脚本,说明boot.S在设置入口点、初始化CPU模式、内存管理等方面的作用。引用[4]涉及Android的boot.img结构,虽然不直接关联boot.S,但可能帮助理解启动流程。 用户的需求是明确boot.S文件的内容、作用和解析。我需要综合这些引用来构建回答。可能需要解释boot.S在不同项目中的角色,比如在U-Boot、FreeNOS中的具体功能,以及常见的代码结构,比如设置异常向量表、初始化硬件、建立堆栈等。 同时,用户可能对boot.S的具体代码示例感兴趣,比如如何编写或分析这样的文件。需要提供一些典型的代码片段,并解释关键指令的作用,如汇编指令、模式切换等。此外,链接脚本的作用也很重要,因为boot.S通常与链接脚本配合使用,确定内存布局。 还要注意用户可能的实际应用场景,比如嵌入式开发或操作系统学习,因此在回答中可以提及相关的应用场景和调试方法。此外,用户可能对如何修改或定制boot.S文件感兴趣,比如配置硬件参数或调整启动流程,这也是需要涵盖的内容。 最后,生成的相关问题需要围绕boot.S的扩展知识,比如与链接脚本的关系、不同架构的差异、调试方法等,帮助用户进一步探索。需要确保回答结构清晰,分点说明,并结合示例代码和实际项目参考,增强可信度。</think>#### Boot.S文件深度解析(嵌入式系统/操作系统启动入口) --- ### 一、Boot.S的核心作用 1. **硬件初始化入口**:作为系统启动的第一个汇编文件,负责初始化CPU核心寄存器、关闭中断、设置异常向量表等底层硬件操作[^1][^3] - 示例代码片段(ARM架构): ```assembly .globl _start _start: b reset @ 跳转到reset处理 ldr pc, _undefined_instruction @ 未定义指令异常向量 reset: mrs r0, cpsr @ 读取当前程序状态寄存器 bic r0, r0, #0x1f @ 清除模式位 orr r0, r0, #0x13 @ 设置为SVC模式 msr cpsr_c, r0 @ 写回CPSR ``` 2. **内存管理奠基**:建立临时内存映射表(MMU初始化前),配置Cache策略和内存访问权限[^3] 3. **环境准备**:设置堆栈指针(SP)、初始化BSS段、传递启动参数给C语言入口[^1][^3] --- ### 二、典型Boot.S代码结构 以U-Boot的start.S为例(ARMv7架构): ```assembly #include <asm-offsets.h> #include <config.h> .globl _start _start: b reset @ 复位向量 ldr pc, _undefined_instruction ... @ 其他异常向量 reset: /* 关闭中断 */ mrs r0, cpsr orr r0, r0, #0xc0 msr cpsr, r0 /* 设置SVC模式堆栈 */ ldr sp, =CONFIG_SYS_INIT_SP_ADDR /* 清除BSS段 */ ldr r0, =__bss_start ldr r1, =__bss_end mov r2, #0 clbss_loop: cmp r0, r1 strlo r2, [r0], #4 blo clbss_loop /* 跳转到C入口 */ bl board_init_f ``` **关键指令解析**: - `mrs/msr`:操作程序状态寄存器(CPSR/SPSR) - `ldr sp`:设置堆栈指针(不同模式需独立设置) - `.globl`:声明全局符号供链接器使用[^1] --- ### 三、Boot.S与链接脚本的协同 通过`kernel.ld`等链接脚本确定内存布局: ```ld ENTRY(_start) /* 指定入口符号 */ SECTIONS { . = 0x100000; /* 加载地址1MB */ .text : { *(.text.boot) /* Boot.S代码段 */ *(.text*) } .rodata : { *(.rodata*) } .data : { *(.data*) } .bss : { __bss_start = .; *(.bss*) __bss_end = .; } } ``` **内存布局关键点**: - `.text.boot`段强制放在镜像起始位置 - BSS段边界符号用于清零操作[^3] --- ### 四、不同系统的Boot.S实现差异 | 系统类型 | 核心差异点 | 典型参考 | |----------------|---------------------------|-----------------------| | U-Boot | 多阶段启动(SPL+TPL) | start.S[^1] | | Linux Kernel | ARM的stext入口处理 | arch/arm/kernel/head.S| | FreeNOS | 自定义内存段划分 | boot.S[^3] | | RT-Thread | 快速上下文切换机制 | context_gcc.S | --- ### 五、调试Boot.S的实用方法 1. **QEMU+GDB调试**: ```bash qemu-system-arm -M vexpress-a9 -kernel u-boot -s -S arm-none-eabi-gdb u-boot (gdb) target remote :1234 (gdb) b _start ``` 2. **LED指示灯法**:在关键代码位置插入GPIO操作代码,通过物理LED观察执行流程[^2] 3. **串口输出调试**:初始化UART后通过串口打印寄存器值(需提前配置时钟和引脚)[^2] --- #### 相关问题 1. Boot.S如何与C语言环境进行参数传递? 2. 不同CPU架构(x86 vs ARM)的Boot.S实现有何本质区别? 3. 如何验证Boot.S中内存初始化的正确性? 4. Boot.S中的异常向量表与操作系统中断处理有何关联? (答案中涉及的具体技术细节可参考U-Boot源码的`arch/arm/cpu/armv7/start.S`和FreeNOS的`boot.S`实现[^1][^3])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌云阁主

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值