2.u-boot啟動內核:
[code]theKernel(0,bd->bi_arch_number,bd->bi_boot_params) //啟動內核 bd->bi_arch_number //機器id bd->bi_boot_params //uboot傳入內核參數存放的地址
[code]//head.S: @ and irqs disabled mrc p15, 0, r9, c0, c0 @ get processor id bl __lookup_processor_type @ r5=procinfo r9=cpuid movs r10, r5 @ invalid processor (r5=0)? beq __error_p @ yes, error 'p' bl __lookup_machine_type @ r5=machinfo //查找機器ID movs r8, r5 @ invalid machine (r5=0)? beq __error_a @ yes, error 'a' bl __create_page_tables //head-common.S: 3: #3b地址定義 .long . #3b的虛擬地址 .long __arch_info_begin .long __arch_info_end __lookup_machine_type: adr r3, 3b #r3 = 3b的物理地址 ldmia r3, {r4, r5, r6} sub r3, r3, r4 add r5, r5, r3 add r6, r6, r3 @ physical address space 1: ldr r3, [r5, #MACHINFO_TYPE] @ get machine type teq r3, r1 @ matches loader number? beq 2f @ found add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc cmp r5, r6 blo 1b mov r5, #0 @ unknown machine 2: mov pc, lr //地址轉換過程 adr r3, 3b #r3 = 3b的物理地址 ldmia r3, {r4, r5, r6} # r4= 3標號的虛擬地址 # r5=__arch_info_begin # r6 = __arch_info_end //__arch_info_begin,__arch_info_end在哪兒定義? vmlinux.lds: ...... __arch_info_begin=.; *(.arch.info.init) //這是代碼中定義的一個段 __arch_info_end=.; 再看看:arch.h arch.h #define MACHINE_START(_type,_name) \ static const struct machine_desc __mach_desc_##_type \ __used \ __attribute__((__section__(".arch.info.init"))) = { \ .nr = MACH_TYPE_##_type, \ .name = _name, #define MACHINE_END \ }; //那麼誰在使用這個宏 誰在使用這個宏:以s3c2440為例: MACHINE_START(S3C2440, "SMDK2440") /* Maintainer: Ben Dooks <[email protected]> */ .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, .init_irq = s3c24xx_init_irq, .map_io = smdk2440_map_io, .init_machine = smdk2440_machine_init, .timer = &s3c24xx_timer, MACHINE_END 將其展開: static const struct machine_desc __mach_desc_S3C2440 = { .nr = MACH_TYPE_S3C2440, .name = "SMDK2440", .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, .init_irq = s3c24xx_init_irq, .map_io = smdk2440_map_io, .init_machine = smdk2440_machine_init, .timer = &s3c24xx_timer, }; //machine_desc machine_desc 打開這個結構體 描述一個單板的屬性: struct machine_desc { unsigned int nr; /* architecture number */ unsigned int phys_io; /* start of physical io */ unsigned int io_pg_offst; /* byte offset for io * page tabe entry */ const char *name; /* architecture name */ 機器id unsigned long boot_params; /* tagged list */ 參數 unsigned int video_start; /* start of video RAM */ unsigned int video_end; /* end of video RAM */ unsigned int reserve_lp0 :1; /* never has lp0 */ unsigned int reserve_lp1 :1; /* never has lp1 */ unsigned int reserve_lp2 :1; /* never has lp2 */ unsigned int soft_reboot :1; /* soft reboot */ void (*fixup)(struct machine_desc *, struct tag *, char **, struct meminfo *); void (*map_io)(void);/* IO mapping function */ void (*init_irq)(void); struct sys_timer *timer; /* system tick timer */ void (*init_machine)(void); }; 在看看head_common.S 1: ldr r3, [r5, #MACHINFO_TYPE] @ get machine type teq r3, r1 @ matches loader number? 比較機器id 比較成功之後: bl __create_page_tables @創建頁表 ldr r13, __switch_data @ address to jump to after @ mmu has been enabled adr lr, __enable_mmu @ return (PIC) address #使能MMU add pc, r10, #PROCINFO_INITFUNC 創建頁表,使能MMU之後跳轉到__switch_data __switch_data: .long __mmap_switched .long __data_loc @ r4 .long __data_start @ r5 .long __bss_start @ r6 .long _end @ r7 .long processor_id @ r4 .long __machine_arch_type @ r5 .long cr_alignment @ r6 .long init_thread_union + THREAD_START_SP @ sp /* * The following fragment of code is executed with the MMU on in MMU mode, * and uses absolute addresses; this is not position independent. * * r0 = cp#15 control register * r1 = machine ID * r9 = processor ID */ .type __mmap_switched, %function __mmap_switched: adr r3, __switch_data + 4 ldmia r3!, {r4, r5, r6, r7} cmp r4, r5 @ Copy data segment if needed 1: cmpne r5, r6 ldrne fp, [r4], #4 strne fp, [r5], #4 bne 1b mov fp, #0 @ Clear BSS (and zero fp) 1: cmp r6, r7 strcc fp, [r6],#4 bcc 1b ldmia r3, {r4, r5, r6, sp} str r9, [r4] @ Save processor ID str r1, [r5] @ Save machine type bic r4, r0, #CR_A @ Clear 'A' bit stmia r6, {r0, r4} @ Save control register values b start_kernel #啟動內核 內核的第一個C函數:
總結:Head.s的作用
1、判斷內核支持不支持CPU
2、判斷內核支持不支持單板
3、建立頁表
4、使能MMU
5、跳轉到 start_kernel