Android Boot Loader

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

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

  1. void kmain(void) 
  2.     // get us into some sort of thread context 
  3.     thread_init_early(); 
  4.     // early arch stuff 
  5.     arch_early_init(); 
  6.     // do any super early platform initialization 
  7.     platform_early_init(); 
  8.     // do any super early target initialization 
  9.     target_early_init(); 
  10.     dprintf(INFO, "welcome to lk/n/n"); 
  11.      
  12.     // deal with any static constructors 
  13.     dprintf(SPEW, "calling constructors/n"); 
  14.     call_constructors(); 
  15.     // bring up the kernel heap 
  16.     dprintf(SPEW, "initializing heap/n"); 
  17.     heap_init(); 
  18.     // initialize the threading system 
  19.     dprintf(SPEW, "initializing threads/n"); 
  20.     thread_init(); 
  21.     // initialize the dpc system 
  22.     dprintf(SPEW, "initializing dpc/n"); 
  23.     dpc_init(); 
  24.     // initialize kernel timers 
  25.     dprintf(SPEW, "initializing timers/n"); 
  26.     timer_init(); 
  27. #if (!ENABLE_NANDWRITE) 
  28.     // create a thread to complete system initialization 
  29.     dprintf(SPEW, "creating bootstrap completion thread/n"); 
  30.     thread_resume(thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE)); 
  31.     // enable interrupts 
  32.     exit_critical_section(); 
  33.     // become the idle thread 
  34.     thread_become_idle(); 
  35. #else 
  36.         bootstrap_nandwrite(); 
  37. #endif 

[c-sharp] view plain copy print ?
  1. void kmain(void) 
  2.     // get us into some sort of thread context 
  3.     thread_init_early(); 
  4.     // early arch stuff 
  5.     arch_early_init(); 
  6.     // do any super early platform initialization 
  7.     platform_early_init(); 
  8.     // do any super early target initialization 
  9.     target_early_init(); 
  10.     dprintf(INFO, "welcome to lk/n/n"); 
  11.      
  12.     // deal with any static constructors 
  13.     dprintf(SPEW, "calling constructors/n"); 
  14.     call_constructors(); 
  15.     // bring up the kernel heap 
  16.     dprintf(SPEW, "initializing heap/n"); 
  17.     heap_init(); 
  18.     // initialize the threading system 
  19.     dprintf(SPEW, "initializing threads/n"); 
  20.     thread_init(); 
  21.     // initialize the dpc system 
  22.     dprintf(SPEW, "initializing dpc/n"); 
  23.     dpc_init(); 
  24.     // initialize kernel timers 
  25.     dprintf(SPEW, "initializing timers/n"); 
  26.     timer_init(); 
  27. #if (!ENABLE_NANDWRITE) 
  28.     // create a thread to complete system initialization 
  29.     dprintf(SPEW, "creating bootstrap completion thread/n"); 
  30.     thread_resume(thread_create("bootstrap2", &bootstrap2, NULL,  
  31. DEFAULT_PRIORITY, DEFAULT_STACK_SIZE)); 
  32.     // enable interrupts 
  33.     exit_critical_section(); 
  34.     // become the idle thread 
  35.     thread_become_idle(); 
  36. #else 
  37.         bootstrap_nandwrite(); 
  38. #endif 

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

  1. /* debug levels */ 
  2. #define CRITICAL 0 
  3. #define ALWAYS 0 
  4. #define INFO 1 
  5. #define SPEW 2 

[c-sharp:nogutter] view plain copy print ?
  1. /* debug levels */ 
  2. #define CRITICAL 0 
  3. #define ALWAYS 0 
  4. #define INFO 1 
  5. #define SPEW 2 

In include/debug.h:

  1. #define dprintf(level, x...) do { if ((level) <= DEBUGLEVEL) { _dprintf(x); } } while (0) 

[c-sharp:nogutter] view plain copy print ?
  1. #define dprintf(level, x...) do { if ((level)  
  2. <= DEBUGLEVEL) { _dprintf(x); } } while (0) 

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

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

  1. void thread_init_early(void) 
  2.         int i; 
  3.         /* initialize the run queues */ 
  4.         for (i=0; i < NUM_PRIORITIES; i++) 
  5.                 list_initialize(&run_queue[i]); 
  6.         /* initialize the thread list */ 
  7.         list_initialize(&thread_list); 
  8.         /* create a thread to cover the current running state */ 
  9.         thread_t *t = &bootstrap_thread; 
  10.         init_thread_struct(t, "bootstrap"); 
  11.         /* half construct this thread, since we're already running */ 
  12.         t->priority = HIGHEST_PRIORITY; 
  13.         t->state = THREAD_RUNNING; 
  14.         t->saved_critical_section_count = 1; 
  15.         list_add_head(&thread_list, &t->thread_list_node); 
  16.         current_thread = t; 

[c-sharp:nogutter] view plain copy print ?
  1. void thread_init_early(void) 
  2.         int i; 
  3.         /* initialize the run queues */ 
  4.         for (i=0; i < NUM_PRIORITIES; i++) 
  5.                 list_initialize(&run_queue[i]); 
  6.         /* initialize the thread list */ 
  7.         list_initialize(&thread_list); 
  8.         /* create a thread to cover the current running state */ 
  9.         thread_t *t = &bootstrap_thread; 
  10.         init_thread_struct(t, "bootstrap"); 
  11.         /* half construct this thread, since we're already running */ 
  12.         t->priority = HIGHEST_PRIORITY; 
  13.         t->state = THREAD_RUNNING; 
  14.         t->saved_critical_section_count = 1; 
  15.         list_add_head(&thread_list, &t->thread_list_node); 
  16.         current_thread = t; 

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

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

  1. static inline void list_initialize(struct list_node *list) 
  2.         list->prev = list->next = list; 

