在下载了内核镜像之后,进入到最后一个阶段
OEMLaunch
,在这里将完成
eboot
的最后一部分任务,并将跳转到
OAL.exe
开始启动内核。还是先给出该函数的源码如下:
先来看看这几个参数,都是从
DownloadImage
函数获得的,
dwImageStart
是镜像的起始位置,
dwImageLength
是镜像的大小,
dwLaunchAddr
是内核的启动地址,
pRomHdr
指向
TOC
数据。
1273
行判断是否需要将镜像文件写入到
nand flash
中,当前镜像只是下载到了
RAM
中,一般都会写入
flash
中,否则掉电重启后,
RAM
中的镜像就不存在了,又需要重新下载镜像实现启动。
1278
到
1342
行根据镜像的类型是
stepldr
、
bootloader
还是
nk
分别写入对应的
nand flash
位置。如果镜像类型是
stepldr
或者
bootloader
,通过函数
WriteRawImageToBootMedia
完成实现的
flash
写操作,主要是完成
nand Flash
的坏块检测、块擦除、写块、读块、设置
TOC
等操作,有兴趣的可以查看源码,该函数位于文件
WINCEROOT\SMDK6410\SRC\BOOTLOADER\EBOOT\Nand.cpp
中。如果镜像类型是
nk
,则通过函数
WriteOSImageToBootMedia
到
nand
中,该函数放到后面详细解析。由于
TOC
记录的数据与
bootloader
、
NK
都有关系,所以如果是这两种镜像类型,在写入
nand flash
以后还需要更新
TOC
中的数据信息,如
TOC_Write
函数的调用。而
stepldr
则与
TOC
无关,无需更新。
1343
到
1360
行则是判断为不需要将镜像写入
nand flash
时的处理情况,从代码中可以看出,如果镜像是
stepldr
或
bootloader
,则必须写入
flash
中,否则提示无法从
RAM
中启动。
1366
到
1391
行是当采用网卡下载镜像时的处理,还包含了关于
KITL
的处理,由于本平台是从
USB
下载,这部分不会执行,所以不作详细的分析。
1396
到
1404
行是将内核的启动地址记录到
TOC
数据中,这样在下一次跳转到内核镜像的时候就不需要重新获取跳转地址,而是直接按
TOC
记录的进行跳转。
1408
到
1413
行中,
dwPhysLaunchAddr
便是启动内核的物理地址,作为
Launch
函数的输入参数完成跳转到内核启动。
Launch
函数是汇编实现的,在介绍
startup.s
的博文中提到过。
到这里
eboot
的全部任务就完成了。
下面解析一下
WriteOSImageToBootMedia
函数的源码,该函数位于文件
WINCEROOT\SMDK6410\SRC\BOOTLOADER\EBOOT\Nand.cpp
中,下面给出源码:
364
到
372
行是判断
TOC
数据是否有效,这种代码在
eboot
的经常会用到。
377
到
414
行用来检测当前下载的镜像中是否包含
nk.exe
,并返回其扩展指针。主要通过
GetKernelExtPointer
函数来完成此任务。
418
到
445
行负责检查用来的创建
BINFS
分区的空间是否足够。
451
到
461
行通过函数
BP_OpenPartition
来在
nand flash
设备上创建分区。该函数在文件
WINCEROOT\SMDK6410\SRC\BOOTLOADER\EBOOT\Bootpart1.cpp
中。第一个参数
dwStartSector
为起始逻辑扇区,
(IMAGE_START_BLOCK+1)*PAGES_PER_BLOCK
即使
OSImage
所在的
Block
,加
1
是因为
MBR
保存在
IMAGE_START_BLOCK
开始的第一个
block
中;第二个参数
dwNumSectors
为该分区包含多少个扇区,根据下载的
NK.BIN
需要的
page
数来计算;第三个参数
dwPartType
表示分区的类型,
PART_BINFS
表示要创建
BINFS
格式的文件系统;第四个参数
fActive
为是否激活该分区,
TRUE
表明激活;第五个参数
dwCreationFlags
标识是创建分区还是打开分区,
PART_OPEN_ALWAYS
表示如果不存在这个分区则创建,如果存在则打开。最后返回该分区的句柄。
465
到
524
行将
OSImage
写入到
BINFS
分区当中。由于只是单个的
NK.BIN
文件,所以
g_BINRegionInfo.dwNumRegions = 1
,
for
循环只进行一遍。
476
到
480
行调用函数
BP_SetDataPointer
设置该分区的数据指针实际上数据指针是指在该分区中下一次被读或写的位置。该函数位于文件
WINCEROOT\SMDK6410\SRC\BOOTLOADER\EBOOT\Bootpart1.cpp
中。第一个参数
hPartition
为被创建分区的句柄,第二个参数
dwAddress
为数据指针的新位置。一般会配合
BP_ReadData()
和
BP_WriteData()
两个函数来用。
484
到
488
行调用函数
BP_WriteData
向该分区写入数据,即将
OSImage
写入
BINFS
分区中。该函数位于
WINCEROOT\SMDK6410\SRC\BOOTLOADER\EBOOT\Bootpart1.cpp
文件中。第一个参数
hPartition
为被创建的分区的句柄,第二个参数
pbBuffer
为要写入数据的
Buffer
,第三个参数
dwLength
为要写入数据的长度。
492
到
524
行完成更新
TOC
并把内核拷贝到
SDRAM
中,为下一步的跳转执行做准备。
528
到
537
行用来将剩余的
nand flash
空间创建扩展分区,仍然调用
BP_OpenPartition
来完成,分区类型变为了
PART_DOS32
表明是创建
FAT32
文件系统。
本文转自jazka 51CTO博客,原文链接:http://blog.51cto.com/jazka/612722,如需转载请自行联系原作者