Android 开发之 ---- bootloader (LK)
LK是什么
???????????LK 是 Little Kernel 它是 appsbl (Applications ARM Boot Loader)流程代碼? ,little kernel 是小內核小操作系統。
?????????? LK 代碼 在 bootable/bootloadler/lk 目錄下
?????????? LK 代碼結構
?????????? +app??????????? // 應用相關
?????????? +arch?????????? // arm 體系?
?????????? +dev??????????? // 設備相關
?????????? +include????? // 頭文件
?????????? +kernel??????? // lk系統相關???
?????????? +platform??? //?相關驅動
?????????? +projiect???? // makefile文件
?????????? +scripts????? // Jtag 腳本
?????????? +target??????? // 具體板子相關
?
LK 流程分析
????????? 在?bootable/bootloadler/lk/arch/arm/ssystem-onesegment.ld 連接文件中 ENTRY(_start)指定 LK 從_start 函數開始,_start 在 lk/arch/crt0.S中 。crt0.S 主要做一些基本的 CPU 的初始化再通過 bl? kmain ;跳轉到 C 代碼中。
????????? kmain 在 lk/kernel/main.c 中
?
kmain()
??????????? kmain 主要做兩件事:1、本身 lk 這個系統模塊的初始化;2、boot 的啟動初始化動作。
??????????? kmain 源碼分析:
???????????? void kmain()
????????? {
???????????1.初始化進程(lk 中的簡單進程)相關結構體。
?????? ? ? ? thread_init_early();
???????????2.做一些如 關閉 cache,使能 mmu 的 arm 相關工作。
??????????? arch_early_init();
?????????? 3.相關平臺的早期初始化
??????????? platform_early_init();
???????????4.現在就一個函數跳轉,初始化UART(板子相關)
??????????? target_early_init();
???????????5.構造函數相關初始化
??????? ? ? call_constructors();
???????????6.lk系統相關的堆棧初始化
??????????? heap_init();
?????????? 7.簡短的初始化定時器對象
??????????? thread_init();
???????????8.lk系統控制器初始化(相關事件初始化)
??????????? dpc_init();
???????????9.初始化lk中的定時器
??????????? timer_init();
???????????10.新建線程入口函數?bootstrap2 用于boot 工作(重點)
?????????? thread_resume(thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
?????????}
???以上與 boot 啟動初始化相關函數是?arch_early_init、? platform_early_init 、bootstrap2,這些是啟動的重點,我們下面慢慢來看。
?
arch_early_init()
?????????體系架構相關的初始化我們一般用的 ARM 體系
?????????1.關閉cache
???????? arch_disable_cache(UCACHE);
?????????2.設置向量基地址(中斷相關)
???????? set_vector_base(MEMBASE);
?????????3.初始化MMU
???????? arm_mmu_init();
?????????4.初始化MMU映射__平臺相關
???????? platform_init_mmu_mappings();
? ? ? ???5.開啟cache ????????
???????? arch_enable_cache(UCACHE)
?????????6.使能 cp10 和 cp11
???????? __asm__ volatile("mrc?? ?p15, 0, %0, c1, c0, 2" : "=r" (val));
???????? val |= (3<<22)|(3<<20);
?????? ? __asm__ volatile("mcr?? ?p15, 0, %0, c1, c0, 2" :: "r" (val));
?
?? ? ???7.設置使能 fpexc 位?(中斷相關)
??? ??? __asm__ volatile("mrc? p10, 7, %0, c8, c0, 0" : "=r" (val));
??????? val |= (1<<30);
??????? __asm__ volatile("mcr? p10, 7, %0, c8, c0, 0" :: "r" (val));
? ? ? ??8.使能循環計數寄存器
??????? __asm__ volatile("mrc?? ?p15, 0, %0, c9, c12, 0" : "=r" (en));
??????? en &= ~(1<<3);?/*循環計算每個周期*/
??????? en |= 1;?
??????? __asm__ volatile("mcr?? ?p15, 0, %0, c9, c12, 0" :: "r" (en));
???????9.使能循環計數器
?????? en = (1<<31);
?????? __asm__ volatile("mcr?? ?p15, 0, %0, c9, c12, 1" :: "r" (en));
?
platform_early_init()
???????平臺相關初始化不同平臺不同的初始化下面是msm7x30
? ? ? ??1.初始化中斷
?? ?? ??platform_init_interrupts();
????????2.初始化定時器
????????platform_init_timer();
?
bootstrap2?
?????????bootstrap2?在kmain的末尾以線程方式開啟。主要分三步:platform_init、target_init、apps_init。
????????1.platform_init
???????????????platform_init 中主要是函數 acpu_clock_init。
?????????????? 在 acpu_clock_init?對 arm11 進行系統時鐘設置,超頻?
????????2.target_init
??????????? ? 針對硬件平臺進行設置。主要對 arm9 和 arm11 的分區表進行整合,初始化flash和讀取FLASH信息
? ? ? ??3.apps_init??
???????????? apps_init 是關鍵,對 LK 中所謂 app 初始化并運行起來,而 aboot_init 就將在這里開始被運行,Android?Linux?內核的加載工作就在 aboot_init 中完成的 。
?
aboot_init
????????1.設置NAND/?EMMC讀取信息頁面大小
????????if (target_is_emmc_boot())
??????? {
????????????????? page_size = 2048;
????????????????? page_mask = page_size - 1;
??????? }
?????? else
?????? {
???????????????? page_size = flash_page_size();
???????????????? page_mask = page_size - 1;
??????? }
????? 2.讀取按鍵信息,判斷是正常開機,還是進入 fastboot ,還是進入recovery 模式
?????? 。。。。。。。。。
??????通過一系列的 if (keys_get_state() == XXX) 判斷
?????? 。。。。。。。。。
????? 3.從 nand 中加載 內核
??????boot_linux_from_flash();
?
????? partition_dump();
????? sz = target_get_max_flash_size();
????? fastboot_init(target_get_scratch_address(), sz);
????? udc_start(); // 開始 USB 協議
?
boot_linux_from_flash
???????????? 主要是內核的加載過程,我們的 boot.img 包含:kernel 頭、kernel、ramdisk、second stage(可以沒有)。
???????????1.讀取boot 頭部
?????????? flash_read(p, offset, raw_header, 2048)?
?????????? offset += 2048;
? ? ? ? ???2.讀取 內核 ???
?????????? memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)
?????????? n = (hdr->kernel_size + (FLASH_PAGE_SIZE - 1)) & (~(FLASH_PAGE_SIZE - 1));
? ? ? ? ?? flash_read(p, offset, (void*) hdr->kernel_addr, n)
?? ? ? ? ? offset += n;
???????????3.讀取 ramdisk
? ? ? ? ?? n = (hdr->ramdisk_size + (FLASH_PAGE_SIZE - 1)) & (~(FLASH_PAGE_SIZE - 1));
?????????? flash_read(p, offset, (void*) hdr->ramdisk_addr, n)
?????????? offset += n;
????????????4.啟動內核,
????????????? ??boot_linux();//在boot_linux 中entry(0,machtype,tags);從kernel加載在內核中的地址開始運行了。
??????
????????到這里LK的啟動過程就結束了。
總結
以上是生活随笔為你收集整理的Android 开发之 ---- bootloader (LK)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于 Python3 的编码
- 下一篇: 微信小程序注意点及快捷键