[c-sharp:nogutter] view plain copy print ?
  1. static  
  2. inline void list_initialize(struct list_node *list) 
  3.         list->prev = list->next = list; 

run_queue 是 static struct list_node run_queue[NUM_PRIORITIES]

thread_list 是 static struct list_node thread_list

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

  1. void arch_early_init(void) 
  2.     /* turn off the cache */ 
  3.     arch_disable_cache(UCACHE); 
  4.     /* set the vector base to our exception vectors so we dont need to double map at 0 */ 
  5. #if ARM_CPU_CORTEX_A8 
  6.     set_vector_base(MEMBASE); 
  7. #endif 
  8. #if ARM_WITH_MMU 
  9.     arm_mmu_init(); 
  10.     platform_init_mmu_mappings(); 
  11. #endif 
  12.     /* turn the cache back on */ 
  13.     arch_enable_cache(UCACHE); 
  14. #if ARM_WITH_NEON 
  15.     /* enable cp10 and cp11 */ 
  16.     uint32_t val; 
  17.     __asm__ volatile("mrc   p15, 0, %0, c1, c0, 2" : "=r" (val)); 
  18.     val |= (3<<22)|(3<<20); 
  19.     __asm__ volatile("mcr   p15, 0, %0, c1, c0, 2" :: "r" (val)); 
  20.     /* set enable bit in fpexc */ 
  21.     val = (1<<30); 
  22.     __asm__ volatile("mcr  p10, 7, %0, c8, c0, 0" :: "r" (val)); 
  23. #endif 

[c-sharp:nogutter] view plain copy print ?
  1. void  
  2. arch_early_init(void) 
  3.     /* turn off the cache */ 
  4.     arch_disable_cache(UCACHE); 
  5.     /* set the vector base to our exception vectors so we dont need to 
  6. double map at 0 */ 
  7. #if ARM_CPU_CORTEX_A8 
  8.     set_vector_base(MEMBASE); 
  9. #endif 
  10. #if ARM_WITH_MMU 
  11.     arm_mmu_init(); 
  12.     platform_init_mmu_mappings(); 
  13. #endif 
  14.     /* turn the cache back on */ 
  15.     arch_enable_cache(UCACHE); 
  16. #if ARM_WITH_NEON 
  17.     /* enable cp10 and cp11 */ 
  18.     uint32_t val; 
  19.     __asm__ volatile("mrc   p15, 0, %0, c1, c0, 2" : "=r" (val)); 
  20.     val |= (3<<22)|(3<<20); 
  21.     __asm__ volatile("mcr   p15, 0, %0, c1, c0, 2" :: "r" (val)); 
  22.     /* set enable bit in fpexc */ 
  23.     val = (1<<30); 
  24.     __asm__ volatile("mcr  p10, 7, %0, c8, c0, 0" :: "r" (val)); 
  25. #endif 

