第一阶段完了之后,就跳到了start_armboot这个函数里面了。从这里开始就属于第二阶段了。
这个阶段的流程如下:
1.首先是定义了gd,bd结构体指针,并且将他们指向在第一阶段中已经分配好的对应的空间。
2.顺序执行init_sequence中的初始化函数。
3.从NAND FLASH中读取环境变量至SDRAM中。
4.初始化串口。
5.从环境变量中获取load_addr和bootfile这两个变量的值。
6.初始化网卡。
7.进入主循环等待用户输入命令。
第二阶段另外一个比较重要的东西就是命令系统了,一般最常用到的命令就是设置bootargs以及使用bootm来启动内核了。设置bootargs就是把相应的值写入全局变量,没有什么太多可说的,所以先分析一下bootm的流程。
先来个与这个流程有关的结构体。
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;
我们知道,UBoot所启动的镜像文件是linux的核加上一部分头部信息组合而来,而与这个头部信息相对应的就是这个结构体。而我制作UBoot启动镜像文件所使用的命令如下:mkimage -n ‘linux-2.6.28′ -A arm -O linux -T kernel -C none -a 30008000 -e 30008000 -d zImage zImage.img
从这里可以看出,linux内核最终的加载地址是0x30008000,最终的入口地址是0x30008000。也就是UBoot会把内核加载到0x30008000这个地址,然后跳转至0x30008000执行。我所使用的这两个地址是相同的,看样子其他的芯片有可能这两个地址是不相同的,暂时不管了。
然后我使用tftp把上面生成的zImage.img下载至SDRAM的0x30200000这个地址,再使用bootm 0x30200000命令就进入了bootm函数了。
进入bootm函数之后,首先就是把zImage.img中的头文件赋值给上面的这个结构体,然后把内核拷贝到加载地址上,最后进入do_bootm_linux()来做进入内核前最后的准备工作。
在do_bootm_linux()中,主要做了这么几件事,获取machid,设置参数标记列表,禁中断和cache。做完这些之后就跳至内核的入口地址,需要注意一下所传的三个参数。这些动作都是按照linux内核的要求来的,具体要求可以在linux源码中的head.S文件的注释中看到,现摘抄一点:
/* * Kernel startup entry point. * --------------------------- * * This is normally called from the decompressor code. The requirements * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0, * r1 = machine nr, r2 = atags pointer. * * This code is mostly position independent, so if you link the kernel at * 0xc0008000, you call this at __pa(0xc0008000). * * See linux/arch/arm/tools/mach-types for the complete list of machine * numbers for r1. * * We're trying to keep crap to a minimum; DO NOT add any machine specific * crap here - that's what the boot loader (or in extreme, well justified * circumstances, zImage) is for. */
至此,UBoot的工作已经做完,在linux启动起来之后,UBoot所占用的SDRAM也会被清掉,那就彻底的灰飞烟灭了。