WinCE开发中Boot Loader的点点滴滴

简介: 我很庆幸在公司的产品开发过程中并没有受到Boot Loader带来的阻力,因为我们采用MSDOS+Loadcepc来启动CE操作系统。显然这样的幸运不是永远的,所以对Boot Loader应该有足够的研究和了解,做到未雨绸缪。
我很庆幸在公司的产品开发过程中并没有受到Boot Loader带来的阻力,因为我们采用MSDOS+Loadcepc来启动CE操作系统。显然这样的幸运不是永远的,所以对Boot Loader应该有足够的研究和了解,做到未雨绸缪。
  Boot Loader是定制Windows CE操作系统过程中一个重要的开发环节。Boot Loader的作用正如名字中的两个单词:Boot,既引导系统,如果基于CE的产品采用BIOS实现硬件初始化和配置,那么Boot Loader只需引导软件系统。如果没有采用BIOS,那么Boot Loader的作用还包括实现BIOS的基本功能;Loader,既加载操作系统,在整个系统正常启动后Boot Loader通过不同的方式加载CE的内核文件nk.bin。当Boot Loader把nk.bin解压到RAM后就把CPU控制权交给CE内核。x86平台的Boot Loader种类最多,下面就对x86平台的Boot Loader做一说明:
  x86 ROM Boot Loader
  又叫Rom Boot,记得以前写过的文章中提到了Rom Boot。Rom Boot 被设计存放在Flash/EEPROM中,也就是原来BIOS的位置,这样当上电后CPU到固定地址执行代码,也就是执行了Rom Boot包含的代码,它对整个硬件系统进行初始化和检测,并且支持通过网卡从远程机器上下载nk.bin或者从本地IDE/ATA 硬盘的活动分区中寻找nk.bin文件加载。Rom Boot的优点就是引导并且加载速度快,而且它自身完成了所有的操作,这样就不用BIOS、MSDOS,更不用Loadcepc了。缺点就是需要CE开发者读懂它的源码并修改。CE提供了Rom Boot的所有源码,读者可以查找标题为“x86 Source Organization”的帮助文档,在这个文档中列举了所有相关的目录及内容,另外还列举了四种网卡的驱动程序源码所在目录。
  x86 BIOS Boot Loader
  BIOS Boot Loader和MSDOS+Loadcepc两种方式差不多,BIOS Boot Loader只是不需要MSDOS操作系统,它仍然需要BIOS和FAT文件系统。下面讲一下采用BIOS Boot Loader的系统的引导顺序:系统上电后BIOS执行完硬件初始化和配置后,BIOS检查引导设备的启动顺序,如果引导设备是硬盘、CF卡、DOC(Disk-On-Chip)一类的存储设备,那么就加载这些存储器上的主引导扇区(Master Boot Sector)中的实模式代码到内存,然后执行这些代码。这里提到的代码被称为主引导记录(MBR)。MBR首先在分区表(同样位于主引导扇区)中寻找活动分区,如果存在活动分区,那么加载位于这个活动分区的第一个扇区上的代码到内存,然后执行这些代码。这里提到的活动分区的第一个扇区被称为引导扇区(Boot Sector)。引导扇区上的代码的功能是找到并且加载BIOS Boot Loader,BIOS Boot Loader再加载nk.bin。引导扇区的源码位于%_WINCEROOT%/Public/Common/Oak/Csp/i486/Biosloader/Bootsector目录下。有一个现成的引导扇区镜像文件,它的路径为%_WINCEROOT%/Public/Common/Oak/Csp/i486/Biosloader/Diskimages/Setupdisk/Bsect.img 。而对于BIOS Boot Loader,CE提供了Setupdisk.144和Bootdisk.144两个文件,以“.144”为扩展名的文件的解压我在前面的文章中讲过了。这两个文件解开后都包含了引导扇区和Boot Loader的镜像文件。执行“mkdisk C:”批处理命令将这两个镜像文件写到磁盘上。mkdisk会设置Boot Loader的隐藏属性,这样在列出根目录下所有文件时不会显示Boot Loader的文件。
  MSDOS+Loadcepc
  这种方式非常简单,在MSDOS启动后再执行loadcepc.exe,让loadcepc加载nk.bin到内存后再把CPU控制权交给CE内核程序。loadcepc在前面的文章中已经讲过了。
  下面根据一般的Boot Loader源码来分析一下Boot Loader的组成:
  Boot Loader由两部分组成:OEM启动代码(OEM startup code)和主代码(main code)。OEM启动代码是最先执行的部分,它的功能是初始化内存寄存器、设置CPU频率、初始化高速缓存等。之后它跳转到主代码中执行。一般OEM启动代码都是用汇编编写。主代码一般用C语言编写,它负责其它所有任务,在执行的同时还能够将执行的相关信息显示在屏幕上。一般添加公司LOGO或者其它启动LOGO都在此修改。
  主代码主要由几个部分组成:镜像下载代码,通过并口或者网卡来实现从远程计算机下载nk.bin;串口调试代码,包含对串口的读写函数,用户调用这些函数就可以通过串口在远程计算机和本地计算机之间通信;写flash代码,包含写镜像到flash的函数;硬件监控代码。
  一般的Boot Loader的执行流程见下图:
  上图中每个函数的功能如下:
   StartUp() :CPU最先执行的函数。也就是启动代码。
   BootLoaderMain() :先后调用KernelRelocate、OEMDebugInit、OEMPlatformInit、OEMPreDownload等函数。此函数源码文件路径为%_WINCEROOT%/public/common/oak/drivers/ethdbg/blcommon 。
   OEMDebugInit() :初始化串口。
   OEMPlatformInit() :执行特定平台的初始化工作,如时钟、一些驱动程序。
   OEMPreDownload() :做下载前的准备工作。一般用于反馈给用户一些信息。
   DownloadImage() :下载操作系统镜像到RAM或者Flash。
   OEMLaunch() :负责启动镜像。
   OEMReadData() :从远程计算机读取数据。
   OEMMapMemAddr() :专用于写Flash时使用。因为写flash的速度非常慢,所以此函数将Flash镜像临时缓冲到RAM中。
   OEMShowProgress() :从函数名就能看出。
   OEMIsFLashAddr() :判断一个地址是否是Flash的地址。
   OEMFinishEraseFlash() :判断是否完成了擦除Flash内容工作。
   OEMWriteFlash() :写镜像到Flash。
   OEMStartEraseFlash() :开始擦除Flash。
   OEMContinueEraseFlash() :继续擦除Flash工作。