现代操作系统普遍采用虚拟内存管理(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

  1. void platform_early_init(void) 
  2.     uart_init(); 
  3.     platform_init_interrupts(); 
  4.     platform_init_timer(); 

[c-sharp:nogutter] view plain copy print ?
  1. void platform_early_init(void) 
  2.     uart_init(); 
  3.     platform_init_interrupts(); 
  4.     platform_init_timer(); 

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

  1. void uart_init(void) 
  2.     uwr(0x0A, UART_CR);  /* disable TX and RX */ 
  3.      
  4.     uwr(0x30, UART_CR);  /* reset error status */ 
  5.     uwr(0x10, UART_CR);  /* reset receiver */ 
  6.     uwr(0x20, UART_CR);  /* reset transmitter */ 
  7.     
  8. #if PLATFORM_QSD8K 
  9.     /* TCXO */ 
  10.     uwr(0x06, UART_MREG); 
  11.     uwr(0xF1, UART_NREG); 
  12.     uwr(0x0F, UART_DREG); 
  13.     uwr(0x1A, UART_MNDREG); 
  14. #else 
  15.     /* TCXO/4 */ 
  16.     uwr(0xC0, UART_MREG); 
  17.     uwr(0xAF, UART_NREG); 
  18.     uwr(0x80, UART_DREG); 
  19.     uwr(0x19, UART_MNDREG);     
  20. #endif 
  21.      
  22.     uwr(0x10, UART_CR);  /* reset RX */ 
  23.     uwr(0x20, UART_CR);  /* reset TX */ 
  24.     uwr(0x30, UART_CR);  /* reset error status */ 
  25.     uwr(0x40, UART_CR);  /* reset RX break */ 
  26.     uwr(0x70, UART_CR);  /* rest? */ 
  27.     uwr(0xD0, UART_CR);  /* reset */ 
  28.      
  29.     uwr(0x7BF, UART_IPR); /* stale timeout = 630 * bitrate */ 
  30.     uwr(0, UART_IMR); 
  31.     uwr(115, UART_RFWR); /* RX watermark = 58 * 2 - 1 */ 
  32.     uwr(10, UART_TFWR);  /* TX watermark */ 
  33.      
  34.     uwr(0, UART_RFWR);  
  35.      
  36.     uwr(UART_CSR_115200, UART_CSR); 
  37.     uwr(0, UART_IRDA); 
  38.     uwr(0x1E, UART_HCR); 
  39. //  uwr(0x7F4, UART_MR1); /* RFS/ CTS/ 500chr RFR */ 
  40.     uwr(16, UART_MR1); 
  41.     uwr(0x34, UART_MR2); /* 8N1 */ 
  42.      
  43.     uwr(0x05, UART_CR); /* enable TX & RX */ 
  44.     uart_ready = 1; 

[c-sharp:nogutter] view plain copy print ?
  1. void uart_init(void) 
  2.     uwr(0x0A, UART_CR);  /* disable TX and RX */ 
  3.      
  4.     uwr(0x30, UART_CR);  /* reset error status */ 
  5.     uwr(0x10, UART_CR);  /* reset receiver */ 
  6.     uwr(0x20, UART_CR);  /* reset transmitter */ 
  7.     
  8. #if PLATFORM_QSD8K 
  9.     /* TCXO */ 
  10.     uwr(0x06, UART_MREG); 
  11.     uwr(0xF1, UART_NREG); 
  12.     uwr(0x0F, UART_DREG); 
  13.     uwr(0x1A, UART_MNDREG); 
  14. #else 
  15.     /* TCXO/4 */ 
  16.     uwr(0xC0, UART_MREG); 
  17.     uwr(0xAF, UART_NREG); 
  18.     uwr(0x80, UART_DREG); 
  19.     uwr(0x19, UART_MNDREG);     
  20. #endif 
  21.      
  22.     uwr(0x10, UART_CR);  /* reset RX */ 
  23.     uwr(0x20, UART_CR);  /* reset TX */ 
  24.     uwr(0x30, UART_CR);  /* reset error status */ 
  25.     uwr(0x40, UART_CR);  /* reset RX break */ 
  26.     uwr(0x70, UART_CR);  /* rest? */ 
  27.     uwr(0xD0, UART_CR);  /* reset */ 
  28.      
  29.     uwr(0x7BF, UART_IPR); /* stale timeout = 630 * bitrate */ 
  30.     uwr(0, UART_IMR); 
  31.     uwr(115, UART_RFWR); /* RX watermark = 58 * 2 - 1 */ 
  32.     uwr(10, UART_TFWR);  /* TX watermark */ 
  33.      
  34.     uwr(0, UART_RFWR);  
  35.      
  36.     uwr(UART_CSR_115200, UART_CSR); 
  37.     uwr(0, UART_IRDA); 
  38.     uwr(0x1E, UART_HCR); 
  39. //  uwr(0x7F4, UART_MR1); /* RFS/ CTS/ 500chr RFR */ 
  40.     uwr(16, UART_MR1); 
  41.     uwr(0x34, UART_MR2); /* 8N1 */ 
  42.      
  43.     uwr(0x05, UART_CR); /* enable TX & RX */ 
  44.     uart_ready = 1; 

platform_init_interrupts: defined in platform/msm8x60/interrupts.c

  1. void platform_init_interrupts(void) 
  2.     platform_gic_dist_init(); 
  3.     platform_gic_cpu_init(); 

[c-sharp:nogutter] view plain copy print ?
  1. void platform_init_interrupts(void) 
  2.     platform_gic_dist_init(); 
  3.     platform_gic_cpu_init(); 

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

  1. void platform_init_timer(void) 
  2.     writel(0, DGT_ENABLE); 

[c-sharp:nogutter] view plain copy print ?
  1. void platform_init_timer(void) 
  2.     writel(0, DGT_ENABLE); 

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

  1. /*
  2. * default implementations of these routines, if the target code
  3. * chooses not to implement.
  4. */ 
  5. __WEAK void target_early_init(void) 
  6. __WEAK void target_init(void) 

[c-sharp:nogutter] view plain copy print ?
  1. /*
  2. * default implementations of these routines, if the target code
  3. * chooses not to implement.
  4. */ 
  5. __WEAK void target_early_init(void) 
  6. __WEAK void target_init(void) 

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

  1. static void call_constructors(void) 
  2.     void **ctor; 
  3.     
  4.     ctor = &__ctor_list; 
  5.     while(ctor != &__ctor_end) { 
  6.         void (*func)(void); 
  7.         func = (void (*)())*ctor; 
  8.         func(); 
  9.         ctor++; 
  10.     } 

[c-sharp:nogutter] view plain copy print ?
  1. static void call_constructors(void) 
  2.     void **ctor; 
  3.     
  4.     ctor = &__ctor_list; 
  5.     while(ctor != &__ctor_end) { 
  6.         void (*func)(void); 
  7.         func = (void (*)())*ctor; 
  8.         func(); 
  9.         ctor++; 
  10.     } 

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

  1. void heap_init(void) 
  2.     LTRACE_ENTRY; 
  3.     // set the heap range 
  4.     theheap.base = (void *)HEAP_START; 
  5.     theheap.len = HEAP_LEN; 
  6.     LTRACEF("base %p size %zd bytes/n", theheap.base, theheap.len); 
  7.     // initialize the free list 
  8.     list_initialize(&theheap.free_list); 
  9.     // create an initial free chunk 
  10.     heap_insert_free_chunk(heap_create_free_chunk(theheap.base, theheap.len)); 
  11.     // dump heap info 
  12. //  heap_dump(); 
  13. //  dprintf(INFO, "running heap tests/n"); 
  14. //  heap_test(); 

[c-sharp:nogutter] view plain copy print ?
  1. void  
  2. heap_init(void) 
  3.     LTRACE_ENTRY; 
  4.     // set the heap range 
  5.     theheap.base = (void *)HEAP_START; 
  6.     theheap.len = HEAP_LEN; 
  7.     LTRACEF("base %p size %zd bytes/n", theheap.base, theheap.len); 
  8.     // initialize the free list 
  9.     list_initialize(&theheap.free_list); 
  10.     // create an initial free chunk 
  11.     heap_insert_free_chunk(heap_create_free_chunk(theheap.base,  
  12. theheap.len)); 
  13.     // dump heap info 
  14. //  heap_dump(); 
  15. //  dprintf(INFO, "running heap tests/n"); 
  16. //  heap_test(); 

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

  1. void thread_init(void) 

[c-sharp:nogutter] view plain copy print ?
  1. void  
  2. thread_init(void) 

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

  1. void dpc_init(void) 
  2.     event_init(&dpc_event, false, 0); 
  3.     thread_resume(thread_create("dpc", &dpc_thread_routine, NULL, DPC_PRIORITY, DEFAULT_STACK_SIZE)); 

[c-sharp:nogutter] view plain copy print ?
  1. void  
  2. dpc_init(void) 
  3.     event_init(&dpc_event, false, 0); 
  4.     thread_resume(thread_create("dpc", &dpc_thread_routine, NULL,  
  5. DPC_PRIORITY, DEFAULT_STACK_SIZE)); 

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

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

  1. void timer_init(void) 
  2.     list_initialize(&timer_queue); 
  3.     /* register for a periodic timer tick */ 
  4.     platform_set_periodic_timer(timer_tick, NULL, 10); /* 10ms */ 

[c-sharp:nogutter] view plain copy print ?
  1. void  
  2. timer_init(void) 
  3.     list_initialize(&timer_queue); 
  4.     /* register for a periodic timer tick */ 
  5.     platform_set_periodic_timer(timer_tick, NULL, 10); /* 10ms */ 

执行 thread_resume 或是 bootstrap_nandwrite

  1. #if (!ENABLE_NANDWRITE) 
  2.     // create a thread to complete system initialization 
  3.     dprintf(SPEW, "creating bootstrap completion thread/n"); 
  4.     thread_resume(thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE)); 
  5.     // enable interrupts 
  6.     exit_critical_section(); 
  7.     // become the idle thread 
  8.     thread_become_idle(); 
  9. #else 
  10.         bootstrap_nandwrite(); 
  11. #endif 

