分类:Android 941人阅读 评论(0) 收藏 举报 android descriptor thread timer list linux

http://hi.baidu.com/ktpeng/blog/item/9872d589666b0d03c8fc7a96.html


(L)ittle (K)ernelbootloader

1.主要功能,红色部分是android特有的一些功能,如fastboot,recovery模式等:

* Variety of nand devices for bootup

* USB driver to enable upgrading images over usb during development

* Keypad driver to enable developers enter ‘fastboot’ mode for image upgrades

* Display driver for debugging and splash screen

* Enable Android recovery image and image upgrades

2.配置dram内存大小,供linux kernel使用

The memory tags can be customized inlk/target/<target_name>/atags.c

3.fastboot模式,可以自行打开或者关闭

如,在boot中关闭按键或者usb 驱动,都可以达到此目的

相关文件

k/app/aboot/fastboot.c

lk/app/aboot/aboot.c

4.MTD block setting

可以配置各个mtd image 分区在如下文件中
lk\target\tcc8900_evm\init.c
static struct ptentry board_part_list[]

5.打开或者关闭splash screen in the bootloader

DISPLAY_SPLASH_SCREEN功能可以来打开关闭

开机时候,boot会从’splash’ MTD分区中读取原始的文件到framebuffer中显示,所以也需要加载display 的驱动


*****************************************************************************************************************************************************************************************


http://blog.csdn.net/hankhanti/article/details/6133570

Android Boot loader 的 code 在 bootable/bootloader/lk 底下, LK 是 Little Kernel 的缩写, 是 andriod bootloader 的核心精神.

入口函数在 kernel/main.c 中的 kmain(), 以下就来读读这一段 code.

view plain print ?
  1. voidkmain(void)
  2. {
  3. //getusintosomesortofthreadcontext
  4. thread_init_early();
  5. //earlyarchstuff
  6. arch_early_init();
  7. //doanysuperearlyplatforminitialization
  8. platform_early_init();
  9. //doanysuperearlytargetinitialization
  10. target_early_init();
  11. dprintf(INFO,"welcometolk/n/n");
  12. //dealwithanystaticconstructors
  13. dprintf(SPEW,"callingconstructors/n");
  14. call_constructors();
  15. //bringupthekernelheap
  16. dprintf(SPEW,"initializingheap/n");
  17. heap_init();
  18. //initializethethreadingsystem
  19. dprintf(SPEW,"initializingthreads/n");
  20. thread_init();
  21. //initializethedpcsystem
  22. dprintf(SPEW,"initializingdpc/n");
  23. dpc_init();
  24. //initializekerneltimers
  25. dprintf(SPEW,"initializingtimers/n");
  26. timer_init();
  27. #if(!ENABLE_NANDWRITE)
  28. //createathreadtocompletesysteminitialization
  29. dprintf(SPEW,"creatingbootstrapcompletionthread/n");
  30. thread_resume(thread_create("bootstrap2",&bootstrap2,NULL,DEFAULT_PRIORITY,DEFAULT_STACK_SIZE));
  31. //enableinterrupts
  32. exit_critical_section();
  33. //becometheidlethread
  34. thread_become_idle();
  35. #else
  36. bootstrap_nandwrite();
  37. #endif
  38. }

In include/debug.h: 我们可以看到 dprintf 的第一个参数是代表 debug level.

view plain print ?
  1. /*debuglevels*/
  2. #defineCRITICAL0
  3. #defineALWAYS0
  4. #defineINFO1
  5. #defineSPEW2

In include/debug.h:

view plain print ?
  1. #definedprintf(level,x...)do{if((level)<=DEBUGLEVEL){_dprintf(x);}}while(0)

所以 dprintf 会依 DEBUGLEVEL 来判断是否输出信息.

来看第一个 call 的函数: thread_init_early, define in thread.c

