mrc p15, 0, r9, c0, c0 @ get processor id bl __lookup_processor_type bl __lookup_machine_type //判断能否支持该cpu及machine,看① bl __create_page_tables //因链接地址是(0xc0000000) + 0x00008000!=物理地址ox30000000 ldr r13, __switch_data @ address to jump to after mmu has been enabled adr lr, __enable_mmu |
__mmap_switched:
b start_kernel start_kernel //第一个c函数,Main.c (init) printk(linux_banner); //输出内核版本信息 setup_arch parse_cmdline setup_command_line //处理u-boot传入参数 do_early_param //从__setup_start到__setup_end调用非early属性setup_func函数,看② parse_early_param unknown_bootoption obsolete_checksetup //从__setup_start到__setup_end调用early属性setup_func函数,看② rest_init kernel_thread(kernel_init,… prepare_namespace // decide what/where to mount,看② mount_root init_post sys_open((const char __user *) "/dev/console", O_RDWR, 0) run_init_process("/etc/init"); ——————/① 3: .long . //编译到此处时虚拟地址 .long __arch_info_begin .long __arch_info_end __lookup_machine_type: //arch/arm/kernel/head-common.S adr r3, 3b //得到标号3所处物理地址,由pc+offset决定,此时mmu还未启动 ldmia r3, {r4, r5, r6} //分别存入 sub r3, r3, r4 @ get offset between virt&phys add r5, r5, r3 @ convert virt addresses to,获得__arch_info_begin物理地址 add r6, r6, r3 @ physical address space 1: ldr r3, [r5, #MACHINFO_TYPE] @ get machine type teq r3, r1 @ matches loader number? r1存放u-boot传入机器id 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 __arch_info_begin = .; //arch/arm/kernel/vmlinux.lds *(.arch.info.init) __arch_info_end = .; #define MACHINE_START(_type,_name) \ //include/asm-arm/mach/arch.h static const struct machine_desc __mach_desc_##_type \ __used \ __attribute__((__section__(".arch.info.init"))) = { \ .nr = MACH_TYPE_##_type, \ .name = _name, #define MACHINE_END }; MACHINE_START(S3C2440, "SMDK2440") //Mach-smdk2440.c (arch\arm\mach-s3c2440)板文件 .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 \ __used \ __attribute__((__section__(".arch.info.init"))) = { \ .nr = MACH_TYPE_ S3C2440, \ //机器id .name = "SMDK2440", .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, //u-boot传入参数位置 .init_irq = s3c24xx_init_irq, .map_io = smdk2440_map_io, .init_machine = smdk2440_machine_init, .timer = &s3c24xx_timer, }; |
内核配置结束,能支持几种单板,便有几个该结构,全部放于.arch.info.init段
内核启动时,将u-boot传入机器id与.arch.info.init段所有nr比较,若相等则调用对应初始化函数
——————/② root_device_name = saved_root_name; ROOT_DEV = name_to_dev_t(root_device_name); mount_root(); 搜saved_root_name: static char __initdata saved_root_name[64]; static int __init root_dev_setup(char *line) { strlcpy(saved_root_name, line, sizeof(saved_root_name)); return 1; } __setup("root=", root_dev_setup); //宏,据root=/dev/mtdblock3,调root_dev_setup,且line指向/dev/mtdblock3 #define __setup(str, fn) __setup_param(str, fn, fn, 0) //init.h #define __setup_param(str, unique_id, fn, early) \ static char __setup_str_##unique_id[] __initdata = str; \ static struct obs_kernel_param __setup_##unique_id \ __attribute_used__ \ __attribute__((__section__(".init.setup"))) \ __attribute__((aligned((sizeof(long))))) \ = { __setup_str_##unique_id, fn, early } 解压后: static char __setup_str_root_dev_setup[] __initdata = "root="; static struct obs_kernel_param __setup_root_dev_setup \ __attribute_used__ \ __attribute__((__section__(".init.setup"))) \ __attribute__((aligned((sizeof(long))))) \ = { __setup_str_root_dev_setup, root_dev_setup, 0} |
链接脚本中:
__setup_start.;
*(.init.setup);
__setup_end.;