[c-sharp:nogutter] view plain copy print ?
  1. #if (!ENABLE_NANDWRITE) 
  2.     // create a thread to complete system initialization 
  3.     dprintf(SPEW, "creating bootstrap completion thread/n"); 
  4.     thread_resume(thread_create("bootstrap2", &bootstrap2, NULL,  
  5. DEFAULT_PRIORITY, DEFAULT_STACK_SIZE)); 
  6.     // enable interrupts 
  7.     exit_critical_section(); 
  8.     // become the idle thread 
  9.     thread_become_idle(); 
  10. #else 
  11.         bootstrap_nandwrite(); 
  12. #endif 

In kermel/main.c:

  1. static int bootstrap2(void *arg) 
  2.     dprintf(SPEW, "top of bootstrap2()/n"); 
  3.     arch_init(); 
  4.     // initialize the rest of the platform 
  5.     dprintf(SPEW, "initializing platform/n"); 
  6.     platform_init(); 
  7.      
  8.     // initialize the target 
  9.     dprintf(SPEW, "initializing target/n"); 
  10.     target_init(); 
  11.     dprintf(SPEW, "calling apps_init()/n"); 
  12.     apps_init(); 
  13.     return 0; 
  14. #if (ENABLE_NANDWRITE) 
  15. void bootstrap_nandwrite(void) 
  16.     dprintf(SPEW, "top of bootstrap2()/n"); 
  17.     arch_init(); 
  18.     // initialize the rest of the platform 
  19.     dprintf(SPEW, "initializing platform/n"); 
  20.     platform_init(); 
  21.     // initialize the target 
  22.     dprintf(SPEW, "initializing target/n"); 
  23.     target_init(); 
  24.     dprintf(SPEW, "calling nandwrite_init()/n"); 
  25.     nandwrite_init(); 
  26.     return 0; 
  27. #endif 

[c-sharp:nogutter] view plain copy print ?
  1. static int bootstrap2(void *arg) 
  2.     dprintf(SPEW, "top of bootstrap2()/n"); 
  3.     arch_init(); 
  4.     // initialize the rest of the platform 
  5.     dprintf(SPEW, "initializing platform/n"); 
  6.     platform_init(); 
  7.      
  8.     // initialize the target 
  9.     dprintf(SPEW, "initializing target/n"); 
  10.     target_init(); 
  11.     dprintf(SPEW, "calling apps_init()/n"); 
  12.     apps_init(); 
  13.     return 0; 
  14. #if (ENABLE_NANDWRITE) 
  15. void bootstrap_nandwrite(void) 
  16.     dprintf(SPEW, "top of bootstrap2()/n"); 
  17.     arch_init(); 
  18.     // initialize the rest of the platform 
  19.     dprintf(SPEW, "initializing platform/n"); 
  20.     platform_init(); 
  21.     // initialize the target 
  22.     dprintf(SPEW, "initializing target/n"); 
  23.     target_init(); 
  24.     dprintf(SPEW, "calling nandwrite_init()/n"); 
  25.     nandwrite_init(); 
  26.     return 0; 
  27. #endif 

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

  1. #include <app.h> 
  2. #include <kernel/thread.h> 
  3. extern const struct app_descriptor __apps_start; 
  4. extern const struct app_descriptor __apps_end; 
  5. static void start_app(const struct app_descriptor *app); 
  6. /* one time setup */ 
  7. void apps_init(void) 
  8.     const struct app_descriptor *app; 
  9.     /* call all the init routines */ 
  10.     for (app = &__apps_start; app != &__apps_end; app++) { 
  11.         if (app->init) 
  12.             app->init(app); 
  13.     } 
  14.     /* start any that want to start on boot */ 
  15.     for (app = &__apps_start; app != &__apps_end; app++) { 
  16.         if (app->entry && (app->flags & APP_FLAG_DONT_START_ON_BOOT) == 0) { 
  17.             start_app(app); 
  18.         } 
  19.     } 
  20. static int app_thread_entry(void *arg) 
  21.     const struct app_descriptor *app = (const struct app_descriptor *)arg; 
  22.     app->entry(app, NULL); 
  23.     return 0; 
  24. static void start_app(const struct app_descriptor *app) 
  25.     printf("starting app %s/n", app->name); 
  26.     thread_resume(thread_create(app->name, &app_thread_entry, (void *)app, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));    

