Upload
mahola
View
137
Download
2
Embed Size (px)
DESCRIPTION
国家 ASIC 系统工程技术研究中心 SOC 系统部. Windows CE 操作系统. BootLoader 的设计与实现. 重定位问题??. 定义 1. 当编译器或汇编器编译一个单独的模块时,它不知道这个模块会被加载到内存的何处,这时编译器输出代码时就遵循一个惯例,编译每个模块都是从地址 0 开始。当这个模块真正装入内存时,他一般不可能从 0 开始,这时就要一个地址转换的过程,称之为重定位. 重地位 分类. 1 )静态重定位 在程序被加载到内存之前已经知道了它将要加载到内存的开始地址,这样就可以事先进行地址转换,把相对地址转换成绝对地址。 - PowerPoint PPT Presentation
Citation preview
LOGO
BootLoader 的设计与实现
国家 ASIC 系统工程技术研究中心 SOC 系统部
Windows CE 操作系统
www.themegallery.com LOGO
重定位问题??
定义1. 当编译器或汇编器编译一个单独的模块时,它
不知道这个模块会被加载到内存的何处,这时编译器输出代码时就遵循一个惯例,编译每个模块都是从地址 0 开始。当这个模块真正装入内存时,他一般不可能从 0 开始,这时就要一个地址转换的过程,称之为重定位
www.themegallery.com LOGO
重地位 分类
1 )静态重定位 在程序被加载到内存之前已经知道了它将要加载到内存的开始地址,这样就可以事先进行地址转换,把相对地址转换成绝对地址。
2 )动态重地位 作业装入内存后所有的地址仍然是相对地址,将相对地址转换成绝对地址的过程被推迟到程序指令要真正执行时进行。动态重定位要硬件--重定位寄存器支持
www.themegallery.com LOGO
1 BootLoader 概述1.1 BootLoader 的概念1.2 BootLoader 的操作模式1.3 嵌入式系统的引导模式1.4 BootLoader 的功能特性
★2 BootLoader 的体系结构2.1 BooterLoader 的架构2.2 BooterLoader 的支持库
内容安排
www.themegallery.com LOGO
3 BootLoader 的代码的组件和执行流程3.1 BooterLoader 代码组件3.2 BooterLoader 代码的执行流程
4 BootLoader 开发前的硬件考虑4.1 考虑的原因4.2 考虑的因素4.3 基于 s3c2440 的开发板
★5 BootLoader 的设计与实现5.1 构建创建环境
内容安排
www.themegallery.com LOGO
5.2 startup 函数的设计与实现5.3 主函数 main 的设计与实现5.4 控制流函数的设计与实现5.5 调试函数的设计与实现5.6 以太网控制器相关的函数5.7 写 FLASH 函数的设计与实现5.8 镜像下载函数的设计与实现5.9 时间相关函数的设计与实现5.10 配置文件
内容安排
www.themegallery.com LOGO
1 BootLoader 概述 1.1 BootLoader 的概念◆ BootLoader 的描述
操作系统内核运行前运行地一段小程序 。初始化硬件、建立内存空间映射图,为 OS 的运行准备好正确的环境。带有BootLoader 的固态存储介质典型空间分配如图 1 所示
◆ BootLoader 的功能● 引导系统
● 加载操作系统
图 1
www.themegallery.com LOGO
1.2 BootLoader 的操作模式◆ 启动加载模式
又叫自主模式, BootLoader 将预先存储在永久固态介质上 的 OS 镜像加载到 RAM 中运行。
◆ 下载模式 目标机通过串口、网口或者 USB 从主机端下载镜像到目标机端点 RAM 中,然后再被 BootLoader 写到目标机上的 FLASH 类固态存储设备中
www.themegallery.com LOGO
1.3 嵌入式系统的引导模式
◆ BootLoader 引导模式 优点:可以轻松实现内核升级
◆ 非 BootLoader 引导模式??操作系统事先写入到 CPU 开始执行的地址位置,或者在 CPU
开始执行的地址位置写入一个 RESETVECTOR 变量,由它来定义一个跳转地址,指向操作系统的起始位置
www.themegallery.com LOGO
1.4 BootLoader 的功能特性并非所有平台都支持下面列出的功能特性,但大部分特性对所有平台来说都是有用的
◆ BootLoader 典型特性● BootLoader应驻留在 FLASH等永久存储介质里● BootLoader应提供消息反馈机● 尽量使用微软提供的支持库开发 BootLoader● BootLoader 要能加载 BootLoader 镜像和 OS 镜像,对OS 镜像要既能从 RAM 加载,也能从 FLASH 加载● 提供数据正确性保障● 要和 OAL共享相同的硬件初始化代码
www.themegallery.com LOGO
◆ BootLoader 的附加功能特性● 在 BootLoader 的输出信息中,应包含版本、开发者和构建日期等信息● 设计一个序列化的功能选项菜单,为用户开发提供便利● 支持自更新● 与 PB协调工作,实现复位下载,复位跳转和自更新● 提供一种监视和反馈机制,监控下载过程● 在其中尽肯能的包含以太网调试驱动
www.themegallery.com LOGO
2 BootLoader 的体系结构
2.1 BooterLoader 的架构BooterLoader 的结构如图 2 所是:
BLCommon
OEM代码
NE2000
CS8900
RTL8139EBOOT
BootPart
Fl ash FMD
图 2
www.themegallery.com LOGO
◆ 五个组成部分BLCommon 库, OEM 代码, Eboot 库, EDBG驱动,以及存储管理● OEM 代码必须由用户自己编写● EDBG驱动,以及存储管理可能需要修改,视具体情况● BLCommon 库和 Eboot 库完全不用改
◆ OEM 代码用户根据自己的平台特点编写或修改的代码● 存放路径为:
%_WINCEROOT%\Platform\<Hardware Platform Name>\Src\Eboot
www.themegallery.com LOGO
2.1 BooterLoader 支持库微软提供的众多静态库中, BootLoader 中常用的有以下所述的四种
◆ BLCommon 库● 存放路径:
%_WINCEROOT%\Public\Common\Oak\Drivers\Ethdbg\Blcommon
● 功能:把 bootloader搬运到 RAM里以获得更快的访问速度,即重定位 BooterLoader在 RAM 中的位置,解码 .bin 文件的内容、验证校验及加载跟踪过程,调用 OEM代码处理硬件初始化等● Blcommond 代码的入口点: BootloaderMain
www.themegallery.com LOGO
◆ Eboot 库● 存放路径:
%_WINCEROOT%\Public\Common\Oak\Drivers\Ethdbg\Eboot
● 功能:为 BooterLoader提供 DHCP、 TFTP和 UDP服务
DHCP 是动态主机分配协议TFTP 是简单文件传输协议UDP 是用户数据协议
◆ EDBG驱动是一组以太网卡的驱动程序代码● 存放路径:
%_WINCEROOT%\Public\Common\Oak\Drivers\Ethdbg
● 功能:提供常用以太网卡驱动,为 BootLoader和OS的通信提供通用接口● WINCE5.0 下已有的驱动:
NE2000、 CS8900、 RTL8139、 SMC9000、 DEC21140 等
www.themegallery.com LOGO
◆ 存储管理
● BootPart 部分存放路径:%_WINCEROOT%\Public\Common\Oak\Drivers\Ethdbg\BootPart
● 功能:辅助 BootLoader 进行分区管理,存储设备读 /写等操作和管理
● Flash FMD 部分是用户自己编写的,存放在:%_WINCEROOT%\Platform\<Hardware Platform Name>\Src\Eboot
www.themegallery.com LOGO
3 BootLoader 的代码的组件和执行流程
2.1 BootLoader 代码组件由两部分组成● OEM 启动代码
汇编编写,最先执行,完成对 CPU 时钟频率,内部寄存器,高速缓存及其他一些硬件相关功能的初始化。
● OEM 主代码 C 语言编写, BootLoader 的主要代码区,通常包含镜像下载,串口调试,写 Flash(可选),硬件监视器(可选)等几部分的代码
www.themegallery.com LOGO
BootLoader代码的控制流程如图 3所示:
图 3
www.themegallery.com LOGO
2.1 BootLoader 代码的执行流程根据 BootLoader 的任务来划分,可将其代码的执行分为两个阶段:
◆ Stage1 完成对 CPU 的初始化,地址的映射,然后跳到 main 函数
◆ Stage2 数据的重定位,平台的初始化(主要是各种外围模块),镜像的加载
整个 BootLoader 代码的执行过程,用交互图表示如下,
www.themegallery.com LOGO
startup. s Mai n. c Bl common. c
1.跳转2.调用BootLoaderMai n()
3.调用Kernal Rel ocate()
4.调用OEMDebugI ni t()
5.调用OEMPl atFormI ni t()
6.调用OEMPreDownLoad()
7.调用Downl oadI mage()
8.调用OEMLaunch()
BootLoader 代码的执行过程的交互图 图 4
系统初始化函
数
www.themegallery.com LOGO
4 BootLoader 开发前的硬件考虑
4.1 考虑的原因◆ 硬件密切相关
◆ 不同操作系统 BootLoader 的功能相同,但实现方式不同
每种不同的 CPU 体系结构都有不同的 Boot Loader 。有些 Boot Loader 也支持多种体系结构的 CPU ,比如 U-Boot 就同时支持 ARM 体系结构和 MIPS 体系结构。除了依赖于 CPU 的体系结构外, Boot Loader 实际上也依赖于具体的嵌入式板级设备的配置。这也就是说,对于两块不同的嵌入式板而言,即使它们是基于同一种 CPU 而构建的,要想让运行在一块板子上的 Boot Loader 程序也能运行在另一块板子上,通常也都需要修改 Boot Loader 的源程序。
www.themegallery.com LOGO
5 BootLoader 的设计与实现以下设计过程中的代码均是以 s3c2440BSP 为例
5.1 构建创建环境● 为要新建的 BootLoader 创建一个新的目录,路径为:
%_WINCEROOT%\Platform\MyPlatform\Src\BootLoader\EbootMyPlatform 是要创建 BootLoader 的平台名
● 创建命令行环境为 BootLoader提供所需要的静态库
● 创建 SOURCES 文件和 makefile 文件 SOURCES 文件为编译器提供编译信息 makefile 文件用于驱动编译过程
www.themegallery.com LOGO
5.2 startup 函数的设计与实现
◆ BootLoader 的入口代码 最早编写的 BootLoader 函数,汇编编写,存放路径如下:
%_WINCEROOT%\Platform\MyPlatform\Src\BootLoader\Eboot
MyPlatform 是要创建 BootLoader 的平台名,文件扩展名为 .s
◆ s3c2440的 startup 函数在这函数中主要完成的工作是对 CPU 的初始化,地址映
射。 2440BSP 中的 startup.s 函数的流程图如图 5 所示:
www.themegallery.com LOGO
图 5
开始
清空TLB
禁止I CACHE和DCACHE
屏蔽所有中断
将所有中断都设为I RQ
设置总线模式
配置PLL
配置电源管理
初始化存储控制器
搬运BootLoader
地址映射
清空I +D的TLB
使能CACHE
使能MMU
初始化超级页堆栈
跳转到主函mai n()
结束
www.themegallery.com LOGO
◆ 5.3 主函数 main 的设计与实现由 Startup 函数调用, C 语言代码的入口点,在该函数中调用 Blcommon 库中的 BootLoaderMain 函数。 2440BSP 中主函数为 main● main 函数的代码
void main(void){
// Clear LEDs. // OEMWriteDebugLED(0, 0x3);
// Common boot loader (blcommon) main routine. // BootloaderMain();
// Should never get here. // SpinForever();}
www.themegallery.com LOGO
● BootLoaderMain 函数的代码
BootLoader 的主控函数,完成的下工作通过图 6 所示的流程可以看出。
● OEMWriteDebugLED 函数的代码开发者根据自己的平台特点编写该代码,不是必须的。
2440BSP包下的示例代码如下:void OEMWriteDebugLED(UINT16 Index,
DWORD Pattern){ volatile S3C2440A_IOPORT_REG
*s2440IOP = (S3C2440A_IOPORT_REG *)OALPAtoVA(S3C2440A_BASE_REG_PA_IOPORT, FALSE);
// The S24x0X01 Eval platform supports //4 LEDs..
//
s2440IOP->GPFDAT=(s2440IOP->GPFDAT & 0xf) | ((Pattern & 0xf)<<4);
}
开始
全局变量的重定位
初始化调试端口
平台初始化
镜像下载
启动镜像
结束
图 6
www.themegallery.com LOGO
◆ 5.4 控制流函数的设计与实现
BootLoader 的控制流函数有以下几个:◆ OEMDebugInit ()◆ OEMPlatformInit ()◆ OEMPreDownload ()◆ OEMLaunch ()
这几个函数是 BootLoader 主控函数 BootLoaderMain 的重要组成部分,它们共同完成了内核代码的引导和加载
www.themegallery.com LOGO
◆ OEMDebugInit ()函数该函数的主要作用:● 初始化调试端口,通常识异步串行通信口(UART )
实例代码:BOOL OEMDebugInit(void){ // Set up function callbacks used by blcommon. // g_pOEMVerifyMemory = OEMVerifyMemory; // Verify RAM. g_pOEMMultiBINNotify = OEMMultiBINNotify;
// Call serial initialization routine (shared with the OAL). // OEMInitDebugSerial();
return(TRUE);}
www.themegallery.com LOGO
◆ OEMPlatformInit ()函数 该函数和硬件高度相关,主要作用: ● 初始化 RTC( Real Time Clock )或任何被 OEMEthGetSecs 函
数使用的和时间保存相关的设备 ● 初始化显示屏,此为可选项。如开机显示 LOGO ● 初始化 Flash或 Flash 控制器。 ● 如果网络设备挂载在 PCI总线上,初始化主 PCI桥,对总线进行枚举来确定网络控制器以便进行镜像下载,配置 PCI 的硬件需求来使能网络控制器
● 如果网络设备挂载在 PCMCIA总线上,则初始化 PCMCIA桥或是控制器
● 初始化网络控制器,以便进行镜像下载
2440BSP中 OEMPlatformInit 函数的流程图如下:
www.themegallery.com LOGO
开始
初始化显示屏
初始化BSP参数的结构体
初始化USB
初始化中断
初始化引导驱动器和BI N文件分区
获取FLASH信息
读取TOC
显示引导信息
配置以太网控制器
结束
OEMPlatformInit 函数流程 图 7
www.themegallery.com LOGO
◆ OEMPreDownload ()函数
该函数的主要作用: ● 为 PB 下载镜像产生一个唯一的目标硬件平台名,该平台名一般是与网络接口卡的 MAC 地址相关联的静态文本字符串 ● 从 DHCP( Dynamic Host Configuration Protocol )服务获得一个动态 IP 地址,或是直接分配一个静态 IP 地址 ● 初始化 TFTP传输协议或是 PB 下载协议。
www.themegallery.com LOGO
◆ OEMLaunch ()函数 该函数的主要任务:
● OEMLaunch 可以用在 Eboot.lib 中定义的EbootWaitForHostConnect 函数,等待 PB 发送关于启动什么服务和从哪个端口启动服务
● 检查 EbootWaitForHostConnect 的返回值,然后将端口信息和 IP保存到 DriverGlobals参数里,后面 OAL 将会用到这些
● 跳转到 dwLaunchAddr参数指定的第一条指定点地址,该指令就是 BootLoader 镜像的 Startup 函数
2440BSP中 OEMLaunch 函数的流程图如下:
www.themegallery.com LOGOOEMLaunch 函数流程 图 8
开始
将已下载的镜像写入FLASH
等待PB发送用于服务连接的I P和端口设置,以及KI TL标志
保存内存加载地址或在下载时没有提供这个地址时回调已存储的地址
结束
跳转到下载镜像
www.themegallery.com LOGO
◆ 5.5 调试函数的设计与实现
BootLoader和 OAL共享,包含以下几个函数:
◆ OEMInitDebugSerial ()◆ OEMReadDebugByte ()◆ OEMWriteDebugByte ()◆ OEMWriteDebugString()
实现这些函数的文件路径:MyPlatfor\Src\Kernel\Oal\debug.c
www.themegallery.com LOGO
◆ OEMInitDebugSerial ()函数 初始化调试端口,一般是异步串口(UART )
◆ OEMReadDebugByte ()函数 从调试端口读取一个字节
◆ OEMWriteDebugByte ()函数向调试端口输出一个字节
◆ OEMWriteDebugString() 函数 向调试端口输出一个字符串
www.themegallery.com LOGO
◆ 5.6 以太网网控制器相关的函数主要有以下几个函数:◆ OEMEthGetFrame ()◆ OEMEthSendFrame ()◆ EbootInitEtherTransport ()◆ EbootGetDHCPAddr ()◆ EbootEtherReadData ()◆ EbootWaitForHostConnect ()
◆ OEMEthGetFrame ()函数// 从网卡读取数据BOOL OEMEthGetFrame(PUCHAR pData, PUSHORT pwLength) {
return(pfnEDbgGetFrame(pData, pwLength));}
pfnEDbgGetFrame 是在 OEMPlatformInit 函数中调用的InitEthDevice 函数中初始化的
www.themegallery.com LOGO
◆ OEMEthSendFrame ()函数// 写数据到网卡BOOL OEMEthSendFrame(PUCHAR pData, DWORD dwLength){
BYTE Retries = 0;
while (Retries++ < 4) // 允许重发 4 次 { if (!pfnEDbgSendFrame(pData, dwLength)) return(TRUE);
EdbgOutputDebugString("INFO: OEMEthSendFrame: retrying send (%u)\r\n", Retries);
}
return(FALSE);}
pfnEDbgSendFrame 是在 OEMPlatformInit 函数中调用的InitEthDevice 函数中初始化的
www.themegallery.com LOGO
◆ EbootInitEtherTransport ()函数 初始化以太网镜像下载
◆ EbootGetDHCPAddr ()函数 通过 DHCP获取 IP 地址
◆ EbootEtherReadData ()函数 从传输端口读取指定数目的数据到调用者指定的缓冲区中。该函数最终调用的还是函数 OEMEthGetFrame
◆ EbootWaitForHostConnect ()函数与工作站上的 PB 通信,获取 EDBG_OS_CONFIG_DATA 结构体内容。 EDBG_OS_CONFIG_DATA 的具体内容如下:
www.themegallery.com LOGO
typedef struct _EDBG_OS_CONFIG_DATA{ UCHAR Flags; // Flags that will be used to determine what
//features are // enabled over ethernet (saved in driver globals
//by bootloader)#define EDBG_FL_DBGMSG 0x01 // Debug messages#define EDBG_FL_PPSH 0x02 // Text shell#define EDBG_FL_KDBG 0x04 // Kernel debugger#define EDBG_FL_CLEANBOOT 0x08 // Force a clean boot
UCHAR KitlTransport; // Tells KITL which transport to start
// The following specify addressing info, only valid if the corresponding
// flag is set in the Flags field. DWORD DbgMsgIPAddr; USHORT DbgMsgPort; DWORD PpshIPAddr; USHORT PpshPort; DWORD KdbgIPAddr; USHORT KdbgPort; } EDBG_OS_CONFIG_DATA, *PEDBG_OS_CONFIG_DATA;
www.themegallery.com LOGO
◆ 5.7 写 FLASH 代码的设计与实现BootLoader 中操作 FLASH 存储器的函数,包含以下几个函数:◆ OEMContinueEraseFlash () ◆ OEMFinishEraseFlash ()◆ OEMIsFlashAddr ()◆ OEMStartEraseFlash ()◆ OEMWriteFlash ()
◆ OEMContinueEraseFlash ()函数void OEMContinueEraseFlash(void) // 下载过程中不断调用该函数,继续对
// FLASH 进行擦除操作{
//2440BSP 尚未空函数,自己编写}
www.themegallery.com LOGO
◆ OEMStartEraseFlash ()函数// 初始化 FLASH 存储器的擦除过程BOOL OEMStartEraseFlash(DWORD dwStartAddr, DWORD dwLength){
//2440BSP 中尚为空,直接返回 TRUE ,需要自己编写return(TRUE);
}
◆ OEMFinishEraseFlash ()//写 OS 镜像时调用,以所需要的 FLASH 存储空间是否完全擦除BOOL OEMFinishEraseFlash(void){
//2440BSP 中尚为空,直接返回 TRUE ,需要自己编写return(TRUE);
}
www.themegallery.com LOGO
◆ OEMIsFlashAddr ()函数// 判断地址是 FLASH 地址还是 RAM 地址BOOL OEMIsFlashAddr(DWORD dwAddr){ //2440BSP 中尚为空函数,直接返回 FLASE ,表示不在 FLASH 内 // 需要自己编写 return(FALSE);}
◆ OEMWriteFlash ()函数//向 FLASH 中写 OS 镜像BOOL OEMWriteFlash(DWORD dwStartAddr, DWORD dwLength){ //2440BSP 尚为空,需要自己编写 return(TRUE);}
www.themegallery.com LOGO
◆ 5.8 镜像下载代码的设计与实现镜像下载函数主要有以下几个 :
◆ OEMMapMemAddr ()◆ OEMReadData ()◆ OEMShowProgress ()
◆ OEMMapMemAddr ()函数// 为要烧写到 FLASH 中的镜像提供一个位于 RAM 中的临时缓冲区,存放当前已下载的
镜像,以便下载完成后一并写入 FLASHLPBYTE OEMMapMemAddr(DWORD dwImageStart, DWORD dwAddr){
if (g_ImageType & IMAGE_TYPE_STEPLDR){
dwAddr = (FILE_CACHE_START + (dwAddr - STEPLDR_RAM_IMAGE_BASE));
return (LPBYTE)dwAddr;}
else
www.themegallery.com LOGO
if (g_ImageType & IMAGE_TYPE_LOADER) {
dwAddr = (FILE_CACHE_START + (dwAddr - EBOOT_RAM_IMAGE_BASE)); return (LPBYTE)dwAddr;}else
if (g_ImageType & IMAGE_TYPE_RAWBIN) { OALMSG(TRUE, (TEXT("OEMMapMemAddr 0x%x
0x%x\r\n"),dwAddr,(FILE_CACHE_START + dwAddr)));dwAddr = FILE_CACHE_START + dwAddr;
return (LPBYTE)dwAddr;}
return (LPBYTE)dwAddr;}
www.themegallery.com LOGO
◆ OEMReadData ()函数
// 镜像下载所用的传输函数BOOL OEMReadData(DWORD dwData, PUCHAR pData) {
// 判断下载方式if ( g_bUSBDownload == FALSE ){
ret = EbootEtherReadData(dwData, pData); }
else{
ret = UbootReadData(dwData, pData); }
return ret ;}
www.themegallery.com LOGO
◆ OEMShowProgress ()函数
// 提供下载进度指示
void OEMShowProgress(DWORD dwPacketNum){ //2440BSP 中该函数尚为空,需要自己编写
OALMSG(OAL_FUNC, (TEXT("+OEMShowProgress.\r\n")));}
www.themegallery.com LOGO
◆ 5.9 时间相关函数的设计与实现BootLoader 用来返回从某个过去的时间到现在的秒数用到如下两个函数
◆ OEMEthGetSecs ()◆ OEMGetRealTime ()
◆ OEMEthGetSecs ()函数DWORD OEMEthGetSecs(void) // 返回从某个特定时间到目前为止的秒数{
SYSTEMTIME sTime;
OEMGetRealTime(&sTime); // 内核调用函数,获取 RTC ,自己编写
return((60UL * (60UL * (24UL * (31UL * sTime.wMonth + sTime.wDay) + sTime.wHour) + sTime.wMinute)) + sTime.wSecond);
}
www.themegallery.com LOGO
◆ OEMGetRealTime ()函数//获取系统时间static BOOL OEMGetRealTime(LPSYSTEMTIME lpst) { volatile S3C2440A_RTC_REG *s2440RTC = (S3C2440A_RTC_REG
*)OALPAtoVA(S3C2440A_BASE_REG_PA_RTC, FALSE);
do { lpst->wYear = FROM_BCD(s2440RTC->BCDYEAR) + 2000 ; lpst->wMonth = FROM_BCD(s2440RTC->BCDMON & 0x1f); lpst->wDay = FROM_BCD(s2440RTC->BCDDAY & 0x3f);
lpst->wDayOfWeek = (s2440RTC->BCDDATE - 1);
lpst->wHour = FROM_BCD(s2440RTC->BCDHOUR & 0x3f); lpst->wMinute = FROM_BCD(s2440RTC->BCDMIN & 0x7f); lpst->wSecond = FROM_BCD(s2440RTC->BCDSEC & 0x7f); lpst->wMilliseconds = 0; } while (!(lpst->wSecond)); return(TRUE);}
www.themegallery.com LOGO
● SYSTEMTIME 结构体的定义如下:typedef struct _SYSTEMTIME {
WORD wYear; WORD wMonth; WORD wDayOfWeek; 星期(如 Sunday = 0,Monday = 1 ) WORD wDay; WORD wHour; WORD wMinute; WORD wSecond; WORD wMilliseconds;
} SYSTEMTIME;
● OEMGetRealTime是OAL 中实现的函数,要被内核调用的,函数必须是可重入函数
www.themegallery.com LOGO
◆ 5.10 配置文件的设计与实现
● sources 文件 和普通的 sources 有差异
● boot.bib 文件
● makefile.inc 文件 可选的伪目标文件。用户定制自己的规则
www.themegallery.com LOGO
谢 谢!