view plain print ?
  1. voidthread_init_early(void)
  2. {
  3. inti;
  4. /*initializetherunqueues*/
  5. for(i=0;i<NUM_PRIORITIES;i++)
  6. list_initialize(&run_queue[i]);
  7. /*initializethethreadlist*/
  8. list_initialize(&thread_list);
  9. /*createathreadtocoverthecurrentrunningstate*/
  10. thread_t*t=&bootstrap_thread;
  11. init_thread_struct(t,"bootstrap");
  12. /*halfconstructthisthread,sincewe'realreadyrunning*/
  13. t->priority=HIGHEST_PRIORITY;
  14. t->state=THREAD_RUNNING;
  15. t->saved_critical_section_count=1;
  16. list_add_head(&thread_list,&t->thread_list_node);
  17. current_thread=t;
  18. }

#define NUM_PRIORITIES 32 in include/kernel/thread.h

list_initialize() defined in include/list.h: initialized a list

view plain print ?
  1. staticinlinevoidlist_initialize(structlist_node*list)
  2. {
  3. list->prev=list->next=list;
  4. }

run_queue 是static struct list_node run_queue[NUM_PRIORITIES]

thread_list 是static struct list_node thread_list

再来要 call 的函数是: arch_early_init() defined inarch/arm/arch.c

view plain print ?
  1. voidarch_early_init(void)
  2. {
  3. /*turnoffthecache*/
  4. arch_disable_cache(UCACHE);
  5. /*setthevectorbasetoourexceptionvectorssowedontneedtodoublemapat0*/
  6. #ifARM_CPU_CORTEX_A8
  7. set_vector_base(MEMBASE);
  8. #endif
  9. #ifARM_WITH_MMU
  10. arm_mmu_init();
  11. platform_init_mmu_mappings();
  12. #endif
  13. /*turnthecachebackon*/
  14. arch_enable_cache(UCACHE);
  15. #ifARM_WITH_NEON
  16. /*enablecp10andcp11*/
  17. uint32_tval;
  18. __asm__volatile("mrcp15,0,%0,c1,c0,2":"=r"(val));
  19. val|=(3<<22)|(3<<20);
  20. __asm__volatile("mcrp15,0,%0,c1,c0,2"::"r"(val));
  21. /*setenablebitinfpexc*/
  22. val=(1<<30);
  23. __asm__volatile("mcrp10,7,%0,c8,c0,0"::"r"(val));
  24. #endif
  25. }

现代操作系统普遍采用虚拟内存管理(Virtual Memory Management)机制,这需要处理器中的MMU(Memory Management Unit,

内存管理单元)提供支持。

CPU执行单元发出的内存地址将被MMU截获,从CPU到MMU的地址称为虚拟地址(Virtual Address,以下简称VA),而MMU将这个地

址翻译成另一个地址发到CPU芯片的外部地址引脚上,也就是将VA映射成PA

MMU将VA映射到PA是以页(Page)为单位的,32位处理器的页尺寸通常是4KB。例如,MMU可以通过一个映射项将VA的一页

0xb7001000~0xb7001fff映射到PA的一页0x2000~0x2fff,如果CPU执行单元要访问虚拟地址0xb7001008,则实际访问到的物理地

址是0x2008。物理内存中的页称为物理页面或者页帧(Page Frame)。虚拟内存的哪个页面映射到物理内存的哪个页帧是通过页

表(Page Table)来描述的,页表保存在物理内存中,MMU会查找页表来确定一个VA应该映射到什么PA。


操作系统和MMU是这样配合的:

1. 操作系统在初始化或分配、释放内存时会执行一些指令在物理内存中填写页表,然后用指令设置MMU,告诉MMU页表在物理内存中

的什么位置。

2. 设置好之后,CPU每次执行访问内存的指令都会自动引发MMU做查表和地址转换操作,地址转换操作由硬件自动完成,不需要用指令

控制MMU去做。

MMU除了做地址转换之外,还提供内存保护机制。各种体系结构都有用户模式(User Mode)和特权模式(Privileged Mode)之分,