[c-sharp] view plain copy print ?
  1. #include  
  2. <app.h> 
  3. #include <kernel/thread.h> 
  4. extern const struct app_descriptor __apps_start; 
  5. extern const struct app_descriptor __apps_end; 
  6. static void start_app(const struct app_descriptor *app); 
  7. /* one time setup */ 
  8. void apps_init(void) 
  9.     const struct app_descriptor *app; 
  10.     /* call all the init routines */ 
  11.     for (app = &__apps_start; app != &__apps_end; app++) { 
  12.         if (app->init) 
  13.             app->init(app); 
  14.     } 
  15.     /* start any that want to start on boot */ 
  16.     for (app = &__apps_start; app != &__apps_end; app++) { 
  17.         if (app->entry && (app->flags &  
  18. APP_FLAG_DONT_START_ON_BOOT) == 0) { 
  19.             start_app(app); 
  20.         } 
  21.     } 
  22. static int app_thread_entry(void *arg) 
  23.     const struct app_descriptor *app = (const struct app_descriptor *)arg; 
  24.     app->entry(app, NULL); 
  25.     return 0; 
  26. static void start_app(const struct app_descriptor *app) 
  27.     printf("starting app %s/n", app->name); 
  28.     thread_resume(thread_create(app->name, &app_thread_entry, (void  
  29. *)app, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));   

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

  1. #define APP_START(appname) struct app_descriptor _app_##appname __SECTION(".apps") = { .name = #appname, 
  2. #define APP_END }; 

[c-sharp:nogutter] view plain copy print ?
  1. #define APP_START(appname) struct  
  2. app_descriptor _app_##appname __SECTION(".apps") = { .name = #appname, 
  3. #define APP_END }; 

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

  1. APP_START(aboot) 
  2.         .init = aboot_init, 
  3. APP_END 

[c-sharp:nogutter] view plain copy 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()

  1. void aboot_init(const struct app_descriptor *app) 
  2.     unsigned reboot_mode = 0; 
  3.     unsigned disp_init = 0; 
  4.     unsigned usb_init = 0; 
  5.     //test_ram(); 
  6.     /* Setup page size information for nand/emmc reads */ 
  7.     if (target_is_emmc_boot()) 
  8.     { 
  9.         page_size = 2048; 
  10.         page_mask = page_size - 1; 
  11.     } 
  12.     else 
  13.     { 
  14.         page_size = flash_page_size(); 
  15.         page_mask = page_size - 1; 
  16.     } 
  17.     /* Display splash screen if enabled */ 
  18.     #if DISPLAY_SPLASH_SCREEN 
  19.     display_init(); 
  20.     dprintf(INFO, "Diplay initialized/n"); 
  21.     disp_init = 1; 
  22.     diplay_image_on_screen(); 
  23.     #endif 
  24.     /* Check if we should do something other than booting up */ 
  25.     if (keys_get_state(KEY_HOME) != 0) 
  26.         boot_into_recovery = 1; 
  27.     if (keys_get_state(KEY_BACK) != 0) 
  28.         goto fastboot; 
  29.     if (keys_get_state(KEY_CLEAR) != 0) 
  30.         goto fastboot; 
  31.     #if NO_KEYPAD_DRIVER 
  32.     /* With no keypad implementation, check the status of USB connection. */ 
  33.     /* If USB is connected then go into fastboot mode. */ 
  34.     usb_init = 1; 
  35.     udc_init(&surf_udc_device); 
  36.     if (usb_cable_status()) 
  37.         goto fastboot; 
  38.     #endif 
  39.     init_vol_key(); 
  40.     if(voldown_press()) 
  41.         goto fastboot; 
  42.     reboot_mode = check_reboot_mode(); 
  43.     if (reboot_mode == RECOVERY_MODE) { 
  44.         boot_into_recovery = 1; 
  45.     } else if(reboot_mode == FASTBOOT_MODE) { 
  46.         goto fastboot; 
  47.     } 
  48.     if (target_is_emmc_boot()) 
  49.     { 
  50.         boot_linux_from_mmc(); 
  51.     } 
  52.     else 
  53.     { 
  54.         recovery_init(); 
  55.         boot_linux_from_flash(); 
  56.     } 
  57.     dprintf(CRITICAL, "ERROR: Could not do normal boot. Reverting " 
  58.         "to fastboot mode./n"); 
  59. fastboot: 
  60.     if(!usb_init) 
  61.         udc_init(&surf_udc_device); 
  62.     fastboot_register("boot", cmd_boot); 
  63.     if (target_is_emmc_boot()) 
  64.     { 
  65.         fastboot_register("flash:", cmd_flash_mmc); 
  66.         fastboot_register("erase:", cmd_erase_mmc); 
  67.     } 
  68.     else 
  69.     { 
  70.         fastboot_register("flash:", cmd_flash); 
  71.         fastboot_register("erase:", cmd_erase); 
  72.     } 
  73.     fastboot_register("continue", cmd_continue); 
  74.     fastboot_register("reboot", cmd_reboot); 
  75.     fastboot_register("reboot-bootloader", cmd_reboot_bootloader); 
  76.     fastboot_publish("product", TARGET(BOARD)); 
  77.     fastboot_publish("kernel", "lk"); 
  78.      
  79.     fastboot_init(target_get_scratch_address(), 120 * 1024 * 1024); 
  80.      
  81.     udc_start(); 
  82.     target_battery_charging_enable(1, 0); 

