深入剖析windows mobile启动过程
深入剖析windows mobile启动过程
转自winbile.net
介绍一下mobile系统的启动流程,仅供大家学习之用:
硬件平台:TI omap
软件平台:WM5.0
相关术语:
RTOS Real-time Operating System
EBOOT ETHERNET BOOT
IPL Initial Program Loader
整体流程:
powerON--〉BootROM--->x-loader---->Eboot----->IPL--->OS
下面围绕上述过程展开:
1 powerON
这里指的是硬件power ON,当按触powerON键后,系统上电,同时触发CPU复位管脚。系统进入到BootROM中,执行其中固化的代码。
2 BootROM:
BootROM中固化了一段引导代码,用于系统初始化,初始化必要的寄存器,决定启动流程是正常启动或者启动flashing,进入到x-loader。
Boot ROM的初始化工作有:
l 关闭可屏蔽中断
l 时钟设置和DPLL设置
l 配置ULPD寄存器,为UART提供48MHz的时钟频率
l 配置ARM CORE内部寄存器
l 配置EMIFS寄存器
l 建立ARM CORE中断向量表
上面的工作实际上就是初始化必要寄存器,例如EMIFS初始化。
在系统上电时候,BootROM代码会检测是否需要擦写flash内容,可以是部分擦写也可以是全部擦写。
擦写工作一般在上电时刻进行,BootROM代码初始化可编程接口(例如USB或者UART串口),然后等待从上位机发过来的boot command命令,如果在没有收到或者等待超时,系统正常启动。
(注;上位机是指:人可以直接发出操控命令的计算机,一般是PC。从概念上说控制者和提供服务者是上位机,被控制者和被服务者是下位机。可以理解为主机和从机的关系)
如果等到上位机的boot command命令,上位机会download Flash loader程序到omap的interal ram 空间中。Flash loader是由自身的header,flash loader应用程序和一些附加程序构成。
接着Boot ROM程序在安全模式下,检查flash loader的signatures来校验其完整性,如果检查失败,系统重启。如果检查通过,flash loader程序开始运行,它将较大size的OS image downloader到Flash介质中。
Boot ROM决定启动方式:
1)从NOR或者NAND Flash 正常启动
2)通过USB或者UART编程后,然后重新正常启动。
Boot ROM加载 x-loader:
OS Image 下载到flash后,boot ROM代码会从NOR或者NAND flash中查找TOC。
TOC是在flash上的一个数据结构,包含了Image信息,起始位置,大小等等。TOC可以有多个,每个TOC都对应着一个Image。NAND flash上TOC最多为16个,最大size为512B。NOR flash情况不一样。
Boot ROM 检测项目名为“x-loader”的TOC,让后将对应的Image加载到内存。x-loader是一个通用的loader程序,被Boot ROM从FLASH中启动(NOR),x-loader承担OS的启动,x-loader会被校验然后才会授予权限继续运行。
NOR flash上的 sub-image 具有XIP特性,因此NOR flash上的x-loader大小不受限制。对于NAND flash由于其不支持XIP,所以Boot ROM在其开始处预留了64K空间,这个预留空间用于启动扇区,至少包含一个TOC,TOC和其对应的image 被copy到RAM空间,然后才能被执行。
3 x-loader
x-loader的功能有哪些?
a,初始化硬件,如GPIO初始化。
b,加载Eboot代码到RAM空间
c, 跳转到Eboot代码
介绍一下x-loader TOC实现机制:
xldr_startup.s (src\boot\xldr\)
。。。。。。
ALIGN 0x200
DCD 0x00000040 ; Startoffset from TOC start (0x240)
DCD 0x00000800 ; Size
DCD 0x00000000 ; Flags
DCD 0x00000000 ; Align
DCD 0x00000000 ; Spare
DCD 0x4F4C2D58 ; Filename - X-LO
DCD 0x52454441 ; Filename - ADER
DCD 0x00000000 ; Filename - Blank
DCD 0xFFFFFFFF ; terminating TOC entry
DCD 0xFFFFFFFF
DCD 0xFFFFFFFF
DCD 0xFFFFFFFF
DCD 0xFFFFFFFF
DCD 0xFFFFFFFF
DCD 0xFFFFFFFF
DCD 0xFFFFFFFF
StartUp ;(0x240)//X-LOADER入口地址
EXPORT StartUp
INCLUDE..\..\..\common\src\ARM\TI\omap730\startup\hwinit.s
Hwinit.s的主要功能:
l Set SVC mode & disable IRQ/FIQ
l Initialize cache & CP15 control register
l Initialize TIPB Bridges
l Initialize EMIFS (flash & debug board controller)
l Initialize EMIFF (DRAM controller)
l Initialize OCPT1/OCPT2
l Initialize OCPI
l Initialize UPLD
l Initialize CLKM
l Configure OMAP730 SoC multiplexing
l Configure OMAP730 SoC GPIO
l Disable Watchdog Timer
l Set DMA to OMAP3.2 mode
l Reset USB modules
4 EBoot
EBoot(ethernet boot)位于MDOC的SPL分区,EBoot主要被PLATFORM BUILDER用来完成对DOC的编程,作为一个系统引导,下载工具,对菜单选项进行操作,并且通过EBoot能够对引导参数进行配置.
首先看看EBOOT对系统进行参数配置所设计到几个重要变量。
l g_bootCfg
typedef struct {
UINT32 signature; // Structure signature
UINT32 version; // Structure version
DEVICE_LOCATION bootDevLoc; // Boot device
DEVICE_LOCATION kitlDevLoc;
UINT32 kitlFlags; // Debug/KITL mode
UINT32 ipAddress;
UINT32 ipMask;
UINT32 ipRoute;
} BOOT_CFG;
这个全局变量用来保存系统启动配置参数,实际上对菜单选项的操作实质上是对这个结构变量对应部分的设置。通过BLMenu()来进行菜单选项的操作。
l g_eboot
typedef struct {
OAL_KITL_TYPE bootDeviceType;
UINT32 type;
UINT32 numRegions;
UINT32 launchAddress;
REGION_INFO_EX region[BL_MAX_BIN_REGIONS];
UINT32 recordOffset;
UINT8 *pReadBuffer;
UINT32 readSize;
} EBOOT_CONTEXT;
启动参数的配置是通过菜单选项来实现的,系统通过两个全局变量g_menuNetwork,g_menuMain定义了菜单项,
首先来看看这两个变量的内容:
l static OAL_BLMENU_ITEM g_menuNetwork[] = {
{
L'1', L"Show Current Settings", ShowNetworkSettings,//系统当前设置
NULL, NULL, NULL
}, {
L'2', L"Enable/disable KITL", OALBLMenuEnable,// 关闭或者使能 KITL
L"KITL", &g_bootCfg.kitlFlags, (VOID*)OAL_KITL_FLAGS_ENABLED
}, {
L'3', L"KITL interrupt/poll mode", SetKitlMode,//设置KITL工作模式
NULL, NULL, NULL
}, {
L'4', L"Enable/disable DHCP", OALBLMenuEnable,// 关闭或者使能 DHCP
L"DHCP", &g_bootCfg.kitlFlags, (VOID*)OAL_KITL_FLAGS_DHCP
}, {
L'5', L"Set IP address", OALBLMenuSetIpAddress,//设置IP地址
L"Device", &g_bootCfg.ipAddress, NULL
}, {
L'6', L"Set IP mask", OALBLMenuSetIpMask,//设置掩码地址
L"Device", &g_bootCfg.ipMask, NULL
}, {
L'7', L"Set default router", OALBLMenuSetIpAddress,//设置缺省路由
L"Default router", &g_bootCfg.ipRoute, NULL
}, {
L'8', L"Enable/disable VMINI", OALBLMenuEnable, // 关闭或者使能 VMINI
L"VMINI", &g_bootCfg.kitlFlags, (VOID*)OAL_KITL_FLAGS_VMINI
}, {
L'0', L"Exit and Continue", NULL, // 退出或者继续
NULL, NULL, NULL
}, {
0, NULL, NULL,
NULL, NULL, NULL
}
};
这个变量主要定义了对设备端网络的配置,当选择其中一项时,系统回调用其对应的登记函数进行相应的系统设置,例如输入‘4’时,选择设置IP地址,系统会通过OALBLMenuSetIpAddress对g_bootCfg.ipRoute进行操作
l g_menuMain数据结构
static OAL_BLMENU_ITEM g_menuMain[] = {
{
L'1', L"Show Current Settings", ShowSettings,// 系统当前设置
NULL, NULL, NULL
}, {
L'2', L"Select Boot Device", OALBLMenuSelectDevice, // 选择启动设备
L"Boot", &g_bootCfg.bootDevLoc, g_bootDevices
}, {
L'3', L"Select Debug Device", OALBLMenuSelectDevice, // 选择设置DEBUG设备
L"Debug", &g_bootCfg.kitlDevLoc, g_kitlDevices
}, {
L'4', L"Network Settings", OALBLMenuShow, // 设置网络
L"Network Settings", &g_menuNetwork, NULL
}, {
L'5', L"MDOC Flash", OALBLMenuShow, // 选择设置MDOC
L"MDOC Flash", &g_menuFlash, NULL
}, {
L'6', L"Save Settings", SaveSettings, // 保持系统设置
NULL, NULL, NULL
}, {
L'0', L"Exit and Continue", NULL,
NULL, NULL, NULL
}, {
0, NULL, NULL,
NULL, NULL, NULL
}
};
这个变量定义了系统主菜单选项,通过在这里选择‘4’ 进入网络设置菜单,当然这里面还有对其他参数的配置了,启动介质,调试设备等等。如何进入这个菜单呢,在用超级终端调试时,敲SPACEBAR键就可以了
OEM API功能说明:
l OEMPlatformInit ()
完成一些初始化的工作,32K TIMER的初始化,部分RAM区域的初始化
l OEMPreDownload ()
初始化g_bootCfg,配置参数,在这里可以通过按键来对g_bootCfg进行设置,并且根据选择的下载方式或者协议,来完成IMAGE的DOWNLOAD.
l OEMLaunch ()
负责加载IMAGE.
这个几OEM API是系统EBOOT阶段使用的底层API,具有非常重要的作用,理解这几个OEM API将有利用理解EBOOT对系统的设置
5 IPL
IPL会使用FMD去装载OS image或者 ULDR,下面将会提到如何进入OS,ULDR模式,当然前提是FMD API要被加载了。IPL里面的主要工作包括设置SYREN模块,电池充电,开机画面显示,完成OS image的加载,这里主要分析进入和如何进入ULDR:
描述IPL的充电,开机画面显示,设置跳转参数过程,OEMInit() ,这些过程都是在OEMIPLInit()来完成的,所以就放在一起进行分析。
l IPL的充电
重要的数据结构数组s_stChargeImage,用来定义充电LOG图形的二进制内容
下面的这几个API都是直接通过系统BATTERY的GPIO来完成充电,判断充电状态。
InitCharge()主要用来初始化充电,
IsCharging(),主要用来报告充电状态,
IsChargeDone()主要用来报告充电完成的状态
l IPL的开机画面显示
(当然之前会有对LCD CONTROLLER初始化操作)开机画面显示在IsDisplayInitOK()返回初始化完成后,用FillImage()用来加载图片内容,然后打开背光显示。
重要的数据结构数组g_iImageData[]用来定义启动LOG图片的二进制内容
l IPL的设置跳转参数过程
OALArgsSet()来设置系统ULDR后进入的模式,OALArgsSet()主要通过按键来确定进入模式,OALArgsQuery用来查询系统ULDR后进入的模式。通过OEMGetUpdateMode()来判断是否进入ULDR模式.
ulPartType = ((OEMGetUpdateMode() == TRUE) ? PART_BOOTSECTION : PART_ROMIMAGE);
如果正常启动(不进入ULDR),则要用FAL_LockFlashRegion()将NK,SYSTEM FILE 区域锁住,否则要用FAL_UnlockFlashRegion()打开这段区域的读写特性。如果正常启动,会将IMAGE拷贝到RAM中去,跳转执行IMAGE代码,否则将会执行ULDR.
系统调用的重要OEM API:
l OEMIPLInit ()
l OEMGetUpdateMode()
转自winbile.net
介绍一下mobile系统的启动流程,仅供大家学习之用:
硬件平台:TI omap
软件平台:WM5.0
相关术语:
RTOS Real-time Operating System
EBOOT ETHERNET BOOT
IPL Initial Program Loader
整体流程:
powerON--〉BootROM--->x-loader---->Eboot----->IPL--->OS
下面围绕上述过程展开:
1 powerON
这里指的是硬件power ON,当按触powerON键后,系统上电,同时触发CPU复位管脚。系统进入到BootROM中,执行其中固化的代码。
2 BootROM:
BootROM中固化了一段引导代码,用于系统初始化,初始化必要的寄存器,决定启动流程是正常启动或者启动flashing,进入到x-loader。
Boot ROM的初始化工作有:
l 关闭可屏蔽中断
l 时钟设置和DPLL设置
l 配置ULPD寄存器,为UART提供48MHz的时钟频率
l 配置ARM CORE内部寄存器
l 配置EMIFS寄存器
l 建立ARM CORE中断向量表
上面的工作实际上就是初始化必要寄存器,例如EMIFS初始化。
在系统上电时候,BootROM代码会检测是否需要擦写flash内容,可以是部分擦写也可以是全部擦写。
擦写工作一般在上电时刻进行,BootROM代码初始化可编程接口(例如USB或者UART串口),然后等待从上位机发过来的boot command命令,如果在没有收到或者等待超时,系统正常启动。
(注;上位机是指:人可以直接发出操控命令的计算机,一般是PC。从概念上说控制者和提供服务者是上位机,被控制者和被服务者是下位机。可以理解为主机和从机的关系)
如果等到上位机的boot command命令,上位机会download Flash loader程序到omap的interal ram 空间中。Flash loader是由自身的header,flash loader应用程序和一些附加程序构成。
接着Boot ROM程序在安全模式下,检查flash loader的signatures来校验其完整性,如果检查失败,系统重启。如果检查通过,flash loader程序开始运行,它将较大size的OS image downloader到Flash介质中。
Boot ROM决定启动方式:
1)从NOR或者NAND Flash 正常启动
2)通过USB或者UART编程后,然后重新正常启动。
Boot ROM加载 x-loader:
OS Image 下载到flash后,boot ROM代码会从NOR或者NAND flash中查找TOC。
TOC是在flash上的一个数据结构,包含了Image信息,起始位置,大小等等。TOC可以有多个,每个TOC都对应着一个Image。NAND flash上TOC最多为16个,最大size为512B。NOR flash情况不一样。
Boot ROM 检测项目名为“x-loader”的TOC,让后将对应的Image加载到内存。x-loader是一个通用的loader程序,被Boot ROM从FLASH中启动(NOR),x-loader承担OS的启动,x-loader会被校验然后才会授予权限继续运行。
NOR flash上的 sub-image 具有XIP特性,因此NOR flash上的x-loader大小不受限制。对于NAND flash由于其不支持XIP,所以Boot ROM在其开始处预留了64K空间,这个预留空间用于启动扇区,至少包含一个TOC,TOC和其对应的image 被copy到RAM空间,然后才能被执行。
3 x-loader
x-loader的功能有哪些?
a,初始化硬件,如GPIO初始化。
b,加载Eboot代码到RAM空间
c, 跳转到Eboot代码
介绍一下x-loader TOC实现机制:
xldr_startup.s (src\boot\xldr\)
。。。。。。
ALIGN 0x200
DCD 0x00000040 ; Startoffset from TOC start (0x240)
DCD 0x00000800 ; Size
DCD 0x00000000 ; Flags
DCD 0x00000000 ; Align
DCD 0x00000000 ; Spare
DCD 0x4F4C2D58 ; Filename - X-LO
DCD 0x52454441 ; Filename - ADER
DCD 0x00000000 ; Filename - Blank
DCD 0xFFFFFFFF ; terminating TOC entry
DCD 0xFFFFFFFF
DCD 0xFFFFFFFF
DCD 0xFFFFFFFF
DCD 0xFFFFFFFF
DCD 0xFFFFFFFF
DCD 0xFFFFFFFF
DCD 0xFFFFFFFF
StartUp ;(0x240)//X-LOADER入口地址
EXPORT StartUp
INCLUDE..\..\..\common\src\ARM\TI\omap730\startup\hwinit.s
Hwinit.s的主要功能:
l Set SVC mode & disable IRQ/FIQ
l Initialize cache & CP15 control register
l Initialize TIPB Bridges
l Initialize EMIFS (flash & debug board controller)
l Initialize EMIFF (DRAM controller)
l Initialize OCPT1/OCPT2
l Initialize OCPI
l Initialize UPLD
l Initialize CLKM
l Configure OMAP730 SoC multiplexing
l Configure OMAP730 SoC GPIO
l Disable Watchdog Timer
l Set DMA to OMAP3.2 mode
l Reset USB modules
4 EBoot
EBoot(ethernet boot)位于MDOC的SPL分区,EBoot主要被PLATFORM BUILDER用来完成对DOC的编程,作为一个系统引导,下载工具,对菜单选项进行操作,并且通过EBoot能够对引导参数进行配置.
首先看看EBOOT对系统进行参数配置所设计到几个重要变量。
l g_bootCfg
typedef struct {
UINT32 signature; // Structure signature
UINT32 version; // Structure version
DEVICE_LOCATION bootDevLoc; // Boot device
DEVICE_LOCATION kitlDevLoc;
UINT32 kitlFlags; // Debug/KITL mode
UINT32 ipAddress;
UINT32 ipMask;
UINT32 ipRoute;
} BOOT_CFG;
这个全局变量用来保存系统启动配置参数,实际上对菜单选项的操作实质上是对这个结构变量对应部分的设置。通过BLMenu()来进行菜单选项的操作。
l g_eboot
typedef struct {
OAL_KITL_TYPE bootDeviceType;
UINT32 type;
UINT32 numRegions;
UINT32 launchAddress;
REGION_INFO_EX region[BL_MAX_BIN_REGIONS];
UINT32 recordOffset;
UINT8 *pReadBuffer;
UINT32 readSize;
} EBOOT_CONTEXT;
启动参数的配置是通过菜单选项来实现的,系统通过两个全局变量g_menuNetwork,g_menuMain定义了菜单项,
首先来看看这两个变量的内容:
l static OAL_BLMENU_ITEM g_menuNetwork[] = {
{
L'1', L"Show Current Settings", ShowNetworkSettings,//系统当前设置
NULL, NULL, NULL
}, {
L'2', L"Enable/disable KITL", OALBLMenuEnable,// 关闭或者使能 KITL
L"KITL", &g_bootCfg.kitlFlags, (VOID*)OAL_KITL_FLAGS_ENABLED
}, {
L'3', L"KITL interrupt/poll mode", SetKitlMode,//设置KITL工作模式
NULL, NULL, NULL
}, {
L'4', L"Enable/disable DHCP", OALBLMenuEnable,// 关闭或者使能 DHCP
L"DHCP", &g_bootCfg.kitlFlags, (VOID*)OAL_KITL_FLAGS_DHCP
}, {
L'5', L"Set IP address", OALBLMenuSetIpAddress,//设置IP地址
L"Device", &g_bootCfg.ipAddress, NULL
}, {
L'6', L"Set IP mask", OALBLMenuSetIpMask,//设置掩码地址
L"Device", &g_bootCfg.ipMask, NULL
}, {
L'7', L"Set default router", OALBLMenuSetIpAddress,//设置缺省路由
L"Default router", &g_bootCfg.ipRoute, NULL
}, {
L'8', L"Enable/disable VMINI", OALBLMenuEnable, // 关闭或者使能 VMINI
L"VMINI", &g_bootCfg.kitlFlags, (VOID*)OAL_KITL_FLAGS_VMINI
}, {
L'0', L"Exit and Continue", NULL, // 退出或者继续
NULL, NULL, NULL
}, {
0, NULL, NULL,
NULL, NULL, NULL
}
};
这个变量主要定义了对设备端网络的配置,当选择其中一项时,系统回调用其对应的登记函数进行相应的系统设置,例如输入‘4’时,选择设置IP地址,系统会通过OALBLMenuSetIpAddress对g_bootCfg.ipRoute进行操作
l g_menuMain数据结构
static OAL_BLMENU_ITEM g_menuMain[] = {
{
L'1', L"Show Current Settings", ShowSettings,// 系统当前设置
NULL, NULL, NULL
}, {
L'2', L"Select Boot Device", OALBLMenuSelectDevice, // 选择启动设备
L"Boot", &g_bootCfg.bootDevLoc, g_bootDevices
}, {
L'3', L"Select Debug Device", OALBLMenuSelectDevice, // 选择设置DEBUG设备
L"Debug", &g_bootCfg.kitlDevLoc, g_kitlDevices
}, {
L'4', L"Network Settings", OALBLMenuShow, // 设置网络
L"Network Settings", &g_menuNetwork, NULL
}, {
L'5', L"MDOC Flash", OALBLMenuShow, // 选择设置MDOC
L"MDOC Flash", &g_menuFlash, NULL
}, {
L'6', L"Save Settings", SaveSettings, // 保持系统设置
NULL, NULL, NULL
}, {
L'0', L"Exit and Continue", NULL,
NULL, NULL, NULL
}, {
0, NULL, NULL,
NULL, NULL, NULL
}
};
这个变量定义了系统主菜单选项,通过在这里选择‘4’ 进入网络设置菜单,当然这里面还有对其他参数的配置了,启动介质,调试设备等等。如何进入这个菜单呢,在用超级终端调试时,敲SPACEBAR键就可以了
OEM API功能说明:
l OEMPlatformInit ()
完成一些初始化的工作,32K TIMER的初始化,部分RAM区域的初始化
l OEMPreDownload ()
初始化g_bootCfg,配置参数,在这里可以通过按键来对g_bootCfg进行设置,并且根据选择的下载方式或者协议,来完成IMAGE的DOWNLOAD.
l OEMLaunch ()
负责加载IMAGE.
这个几OEM API是系统EBOOT阶段使用的底层API,具有非常重要的作用,理解这几个OEM API将有利用理解EBOOT对系统的设置
5 IPL
IPL会使用FMD去装载OS image或者 ULDR,下面将会提到如何进入OS,ULDR模式,当然前提是FMD API要被加载了。IPL里面的主要工作包括设置SYREN模块,电池充电,开机画面显示,完成OS image的加载,这里主要分析进入和如何进入ULDR:
描述IPL的充电,开机画面显示,设置跳转参数过程,OEMInit() ,这些过程都是在OEMIPLInit()来完成的,所以就放在一起进行分析。
l IPL的充电
重要的数据结构数组s_stChargeImage,用来定义充电LOG图形的二进制内容
下面的这几个API都是直接通过系统BATTERY的GPIO来完成充电,判断充电状态。
InitCharge()主要用来初始化充电,
IsCharging(),主要用来报告充电状态,
IsChargeDone()主要用来报告充电完成的状态
l IPL的开机画面显示
(当然之前会有对LCD CONTROLLER初始化操作)开机画面显示在IsDisplayInitOK()返回初始化完成后,用FillImage()用来加载图片内容,然后打开背光显示。
重要的数据结构数组g_iImageData[]用来定义启动LOG图片的二进制内容
l IPL的设置跳转参数过程
OALArgsSet()来设置系统ULDR后进入的模式,OALArgsSet()主要通过按键来确定进入模式,OALArgsQuery用来查询系统ULDR后进入的模式。通过OEMGetUpdateMode()来判断是否进入ULDR模式.
ulPartType = ((OEMGetUpdateMode() == TRUE) ? PART_BOOTSECTION : PART_ROMIMAGE);
如果正常启动(不进入ULDR),则要用FAL_LockFlashRegion()将NK,SYSTEM FILE 区域锁住,否则要用FAL_UnlockFlashRegion()打开这段区域的读写特性。如果正常启动,会将IMAGE拷贝到RAM中去,跳转执行IMAGE代码,否则将会执行ULDR.
系统调用的重要OEM API:
l OEMIPLInit ()
l OEMGetUpdateMode()