操作系统可以在页表中设置每个内存页面的访问权限,有些页面不允许访问,有些页面只有在CPU处于特权模式时才允许访问,有些页面

在用户模式和特权模式都可以访问,访问权限又分为可读、可写和可执行三种。这样设定好之后,当CPU要访问一个VA时,MMU会检查

CPU当前处于用户模式还是特权模式,访问内存的目的是读数据、写数据还是取指令,如果和操作系统设定的页面权限相符,就允许访

问,把它转换成PA,否则不允许访问,产生一个异常(Exception)


常见的 segmentation fault 产生的原因:

用户程序要访问一段 VA, 经 MMU 检查后无权访问, MMU 会产生异常, CPU 从用户模式切换到特权模式, 跳转到内核代码中执行异常服务程序.

内核就会把这个异常解释为 segmentation fault, 将引发异常的程序终止.

简单的讲一下 NEON:NEON technology can accelerate multimedia and signal processing algorithms such as video encode/decode,

2D/3D graphics, gaming, audio and speech processing,image processing, telephony, and sound synthesis.

platform_early_init() defined in platform/<your-platform>/platform.c

view plain print ?
  1. voidplatform_early_init(void)
  2. {
  3. uart_init();
  4. platform_init_interrupts();
  5. platform_init_timer();
  6. }

uart_init.c defined in platform/<your-platform>/uart.c 所有用到的变数,也都定义在 uart.c

view plain print ?
  1. voiduart_init(void)
  2. {
  3. uwr(0x0A,UART_CR);/*disableTXandRX*/
  4. uwr(0x30,UART_CR);/*reseterrorstatus*/
  5. uwr(0x10,UART_CR);/*resetreceiver*/
  6. uwr(0x20,UART_CR);/*resettransmitter*/
  7. #ifPLATFORM_QSD8K
  8. /*TCXO*/
  9. uwr(0x06,UART_MREG);
  10. uwr(0xF1,UART_NREG);
  11. uwr(0x0F,UART_DREG);
  12. uwr(0x1A,UART_MNDREG);
  13. #else
  14. /*TCXO/4*/
  15. uwr(0xC0,UART_MREG);
  16. uwr(0xAF,UART_NREG);
  17. uwr(0x80,UART_DREG);
  18. uwr(0x19,UART_MNDREG);
  19. #endif
  20. uwr(0x10,UART_CR);/*resetRX*/
  21. uwr(0x20,UART_CR);/*resetTX*/
  22. uwr(0x30,UART_CR);/*reseterrorstatus*/
  23. uwr(0x40,UART_CR);/*resetRXbreak*/
  24. uwr(0x70,UART_CR);/*rest?*/
  25. uwr(0xD0,UART_CR);/*reset*/
  26. uwr(0x7BF,UART_IPR);/*staletimeout=630*bitrate*/
  27. uwr(0,UART_IMR);
  28. uwr(115,UART_RFWR);/*RXwatermark=58*2-1*/
  29. uwr(10,UART_TFWR);/*TXwatermark*/
  30. uwr(0,UART_RFWR);
  31. uwr(UART_CSR_115200,UART_CSR);
  32. uwr(0,UART_IRDA);
  33. uwr(0x1E,UART_HCR);
  34. //uwr(0x7F4,UART_MR1);/*RFS/CTS/500chrRFR*/
  35. uwr(16,UART_MR1);
  36. uwr(0x34,UART_MR2);/*8N1*/
  37. uwr(0x05,UART_CR);/*enableTX&RX*/
  38. uart_ready=1;
  39. }

platform_init_interrupts: defined in platform/msm8x60/interrupts.c

view plain print ?
  1. voidplatform_init_interrupts(void)
  2. {
  3. platform_gic_dist_init();
  4. platform_gic_cpu_init();
  5. }

GIC 指的是 Generic Interrupt Controller. The gic-cpu and gic-dist are two subcomponents of GIC.

Devices are wired to the git-dist which is in charge of distributing interrupts to the gic-cpu (per cpu IRQ IF).