[c-sharp:nogutter] view plain copy print ?
  1. void  
  2. aboot_init(const struct app_descriptor *app) 
  3.     unsigned reboot_mode = 0; 
  4.     unsigned disp_init = 0; 
  5.     unsigned usb_init = 0; 
  6.     //test_ram(); 
  7.     /* Setup page size information for nand/emmc reads */ 
  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.     /* Display splash screen if enabled */ 
  19.     #if DISPLAY_SPLASH_SCREEN 
  20.     display_init(); 
  21.     dprintf(INFO, "Diplay initialized/n"); 
  22.     disp_init = 1; 
  23.     diplay_image_on_screen(); 
  24.     #endif 
  25.     /* Check if we should do something other than booting up */ 
  26.     if (keys_get_state(KEY_HOME) != 0) 
  27.         boot_into_recovery = 1; 
  28.     if (keys_get_state(KEY_BACK) != 0) 
  29.         goto fastboot; 
  30.     if (keys_get_state(KEY_CLEAR) != 0) 
  31.         goto fastboot; 
  32.     #if NO_KEYPAD_DRIVER 
  33.     /* With no keypad implementation, check the status of USB connection. 
  34. */ 
  35.     /* If USB is connected then go into fastboot mode. */ 
  36.     usb_init = 1; 
  37.     udc_init(&surf_udc_device); 
  38.     if (usb_cable_status()) 
  39.         goto fastboot; 
  40.     #endif 
  41.     init_vol_key(); 
  42.     if(voldown_press()) 
  43.         goto fastboot; 
  44.     reboot_mode = check_reboot_mode(); 
  45.     if (reboot_mode == RECOVERY_MODE) { 
  46.         boot_into_recovery = 1; 
  47.     } else if(reboot_mode == FASTBOOT_MODE) { 
  48.         goto fastboot; 
  49.     } 
  50.     if (target_is_emmc_boot()) 
  51.     { 
  52.         boot_linux_from_mmc(); 
  53.     } 
  54.     else 
  55.     { 
  56.         recovery_init(); 
  57.         boot_linux_from_flash(); 
  58.     } 
  59.     dprintf(CRITICAL, "ERROR: Could not do normal boot. Reverting " 
  60.         "to fastboot mode./n"); 
  61. fastboot: 
  62.     if(!usb_init) 
  63.         udc_init(&surf_udc_device); 
  64.     fastboot_register("boot", cmd_boot); 
  65.     if (target_is_emmc_boot()) 
  66.     { 
  67.         fastboot_register("flash:", cmd_flash_mmc); 
  68.         fastboot_register("erase:", cmd_erase_mmc); 
  69.     } 
  70.     else 
  71.     { 
  72.         fastboot_register("flash:", cmd_flash); 
  73.         fastboot_register("erase:", cmd_erase); 
  74.     } 
  75.     fastboot_register("continue", cmd_continue); 
  76.     fastboot_register("reboot", cmd_reboot); 
  77.     fastboot_register("reboot-bootloader", cmd_reboot_bootloader); 
  78.     fastboot_publish("product", TARGET(BOARD)); 
  79.     fastboot_publish("kernel", "lk"); 
  80.      
  81.     fastboot_init(target_get_scratch_address(), 120 * 1024 * 1024); 
  82.      
  83.     udc_start(); 
  84.     target_battery_charging_enable(1, 0); 


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

  1. __WEAK int target_is_emmc_boot(void) 
  2. #if _EMMC_BOOT 
  3.     return 1; 
  4. #else 
  5.     return 0; 
  6. #endif 

[c-sharp:nogutter] view plain copy print ?
  1. __WEAK  
  2. int target_is_emmc_boot(void) 
  3. #if _EMMC_BOOT 
  4.     return 1; 
  5. #else 
  6.     return 0; 
  7. #endif 

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

  1. unsigned check_reboot_mode(void) 
  2.         unsigned restart_reason = 0; 
  3.         void *restart_reason_addr = 0x401FFFFC; 
  4.         /* Read reboot reason and scrub it */ 
  5.         restart_reason = readl(restart_reason_addr); 
  6.         writel(0x00, restart_reason_addr); 
  7.         return restart_reason; 

[c-sharp:nogutter] view plain copy print ?
  1. unsigned 
  2. check_reboot_mode(void) 
  3.         unsigned restart_reason = 0; 
  4.         void *restart_reason_addr = 0x401FFFFC; 
  5.         /* Read reboot reason and scrub it */ 
  6.         restart_reason = readl(restart_reason_addr); 
  7.         writel(0x00, restart_reason_addr); 
  8.         return restart_reason; 

reboot mode in bootloader:

  1. #define RECOVERY_MODE   0x77665502 
  2. #define FASTBOOT_MODE   0x77665500 

[c-sharp:nogutter] view plain copy print ?
  1. #define RECOVERY_MODE   0x77665502 
  2. #define FASTBOOT_MODE   0x77665500 

