下面分析一下boot.axf, 其代码都在目录lichee/boot/boot1/apps/Boot_Android中
1.链接脚本
-
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
-
OUTPUT_ARCH(arm)
-
SECTIONS
-
{
-
. = 0x42800000;
-
EGON2_MAGIC : { magic.o(.rodata) }
-
.text : { *(.text) *(.rodata)}
-
.data : { *(.data) }
-
.bss : { *(.bss) }
-
-
}
2. magic.c
在lichee/boot/boot1/apps/Boot_Android/magic.c中
-
const eGon2_mod_t modinfo =
-
{
-
{'e','G','o','n','2','a','p','p'},
-
0x01000000,
-
0x0,
-
BootMain, //虽然还不是很理解,但是这应该就是首地址了
-
0
-
};
3. BootMain
在lichee/boot/boot1/apps/Boot_Android/BootMain.c中
-
int BootMain(int argc, char **argv)
-
{
-
memset(&board_res, 0, sizeof(boot_hardware_res));
-
memset(&boot1_priv_para, 0, sizeof(boot1_private_head_t));
-
-
ret = wBoot_get_para(WBOOT_PARA_GLOBAL, &boot1_priv_para);
-
-
global_info = (boot_global_info_t *)wBoot_malloc(sizeof(boot_global_info_t));
-
memset(global_info, 0, sizeof(boot_global_info_t));
-
ret = script_patch("c:\\boot.ini", global_info, 0); //3.1 解析boot.ini,将解析结果放在global_info中
-
BoardInit_Display(global_info->display_device, global_info->display_mode); //按照boot.ini中的参数进行显示的初始化
-
if(check_power_status())
-
{
-
ret = -1;
-
}
-
else
-
{
-
//3.2解析c:\linux\linux.ini,读取里面的img_name(u-boot.bin),到内存地img_base(0x4A000000)处
-
//para_addr为空, kernal_addr=0x4a000000, logo_status=0
-
BootOS_detect_os_type(¶_addr, &kernal_addr, (void *)global_info, &logo_status);
-
}
-
BoardExit(logo_status, ret);
-
BootOS(para_addr, kernal_addr); //3.3跳到kernel_addr处运行
-
}
3.1
解析boot.ini,结果存在global_info中
script_patch
("c:\\boot.ini", global_info
, 0
);
-
__s32 script_patch(char *script_name, void *script_buf, __s32 boot_script_type)
-
{
-
//打开boot.ini
-
script_file = wBoot_fopen(script_name, "rb");
-
//查找boot.ini的长度
-
script_len = wBoot_flen(script_file);
-
//在堆上为boot.ini分配空间
-
script_addr = (char *)wBoot_malloc(script_len);
-
//将boot.ini读到内存中
-
wBoot_fread(script_addr, 1, script_len, script_file);
-
wBoot_fclose(script_file);
-
//参数boot_script_type=0
-
if(!boot_script_type)
-
{
-
//解析boot.ini,并将解析后的值存在script_buf中
-
//这个script_buf使用时转为结构体boot_global_info_t
-
ret = parser_script_os_sel(script_addr, script_len, script_buf);
-
}
-
else
-
{
-
ret = parser_script_os_img(script_addr, script_len, script_buf);
-
}
-
-
return ret;
-
}
parser_script_os_sel这个函数进行具体的解析工作:
按行读取boot.ini中的内容,每行的首字节代表了该行的类型,
; --> 注释行
[ --> 主键行
空行忽略,其它为sub_key
对sub_key中的字符串进行匹配,需要数字的将字符串中的值转为数字
3.2 解析参数并加载u-boot
调用:BootOS_detect_os_type
(¶_addr
, &kernal_addr
, (void
*)global_info
, &logo_status
);
其中global_info
是解析自
boot.ini的参数指明了当前的system类型,其它的3个参数是需要赋值的
-
__s32 BootOS_detect_os_type(__u32 *para_addr, __u32 *kernal_addr, void *os_info, int *logo_status)
-
{
-
//解析linux/linux.ini的配置到os_img_info中
-
script_patch("c:\\linux\\linux.ini", &os_img_info, 1);
-
boot_show_logo("c:\\os_show\\bootlogo.bmp", 1, BOOT_LOGO_MEM_BASE); //show logo
-
PreBootOS((char *)&os_img_info, kernal_addr, para_addr, logo_status);
-
read_boot_img(boot_part_start,0x40007800);
-
-
return ret;
-
}
3.2.1 解析参数并加载u-boot
调用:PreBootOS
((char
*)&os_img_info
, kernal_addr
, para_addr
, logo_status
);
其中os_img_info是从c:\linux\linux.ini解析出来的参数,其它的3个参数是需要赋值的
-
__s32 PreBootOS(char *os_para, __u32 *kernal_addr, __u32 *para_addr, __s32 *logo_status)
-
{
-
boot_sys_img_set_t *os_img;
-
os_img = (boot_sys_img_set_t *)os_para;
-
*logo_status = os_img->logo_off; //赋值logo_staus值为0
-
boot_show_logo(os_img->logo_name, os_img->logo_show, BOOT_LOGO_MEM_BASE); //show logo
-
ret = boot_dsipatch_kernal(os_img, kernal_addr, para_addr); //加载u-boot.bin,kernal_addr就是加载的地址(0x4a000000)
-
return 0;
-
}
3.2.1.1 加载u-boot.bin
将u-boot.bin加载到内存的0x4a000000处,kenel_addr是加载的内存地址(0x4a000000),para_addr是参数的地址(为空)
-
static __s32 boot_dsipatch_kernal(boot_sys_img_set_t *os_img, __u32 *kernal_addr, __u32 *para_addr)
-
{
-
__inf("load kernel start\n");
-
#ifndef SPEED_UP_BOOT
-
count = os_img->img_count;
-
for(i = 0; i < count; i++)
-
{
-
if(1 != i)
-
{
-
address = (void *)os_img->img_set[i].img_base;
-
}
-
else
-
{
-
address = wBoot_malloc(64 * 1024);
-
}
-
-
hd_file = wBoot_fopen(os_img->img_set[i].img_name, "rb");
-
-
file_length = wBoot_flen(hd_file);
-
-
wBoot_fread(address, 1, file_length, hd_file);
-
wBoot_fclose(hd_file);
-
-
os_img->img_set[i].img_full_size = file_length;
-
if(1 == i)
-
{
-
do_boot_linux((char *)os_img->img_set[1].img_base, (char *)address, file_length);
-
wBoot_free(address);
-
}
-
address = NULL;
-
hd_file = NULL;
-
file_length = 0;
-
}
-
address = (void *)os_img->script_info.img_base;
-
memcpy(address, (void *)SCRIPT_BASE, os_img->script_info.img_size);
-
os_img->script_info.img_full_size = os_img->script_info.img_size;
-
*kernal_addr = os_img->img_set[0].img_base;
-
*para_addr = os_img->img_set[1].img_base;
-
#else
-
//这儿执行的应该是上面的#ifndef,上下都是同一个意思,而且下面的看起来更清楚一些
-
//这儿的kernel_addr与wBoot_fopen都是直接赋的值,其实应该是从c:\linux\linux.ini中读取
-
//作用是将u-boot.bin加载到内存的0x4a000000处
-
*kernal_addr = 0x4a000000;
-
hd_file = wBoot_fopen("c:\\linux\\u-boot.bin", "rb");
-
file_length = wBoot_flen(hd_file);
-
wBoot_fread((void *)(*kernal_addr), 1, file_length, hd_file);
-
wBoot_fclose(hd_file);
-
#endif
-
__inf("load kernel successed\n");
-
-
return 0;
-
}
3.3 执行u-boot
调用BootOS
(para_addr
, kernal_addr
),
实际上是产生了一个软中断
-
void BootOS(__u32 para_addr, __u32 kernal_addr)
-
{
-
wBoot_jump_to_linux(0, 3495, para_addr, kernal_addr);
-
}
3.3.1 产生软中断
产生一个软中断EGON2_SWI_JUMP_TO_LINUX
在lichee/boot/boot1/misc/syacall/syscall_misc.c中
-
int wBoot_jump_to_linux(int addr, int mod_id, unsigned int paddr, unsigned int kernal_addr)
-
{
-
asm("stmfd sp!, {lr}");
-
asm("swi %0"::"Ir"(EGON2_SWI_JUMP_TO_LINUX));
-
asm("ldmfd sp!, {lr}");
-
}
3.3.2 进入软中断入口函数
在lichee/boot/boot1/core/arm_board/arm_swi.c中
-
void eGon2_swi_handler_entry(__u32 swi_number, struct swi_regs * swi_reg)
-
{
-
case EGON2_SWI_JUMP_TO_LINUX:
-
{
-
eGon2_jump_to_android_linux(swi_reg->reg[0], swi_reg->reg[1], swi_reg->reg[2], swi_reg->reg[3]);
-
}
-
}
3.3.3 终于开始执行u-boot了
lichee/boot/boot1/core/jump_to/jump.c
-
void eGon2_jump_to_android_linux(__s32 zero, __s32 mod_id, __u32 paddr, __u32 kernal_addr)
-
{
-
void (*kernel_entry)(int zero, int arch, uint params);
-
//一系列的关闭操作
-
...
-
kernel_entry = (void (*)(int, int, __u32))(kernal_addr); //将0x4A000000转为函数指针
-
kernel_entry(zero, mod_id, paddr); //执行
-
return;
-
}
阅读(1664) | 评论(0) | 转发(1) |