目录
相关文章
|
15天前
|
XML 编解码 算法
推荐一款嵌入式C的开源代码框架-tboox / tbox
推荐一款嵌入式C的开源代码框架-tboox / tbox
39 2
|
缓存 中间件 Swift
优酷iOS工程插件化 -- 大量模块壳工程本地如何快速编译
业务快速发展,优酷工程已有大量模块,模块耦合严重且混乱,模块依赖是一颗“树”,甚至于一张“网” ,导致开发体验持续严重下降,如何解决本地调试效率低、不支持模拟器、模块整包依赖不一致等等痛点问题,文中进行了说明。
53974 6
|
12月前
|
XML JavaScript 小程序
Spring Boot 实现万能文件在线预览,已开源,真香!!
Spring Boot 实现万能文件在线预览,已开源,真香!!
|
运维 IDE Devops
Cloud IDE 大比拼 《在线编辑器》
我们知道目前很多云服务商,在实践 DevOps 能力的过程中,云服务的客户往往会把需求、代码、构建、测试、发布、部署、运维、运营等工作全部从本地转移到云端,享受云服务带来的移动性和便利性。但是一直缺乏有效的上云方式,导致开发人员手中没有良好的工具,无法真正实现 DevOps 运维开发一体化的理念,因此一款云上 Coding 的开发工具,也是很多云服务商的必备神器。
440 0
|
Web App开发 编解码 前端开发
常用的前端自动化测试工具介绍 —— Karma
常用的前端自动化测试工具介绍 —— Karma
618 0
常用的前端自动化测试工具介绍 —— Karma
|
XML JSON 开发框架
两个案例五分钟轻松入门Harmony(鸿蒙)开发
两个案例五分钟轻松入门Harmony(鸿蒙)开发
367 0
两个案例五分钟轻松入门Harmony(鸿蒙)开发
|
人工智能 安全 网络协议
YoC开发测试工具介绍一:YoC铁三角
YoC铁三角是指在YoC协作开发中的三个开发实体的简称,通过彼此的相互协作,为开发者提供组件化软硬件云端一体的解决方案。
YoC开发测试工具介绍一:YoC铁三角
|
XML Android开发 数据格式
Android项目实战(四十):Andoird 7.0+ 安装APK适配
原文:Android项目实战(四十):Andoird 7.0+ 安装APK适配       首先看一下安装apk文件的代码    /** * 通过隐式意图调用系统安装程序安装APK */ public static void install(Context...
1136 0