为了方便分析uboot源代码 我们需要先编译 再分析 这样可以降低分析难度 不然很多同名函数都不知道用的哪一个。编译完成后最终要的两个辅助分析文件.map文件以及链接文件,通过map文件我们可以知道那个文件被编译,通过链接文件我们可以获得中体的一个情况。
5 编译流程如下(linux uboot 以及 buildroot基本上都类似 先加载默认配置 然后再配置 最后编译)
make xxx_deconfig
make menuconfig
make
4 imx6ull uboot启动流程
(1) bootcmd启动指令的作用是,读取linux内核到0x30007FC0的位置,读取设备树到0x32000000的位置,最后执行bootm 0x30007FC0 - 0x32000000指令,该指令最终会调用该do_bootm_linux()函数,该函数随着uboot的版本差异会发生变化,该函数一般配置标记列表或者配置设备树相关信息,最后调用kernel_entry(0, machid, r2)启动linux内核
(2) 由于一开始只能移一部分uboot代码,所以在代码重定位之前所有的全局变量都不能用,在c函数运行之前必须指定堆栈指针,此时的堆栈指针位于内部RAM。重定位之后,需要使用绝对跳转指令(ldr pc )跳转到SDRAM中。
3 在嵌入系统的固态存储设备上有相应的分区来存储它们,如图所示为一个典型的分区结构。
“Bootparameters”分区中放一些可设置的参数,比如IP地址、串口波特率、要传递给内核的命令行参数等。正常启动过程中,Bootloader首先运行,然后它将内核复制到内存中 (也有些内核可以在固态存储设备上直接运行),并且在内存某个固定的地址设置好要传递给内核的参数,最后后运行内核。内核启动之后,它会挂接(mount)根文件系统(“Root filesystem”),启动文件系统中的应用程序。
2 配置参数
(1)ENV_IS_EMBEDDED定义:这种情况的环境变量在flash上存着(但是占了flash一个扇区),并且随着代码段(因为环境变量区嵌在代码段内)在start.s重定位时一同载入内存。在环境变量初始化时候,如果这部分能通过校验,就不需要先在堆区开辟空间然后搬移的工作,而是直接使用这部分环境变量(省了搬移工作)。倘若不能通过校验,则使用默认环境变量放到重定位时环境变量所占的空间中。
ENV_IS_EMBEDDED未定义:env_init()函数使用默认的环境变量。env_relocate()函数:先malloc一段内存,后将环境变量从nand/eeprom/nor指定位置读到申请的内存中。
env_init()函数的作用是校验环境变量是否有效,无效使用默认环境变量,有效使用保存的环境变量。
env_relocate()函数:先malloc一段内存,后将环境变量从nand/eeprom/nor指定位置读到申请的内存中。(如果内嵌环境变量校验成功,就不在需要malloc内存了)
#define CFG_ENV_IS_IN_NAND 1 //声明环境变量存储在nandflash中 #define CFG_ENV_OFFSET 0x40000 //环境变量偏移地址 #define CFG_ENV_SIZE64 0xc000 // Total Size of Environment Sector
(2) bootcmd :自动启动时默认执行的一些命令
#define CONFIG_BOOTCOMMAND "nand read.jffs2 0x32000000 kernel; bootm 0x32000000" 将nand flash中的kernel复制到0x32000000,然后执行bootm 0x32000000启动内核
(3) bootargs:启动参数
root //用来指定rootfs(根文件系统)的位置 rootfstype //根文件系统类型(若根文件系统是ext2,此选项可省略,其他类型的根文件系统需要此选项) console //控制终端 initrd,noinitrd//当你没有使用ramdisk启动系统的时候,你需要使用noinitrd这个参数,但是如果使用了的话,就需要指定initrd=r_addr,size, r_addr表示initrd在内存中的位置,size表示initrd的大小。 init//内核启起来后,进入系统中运行的第一个进程,一般init=/linuxrc mem//内存大小
#define CONFIG_BOOTARGS "noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0" //根文件系统位于/dev/mtdblock2 //在文件系统挂载后,运行的第一个程序就是根目录下的linuxrc //控制台为ttySAC0。