Linux内核及ARM的内存管理(再续)

 

有许多事,需要回到u-boot才能说清楚……

 

include/configs/XXXX.h中(XXXX视具体平台而定),一般会作类似如下定义:

 

#define CONFIG_BOOTCOMMAND "mmcinit; fatload mmc 0 0x81c00000 uImage; bootm 0x81c00000"

 

编译时该宏CONFIG_BOOTCOMMAND传递给一个ENV项bootcmd,而在common/main.c中,函数main_loop取出了该env项,作为boot的过程开始启动kernel:

 

s = getenv ("bootcmd");

 

debug ("### main_loop: bootcmd=/"%s/"/n", s ? s : "<UNDEFINED>");

 

if (bootdelay >= 0 && s && !abortboot (bootdelay)) {

# ifdef CONFIG_AUTOBOOT_KEYED

int prev = disable_ctrlc(1); /* disable Control C checking */

# endif

 

# ifndef CFG_HUSH_PARSER

run_command (s, 0);

 

我们关心的是最后一条命令bootm,在文件common/cmd_bootm.c中已经定义:

 

U_BOOT_CMD(

  bootm, CFG_MAXARGS, 1, do_bootm,

  "bootm   - boot application image from memory/n",

  "[addr [arg ...]]/n    - boot application image stored in memory/n"

  "/tpassing arguments 'arg ...'; when booting a Linux kernel,/n"

  "/t'arg' can be the address of an initrd image/n"

);

 

即,真正要运行的程序是do_bootm。

 

一些关键的数据结构:
1、gd_t
在文件include/asm-arm/global_data.h中定义,在u-boot中广泛使用,通过宏:
DECLARE_GLOBAL_DATA_PTR;
将该数据结构的指针放入寄存器r8。
gd这个数据结构,在lib-arm/board.c文件中的start_armboot函数中进行初始化,详细分析以后再看。
2、bd_t
在文件include/asm-arm/u-boot.h中定义,作为u-boot的接口。
3、image_header_t
在文件include/image.h中定义,是u-boot即将加载的镜像文件头信息,u-boot将根据该头信息确定镜像文件是否正确,校验,镜像文件的起始地址以及入口地址等信息。
typedef struct image_header {
uint32_t ih_magic; /* Image Header Magic Number */
uint32_t ih_hcrc; /* Image Header CRC Checksum */
uint32_t ih_time; /* Image Creation Timestamp */
uint32_t ih_size; /* Image Data Size */
uint32_t ih_load; /* Data Load  Address */
uint32_t ih_ep; /* Entry Point Address */
uint32_t ih_dcrc; /* Image Data CRC Checksum */
uint8_t ih_os; /* Operating System */
uint8_t ih_arch; /* CPU architecture */
uint8_t ih_type; /* Image Type */
uint8_t ih_comp; /* Compression Type */
uint8_t ih_name[IH_NMLEN]; /* Image Name */
} image_header_t;
do_bootm函数会读出即将加载的镜像文件头,填入由该数据结构声明的全局变量header中,do_bootm函数通过对header的分析,确定是一个Linux镜像,则会调用do_bootm_linux函数,开始启动Linux的Kernel。
do_bootm_linux函数(在文件lib_arm/armlinux.c中),目前只关心最后一句:
theKernel (0, bd->bi_arch_number, bd->bi_boot_params);
theKernel在前面被定义为:
theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);
hdr->ih_ep使用的是do_bootm函数从image头中读取的入口,对于我们的板子来说,就是0x80008000;
bd->bi_arch_number, bd->bi_boot_params两个入口参数在的board_init函数中定义,bd->bi_arch_number赋值为板子的ID,bd->bi_boot_params赋值为0x80000100,该地址保存着do_bootm_linux函数创建的一系列ATAG。
参数的传递要看APCS(ARM过程调用标准),前四个参数会依次放入a1~a4,这是APCS为寄存器起的别名,对应于r0~r3,即,调用到kernel时,寄存器r0为0,r1为1967,r2为0x80000100。
u-boot的事情还远未说清楚,但是与目前有关的,大致差不多了。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值