再来就会执行 boot_linux_from_mmc():

  1. int boot_linux_from_mmc(void) 
  2.     struct boot_img_hdr *hdr = (void*) buf; 
  3.     struct boot_img_hdr *uhdr; 
  4.     unsigned offset = 0; 
  5.     unsigned long long ptn = 0; 
  6.     unsigned n = 0; 
  7.     const char *cmdline; 
  8.     uhdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR; 
  9.     if (!memcmp(uhdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) { 
  10.         dprintf(INFO, "Unified boot method!/n"); 
  11.         hdr = uhdr; 
  12.         goto unified_boot; 
  13.     } 
  14.     if(!boot_into_recovery) 
  15.     { 
  16.         ptn = mmc_ptn_offset("boot"); 
  17.         if(ptn == 0) { 
  18.             dprintf(CRITICAL, "ERROR: No boot partition found/n"); 
  19.                     return -1; 
  20.         } 
  21.     } 
  22.     else 
  23.     { 
  24.         ptn = mmc_ptn_offset("recovery"); 
  25.         if(ptn == 0) { 
  26.             dprintf(CRITICAL, "ERROR: No recovery partition found/n"); 
  27.                     return -1; 
  28.         } 
  29.     } 
  30.     if (mmc_read(ptn + offset, (unsigned int *)buf, page_size)) { 
  31.         dprintf(CRITICAL, "ERROR: Cannot read boot image header/n"); 
  32.                 return -1; 
  33.     } 
  34.     if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) { 
  35.         dprintf(CRITICAL, "ERROR: Invaled boot image header/n"); 
  36.                 return -1; 
  37.     } 
  38.     if (hdr->page_size && (hdr->page_size != page_size)) { 
  39.         page_size = hdr->page_size; 
  40.         page_mask = page_size - 1; 
  41.     } 
  42.     offset += page_size; 
  43.     n = ROUND_TO_PAGE(hdr->kernel_size, page_mask); 
  44.     if (mmc_read(ptn + offset, (void *)hdr->kernel_addr, n)) { 
  45.         dprintf(CRITICAL, "ERROR: Cannot read kernel image/n"); 
  46.                 return -1; 
  47.     } 
  48.     offset += n; 
  49.     n = ROUND_TO_PAGE(hdr->ramdisk_size, page_mask); 
  50.     if (mmc_read(ptn + offset, (void *)hdr->ramdisk_addr, n)) { 
  51.         dprintf(CRITICAL, "ERROR: Cannot read ramdisk image/n"); 
  52.                 return -1; 
  53.     } 
  54.     offset += n; 
  55. unified_boot: 
  56.     dprintf(INFO, "/nkernel  @ %x (%d bytes)/n", hdr->kernel_addr, 
  57.         hdr->kernel_size); 
  58.     dprintf(INFO, "ramdisk @ %x (%d bytes)/n", hdr->ramdisk_addr, 
  59.         hdr->ramdisk_size); 
  60.     if(hdr->cmdline[0]) { 
  61.         cmdline = (char*) hdr->cmdline; 
  62.     } else { 
  63.         cmdline = DEFAULT_CMDLINE; 
  64.     } 
  65.     dprintf(INFO, "cmdline = '%s'/n", cmdline); 
  66.     dprintf(INFO, "/nBooting Linux/n"); 
  67.     boot_linux((void *)hdr->kernel_addr, (void *)TAGS_ADDR, 
  68.            (const char *)cmdline, board_machtype(), 
  69.            (void *)hdr->ramdisk_addr, hdr->ramdisk_size); 
  70.     return 0; 

