现在的位置: 首页 > 综合 > 正文

blob分析(下)

2018年01月10日 ⁄ 综合 ⁄ 共 3874字 ⁄ 字号 评论关闭
下面到了main()里面
/* initialise status */
blob_status.paramType = fromFlash;    //设置boot参数
blob_status.kernelType = fromFlash;    //设置内核
blob_status.ramdiskType = fromFlash;    //设置文件系统加载方式
blob_status.downloadSpeed = baud_38400;    //blob装载速率
blob_status.terminalSpeed = TERMINAL_SPEED;    //串口波特率
blob_status.load_ramdisk = LOAD_RAMDISK;    //设置文件系统装载标志
blob_status.cmdline[0] = '\0';
blob_status.boot_delay = 1;      //boot的延迟时间
先初始化串口
int serial_init(serial_baud_t baudrate)
{
#ifdef BLOB_DEBUG
if(serial_driver == NULL) {
/* we can't print anything over here, so just return
 * an error and hope the developer will figure out.
 */
return -ERANGE;
}
#endif
return serial_driver->init(baudrate);
}
下面初始化函数是init_subsystems();    //加载驱动
我们在src/lib/init.c里面找到
void init_subsystems(void)
{
int i;
/* call all subsystem init functions */
for(i = INIT_LEVEL_MIN; i <= INIT_LEVEL_MAX; i++)    //显然是分等级依次初始化
call_funcs((initlist_t *)&__initlist_start,         //__initlist_start链接的时候会赋值
   (initlist_t *)&__initlist_end,
   INIT_MAGIC, i);
}
结构体为
typedef struct {
u32 magic;
initfunc_t callback;    //指向函数的指针
int level;
} initlist_t;
其中call_funcs函数如下
static void call_funcs(initlist_t *start, initlist_t *end, 
       u32 magic, int level)
{
initlist_t *item;
for(item = start; item != end; item++) {
if(item->magic != magic) {
deprintf("init magic failed at 0x%08x\n",
 (unsigned int)item);
printerror(EMAGIC, NULL);
return;
}
if(item->level == level) {
/* call function */
item->callback();
}
}
}
至于这些结构怎么放到__initlist_start到__initlist_end的,具体查看
#define __initlist(fn, lvl) \
static initlist_t __init_##fn __init = { \
magic:    INIT_MAGIC, \
callback: fn, \
level:
  lvl }
在init.h中还有下面一段宏定义
/* minimum and maximum levels */
#define INIT_LEVEL_MIN (0)
#define INIT_LEVEL_MAX (99)
/* define some useful levels */
#define INIT_LEVEL_DRIVER_SELECTION (0)
#define INIT_LEVEL_INITIAL_HARDWARE (10)
#define INIT_LEVEL_PARAM_LIST (20)
#define INIT_LEVEL_OTHER_HARDWARE (30)
#define INIT_LEVEL_OTHER_STUFF (40)
这个就是初始化列表的顺序
__initlist(littleton_init_hardware, INIT_LEVEL_DRIVER_SELECTION);    //在littleton.c
/* init calls */
__initlist(serial_default_init, INIT_LEVEL_INITIAL_HARDWARE);    //在initcalls.c
__initlist(enable_icache, INIT_LEVEL_INITIAL_HARDWARE);
//__initlist(led_init, INIT_LEVEL_INITIAL_HARDWARE);
__initlist(timer_init, INIT_LEVEL_OTHER_HARDWARE);
__initlist(init_monahans_nand_driver, INIT_LEVEL_OTHER_HARDWARE);    //在nandwrite.c
__initlist(init_flash_io, INIT_LEVEL_OTHER_STUFF + 2);    //在initcalls.c
__initlist(init_part_io, INIT_LEVEL_OTHER_STUFF + 2);
__initlist(init_ram_io, INIT_LEVEL_OTHER_STUFF + 2);
当然这不是全部,还有一些就没有列举了,有时候还要看配置是否决定要初始化。
if(blob_status.load_ramdisk)
do_reload("ramdisk");
加载文件系统
if (blob_status.boot_delay > -1) {
int i;
int retval = 0;
/* wait boot_delay seconds before starting autoboot */
printf("Autoboot (%i seconds) in progress, press any key to stop ",
       blob_status.boot_delay);
if (blob_status.boot_delay == 0) {
retval = SerialInputBlock(commandline, 1, 0); 
} else {
for(i = 0; i < blob_status.boot_delay; i++) {
serial_write('.');
retval = SerialInputBlock(commandline, 1, 1);     //检测是否有按键
if(retval > 0)
break;
}
}
假如没有按键就加载内核和文件系统
if(retval == 0) {
    ……
commandline[0] = '\0';
parse_command("nkernel");
commandline[0] = '\0';
parse_command(gBootArg);
    ……
}
转战到src/blob/linux.c 
先看内核入口函数的位置
static void (*theKernel)(int zero, int arch, u32 params) = 
//#ifdef KERNEL_XIP_BASE
// (void (*)(int, int, u32)) KERNEL_XIP_BASE;
//#else
(void (*)(int, int, u32)) KERNEL_RAM_BASE;
//#endif
static void (*ramKernel)(int zero, int arch, u32 params) =
(void (*)(int, int, u32)) KERNEL_RAM_BASE;
#ifndef CONFIG_NAND_SUPPORT
static void (*xipKernel)(int zero, int arch, u32 params) =
(void (*)(int, int, u32)) KERNEL_XIP_BASE;
#endif 
static int boot_linux(int argc, char *argv[])
{
setup_start_tag();    //构造tag_list,作用是传递必要的信息给内核
setup_memory_tags();    //可用的内存
setup_commandline_tag(argc, argv);    //命令行参数
if (blob_status.load_ramdisk) {
setup_initrd_tag();    //initrd位置 大小
setup_ramdisk_tag();    //ramdisk位置 大小
}
setup_end_tag();    //tag_list 构造结束
……
/* disable subsystems that want to be disabled before kernel boot */
        exit_subsystems();    //关闭subsystems初始化
/* start kernel */
ramKernel(0, ARCH_NUMBER, 0);    //进入内核入口函数,将控制权转给内核
printf("Hey, the kernel returned! This should not happen.\n");
return 0;
}
blob到此结束。
【上篇】
【下篇】

抱歉!评论已关闭.