platform_init_timer(): defined in platform/<your-platform>/timer.c

view plain print ?
  1. voidplatform_init_timer(void)
  2. {
  3. writel(0,DGT_ENABLE);
  4. }

DGT: Digital Game Timer: presents the countdowns of two players, it is also called chess timer or chess clock.

target_early_init(): defined in target/init.c

view plain print ?
  1. /*
  2. *defaultimplementationsoftheseroutines,ifthetargetcode
  3. *choosesnottoimplement.
  4. */
  5. __WEAKvoidtarget_early_init(void)
  6. {
  7. }
  8. __WEAKvoidtarget_init(void)
  9. {
  10. }

call_constructors() is defined in kernel/main.c:

view plain print ?
  1. staticvoidcall_constructors(void)
  2. {
  3. void**ctor;
  4. ctor=&__ctor_list;
  5. while(ctor!=&__ctor_end){
  6. void(*func)(void);
  7. func=(void(*)())*ctor;
  8. func();
  9. ctor++;
  10. }
  11. }

heap_init is defined in lib/heap/heap.c:

view plain print ?
  1. voidheap_init(void)
  2. {
  3. LTRACE_ENTRY;
  4. //settheheaprange
  5. theheap.base=(void*)HEAP_START;
  6. theheap.len=HEAP_LEN;
  7. LTRACEF("base%psize%zdbytes/n",theheap.base,theheap.len);
  8. //initializethefreelist
  9. list_initialize(&theheap.free_list);
  10. //createaninitialfreechunk
  11. heap_insert_free_chunk(heap_create_free_chunk(theheap.base,theheap.len));
  12. //dumpheapinfo
  13. //heap_dump();
  14. //dprintf(INFO,"runningheaptests/n");
  15. //heap_test();
  16. }

thread_init is defined in kernel/thread.c but nothing coded, 先记下.

view plain print ?
  1. voidthread_init(void)
  2. {
  3. }

dpc_init() is defined in kernel/dpc.c:

view plain print ?
  1. voiddpc_init(void)
  2. {
  3. event_init(&dpc_event,false,0);
  4. thread_resume(thread_create("dpc",&dpc_thread_routine,NULL,DPC_PRIORITY,DEFAULT_STACK_SIZE));
  5. }

dpc 为 Delayed Procedure Call 延迟过程调用的缩写.

timer_init() is defined in kernel/timer.c:

view plain print ?
  1. voidtimer_init(void)
  2. {
  3. list_initialize(&timer_queue);
  4. /*registerforaperiodictimertick*/
  5. platform_set_periodic_timer(timer_tick,NULL,10);/*10ms*/
  6. }

执行 thread_resume 或是 bootstrap_nandwrite

view plain print ?
  1. #if(!ENABLE_NANDWRITE)
  2. //createathreadtocompletesysteminitialization
  3. dprintf(SPEW,"creatingbootstrapcompletionthread/n");
  4. thread_resume(thread_create("bootstrap2",&bootstrap2,NULL,DEFAULT_PRIORITY,DEFAULT_STACK_SIZE));
  5. //enableinterrupts
  6. exit_critical_section();
  7. //becometheidlethread
  8. thread_become_idle();
  9. #else
  10. bootstrap_nandwrite();
  11. #endif

In kermel/main.c:

view plain print ?
  1. staticintbootstrap2(void*arg)
  2. {
  3. dprintf(SPEW,"topofbootstrap2()/n");
  4. arch_init();
  5. //initializetherestoftheplatform
  6. dprintf(SPEW,"initializingplatform/n");
  7. platform_init();
  8. //initializethetarget
  9. dprintf(SPEW,"initializingtarget/n");
  10. target_init();
  11. dprintf(SPEW,"callingapps_init()/n");
  12. apps_init();
  13. return0;
  14. }
  15. #if(ENABLE_NANDWRITE)
  16. voidbootstrap_nandwrite(void)
  17. {
  18. dprintf(SPEW,"topofbootstrap2()/n");
  19. arch_init();
  20. //initializetherestoftheplatform
  21. dprintf(SPEW,"initializingplatform/n");
  22. platform_init();
  23. //initializethetarget
  24. dprintf(SPEW,"initializingtarget/n");
  25. target_init();
  26. dprintf(SPEW,"callingnandwrite_init()/n");
  27. nandwrite_init();
  28. return0;
  29. }
  30. #endif

