一、BOOTLOADER启动过程
1.建立和初始化RAM。
要求:必须
功能:探测所有的RAM位置和大小,并对RAM进行初始化。
2.初始化一个串口。
要求:可选,建议
功能:Bootloader应该初始化并启动一个串口。这可以让内核的串口驱动自动探测哪个串口作为内核的控制台。另外也可以通过给内核传递“console=”参数完成此工作。
3.检测机器的系统结构。
要求:必须
功能:Bootloader应该通过某种方法探测机器类型,最后传递给内核一个MACH_TYPE_xxx值,这些值参看linux/arch/arm/tools/mach-types。
4.建立内核的tagged list。
要求:必须
功能:Bootloader必须创建和初始化内核的tagged list。一个合法的tagged list开始于ATAG_CORE并结束于ATAG_NONE。ATAG_CORE tag可以为空。一个空的ATAG_CORE tag的size字段设为“2”(0x00000002)。ATAG_NONE 的size字段必须设为“0”。tagged list可以有任意多的tag。Bootloader必须至少传递系统内存的大小和位置,以及根文件系统的位置,一个最小化的tagged list应该像如下:
+-----------+
base -> | ATAG_CORE | |
+-----------+ |
| ATAG_MEM | | increasing address
+-----------+ |
| ATAG_NONE | |
+-----------+ v
tagged list应该放在内核解压时和initrd的”bootp”程序都不会覆盖的内存区域。建议放在RAM的起始的16K大小的地方。
5.调用内核镜像。
要求:必须
功能:可以从flash调用内核,也可以从系统RAM中调用内核。对于后者需要注意,内核使用内核镜像以下的16K内存作为页表,建议把内核起始放在RAM的32K处。无论是哪种方法,如下条件必须满足:
- CPU register settings
r0 = 0,
r1 = machine type number discovered in (3) above.
r2 = physical address of tagged list in system RAM.
- CPU mode
All forms of interrupts must be disabled (IRQs and FIQs)
The CPU must be in SVC mode. (A special exception exists for Angel)
- Caches, MMUs
The MMU must be off.
Instruction cache may be on or off.
Data cache must be off.
- The boot loader is expected to call the kernel image by jumping
directly to the first instruction of the kernel image.
二、ARM LINUX启动
LINUX启动后执行的第一个文件是arch/arm/kernel下的head-($PROCESSOR).S文件,PROCESSOR是由include/linux/autoconf.h中#define CONFIG_CPU_32 1得到了在arch/arm/Makefile中通过
ifeq ($(CONFIG_CPU_32),y)
PROCESSOR = armv
TEXTADDR = 0xC0008000
LDSCRIPT = arch/arm/vmlinux-armv.lds.in
endif
得到的。
但是我看了一下linux 2.6.25.3内核中没有这个东西。
但我还是先分析一下arch/arm/kernel/head-armv.S这个文件:
后悔了,看来不太可行。为什么大家都说文件中有stext呢?我怎么就没看到??
终于找到了一个网站讨论2.6内核的。
ARM Linux Boot Sequence
The following traces the Linux boot sequence for ARM-based systems in the 2.6.18 kernel. It looks at just the earliest stages of the boot process, until the generic non-processor-specific start_kernel function is called. The line numbers of each statement are in parenthese at the end of the line; the kernel source itself can be conveniently browsed on the .
zImage decompression
- arch/arm/boot/compressed/head.S: start (108)
- First code executed, jumped to by the bootloader, at label "start" (108)
- save contents of registers r1 and r2 in r7 and r8 to save off architecture ID and atags pointer passed in by bootloader (118)
- execute arch-specific code (inserted at 146)
- arch/arm/boot/compressed/head-xscale.S or other arch-specific code file
- added to build in arch/arm/boot/compressed/Makefile
- linked into head.S by linker section declaration: .section “start”
- flush cache, turn off cache and MMU
- load registers with stored parameters (152)
- sp = stack pointer for decompression code (152)
- r4 = zreladdr = kernel entry point physical address
- check if running at link address, and fix up global offset table if not (196)
- zero decompression bss (205)
- call cache_on to turn on cache (218)
- defined at arch/arm/boot/compressed/head.S (320)
- call call_cache_fn to turn on cache as appropriate for processor variant
- defined at arch/arm/boot/compressed/head.S (505)
- walk through proc_types list (530) until find corresponding processor
- call cache-on function in list item corresponding to processor (511)
- for ARMv5tej core, cache_on function is __armv4_mmu_cache_on (417)
- call setup_mmu to set up initial page tables since MMU must be on for cache to be on (419)
- turn on cache and MMU (426)
- check to make sure won't overwrite image during decompression; assume not for this trace (232)
- call decompress_kernel to decompress kernel to RAM (277)
- branch to call_kernel (278)
- call cache_clean_flush to flush cache contents to RAM (484)
- call cache_off to turn cache off as expected by kernel initialization routines (485)
- jump to start of kernel in RAM (489)
- jump to address in r4 = zreladdr from previous load
- zreladdr = ZRELADDR = zreladdr-y
- zreladdr-y specified in arch/arm/mach-vx115/Makefile.boot
ARM-specific kernel code
- arch/arm/kernel/head.S: stext (72)
- call __lookup_processor_type (76)
- defined in arch/arm/kernel/head-common.S (146)
- search list of supported processor types __proc_info_begin (176)
- kernel may be built to support more than one processor type
- list of proc_info_list structs
- defined in arch/arm/mm/proc-arm926.S (467) and other corresponding proc-*.S files
- linked into list by section declaration: .section ".proc.info.init"
- return pointer to proc_info_list struct corresponding to processor if found, or loop in error if not
- call __lookup_machine_type (79)
- defined in arch/arm/kernel/head-common.S (194)
- search list of supported machines (boards)
- kernel may be built to support more than one board
- list of machine_desc structs
- machine_desc struct for boards defined in board-specific file vx115_vep.c
- linked into list by section declaration that's part of MACHINE_DESC macro
- return pointer to machine_desc struct corresponding to machine (board)
- call __create_page_tables to set up initial MMU tables (82)
- set lr to __enable_mmu, r13 to address of __switch_data (91, 93)
- lr and r13 used for jumps after the following calls
- __switch_data defined in arch/arm/kernel/head-common.S (15)
- call the __cpu_flush function pointer in the previously returned proc_info_list struct (94)
- offset is #PROCINFO_INITFUNC into struct
- this function is __arm926_setup for the ARM 926EJ-S, defined in arch/arm/mm/proc-arm926.S (392)
- initialize caches, writebuffer
- jump to lr, previously set to address of __enable_mmu
- __enable_mmu (147)
- set page table pointer (TTB) in MMU hardware so it knows where to start page-table walks (167)
- enable MMU so running with virtual addresses (185)
- jump to r13, previously set to address of __switch_data, whose first field is address of __mmap_switched
- __switch_data defined in arch/arm/kernel/head-common.S (15)
- arch/arm/kernel/head-common.S: __mmap_switched (35)
- copy data segment to RAM (39)
- zero BSS (45)
- branch to start_kernel (55)
Processor-independent kernel code
- init/main.c: start_kernel (456)