WINCE4.2到5.0(五)
eboot备忘
本文原创 转载请保持完整性
eboot有全部源码,5.0下的没有4.2的功能全,所以继续用4.2下的eboot。具体的代码我都拷贝出来做了注释,也很好理解。有几个地方做个记录:
1.分区
分区有函数直接支持,在wince420/public/common/oak/drivers/ethdbg/bootpart/bootpart.cpp。先说说bootpart相关的几个函数:
BP_Init():初始化几个全局变量,给全局变量分配内存,重要的有
g_pbMBRSector:存放MBR的一块内存地址,在操作MBR相关动作时,作为存放地址。大小为一个SECTOR_SIZE(512 byte)
g_pbBlock:存放Block的地址,大小为一个BLOCK_SIZE(512*32)
g_pSectorInfoBuf:存放一个Block的Secto Spare,它的大小为32个SectorInfo大小=32*16
这几个变量在进行NandFlash相关操作时,经常会用到。也就是存放数据的地址。
BP_LowLevelFormat(): 格式化NandFlash,并初始化MBR后将MBR写入到IMAGE_START_BLOCK的第一个扇区。这个函数非常费时,花费时间跟 NandFlash的大小成正比。因为它调用了一个EraseBlocks()的函数,此EraseBlocks()函数会对要擦除的块的进行擦除测试, 块的每个页与Spare区进行写1测试、写0测试,然后再擦除。如果坏块,则标记出坏块的第一个扇区的Spare区的第6个字节为0x00(0xFF为好 块)。EraseBlock()在测试前会先检查要擦除的块是否为坏块,如果是则跳过。擦除功能是调用FMD_EraseBlock()进行的,此函数在 将块擦除的同时,也会将Spare区的前8个字节置成0xFF,也就是会对BadBlock位(Spare的第6个字节,具体可以查看 SectorInfo结构体的定义)设为"好块"。以前一直有个疑问:一个块在被标记为坏块后不就永远成为坏块了?其实不是这样的,任何调用 FMD_EraseBlock()函数的动作都会将块置成好块。注意这个BP_LowLevelFormat()函数的第一个参数 dwStartBlock是物理Block地址,而非逻辑块的地址。再说另一个跟此函数有关的注意事项:我在eboot中看到有个地方 (BP_OpenPartition)用0做为第一个参数进行调用,那不是连bootloader、eboot及相关的参数部份Block都要被擦除?也 不是的,上面说了EraseBlocks()会先检查此块是否是好块,幸运的是IMAGE_START_BLOCK之前的块都被定义成了坏块。那么如何保 证在以0为参数调用BP_LowLevelFormat()之前,它们都已经被定义成坏块了呢?有两个地方可以保证:1>bootloader在将 eboot写入到nandflash时会将eboot所占的block都定义成坏块。但这还不够,bootloader所占的块呢?2>在 eboot的BootMonitor()中使用"F"功能时,会将0~IMAGE_START_BLOCK-1所有的块(扇区)定义为坏块。
做 个测试:用JTAG烧录bootloader后启动(不能用bootloader烧录bootloader。第一个扇区的BadBlock 被标记为好块)。进入EBOOT后在BootMonitor()运行时不按"F"("F"功能主要是标记0~IMAGE_START_BLOCK-1块为 坏块,然后擦除第IMAGE_START_BLOCK及以后所有的块)、不按"9"("9"的功能是擦除、测试flash然后建立MBR,这里不建立 MBR),直接下载 NK。等启动后下电再次重启,现像是启动不了,因为第0块在分区时被擦除了,但其它eboot、参数块都还在。因为其它块是bootloader烧录的, 我的bootloader在写Secotr时会将所占的块标记为坏块。
原因是这样的:eboot中在下载完Image文件,写进 flash之前会调用BP_OpenPartition()函数进行分区,这个函数在发现无效的MBR(就是上面测试的eboot不按"9")后,直接用 0作为第一个参数调用BP_LowLvevlFormat()->EraseBlocks(),擦除之前会先进行判断是否为好块,坏块则跳过,而刚 好此时第0块为好块,所有就被擦除了。EBOOT中调用"F"后,会将0~IMAGE_START_SECTOR-1所有的块全部标记为坏块,这样,即使 在eboot中不使用"9"号功能(不建立MBR),IMAGE_START_BLOCK之前的块也不会 被之后调用的BP_LowLevelFormat()擦除。所以在拿到一块新flash后,在eboot中,你必须要使用"9"或"F"功能中的一个,当然也可以修改BP_OpenPartition()函数。
注意这里的BP_LowLevelFormat()函数,功能是擦除(仅好块,坏块跳过)、测试指定的块,然后建立MBR。两个地方调用:
1>在eboot的BootMonitor()函数使用"9"号功能时会调用,此时的第一个参数是Image_Start_Sector .如果换成0,也会将bootloader擦除的。
2>BP_OpenPartition()发现无效的MBR后,也会调用。此时的第一个参数是0,所以在这里,如果IMAGE_START_BLOCK之前有被标记为好的块,将会被擦除。
MBR是主引导记录的意思,它记录分区信息,可以理解为分区信息表。bootloader为nboot或其它。
BP_OpenPartition():此函数可用来进行分区操作,对应还有CreatePartition()。但CreatePartition是静态函数。推荐使用BP_OpenPartition()最后一个参数设成PART_OPEN_ALWAYS。切记注意:此BP_OpenPartition()函数的第一个参数为逻辑起始地址。eboot中的代码居然是错误的! 给 的参数是物理地址。虽然也能用,这样白白浪费了10个块,160K大小。不过也不是不能理解,因为我拿到手上的eboot可能是多少人修改后的代码了。逻 辑地址是相对于IMAGE_START_SECTOR的相对地址。eboot会使用Log2Phys()函数进行逻辑到物理地址的转换(如在使用 BP_ReadData,BP_WriteData,WriteLogicalNumbers等函数时)。更改成逻辑地址后,在WINCE控制面板的存储 管理器里也能正常显示NandFlash的容量大小了。BP_OpenPartition()先检查MBR是否正确,如果不正确根据传递的参数决定是否要 使用BP_LowLevelFormat()进行格式化与创建分区表MBR。如果MBR中已存在此分区,则返回分区信息句柄,否则调用 CreatePartition()进行创建分区。CreatePartition()先检查参数,如是否需要全部的剩余空间作为大小,是否有足够的空间 作为分区等等,再使用AddPartitionTableEntry()增加一个分区记录表,记录分区索引、起始扇区、扇区数等。注意这里的扇区地址与 CreatePartition()第一个参数也是逻辑地址。再判断是否是只读分区,如果是,则在属于此分区的每个扇区的dwReserved1标志写入 dwStartSector+序号。然后将MBR信息写进MBR扇区。
2. 关于下载Image部份,我认为还是比较简单的,可以很容易做个非ethernet的下载方法。如usb,蓝牙等.当然必须要脱离PB环境了.胶离PB环 境进行下也是很简单的,可以查看我以前的笔记.根据NK.bin文件结构,我写了一个查看Nk.bin文件的小工具,点此下载 ,注意非viewbin.exe类似.要源码的欢迎来邮索取.
3.NandFlash分配结枸,只是个顺序,除了0块外,其它内容的块地址无意义:
第0块:bootloader内容
第1块:TOC结构体.bootloader与eboot共同使用的参数.
第2~9块:eboot内容
第10块:MBR,实际上也就占了一个扇区大小
第11~镜像文件大小所占的块:Image文件,也就是nk.nb0的内容
之后的块~结束:我把它分了一个区用来存储文件
注:在我使用的系统中是这样的一个顺序,它不能说明什么,完全可以自已定义的.
4.eboot复杂在分区管理与坏块管理、全局变量比较多。最主要的是要找到这些函数分散在哪些文件中(可以参考sources文件)。不过我觉得,只要肯花时间,一定可以理清楚。