continue to see apps_init():app/app.c:void apps_init(void)

view plain print ?
  1. #include<app.h>
  2. #include<kernel/thread.h>
  3. externconststructapp_descriptor__apps_start;
  4. externconststructapp_descriptor__apps_end;
  5. staticvoidstart_app(conststructapp_descriptor*app);
  6. /*onetimesetup*/
  7. voidapps_init(void)
  8. {
  9. conststructapp_descriptor*app;
  10. /*callalltheinitroutines*/
  11. for(app=&__apps_start;app!=&__apps_end;app++){
  12. if(app->init)
  13. app->init(app);
  14. }
  15. /*startanythatwanttostartonboot*/
  16. for(app=&__apps_start;app!=&__apps_end;app++){
  17. if(app->entry&&(app->flags&APP_FLAG_DONT_START_ON_BOOT)==0){
  18. start_app(app);
  19. }
  20. }
  21. }
  22. staticintapp_thread_entry(void*arg)
  23. {
  24. conststructapp_descriptor*app=(conststructapp_descriptor*)arg;
  25. app->entry(app,NULL);
  26. return0;
  27. }
  28. staticvoidstart_app(conststructapp_descriptor*app)
  29. {
  30. printf("startingapp%s/n",app->name);
  31. thread_resume(thread_create(app->name,&app_thread_entry,(void*)app,DEFAULT_PRIORITY,DEFAULT_STACK_SIZE));
  32. }

至于会有那些 app 被放入 boot thread section, 则定义在 include/app.h 中的 APP_START(appname)

view plain print ?
  1. #defineAPP_START(appname)structapp_descriptor_app_##appname__SECTION(".apps")={.name=#appname,
  2. #defineAPP_END};

在 app 中只要像 app/aboot/aboot.c 指定就会在 bootloader bootup 时放入 thread section 中被执行.

view plain print ?
  1. APP_START(aboot)
  2. .init=aboot_init,
  3. APP_END

在我的 bootloader 中有 app/aboot/aboot.c, app/tests/tests.c, app/shell/shell.c, 及 app/stringtests/string_tests.c 皆有此声明.

接下来关注: aboot.c 中的 aboot_init()

