分类: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 来看会比较好理解.

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

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

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

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


更多相关文章

  1. 内存管理Memory Management in Android
  2. Android(安卓)获得本机ip地址和MAC地址
  3. 内存管理Memory Management in Android
  4. Adnroid LearningNotes
  5. Android(安卓)复习笔记之图解Activity的4种加载模式
  6. Android中Activity启动模式详解
  7. android ICS4.0.3去掉相机全景模式
  8. Android硬件服务访问流程
  9. android 音频总结

随机推荐

  1. Android应用自动更新功能的实现!!!软件更新,
  2. Android插件-Android Holo Colors Genera
  3. android文件上传示例分享(android图片上
  4. 替换Android自带apk (adb模式和串口模式)
  5. Android 解决 adapter.notifyDataSetChan
  6. 阿里云OS和android的关系
  7. 文件androidAndroid使用PULL解析和生成XM
  8. Android(安卓)四大组件 - 进程的 fork 创
  9. Android中的服务
  10. 关于如何获取android状态栏高度