load address、entry point、 bootm address以及kernel运行地址
load address:加载地址 load_addr mkimage -a
entry point: 入口地址 entry_point mkimage -e
bootm address:bootm 命令后面紧跟的地址,也就是加载地址 addr
kernel运行地址:zImage自解压后将kernel解压到实际运行的物理地址
所谓加载地址是指bootm将内核镜像文件拷贝到内存空间的位置,入口地址是加载地址确定后bootm从内核镜像文件中开始执行的地址
理论上 zImage转化为uImage需要添加0x40长度的header 头, 所以entry_point == load_addr + 0x40;
bootm对uImage处理:
1.addr == load_addr
也就是说bootm后的地址等于加载地址,即已经将内核镜像(带头部)加载到-a 指定的内存地址load_addr中,
此时:addr == load_addr == entry_point - 0x40;
2.addr != load_addr:
从addr所在地址提取取出内核镜像头部信息中进行处理, 并将去掉头部的内核直接加载到-a指定的地址load_addr。然后进入load_addr进行内核引导(entry_point)。所以此时地址:
addr != load_addr == entry_point
switch (comp) { case IH_COMP_NONE: if (load == blob_start || load == image_start) //addr == load_addr == entry_point - 0x40 { printf(" XIP %s ... ", type_name); no_overlap = 1; } else //addr != load_addr == entry_point { printf(" Loading %s ... ", type_name); memmove_wd((void *)load, (void *)image_start,image_len, CHUNKSZ); } *load_end = load + image_len; puts("OK\n"); break;
..... }
制作镜像头以及下载地址就有两种情况:
1) mkimage -n 'linux-2.6.14' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008000 -d zImage uImage
加载地址和入口地址相同 load_addr == entry_point
tftp 0x31000000 uImage
bootm 0x31000000
下载地址可以任意放.
2) mkimage -n 'linux-2.6.14' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008040 -d zImage uImage
入口地址在加载地址后面64个字节 entry_point == load_addr + 0x40
tftp 0x30008000 uImage
bootm 0x30008000
下载地址一定要在指定的加载地址上.
至于kernel的运行地址,其与前3个地址没有关系,除了要避免内存覆盖导致解压后kernel不完整的情况。zImage的头部有地址无关的自解压程序,因此刚开始执行的时候,zImage所在的内存地址(entry point)不需要同编译kernel的地址相同。自解压程序会把kernel解压到编译时指定的物理地址,然后开始地址相关代码的执行。在开启MMU之前,kernel都是直接使用物理地址