view plain print ?
  1. voidaboot_init(conststructapp_descriptor*app)
  2. {
  3. unsignedreboot_mode=0;
  4. unsigneddisp_init=0;
  5. unsignedusb_init=0;
  6. //test_ram();
  7. /*Setuppagesizeinformationfornand/emmcreads*/
  8. if(target_is_emmc_boot())
  9. {
  10. page_size=2048;
  11. page_mask=page_size-1;
  12. }
  13. else
  14. {
  15. page_size=flash_page_size();
  16. page_mask=page_size-1;
  17. }
  18. /*Displaysplashscreenifenabled*/
  19. #ifDISPLAY_SPLASH_SCREEN
  20. display_init();
  21. dprintf(INFO,"Diplayinitialized/n");
  22. disp_init=1;
  23. diplay_image_on_screen();
  24. #endif
  25. /*Checkifweshoulddosomethingotherthanbootingup*/
  26. if(keys_get_state(KEY_HOME)!=0)
  27. boot_into_recovery=1;
  28. if(keys_get_state(KEY_BACK)!=0)
  29. gotofastboot;
  30. if(keys_get_state(KEY_CLEAR)!=0)
  31. gotofastboot;
  32. #ifNO_KEYPAD_DRIVER
  33. /*Withnokeypadimplementation,checkthestatusofUSBconnection.*/
  34. /*IfUSBisconnectedthengointofastbootmode.*/
  35. usb_init=1;
  36. udc_init(&surf_udc_device);
  37. if(usb_cable_status())
  38. gotofastboot;
  39. #endif
  40. init_vol_key();
  41. if(voldown_press())
  42. gotofastboot;
  43. reboot_mode=check_reboot_mode();
  44. if(reboot_mode==RECOVERY_MODE){
  45. boot_into_recovery=1;
  46. }elseif(reboot_mode==FASTBOOT_MODE){
  47. gotofastboot;
  48. }
  49. if(target_is_emmc_boot())
  50. {
  51. boot_linux_from_mmc();
  52. }
  53. else
  54. {
  55. recovery_init();
  56. boot_linux_from_flash();
  57. }
  58. dprintf(CRITICAL,"ERROR:Couldnotdonormalboot.Reverting"
  59. "tofastbootmode./n");
  60. fastboot:
  61. if(!usb_init)
  62. udc_init(&surf_udc_device);
  63. fastboot_register("boot",cmd_boot);
  64. if(target_is_emmc_boot())
  65. {
  66. fastboot_register("flash:",cmd_flash_mmc);
  67. fastboot_register("erase:",cmd_erase_mmc);
  68. }
  69. else
  70. {
  71. fastboot_register("flash:",cmd_flash);
  72. fastboot_register("erase:",cmd_erase);
  73. }
  74. fastboot_register("continue",cmd_continue);
  75. fastboot_register("reboot",cmd_reboot);
  76. fastboot_register("reboot-bootloader",cmd_reboot_bootloader);
  77. fastboot_publish("product",TARGET(BOARD));
  78. fastboot_publish("kernel","lk");
  79. fastboot_init(target_get_scratch_address(),120*1024*1024);
  80. udc_start();
  81. target_battery_charging_enable(1,0);
  82. }

target_is_emmc_boot() is defined in target/init.c: _EMMC_BOOT 是 compiler 时的 flags

view plain print ?
  1. __WEAKinttarget_is_emmc_boot(void)
  2. {
  3. #if_EMMC_BOOT
  4. return1;
  5. #else
  6. return0;
  7. #endif
  8. }

check_reboot_mode is defined in target/<your-platform>/init.c:

view plain print ?
  1. unsignedcheck_reboot_mode(void)
  2. {
  3. unsignedrestart_reason=0;
  4. void*restart_reason_addr=0x401FFFFC;
  5. /*Readrebootreasonandscrubit*/
  6. restart_reason=readl(restart_reason_addr);
  7. writel(0x00,restart_reason_addr);
  8. returnrestart_reason;
  9. }

reboot mode in bootloader:

view plain print ?
  1. #defineRECOVERY_MODE0x77665502
  2. #defineFASTBOOT_MODE0x77665500

再来就会执行boot_linux_from_mmc():

