WINCE系统启动时是否clean boot
*******************************LoongEmbedded************************
作者:LoongEmbedded
时间:2010.12.09
类别:WINCE嵌入式系统
********************************LoongEmbedded***********************
这里的clean boot可以理解为清除system.hv和user.hv
本系统基于nandflash出去NK.bin之外的空间mount成盘符ResidentFlash,其中system.hv和user.hv就保存在这个文件夹中,也即是保存在nandflash中,看下图
图1
如果clean boot option的值是FALSE,那么保存在ResidentFlash文件夹的内容在重启之后不会丢失;而如果clean boot option的值是TRUE,那么保存在ResidentFlash文件夹的内容在重启之后就会丢失,这是因为系统在启动的时候,Filesys.dll通过删除hive-base注册表的数据所保存在的文件并且重新创建它们来执行clean boot (因为基于Hive的注册表把注册表数据存放在文件系统的文件上,也就是保存在永久性存储介质中,在这里是nandflash),那具体是怎么实现这个动作的呢?
Filesys.dll在初始化基于hive的注册表的时候,Filesys.dll调用OEMIoControl来查询是否需要清除保存在block设备上的hv文件,其CODE代码为IOCTL_HAL_GET_HIVE_CLEAN_FLAG,它的输入参数lpInBuf固定为HIVECLEANFLAG_SYSTEM或HIVECLEANFLAG_USERS,Filesys.dll会分别用这两种参数调用两次IOCTL_HAL_GET_HIVE_CLEAN_FLAG,第一次用HIVECLEANFLAG_SYSTEM来问OEM是否需要清除system.hv,第二次用HIVECLEANFLAG_USERS做参数来查询是否要清除user.hv,如果返回的lpOutBuf中的值为TRUE则做清除操作(这样,保存在nandflash的hv文件就会被清除掉),如果为False则保留block设备上的注册表文件。这两次调用实际上就是调用了函数OALIoCtlHalGetHiveCleanFlag,这个函数被调用的依据见bsp/src/inc/ioctl_tab.h中的内容,见下图
图2
下面我们就来看看OALIoCtlHalGetHiveCleanFla的函数体
图3
下面来看OALArgsQuery函数的主要函数体
图4
图4中IMAGE_SHARE_ARGS_UA_START=0xA0020000,其对应的物理内存地址是0x30020000,这是eboot和OS共享内存的起始地址,这块内存是SDRAM的一块区域,在eboot/boot.bib下的定义如下:
MEMORY
; Name Start Size Type
; ------- -------- -------- ----
ARGS 80020800 00000800 RESERVED
RAM 80021000 0000B000 RAM
……………………………
这段内存主要是用于eboot和OS传递参数的,共享一些参数信息,这段内存保存了结构体BSP_ARGS的数据,这个结构体就是eboot和OS之间共享的参数信息,本系统BSP_ARGS结构体的定义如下
typedef struct {
OAL_ARGS_HEADER header;
UINT8 deviceId[16]; // Device identification
OAL_KITL_ARGS kitl;
UINT8 uuid[16];
BOOL bUpdateMode; // TRUE = Enter update mode on reboot.
BOOL bHiveCleanFlag; // TRUE = Clean hive at boot
BOOL bCleanBootFlag; // TRUE = Clear RAM, hive, user store at boot
BOOL bFormatPartFlag; // TRUE = Format partion when mounted at boot
DWORD nfsblk;
// added by JJG 061106
// Because We cannot read EXTINT0,1,2 register in 2443 EVT2.0 CPU, we can just write only.
// So we must save EXTINT0,1,2 status globally for supporting external interrupt using by device driver.
DWORD EXTINT0;
DWORD EXTINT1;
DWORD EXTINT2;
///////////////////////////////////////////////////////////////////////////////////////////////////////
HANDLE g_SDCardDetectEvent; //kim
DWORD g_SDCardState ;
} BSP_ARGS, *PBSP_ARGS;
其中成员变量bHiveCleanFlag就是是否clean boot的标志位,图4的函数OALArgsQuery就是通过查询这个变量来告诉filesys.dll是否清除system.hv和user.hv,那么bHiveCleanFlag的值是在哪里初始化的呢?而图1中提到的从FALSE改为TRUE是在哪里实现的呢?
在eboot/main.c中,OEMPlatformInit函数会调用TOC_Read函数来获取boot的配置信息,如下
图5
那TOC_Read函数是如何读取TOC(包含了boot的配置信息)的信息的呢?接下来看TOC_Read函数体
图6
TOC_Read函数调用FMD_ReadSector函数读取的TOC结构体的变量成员的值是romimage.exe初始化的,具体见http://blog.csdn.net/chinesedragon2010/archive/2010/10/09/5929007.aspx,下面我们介绍BOOT_CFG结构体,定义如下
//
// Bootloader configuration parameters.
//
typedef struct _BOOTCFG {
ULONG ImageIndex;
ULONG ConfigFlags;
ULONG BootDelay;
EDBG_ADDR EdbgAddr;
ULONG SubnetMask;
} BOOT_CFG, *PBOOT_CFG;
其中成员变量ConfigFlags就是用于指示是否清除system.hv和user.hv的变量,系统初始值,也就是romimage.ex初始化ConfigFlags的值是0x2830,但为什么是这个值呢?目前还不知道,如果图1中的FALSE改为TRUE保存之后,ConfigFlags的值是0x6830。那ConfigFlags和上面提到的bCleanBootFlag有什么关系呢?我们先来看图1中对应的动作在代码中是如何是实现的,首先看eboot/main.c中OEMPlatformInit函数下面的代码
图7
接下来图1中从FLASH改为TRUE对应在MainMenu函数中的实现部分:
图8
第一次boot的时候,ConfigFlags的值是0x2830,这里是和0x00004000进行异或运算,运算之后,ConfigFlags的值变为0x6830,下一次再选择“C”对应的操作时,又是0x2830,选择“C”后需要选择“W”来修改之后的ConfigFlags值,下面就来看是如何把修改之后的ConfigFlags的值来保存到nandflash中的
图9
这里主要是调用TOC_Write来实现
图10
这样修改之后的g_pBootCfg->ConfigFlags的值保存到TOC所在的第1个block中了。修改之后g_pBootCfg->ConfigFlags的值是0x6830,这个值保存在nandflash中,那么重启之后系统启动的时候,我们知道files.dll是通过bCleanBootFlag来查询是否在启动的时候清除system.hv和user.hv的,我们下面就来分析g_pBootCfg->ConfigFlags的值是如何和bCleanBootFlag关联的,系统启动后会执行eboot/main.c函数OEMPlatformInit的下面这部分
图11
g_bCleanBootFlag在eboot/main.c调用的OEMPlatformInit函数的下面代码中实现
图12
这样我们就知道图1中的FALSE改为TRUE后,g_pBootCfg->ConfigFlags=0x6830,所以*g_bCleanBootFlag =TRUE,也就是把eboot与OS共享内存变量g_bCleanBootFlag的值改为TRUE。接下来在系统的启动过程中会调用OEMInit函数的下面代码
图13
这样上面提到的几个值的改变关联如下:
ConfigFlags->bCleanBootFlag->bHiveCleanFlag
这样就filesys.dll调用OALIoCtlHalGetHiveCleanFlag函数来查询bHiveCleanFlag的值来决定是否清除system.hv和user.hv了,下面是help文档中对NKForceCleanBoot函数的描述:
VOID NKForceCleanBoot(void);
This function forces the operating system (OS) to boot from a clean object store file system when called from the OEMInit function.
This function can also be called after the OS has started to force the next boot process to start from a clean object store file system.