uboot流程分爲第一階段(芯片初始化、重定位等)和第二階段(各項功能),在第二階段的最後,啓動內核
1、s = getenv ("bootcmd"); //"nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0"
2、run_command (s, 0);
讀內核到SDRAM:
(1)NAND FLASH分區
#define MTDPARTS_DEFAULT "mtdparts=nandflash0:256k@0(bootloader)," \"128k(params)," \
"2m(kernel)," \
"-(root)"
(2)nand read.jffs2不用考慮地址對齊
nand read.jffs2 0x30007FC0 0x60000 0x200000
bootm流程:
1、uImage包含頭和真正的內核,頭大小64字節,0x30007FC0 + 64 = 0x30008000。
如果當前地址和頭裏面的裝載地址不一致,do_bootm函數會將uImage移動到頭裏面指定的裝載地址,一般不用移動。
typedef struct image_header {
uint32_t ih_magic; /* Image Header Magic Number */
uint32_t ih_hcrc; /* Image Header CRC Checksum */
uint32_t ih_time; /* Image Creation Timestamp */
uint32_t ih_size; /* Image Data Size */
uint32_t ih_load; /* Data Load Address */ //0x30007FC0
uint32_t ih_ep; /* Entry Point Address */ //0x30008000
uint32_t ih_dcrc; /* Image Data CRC Checksum */
uint8_t ih_os; /* Operating System */
uint8_t ih_arch; /* CPU architecture */
uint8_t ih_type; /* Image Type */
uint8_t ih_comp; /* Compression Type */
uint8_t ih_name[IH_NMLEN]; /* Image Name */
} image_header_t;
2、do_bootm_linux
(1)theKernel指向頭裏面的入口地址
theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);
(2)設置參數,參數存放在gd->bd->bi_boot_params = 0x30000100
setup_start_tag (bd);
setup_memory_tags (bd); //start = 0x30000000, size = 0x4000000(64M)
setup_commandline_tag (bd, commandline); //"noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0"
setup_end_tag (bd);
(3)跳入內核
theKernel (0, bd->bi_arch_number, bd->bi_boot_params);