/u-boot/lib_arm/board.c
void start_armboot (void)
{
……
gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));
/********************************************************************
* 堆栈结构:
* _TEXT_BASE
* malloc area
* bdinfo //gd就为bdinfo高地址-gd大小的首地址
* CONFIG_STACKSIZE_IRQ
* CONFIG_STACKSIZE_FIQ
* #12
* SP
*********************************************************************/
memset ((void*)gd, 0, sizeof (gd_t)); // gd数据清零
gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
memset (gd->bd, 0, sizeof (bd_t));
/*********************
* bdinfo的结构:
* gd //在bdinfo高地址处向下
* bd
* ……
*********************/
monitor_flash_len = _bss_start - _armboot_start; //u-boot映像大小
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
if ((*init_fnc_ptr)() != 0) { //依次调用数组中的初始化函数
hang ();
}
}
……
/* main_loop() can return to retry autoboot, if so just run it again. */
for (;;) {
main_loop ();
}
/* NOTREACHED - no way out of command loop except booting */
}
typedef int (init_fnc_t) (void);
init_fnc_t *init_sequence[] = {
cpu_init, /* basic cpu dependent setup */
board_init, /* basic board dependent setup */
interrupt_init, /* set up exceptions */
env_init, /* initialize environment */
init_baudrate, /* initialze baudrate settings */
serial_init, /* serial communications setup */
console_init_f, /* stage 1 init of console */
display_banner, /* say that we are here */
dram_init, /* configure available RAM banks */
display_dram_config,
#if defined(CONFIG_VCMA9)
checkboard,
#endif
NULL,
};
/u-boot/common/cmd_bootm.c
image_header_t header;
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
……
image_header_t *hdr = &header;
……
if (argc < 2) { //只有一个参数时(即bootm 无参数)
addr = load_addr;
} else { //有两个参数时(即bootm argv[1]),该argv[1]在44b0中为0x50000
addr = simple_strtoul(argv[1], NULL, 16);
}
SHOW_BOOT_PROGRESS (1);
printf ("## Booting image at %08lx ...\n", addr);
……
memmove (&header, (char *)addr, sizeof(image_header_t));
//将addr处sizeof(image_header_t)大小的数据拷贝到header中。
//接下来就解析image_header_t结构体
/*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 */
uint32_t ih_ep; /* Entry Point Address */
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;*/
if (ntohl(hdr->ih_magic) != IH_MAGIC) //首先解析ih_magic
{ ……}
SHOW_BOOT_PROGRESS (2);
/*下面进行整个镜像校验处理*/
data = (ulong)&header;
len = sizeof(image_header_t);
checksum = ntohl(hdr->ih_hcrc);
hdr->ih_hcrc = 0;
if (crc32 (0, (char *)data, len) != checksum) {
puts ("Bad Header Checksum\n");
SHOW_BOOT_PROGRESS (-2);
return 1;
}
SHOW_BOOT_PROGRESS (3);
print_image_hdr ((image_header_t *)addr);
//打印下面的相关信息
Image Name: uClinux_test_cqy
Image Type: ARM Linux Kernel Image (gzip compressed)
Data Size: 226491 Bytes = 221 kB = 0 MB
Load Address: c0008000
Entry Point: c0008000
/*下面进行内核校验处理*/
data = addr + sizeof(image_header_t);
len = ntohl(hdr->ih_size);
if (verify) {
puts (" Verifying Checksum ... ");
if (crc32 (0, (char *)data, len) != ntohl(hdr->ih_dcrc)) {
printf ("Bad Data CRC\n");
SHOW_BOOT_PROGRESS (-3);
return 1;
}
puts ("OK\n");
}
SHOW_BOOT_PROGRESS (4);
len_ptr = (ulong *)data; //内核首地址
SHOW_BOOT_PROGRESS (5);
/*下面解析内核类型*/
switch (hdr->ih_type) {
……
case IH_TYPE_KERNEL:
name = "Kernel Image";
break;
……}
SHOW_BOOT_PROGRESS (6);
/*解析压缩类型*/
switch (hdr->ih_comp) {
……
case IH_COMP_GZIP:
printf (" Uncompressing %s ... ", name);
if (gunzip ((void *)ntohl(hdr->ih_load), unc_len,
(uchar *)data, (int *)&len) != 0) {
puts ("GUNZIP ERROR - must RESET board to recover\n");
SHOW_BOOT_PROGRESS (-6);
do_reset (cmdtp, flag, argc, argv);
}
break;
……}
puts ("OK\n");
SHOW_BOOT_PROGRESS (7);
/*下面解析os类型*/
switch (hdr->ih_os) {
default: /* handled by (original) Linux case */
case IH_OS_LINUX:
do_bootm_linux (cmdtp, flag, argc, argv,\
addr, len_ptr, verify); //跳转到do_bootm_linux准备linux启动参数
break;
……}
return 1;
}
/u-boot/lib_arm/ armlinux.c //设置传递给linux的参数并启动linux
void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
ulong addr, ulong *len_ptr, int verify){
……
void (*theKernel)(int zero, int arch, uint params);
bd_t *bd = gd->bd;
#ifdef CONFIG_CMDLINE_TAG
char *commandline = getenv ("bootargs");
#endif
theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);
……
setup_start_tag (bd);
#ifdef CONFIG_SETUP_MEMORY_TAGS
setup_memory_tags (bd);
#endif
#ifdef CONFIG_CMDLINE_TAG
setup_commandline_tag (bd, commandline);
#endif
setup_end_tag (bd);
/* we assume that the kernel is in place */
printf ("\nStarting kernel ...\n\n");
cleanup_before_linux ();
theKernel (0, bd->bi_arch_number, bd->bi_boot_params);
//跳转到linux内核运行,linux启动
}
static void setup_start_tag (bd_t *bd)
{
params = (struct tag *) bd->bi_boot_params; //是在board_init函数中被赋值的
params->hdr.tag = ATAG_CORE;
params->hdr.size = tag_size (tag_core);
params->u.core.flags = 0;
params->u.core.pagesize = 0;
params->u.core.rootdev = 0;
params = tag_next (params);
}
static void setup_memory_tags (bd_t *bd)
{
int i;
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
params->hdr.tag = ATAG_MEM;
params->hdr.size = tag_size (tag_mem32);
params->u.mem.start = bd->bi_dram[i].start; //是在dram_init函数中被赋值的
params->u.mem.size = bd->bi_dram[i].size;
params = tag_next (params);
}
}
static void setup_commandline_tag (bd_t *bd, char *commandline)
{
char *p;
if (!commandline)
return;
/* eat leading white space */
for (p = commandline; *p == ' '; p++);
/* skip non-existent command lines so the kernel will still
* use its default command line.*/
if (*p == '\0')return;
params->hdr.tag = ATAG_CMDLINE;
params->hdr.size =(sizeof (struct tag_header) + strlen (p) + 1 + 4) >> 2;
strcpy (params->u.cmdline.cmdline, p);
params = tag_next (params);
}
static void setup_end_tag (bd_t *bd)
{
params->hdr.tag = ATAG_NONE;
params->hdr.size = 0;
}
/u-boot/borad/$(BOARDDIR)/s3c44b0.c
int board_init (void)
{
DECLARE_GLOBAL_DATA_PTR;
……
/* arch number MACH_TYPE_MBA44B0 */
gd->bd->bi_arch_number = 178;
/* location of boot parameters */
gd->bd->bi_boot_params = 0x0c000100;
return 0;
}
int dram_init (void)
{
DECLARE_GLOBAL_DATA_PTR;
gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
return (0);
}
// PHYS_SDRAM是在ITSN_s3c44b0.h中被定义的
#define PHYS_SDRAM_1 0x0c000000 /* SDRAM Bank #1 */
#define PHYS_SDRAM_1_SIZE 0x00800000 /* 8 MB */
uclinux很久前笔记5
最新推荐文章于 2021-12-03 23:18:07 发布