u-boot/armlinux.c 的theKernel (0, bd->bi_arch_number, bd->bi_boot_params); 是uboot启动时的uboot的结束点,kernel的开始点,bd->bi_arch_number指的是支持的挡板类型。
ENTRY(stext)
msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
@ 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
movs r8, r5@ invalid machine (r5=0)?
beq __error_a@ yes, error 'a'
bl __create_page_tables
__lookup_processor_type 是否支持该cpu
__lookup_machine_type 是否支持该单板
gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;(board\smdk2410\smdk2410.c)(2410的cpu类型)
#define MACH_TYPE_SMDK2410 193 (include\asm-arm\mach-types.h) (2410的cpu类型) 在uboot中
__lookup_machine_type:
adr r3, 3b //3b表示的是地址 (3:.long)如下
ldmia r3, {r4, r5, r6}
sub r3, r3, r4
3: .long .
.long __arch_info_begin
.long __arch_info_end
(linux\arch\arm\kernel\vmlinux.lds.S) :
__arch_info_begin = .;
*(.arch.info.init)
__arch_info_end = .;
#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 \
};
MACHINE_START(S3C2440, "SMDK2440")
/* Maintainer: Ben Dooks
*/ .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
struct machine_desc {
/*
* Note! The first four elements are used
* by assembler code in head-armv.S
*/
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*/
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);
};
uboot传入的参数bd->bi_arch_number正好和内核中的machine_desc类型(内核中编辑进去谁的machine_desc就表示支持哪种单板)对应。驱动内核时,内核的类型要和uboot传入的一一比较,看是否支持单板。
1 判断是否支持内核
2 判断是否支持单板
3 建立页表,
4 启动mmu 因为原来uboot的地址和单板实际地址不一样要地址映射
5 跳到start_kernel
arch/arm/kernel/head.S
start_kernel
setup_arch //解析uboot传入的启动参数
setup_command_line //解析uboot传入的启动参数
rest_init
kernel_init
prepare_namespace
mount_root //挂接根文件系统
init_post
我们的uboot,内核,文件系统是在flash里写死的那么程序怎么知道内核的地址呢。因为在程序里有boot,内核,文件系统的地址;我们烧写flash的时候是根据代码写的地址烧写的。
问:我如何查找地址表呢?
答:开机启动时,串口肯定会打印出内核的相关设置信息,如:
然后可以在源代码中查找“bootloader”字样(grep “”bootloader“” * -nR),查看在哪个文件夹中有(arch/arm/plat-s3c24xx/common_amdk.c)
uboot在.arch.info.init 段处存放支持的类型,
每一个machone_desc都会被放在.arch.info.init 段处,其指的是内核支持的芯片类型,然后__lookup_processor_type函数挨着比较,没有一样的说明不支持。