[c-sharp:nogutter] view plain copy print ?
  1. int  
  2. boot_linux_from_mmc(void) 
  3.     struct boot_img_hdr *hdr = (void*) buf; 
  4.     struct boot_img_hdr *uhdr; 
  5.     unsigned offset = 0; 
  6.     unsigned long long ptn = 0; 
  7.     unsigned n = 0; 
  8.     const char *cmdline; 
  9.     uhdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR; 
  10.     if (!memcmp(uhdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) { 
  11.         dprintf(INFO, "Unified boot method!/n"); 
  12.         hdr = uhdr; 
  13.         goto unified_boot; 
  14.     } 
  15.     if(!boot_into_recovery) 
  16.     { 
  17.         ptn = mmc_ptn_offset("boot"); 
  18.         if(ptn == 0) { 
  19.             dprintf(CRITICAL, "ERROR: No boot partition found/n"); 
  20.                     return -1; 
  21.         } 
  22.     } 
  23.     else 
  24.     { 
  25.         ptn = mmc_ptn_offset("recovery"); 
  26.         if(ptn == 0) { 
  27.             dprintf(CRITICAL, "ERROR: No recovery partition found/n"); 
  28.                     return -1; 
  29.         } 
  30.     } 
  31.     if (mmc_read(ptn + offset, (unsigned int *)buf, page_size)) { 
  32.         dprintf(CRITICAL, "ERROR: Cannot read boot image header/n"); 
  33.                 return -1; 
  34.     } 
  35.     if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) { 
  36.         dprintf(CRITICAL, "ERROR: Invaled boot image header/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: Cannot read kernel image/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: Cannot read ramdisk image/n"); 
  53.                 return -1; 
  54.     } 
  55.     offset += n; 
  56. unified_boot: 
  57.     dprintf(INFO, "/nkernel  @ %x (%d bytes)/n", hdr->kernel_addr, 
  58.         hdr->kernel_size); 
  59.     dprintf(INFO, "ramdisk @ %x (%d bytes)/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, "/nBooting Linux/n"); 
  68.     boot_linux((void *)hdr->kernel_addr, (void *)TAGS_ADDR, 
  69.            (const char *)cmdline, board_machtype(), 
  70.            (void *)hdr->ramdisk_addr, hdr->ramdisk_size); 
  71.     return 0; 

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

  1. unsigned int mmc_read (unsigned long long data_addr, unsigned int* out, unsigned int data_len) 
  2.     int val = 0; 
  3.     val = mmc_boot_read_from_card( &mmc_host, &mmc_card, data_addr, data_len, out); 
  4.     return val; 

[c-sharp:nogutter] view plain copy print ?
  1. unsigned 
  2. int mmc_read (unsigned long long data_addr, unsigned int* out, unsigned 
  3. int data_len) 
  4.     int val = 0; 
  5.     val = mmc_boot_read_from_card( &mmc_host, &mmc_card,  
  6. data_addr, data_len, out); 
  7.     return val; 

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

  1. void boot_linux(void *kernel, unsigned *tags,  
  2.         const char *cmdline, unsigned machtype, 
  3.         void *ramdisk, unsigned ramdisk_size) 
  4.     unsigned *ptr = tags; 
  5.     unsigned pcount = 0; 
  6.     void (*entry)(unsigned,unsigned,unsigned*) = kernel; 
  7.     struct ptable *ptable; 
  8.     int cmdline_len = 0; 
  9.     int have_cmdline = 0; 
  10.     int pause_at_bootup = 0; 
  11.     /* CORE */ 
  12.     *ptr++ = 2; 
  13.     *ptr++ = 0x54410001; 
  14.     if (ramdisk_size) { 
  15.         *ptr++ = 4; 
  16.         *ptr++ = 0x54420005; 
  17.         *ptr++ = (unsigned)ramdisk; 
  18.         *ptr++ = ramdisk_size; 
  19.     } 
  20.     ptr = target_atag_mem(ptr); 
  21.     if (!target_is_emmc_boot()) { 
  22.         /* Skip NAND partition ATAGS for eMMC boot */ 
  23.         if ((ptable = flash_get_ptable()) && (ptable->count != 0)) { 
  24.             int i; 
  25.             for(i=0; i < ptable->count; i++) { 
  26.                 struct ptentry *ptn; 
  27.                 ptn =  ptable_get(ptable, i); 
  28.                 if (ptn->type == TYPE_APPS_PARTITION) 
  29.                     pcount++; 
  30.             } 
  31.             *ptr++ = 2 + (pcount * (sizeof(struct atag_ptbl_entry) / 
  32.                                sizeof(unsigned))); 
  33.             *ptr++ = 0x4d534d70; 
  34.             for (i = 0; i < ptable->count; ++i) 
  35.                 ptentry_to_tag(&ptr, ptable_get(ptable, i)); 
  36.         } 
  37.     } 
  38.     if (cmdline && cmdline[0]) { 
  39.         cmdline_len = strlen(cmdline); 
  40.         have_cmdline = 1; 
  41.     } 
  42.     if (target_is_emmc_boot()) { 
  43.         cmdline_len += strlen(emmc_cmdline); 
  44.     } 
  45.     if (target_pause_for_battery_charge()) { 
  46.         pause_at_bootup = 1; 
  47.         cmdline_len += strlen(battchg_pause); 
  48.     } 
  49.     if (cmdline_len > 0) { 
  50.         const char *src; 
  51.         char *dst; 
  52.         unsigned n; 
  53.         /* include terminating 0 and round up to a word multiple */ 
  54.         n = (cmdline_len + 4) & (~3); 
  55.         *ptr++ = (n / 4) + 2; 
  56.         *ptr++ = 0x54410009; 
  57.         dst = (char *)ptr; 
  58.         if (have_cmdline) { 
  59.             src = cmdline; 
  60.             while ((*dst++ = *src++)); 
  61.         } 
  62.         if (target_is_emmc_boot()) { 
  63.             src = emmc_cmdline; 
  64.             if (have_cmdline) --dst; 
  65.             have_cmdline = 1; 
  66.             while ((*dst++ = *src++)); 
  67.         } 
  68.         if (pause_at_bootup) { 
  69.             src = battchg_pause; 
  70.             if (have_cmdline) --dst; 
  71.             while ((*dst++ = *src++)); 
  72.         } 
  73.         ptr += (n / 4); 
  74.     } 
  75.     /* END */ 
  76.     *ptr++ = 0; 
  77.     *ptr++ = 0; 
  78.     dprintf(INFO, "booting linux @ %p, ramdisk @ %p (%d)/n", 
  79.         kernel, ramdisk, ramdisk_size); 
  80.     if (cmdline) 
  81.         dprintf(INFO, "cmdline: %s/n", cmdline); 
  82.     enter_critical_section(); 
  83.     platform_uninit_timer(); 
  84.     arch_disable_cache(UCACHE); 
  85.     arch_disable_mmu(); 
  86. #if DISPLAY_SPLASH_SCREEN 
  87.     display_shutdown(); 
  88. #endif 
  89.     entry(0, machtype, tags); 

[c-sharp:nogutter] view plain copy print ?
  1. void  
  2. boot_linux(void *kernel, unsigned *tags,  
  3.         const char *cmdline, unsigned machtype, 
  4.         void *ramdisk, unsigned ramdisk_size) 
  5.     unsigned *ptr = tags; 
  6.     unsigned pcount = 0; 
  7.     void (*entry)(unsigned,unsigned,unsigned*) = kernel; 
  8.     struct ptable *ptable; 
  9.     int cmdline_len = 0; 
  10.     int have_cmdline = 0; 
  11.     int pause_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.         /* Skip NAND partition ATAGS for eMMC boot */ 
  24.         if ((ptable = flash_get_ptable()) && (ptable->count != 0)) { 
  25.             int i; 
  26.             for(i=0; i < ptable->count; i++) { 
  27.                 struct ptentry *ptn; 
  28.                 ptn =  ptable_get(ptable, i); 
  29.                 if (ptn->type == TYPE_APPS_PARTITION) 
  30.                     pcount++; 
  31.             } 
  32.             *ptr++ = 2 + (pcount * (sizeof(struct atag_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.         const char *src; 
  52.         char *dst; 
  53.         unsigned n; 
  54.         /* include terminating 0 and round up to a word multiple */ 
  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, "booting linux @ %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. #if DISPLAY_SPLASH_SCREEN 
  88.     display_shutdown(); 
  89. #endif 
  90.     entry(0, machtype, tags); 

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

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

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

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

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

来源:http://blog.csdn.net/sunrock/article/details/6233940

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值