view plain print ?
  1. intboot_linux_from_mmc(void)
  2. {
  3. structboot_img_hdr*hdr=(void*)buf;
  4. structboot_img_hdr*uhdr;
  5. unsignedoffset=0;
  6. unsignedlonglongptn=0;
  7. unsignedn=0;
  8. constchar*cmdline;
  9. uhdr=(structboot_img_hdr*)EMMC_BOOT_IMG_HEADER_ADDR;
  10. if(!memcmp(uhdr->magic,BOOT_MAGIC,BOOT_MAGIC_SIZE)){
  11. dprintf(INFO,"Unifiedbootmethod!/n");
  12. hdr=uhdr;
  13. gotounified_boot;
  14. }
  15. if(!boot_into_recovery)
  16. {
  17. ptn=mmc_ptn_offset("boot");
  18. if(ptn==0){
  19. dprintf(CRITICAL,"ERROR:Nobootpartitionfound/n");
  20. return-1;
  21. }
  22. }
  23. else
  24. {
  25. ptn=mmc_ptn_offset("recovery");
  26. if(ptn==0){
  27. dprintf(CRITICAL,"ERROR:Norecoverypartitionfound/n");
  28. return-1;
  29. }
  30. }
  31. if(mmc_read(ptn+offset,(unsignedint*)buf,page_size)){
  32. dprintf(CRITICAL,"ERROR:Cannotreadbootimageheader/n");
  33. return-1;
  34. }
  35. if(memcmp(hdr->magic,BOOT_MAGIC,BOOT_MAGIC_SIZE)){
  36. dprintf(CRITICAL,"ERROR:Invaledbootimageheader/n");
  37. return-1;
  38. }
  39. if(hdr->page_size&&(hdr->page_size!=page_size)){
  40. page_size=hdr->page_size;
  41. page_mask=page_size-1;
  42. }
  43. offset+=page_size;
  44. n=ROUND_TO_PAGE(hdr->kernel_size,page_mask);
  45. if(mmc_read(ptn+offset,(void*)hdr->kernel_addr,n)){
  46. dprintf(CRITICAL,"ERROR:Cannotreadkernelimage/n");
  47. return-1;
  48. }
  49. offset+=n;
  50. n=ROUND_TO_PAGE(hdr->ramdisk_size,page_mask);
  51. if(mmc_read(ptn+offset,(void*)hdr->ramdisk_addr,n)){
  52. dprintf(CRITICAL,"ERROR:Cannotreadramdiskimage/n");
  53. return-1;
  54. }
  55. offset+=n;
  56. unified_boot:
  57. dprintf(INFO,"/nkernel@%x(%dbytes)/n",hdr->kernel_addr,
  58. hdr->kernel_size);
  59. dprintf(INFO,"ramdisk@%x(%dbytes)/n",hdr->ramdisk_addr,
  60. hdr->ramdisk_size);
  61. if(hdr->cmdline[0]){
  62. cmdline=(char*)hdr->cmdline;
  63. }else{
  64. cmdline=DEFAULT_CMDLINE;
  65. }
  66. dprintf(INFO,"cmdline='%s'/n",cmdline);
  67. dprintf(INFO,"/nBootingLinux/n");
  68. boot_linux((void*)hdr->kernel_addr,(void*)TAGS_ADDR,
  69. (constchar*)cmdline,board_machtype(),
  70. (void*)hdr->ramdisk_addr,hdr->ramdisk_size);
  71. return0;
  72. }

mmc_read() is defined in platform/<your-platform>/mmc.c:

view plain print ?
  1. unsignedintmmc_read(unsignedlonglongdata_addr,unsignedint*out,unsignedintdata_len)
  2. {
  3. intval=0;
  4. val=mmc_boot_read_from_card(&mmc_host,&mmc_card,data_addr,data_len,out);
  5. returnval;
  6. }

boot_linux(): 启动 Linux, 看看函数定义

