设为首页 加入收藏

TOP

ppc-booting-sequence(一)
2014-11-24 12:00:15 来源: 作者: 【 】 浏览:2
Tags:ppc-booting-sequence

Powerpc启动顺序分析。


摘要:本文致力于研究Powerpc的引导技术,其中包括U-boot启动代码分析,kernel for Powerpc 启动代码分析,以及U-boot加载kernel代码分析。以上三个部分属于体系结构相关的内容。


由于时间有限,只是对代码进行粗读。


一、Kernel 启动代码分析
如果由u-boot解压缩内核,则内核的入口点是arch/ppc/head.s,注意,如果使用新的bsp,则arch使用powerpc而不是ppc。Ppc主要针对32位系统,powerpc把32位系统与64位系统整合在一起。


Powerpc有四种子体系:PMAC——PowerMacintosh主要是对mac的支持;PReP主要支持IBM,motorola,我们的ppc 440,460,mpc8548应该属于这个体系;CHRP支持IBM RS/6000,Genesi;APUS Amiga Power-UP Systems (APUS)。每种架构的启动是不一样的。


head.s


1、找到_start,首先根据ABI规范保存r3~r7(保存到r27~r31)。主要是一些内核参数。此时mmu是打开的,当然物理内核和虚拟内存相同。然后跳到early_init中把bss清零,然后判断CPU类型,根据类型判断物理地址(在关掉mmu时需要定位代码所在的物理地址),最后通过r3返回物理地址。


2、Bl mmu_off 关mmu,默认启动mmu是开启的,使用cpu内部的tlb进行内存映射。


3、Bl clear_bats 清除block address table


4、BL Flush_tlbs 应该是刷新tlb//其实都是写寄存器的操作。


5、Bl initial_bats 将前16M内存映射给内核使用。


6、Bl reloc_offset 计算连接地址与实际地址的偏移


7、Call_setup_cpu 设置cpu的ctl寄存器


8、Reloc_kernel 如果有必要则reloc


9、B turn_on_mmu 这个函数通过rfi返回,将SPRN_SRR0设置成start_here地址,rfi中断返回时将跳到这个地址执行,并切换上下文。


10、 Start_here 真正的打开mmu,通过rfi跳转到start_kernel运行。


11、 Start_kernel在main.c中,后面的内容和所有架构下无异。


二、 U-boot启动代码分析
U-Boot启动代码(for ppc)主要关注如下几个文件:1、u-boot.lds,2、start.s,3、board.c。u-boot.lds是链接文件,一般在对应开发板目录下;


Start.s 是启动代码文件,一般在对应得cpu目录下;


Board.c 是板子初始化文件,一般在对应体系结构的lib下;


首先来看u-boot.lds,从这个文件可以找到整个程序的入口位置。开头代码如下:


OUTPUT_ARCH(powerpc) /*代码是for ppc的*/


/* Do we need any of these for elf


__DYNAMIC = 0; */


SECTIONS


{


.resetvec 0xFFFFFFFC : /*定义resetvec段在0xFFFFFFFC位置,这个位置是ppc上电后IP指向的位置*/


{


*(.resetvec) /*段内容*/


} = 0xffff /*用0xffff填充空余部分*/



.bootpg 0xFFFFF000 : /*定义.bootpg段在0xFFFFF000位置*/


{


cpu/ppc4xx/start.o (.bootpg)


} = 0xffff /*用0xffff填充空余部分*/


…………


现在找到resetvec.s 文件。


#include


.section .resetvec,"ax"


#if defined(CONFIG_440)


b _start_440 /*CPU上电后执行的第一条命令:b _start_440*/


#else


#if defined(CONFIG_BOOT_PCI) && defined(CONFIG_MIP405)


b _start_pci


#else


b _start


#endif


#endif



Start.S 代码分析。_start_440在start.s中定义。Ppc440启动时,只有最高位的4k地址被TLB映射,此时控制器将最高4k的内容拷贝到cache中运行(我猜想在启动时440将自己的cache作为ram来使用,这样在不初始化外部ram的时候也能跑代码)。Start.s正是位于这4k当中,因此start.s担负着初始化整个正常环境的重任。接下来:


1) 设置中断控制器寄存器


2) 设置调试寄存器


3) 设置cpu控制器寄存器


4) 安装中断向量


5) 配置cache


6) 初始化mmu控制器,在启动时使用I/D cache控制器中的tlb实现地址映射。


7) 删除所有的tlb entries


8) 建立新的tlb。包括16M启动flash,内存,PCI存储空间,BCSR空间等等。


9) B _start 跳转到_start。


10) 此时需要建立新的工作环境,因此首先需要disable异常和中断。


11) 设置intenal ram


12) 设置电源管理


13) 设置堆栈 (到这里为止代码应该是在cache中)


14) bl cpu_init_f(board.c) 跳到Flash中执行cpu初始化。此时内存并没有完全初始化,堆栈空间很小,BSS也没有初始化。这段代码主要是打开一个console以便于调试,以及初始化RAM。以便把代码全部搬到RAM中运行。还有一个重要工作就是获取全局数据——gd。



Cpu_init_f:


(1) gd = (gd_t *) (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET);全局gd指针。__asm__ __volatile__("": : :"memory"); 内存壁垒,防止编译器优化。清空gd。


(2) for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {


if ((*init_fnc_ptr) () != 0) {


hang ();


}


}/*cpu/board /console… 初始化*/


(3) 设置gd


(4) 初始化sram


(5) 计算需要保护的内存区域(board infor,kernel log buf ,monitor code等等),addr即为除去保护内存后用于存放relocate code的地址,addr_sp为堆栈可以使用的基地址


(6) 调用relocate_code (start.s文件中) ,r3 = a

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇双核处理器ARM+DSP如何实现协同工.. 下一篇移植Linux内核到S3C2410开发板的..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·C++ Lambda表达式保 (2025-12-26 05:49:45)
·C++ Lambda表达式的 (2025-12-26 05:49:42)
·深入浅出 C++ Lambda (2025-12-26 05:49:40)
·C语言指针从入门到基 (2025-12-26 05:21:36)
·【C语言指针初阶】C (2025-12-26 05:21:33)