1、链接脚本:
路径:/bootable/bootloader/lk/arch/arm/system-onesegment.ld
1 OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm","elf32-littlearm")
2 OUTPUT_ARCH(arm)
3
4 ENTRY(_start) //代码从_start开始
5 SECTIONS
6 {
7 . = %MEMBASE%;
8
9 /* text/read-only data */
10 .text.boot : { *(.text.boot) }
11 .text : { *(.text .text.* .glue_7* .gnu.linkonce.t.*) } =0x9090
2、_start汇编入口:
路径:/bootable/bootloader/lk/arch/arm/crt0.S
27 .section ".text.boot"
28 .globl _start
29_start:
30 b reset
31 b arm_undefined
32 b arm_syscall
33 b arm_prefetch_abort
34 b arm_data_abort
35 b arm_reserved
36 b arm_irq
37 b arm_fiq
38
……………………
158 blt .L__copy_loop //copy bootloader到内存
159
160 .L__do_bss:
161 /* clear out the bss */
162 ldr r0, =__bss_start
163 ldr r1, =_end
164 mov r2, #0
165 .L__bss_loop:
166 cmp r0, r1
167 strlt r2, [r0], #4
168 blt .L__bss_loop
169
170 #ifdef ARM_CPU_CORTEX_A8
171 DSB
172 ISB
173 #endif
174
175 bl kmain //跳到kmain出执行
176 b .
2、kmain函数:
路径:/bootable/bootloader/lk/kernel/main.c
启动bootstrap2线程初始化系统:
voidkmain(void)
{
// get us into some sort of thread context
thread_init_early();
// early arch stuff
arch_early_init();
// do any super early platform initialization
platform_early_init();
// do any super early target initialization
target_early_init();
dprintf(INFO, "welcome to lk\n\n");
bs_set_timestamp(BS_BL_START);
// deal with any static constructors
dprintf(SPEW, "calling constructors\n");
call_constructors();
// bring up the kernel heap
dprintf(SPEW, "initializing heap\n");
heap_init();
// initialize the threading system
dprintf(SPEW, "initializing threads\n");
thread_init();
// initialize the dpc system
dprintf(SPEW, "initializing dpc\n");
dpc_init();
// initialize kernel timers
dprintf(SPEW, "initializing timers\n");
timer_init();
#if(!ENABLE_NANDWRITE)
// create a thread tocomplete system initialization
dprintf(SPEW, "creating bootstrap completion thread\n");
thread_resume(thread_create("bootstrap2",&bootstrap2, NULL,
DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
// enable interrupts
exit_critical_section();
// become the idle thread
thread_become_idle();
#else
bootstrap_nandwrite();
#endif
}
3、bootstrap2线程:
路径:/bootable/bootloader/lk/kernel/main.c
staticint bootstrap2(void *arg)
{
dprintf(SPEW, "top of bootstrap2()\n");
arch_init();
// XXX put this somewhere else
#ifWITH_LIB_BIO
bio_init();
#endif
#ifWITH_LIB_FS
fs_init();
#endif
// initialize the rest of the platform
dprintf(SPEW, "initializing platform\n");
platform_init();
// initialize the target
dprintf(SPEW, "initializing target\n");
target_init();
dprintf(SPEW, "calling apps_init()\n");
apps_init();
return 0;
}
其中,target_init函数:
voidtarget_init(void)
{
uint32_t base_addr;
uint8_t slot;
dprintf(INFO, "target_init()\n");
//初始化SPMI控制器
spmi_init(PMIC_ARB_CHANNEL_NUM, PMIC_ARB_OWNER_ID);
//按键初始化,设置音量上下键
target_keystatus();
//初始化MMC
/* Trying Slot 1*/
slot = 1;
base_addr = mmc_sdc_base[slot - 1];
if (mmc_boot_main(slot, base_addr))
{
/* Trying Slot 2 next*/
slot = 2;
base_addr = mmc_sdc_base[slot - 1];
if (mmc_boot_main(slot, base_addr)) {
dprintf(CRITICAL, "mmc init failed!");
ASSERT(0);
}
}
if (target_use_signed_kernel())
target_crypto_init_params();
}
其中,apps_init()函数:
路径:/bootable/bootloader/lk/app/app.c
voidapps_init(void)
{
const struct app_descriptor *app;
/* call all the init routines */
for (app = &__apps_start; app != &__apps_end; app++) {
if (app->init)
app->init(app);
}
/* start any that want to start on boot */
for (app = &__apps_start; app != &__apps_end; app++) {
if (app->entry && (app->flags &APP_FLAG_DONT_START_ON_BOOT) == 0) {
start_app(app);
}
}
}
APP_START(aboot)
.init = aboot_init,
APP_END
通过“.init = aboot_init,”可以看出,“app->init(app);”会调用aboot_init函数。
4、aboot_init函数:
路径:/bootable/bootloader/lk/app/aboot/aboot.c
aboot_init函数分析:
(1)设置page size
/* Setuppage size information for nand/emmc reads */
if (target_is_emmc_boot())
{
//eMMC的page size=2k
page_size = 2048;
page_mask = page_size - 1;
}
else
{
page_size = flash_page_size();
page_mask = page_size - 1;
}
(2)如果kernel签名则读取device信息
if(target_use_signed_kernel())
{
read_device_info(&device);
}
(3)读取UDC串号
target_serialno((unsignedchar *) sn_buf);
dprintf(SPEW,"serial number: %s\n",sn_buf);
surf_udc_device.serialno = sn_buf;
(4)读取重启原因
reboot_mode=check_reboot_mode();
if (reboot_mode == RECOVERY_MODE) {
boot_into_recovery = 1;
} else if(reboot_mode == FASTBOOT_MODE) {
goto fastboot;
}
(5)调用boot_linux_from_mmc函数启动kernel
if(target_is_emmc_boot())
{
if(emmc_recovery_init())
dprintf(ALWAYS,"error in emmc_recovery_init\n");
if(target_use_signed_kernel())
{
if((device.is_unlocked) || (device.is_tampered))
{
#ifdef TZ_TAMPER_FUSE
set_tamper_fuse_cmd();
#endif
#if USE_PCOM_SECBOOT
set_tamper_flag(device.is_tampered);
#endif
}
}
boot_linux_from_mmc();
}
else
{
recovery_init();
#ifUSE_PCOM_SECBOOT
if((device.is_unlocked) || (device.is_tampered))
set_tamper_flag(device.is_tampered);
#endif
boot_linux_from_flash();
}
5、boot_linux_from_mmc函数:
(1)验证是否为unified_boot
//boot image header在emmc中地址
uhdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
//验证uhdr->magic是否为"ANDROID!"
if (!memcmp(uhdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE))
{
dprintf(INFO, "Unified boot method!\n");
hdr = uhdr;
goto unified_boot;
}
(2)验证boot或recovery分区是否存在
if (!boot_into_recovery) {
index =partition_get_index("boot");
ptn =partition_get_offset(index);
if(ptn == 0) {
dprintf(CRITICAL, "ERROR: No boot partition found\n");
return -1;
}
}
else {
index =partition_get_index("recovery");
ptn =partition_get_offset(index);
if(ptn == 0) {
dprintf(CRITICAL, "ERROR: No recovery partition found\n");
return -1;
}
}
(3)读取2K数据到buf中
//page_size=2048
if (mmc_read(ptn +offset, (unsigned int *)buf, page_size)) {
dprintf(CRITICAL, "ERROR: Cannot read boot imageheader\n");
return -1;
}
(4)验证boot.img或recovery.img的BOOT_MAGIC是否为"ANDROID!"
example :
boot.img的头信息如下:
magic[BOOT_MAGIC_SIZE]="ANDROID!"
kernel_size: 0x0052 3448
kernel_addr: 0x0000 8000 2K
ramdisk_size: 0x0005 9D64
ramdisk_addr: 0x0200 0000
second_size: 0x0000 0000
second_addr: 0xF000 0000
tags_addr: 0x01E0 0000
page_size: 0x0000 0800=2048=2K
dt_size: 0x000CD000 820K
if(memcmp(hdr->magic, BOOT_MAGIC,BOOT_MAGIC_SIZE)) {
dprintf(CRITICAL, "ERROR: Invalid boot image header\n");
return -1;
}
(5)验证hdr->page_size是否为2K
//hdr->page_size==2048?
if (hdr->page_size && (hdr->page_size != page_size)) {
page_size = hdr->page_size;
page_mask = page_size - 1;
}
(6)检查默认地址是否存在kernel/ramdisk/tags address
/*
* Update thekernel/ramdisk/tags address if the boot image header
* has default values, thesedefault values come from mkbootimg when
* the boot image is flashedusing fastboot flash:raw
*/
update_ker_tags_rdisk_addr(hdr);
(7)将物理kernel/ramdisk/tags address转换为虚拟地址
/* Get virtual addresses since the hdr saves physicaladdresses. */
hdr->kernel_addr = VA((addr_t)(hdr->kernel_addr));
hdr->ramdisk_addr = VA((addr_t)(hdr->ramdisk_addr));
hdr->tags_addr = VA((addr_t)(hdr->tags_addr));
(8)加载kernel
if(target_use_signed_kernel() && (!device.is_unlocked)&& (!device.is_tampered))
{
…………..
…………..
}
else{
//获取kernel/ramdisk/second的长度
kernel_actual =ROUND_TO_PAGE(hdr->kernel_size, page_mask);
ramdisk_actual = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask);
second_actual =ROUND_TO_PAGE(hdr->second_size, page_mask);
/* Load kernel */ //从EMMC中读取实际kernel
if (mmc_read(ptn + offset, (void *)hdr->kernel_addr,kernel_actual)) {
dprintf(CRITICAL, "ERROR: Cannot read kernel image\n");
return -1;
}
//从EMMC中读取实际RAMDISK
offset += kernel_actual;
/* Load ramdisk */
if(ramdisk_actual != 0)
{
if (mmc_read(ptn + offset, (void *)hdr->ramdisk_addr, ramdisk_actual))
{
dprintf(CRITICAL, "ERROR: Cannot read ramdisk image\n");
return -1;
}
}
offset += ramdisk_actual;
dprintf(INFO, "Loading boot image (%d): done\n",
kernel_actual +ramdisk_actual);
//如果Second image存在则不加载
if(hdr->second_size != 0){
offset += second_actual;
/* Second image loading not implemented. */
ASSERT(0);
}
//读取page_size (2K)的devicetree table数据到dt_buf中
#if DEVICE_TREE
if(hdr->dt_size != 0) {
/* Read the device tree table into buffer */
if(mmc_read(ptn +offset,(unsigned int *) dt_buf, page_size))
{
dprintf(CRITICAL,"ERROR: Cannot read the Device Tree Table\n");
return -1;
}
//device tree table指向dt_buf
table = (struct dt_table*)dt_buf;
/* Restriction that thedevice tree entry table should be less than a page*/
ASSERT(((table->num_entries * sizeof(struct dt_entry))+
DEV_TREE_HEADER_SIZE) < hdr->page_size);
//检查devicetree table 的MAGIC和VERSION
//DEV_TREE_MAGIC: 0x54444351 /*"QCDT" */
//DEV_TREE_VERSION:1
/*Validate the device tree table header */
if((table->magic!= DEV_TREE_MAGIC) && (table->version !=
DEV_TREE_VERSION)) {
dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table\n");
return -1;
}
boot.img镜像导出device tree table header如下:offset=0x57e000
table->magic=0x54444351
table->version=0x01
table->num_entries=0x15
//获取当前平台device tree table的入口点
/* Calculate the offset of device tree within device tree table */
if((dt_entry_ptr = dev_tree_get_entry_ptr(table))== NULL){
dprintf(CRITICAL, "ERROR: Getting device tree addressfailed\n");
return -1;
}
//将eMMC中的devicetree读入hdr->tags_addr中
/* Read device device tree in the "tags_add */
if(mmc_read(ptn + offset +dt_entry_ptr->offset,
(void *)hdr->tags_addr, dt_entry_ptr->size)) {
dprintf(CRITICAL, "ERROR: Cannot read device tree\n");
return -1;
}
example:
offset=0x57e000
dt_entry_ptr->offset=0x4c800
offset +dt_entry_ptr->offset=0x5ca800
6、boot_linux函数:
(1)entry指向kernel内存的物理地址
(2)获取tags和ramdisk的物理地址
(3)更新cmdline
(4)更新device_tree
6、update_device_tree函数:
(1)检查device tree header: 4*10字节
串口读取数据如下:
[1170]fdt_magic(fdt)=0xd00dfeed.......
[1170]fdt_version(fdt)=0x11.......
[1180]fdt_last_comp_version(fdt)=0x10 .......
(2)为创建新节点和属性添加空间:
(3)获取/memory节点的offset:/memory_offset=0x11c
/memory:0x005ca958
/:0x005ca83c
(4)将RAM分区条目添加到devicetree中:
(5)获取/chosen节点的offset:/chosen_offset=0xa8
/chosen: 0x005ca8e4
/:0x005ca83c
(6)将cmdline添加到bootargs属性节点中:
(7)将ramdisk开始地址添加到linux,initrd-start属性节点中:
(8)将ramdisk结束地址添加到linux,initrd-end属性节点中:
7、启动kernel
http://blog.youkuaiyun.com/xichangbao/article/details/51484138