view plain print ?
  1. voidboot_linux(void*kernel,unsigned*tags,
  2. constchar*cmdline,unsignedmachtype,
  3. void*ramdisk,unsignedramdisk_size)
  4. {
  5. unsigned*ptr=tags;
  6. unsignedpcount=0;
  7. void(*entry)(unsigned,unsigned,unsigned*)=kernel;
  8. structptable*ptable;
  9. intcmdline_len=0;
  10. inthave_cmdline=0;
  11. intpause_at_bootup=0;
  12. /*CORE*/
  13. *ptr++=2;
  14. *ptr++=0x54410001;
  15. if(ramdisk_size){
  16. *ptr++=4;
  17. *ptr++=0x54420005;
  18. *ptr++=(unsigned)ramdisk;
  19. *ptr++=ramdisk_size;
  20. }
  21. ptr=target_atag_mem(ptr);
  22. if(!target_is_emmc_boot()){
  23. /*SkipNANDpartitionATAGSforeMMCboot*/
  24. if((ptable=flash_get_ptable())&&(ptable->count!=0)){
  25. inti;
  26. for(i=0;i<ptable->count;i++){
  27. structptentry*ptn;
  28. ptn=ptable_get(ptable,i);
  29. if(ptn->type==TYPE_APPS_PARTITION)
  30. pcount++;
  31. }
  32. *ptr++=2+(pcount*(sizeof(structatag_ptbl_entry)/
  33. sizeof(unsigned)));
  34. *ptr++=0x4d534d70;
  35. for(i=0;i<ptable->count;++i)
  36. ptentry_to_tag(&ptr,ptable_get(ptable,i));
  37. }
  38. }
  39. if(cmdline&&cmdline[0]){
  40. cmdline_len=strlen(cmdline);
  41. have_cmdline=1;
  42. }
  43. if(target_is_emmc_boot()){
  44. cmdline_len+=strlen(emmc_cmdline);
  45. }
  46. if(target_pause_for_battery_charge()){
  47. pause_at_bootup=1;
  48. cmdline_len+=strlen(battchg_pause);
  49. }
  50. if(cmdline_len>0){
  51. constchar*src;
  52. char*dst;
  53. unsignedn;
  54. /*includeterminating0androunduptoawordmultiple*/
  55. n=(cmdline_len+4)&(~3);
  56. *ptr++=(n/4)+2;
  57. *ptr++=0x54410009;
  58. dst=(char*)ptr;
  59. if(have_cmdline){
  60. src=cmdline;
  61. while((*dst++=*src++));
  62. }
  63. if(target_is_emmc_boot()){
  64. src=emmc_cmdline;
  65. if(have_cmdline)--dst;
  66. have_cmdline=1;
  67. while((*dst++=*src++));
  68. }
  69. if(pause_at_bootup){
  70. src=battchg_pause;
  71. if(have_cmdline)--dst;
  72. while((*dst++=*src++));
  73. }
  74. ptr+=(n/4);
  75. }
  76. /*END*/
  77. *ptr++=0;
  78. *ptr++=0;
  79. dprintf(INFO,"bootinglinux@%p,ramdisk@%p(%d)/n",
  80. kernel,ramdisk,ramdisk_size);
  81. if(cmdline)
  82. dprintf(INFO,"cmdline:%s/n",cmdline);
  83. enter_critical_section();
  84. platform_uninit_timer();
  85. arch_disable_cache(UCACHE);
  86. arch_disable_mmu();
  87. #ifDISPLAY_SPLASH_SCREEN
  88. display_shutdown();
  89. #endif
  90. entry(0,machtype,tags);
  91. }

配合 boot.img 来看会比较好理解.

android bootloader (lk)_第1张图片

由此可知boot_img_hdr中各成员值为:

android bootloader (lk)_第2张图片

android bootloader (lk)_第3张图片

TAGS_ADDR 如上 target/<your-platform>/rules.mk 所定义的 : 0x40200100,所以 boot_linux(), 就是传入TAGS_ADDR,

然后将资料写入 tag, tag 的结构如下所示.

android bootloader (lk)_第4张图片

然后进入到 kernel 的入口函数: entry(0, machtype, tags)


更多相关文章

  1. Android 获得本机ip地址和MAC地址
  2. 内存管理Memory Management in Android
  3. Android 复习笔记之图解Activity的4种加载模式
  4. Android获取当前网络状态和获取当前设备网络ip地址
  5. android ICS4.0.3去掉相机全景模式
  6. android资料下载地址汇总
  7. android 查看系统分配程序内存限制

随机推荐

  1. Android 怎么给图片添加一个边框
  2. android添加触摸事件
  3. Android界面设计之:使用水平视图切换
  4. android:WindowTitleBackground错误
  5. Android Developers_DRM
  6. 【Android】安卓六大布局基本了解
  7. Android™ 2.1 android.R.drawable Icon
  8. Android(安卓)Studio开发环境的搭建与And
  9. Android 源码网站
  10. android 4.0 HttpURLConnection. getInpu