UEFI开发探索28 – 用Windbg建立UEFI调试环境

(请保留->发布地址: http://yiiyee.cn/blog/author/luobing/ )

最近的翻译计划和博客计划严重滞后。一方面是因为有两个案子在推进,业余时间也被占用;另外一方面,在尝试用windbg搭建调试环境的时候,遇到了一些阻碍。

大部分情况下,我都是使用win10的虚拟机,配合UDK2018开发的。对照文档,第一次尝试就失败了。

文档中建议的环境是Win 7/Win8 64位,UDK2010。搭建win7的虚拟机,安装Vs2008+UDK2010,再试,不行。

我怀疑虚拟机是不是会有影响,幸好公司到处都是Mini PC。下班后找了台实际机器搭建,还是不行。

在工作间隙和下班后,只要有时间,我就苦苦寻找可能性。各类操作系统,各类UDK,各版本Qemu和各版本windbg,组合起来起码也有20几种。

在我搭建这些环境的次数多到想吐,准备转到Linux下时,今天早上,竟然成功了!

冷静下来思考,发现自己有80%以上的工作,都是无用功。不过正如7个炊饼的故事一样,这些无用功才引导我尝试成功。收拾起心情,把这几天的无用功整理一下。

继续阅读“UEFI开发探索28 – 用Windbg建立UEFI调试环境”

8,238 total views, no views today

UEFI开发探索27 – 用Vs2015建立UEFI调试环境

(请保留->发布地址: http://yiiyee.cn/blog/author/luobing/ )

我使用AppPkg进行Uefi app和UEFI oprom的开发,这样很方便生成在实际硬件中运行的代码。

而在日常的开发调试,不可能有硬件环境,一般会使用UEFI中生成的模拟环境,其执行文件为SecMain.exe,是在Nt32Pkg中生成的。我一般是将生成文件拷贝到其同目录下,运行SecMain.exe,进入模拟UEFI Shell执行生成文件。

当然,调试的办法仍旧是使用Print()函数,打印出需要的信息。再加上一点点想象力,以及对代码的理解,解决遇到的问题。

网上找到的资料,大部分是以Nt32Pkg为例子搭建的环境来构建调试环境。很久以前我也曾经用VS2008搭建过,可以用来编译,调试则没有成功。当时项目时间比较紧,没有去深究,用古老的Print()大法进行调试,好歹是将项目完成了。

这几天在寻找建立UEFI调试环境的过程中,发现intel其实提供了调试工具,名为UDK Debugger Tool。配合windbg和Qemu,可以搭建完整的调试环境。看到windbg,我就被吸引住了。一直觉得自己用得不熟,正好借这个机会好好深入一下。

因此,我准备花点时间用windbg来搭建调试环境。

至于用VS2015自带的调试器,我个人觉得配合SecMain也是可以搭建起来的。在尝试的过程中发现了很多可能性,有些问题我还没有想到解决办法。估计会很花时间,我暂时放弃了。

不过经验难得,我把探索VS2015建立调试环境的过程记录下来了。

1 创建Makefile Project

第一步就遇到困难了。

继续阅读“UEFI开发探索27 – 用Vs2015建立UEFI调试环境”

2,897 total views, no views today

UEFI开发探索26 – UEFI下观察汇编代码

(请保留->发布地址: http://yiiyee.cn/blog/author/luobing/ )

上一篇博客中遇到了奇怪的问题,明明没有使用的函数,在编译的时候竟然报错,提示使用了此函数,而且导致程序无法链接。

这让我意识到,还是得建立完整的调试环境,帮助学习开发。

一直以来,我调试代码的方法大概有三种:

1) 打印输出。这是最常用的,也最方便的。不管是通过屏幕打印输出,还是通过串口、USB口等硬件设备打印,都能知道很多程序的内部信息;
2) 观察汇编代码。 主要用来准确的知道程序内部运行状况、库的链接、各种变量等,配合map、lst等文件综合分析。用来解决一些疑难杂症;
3) 断点调试。  这是最好的调试方法,不过视开发的产品,有时候很难实现。如果是调试Windows driver&app,VS系列产品以及Windbg能发挥很大作用;Linux下用gdb,也很好;调试DOS和Legacy bios时,我用debug.exe较多。开发固件代码时就比较麻烦了,要么用软件模拟器调试,要么用JTAG调试。

帮朋友打个小广告,建议读一读张银奎的《软件调试》, 目前他在筹划第二版四卷本的计划。第二版的第一卷已经出版,值得好好读一读。承张老师惠赠一本,正在拜读:

图1 软件调试第二版 卷1

UEFI下开发APP和Driver,以及我目前的目标Option ROM,在实际硬件中是没法使用断点调试的,至少目前我没有找到方法。实在很怀念用debug.exe调试DOS程序的日子,工具虽然简单,该有的功能都有,UEFI下怎么就没提供这种类似的工具呢?

我准备用几篇博客,谈一谈如何建立第二种观察汇编代码和第三种断点调试的方法。当然,断点调试只能在TianoCore(模拟环境)配合下工作,实际硬件就无能为力了。这就足够了,能大大加快各种代码的开发。

这篇介绍如何去观察汇编代码。

继续阅读“UEFI开发探索26 – UEFI下观察汇编代码”

3,084 total views, no views today

UEFI开发探索25 – 图像显示(PCX)

(请保留->发布地址: http://yiiyee.cn/blog/author/luobing/ )

隔离卡的界面开发中,PCX实际上用得最多。主要是因为它采用了RLE压缩,在颜色不多的情况下,能够比较小。这也逼着我使用各种工具,比如PS、ACDSEE甚至是画图软件,来调整其色彩数,以减少图像尺寸。

毕竟隔离卡的ROM只有64K可用,因此常用的是256色PCX。PCX其实也支持24位真彩色,本篇中我尝试在UEFI Shell下显示24位真彩色PCX文件。

1 PCX格式介绍

PCX文件包含三部分:

  1. 文件头128字节,包含各种信息;
  2. 压缩图像数据部分,任意大小;
  3. 结尾一般带有256色的调色板,供768字节;

文件头如下:

图1 PCX结构

PCX的格式相对比较古老了,这里有篇文档可以参考一下:http://techheap.packetizer.com/compression/graphics/pcxfmt.html

继续阅读“UEFI开发探索25 – 图像显示(PCX)”

2,538 total views, no views today

UEFI开发探索24 – 图像显示(BMP)

(请保留->发布地址: http://yiiyee.cn/blog/author/luobing/ )

BMP是微软推荐和支持的标准图像文件格式,图像数据不经过压缩直接存盘,直译过来是位图(bitmap)。

最早的时候,Windows自带的画图程序只支持bmp格式,现在缺省支持PNG了。

这种格式比较简单,数据结构也非常容易看懂。我在开发隔离卡、Option ROM以及嵌入式产品时,如果需要用到图像,只要空间允许,都是用BMP格式。代码简单,很多时候几行循环代码就搞定。

在Foxdisk的博客中,还没来得及对图像格式进行介绍。那款软件中主要使用了BMP和PCX两种图像格式。

我预备用几篇博客,把常用的图像格式在UEFI Shell下如何显示介绍一下。为了方便,没有使用main函数作为入口,而是使用了ShellAppMian。理由比较简单,main函数入口参数不是Unicode的,需要进行转换;另外,我也想尽可能使用UEFI提供的函数来进行处理,尽量少用标准C的库函数。

先从BMP开始。

继续阅读“UEFI开发探索24 – 图像显示(BMP)”

3,181 total views, no views today

UEFI开发探索23 – File IO(文件读写)

(请保留->发布地址: http://yiiyee.cn/blog/author/luobing/ )

Option ROM的开发中,很少用到文件读写。因此,在最早开发的过程中,我没有仔细研究过文件处理相关的Protocol。

倒是在编写显示图片例程的时候,涉及到了一些。我直接使用了UDK中的例子,改造了显示BMP的函数,函数内部封装了文件读取。

接下来我准备用几篇博客,演示如何显示图片。UEFI画图的程序,在之前的博客中已经讨论演示过了。下面需要做的,是解析图像格式,解压数据,并通过画图函数将其显示在屏幕上。

预备要处理的图像格式包括BMP、PCX,有时间的话研究下Jpeg。

当然,首先还得搞清楚UEFI下怎么进行文件读写。

继续阅读“UEFI开发探索23 – File IO(文件读写)”

5,001 total views, no views today

UEFI开发探索22 – 环境搭建3

(请保留->发布地址: http://yiiyee.cn/blog/author/luobing/ )

之前搭建UDK2017和UDK2018失败,我只能使用以前的开发环境WinXP+UDK2010来调试程序。总感觉自己像个史前程序员,XP下很多工具都没法使用的。比如我想看某个函数的定义,只能使用TotalCmd全文件夹搜索,感觉很不爽。

今天去公司加班,广州有客人来访。下午送走客人后,我盯着以前写的“搭建环境”的博客,下定决心,一定要用上win10+UDK2018为新的开发环境。

继续阅读“UEFI开发探索22 – 环境搭建3”

4,717 total views, no views today

UEFI开发探索21 – SMBUS通信

(请保留->发布地址: http://yiiyee.cn/blog/author/luobing/ )

SMBus是1995年由Intel提出的一种双线通信专利技术,它完全符合系统管理总线规范1.1版,与I2C串行总线兼容。与当前流行的高速串行协议相比,SMBus的速度比较慢,但因其使用硬件少,支持此协议的产品非常多,在当前的计算机行业仍然有很大的应用面。

在开发双网隔离计算机的过程中,需要解决三方通信问题。即Windows/Linux层App、控制卡Firmware和BIOS(包括BIOS oprom)三方的通信。实际上需要解决的是控制卡Firmware与Windows/Linux层App、控制卡Firmware与BIOS通信的问题。

最早我采用PCI/PCIE芯片。问题是厂商提供的驱动不完善,总是有各种问题;加上芯片上的控制引脚不够,无法实现产品目标。

后期换为C8051F320,价格也比较合适。底层的通信(控制卡Firmware与BIOS)定为SMBUS总线通信方式;上层的通信则使用了USB HID协议。

由此开始了我辗转在各种平台上开发SMBUS通信代码的历程。

继续阅读“UEFI开发探索21 – SMBUS通信”

4,761 total views, no views today

UEFI开发探索20 – 串口通信

(请保留->发布地址: http://yiiyee.cn/blog/author/luobing/ )

串口可能是生命力最强的接口标准了,从1980年到现在,仍旧在发挥巨大的作用。特别是工业环境下,可说是王者标准了。

前几年开发过网络转串口,我惊奇的发现很多金融场合也在用串口。

扯远了,回到UEFI下的串口通信。

1 Shell命令查看串口

我的开发环境仍旧是虚拟机winxp+UDK2010,一直没有时间去搭建UDK2018。UEFI Shell中有个命令Sermode,可以查看以及设置串口参数。

图1 TianoCore模拟环境中枚举串口

设备管理器中有两个串口,TianoCore的模拟环境中也列出了两个串口。下面的问题是,如何与虚拟机中的串口通信?

继续阅读“UEFI开发探索20 – 串口通信”

2,770 total views, no views today

UEFI开发探索19 – 使用HII显示汉字4

(请保留->发布地址: http://yiiyee.cn/blog/author/luobing/ )

已经实现了UEFI Shell下使用SimpleFont和Font,在Graphics模式下来实现就相对容易很多了。

我大部分的工作都是在整理文件,以及按照之前的代码结构,专为Hii构建了源代码文件,把一些细节封装起来,以备后用。

图1 整理好的源代码

可以讲解的地方不多,主要是在开发中遇到的一些问题:

继续阅读“UEFI开发探索19 – 使用HII显示汉字4”

4,389 total views, no views today

UEFI开发探索18 – 使用HII显示汉字3

(请保留->发布地址: http://yiiyee.cn/blog/author/luobing/ )

本篇博客的关键字:Font。

今天准备把UEFI另外一种字体Font的方方面面研究一下,仍旧是以代码移植为主,间以解决自己提的几个问题。

1 Text模式和Graphics模式

实验之前,我想谈一下Text模式和Graphics模式。UEFI spec中,对于Text模式和Graphics模式谈的比较少。我一直很疑惑,spec中的Text模式和Graphics模式是不是我所理解的。

继续阅读“UEFI开发探索18 – 使用HII显示汉字3”

3,363 total views, no views today

UEFI开发探索17 – 使用HII显示汉字2

(请保留->发布地址: http://yiiyee.cn/blog/author/luobing/ )

本篇博客的关键字:SimpleFont。

我始终在思考如何在UEFI Shell下显示汉字。上一篇中,参考书中的例子,基本了解了字符串资源是怎么组织的。当在TestString函数中,把参数Language改为”zh-Hans”,什么也没有显示。

看来还是缺少相应的字库。

UEFI下提供了SimpleFont和Font字体,前一个相对简单些,我先拿这个开刀。我参考的例子是《UEFI原理与编程》的\GUIbasics\font\SimpleFont,这个例子直接编译没有成功。我也没有去找原因,还是老办法,把它的例程移植到我自己的程序中来。

1 SimpleFont格式

SimpleFont有两种字体格式,窄字符和宽字符,在书中描述得很清楚。TianoCore的模拟环境中,也使用了SimpleFont的字库。

继续阅读“UEFI开发探索17 – 使用HII显示汉字2”

2,429 total views, no views today

UEFI开发探索16 – 使用HII显示汉字1

(请保留->发布地址: http://yiiyee.cn/blog/author/luobing/ )

上一次博客中,我使用自己的方法显示汉字,其核心思想不外乎利用实现的画点函数,将汉字一个像素一个像素地画出来。

很明显,这种方法只能在图形模式下实现。如果想在字符模式下显示(比如UEFI Shell),则无能无力了。虽然目前商用的Option Rom不可能用到字符模式,奈何寻根究底的程序员本性,驱使着我把UEFI本身提供的Human Interface Infrastructure机制搞明白。

于是开始了我这几天的探索之旅。

所有的探索都是从问题开始,对HII,我提的问题如下:

  1. 如何组织汉字库(其他语言也一样,怎么存储字库?);
  2. 是否能在UEFI Shell下显示汉字,如何实现?
  3. 图形模式下如何显示汉字?
继续阅读“UEFI开发探索16 – 使用HII显示汉字1”

3,804 total views, no views today

UEFI开发探索15 – 图形模式下文字显示

(请保留->发布地址: http://yiiyee.cn/blog/author/luobing/ )

UEFI中提供了HII(Human Interface Infrastructure)用来处理图形界面的文字显示,这一块我一直没有去仔细研究。到目前为止,显示汉字和字符,我都没有采用这种方法。

比如之前博客中演示了测试样卡的界面,图形中用到了各种英文和汉字,都是采用我自己的方法来实现的。

HII的思考方式不大直接,当时我面临着要在几周内完成UEFI Option ROM的开发,需要克服的困难太多,图形模式下的汉字和英文字符的显示,我采用了Foxdisk中的显示方法。

具体来说,在前面的博客中,已经实现了画点函数(putpixel)函数,那么把所有汉字及英文字符看做一个个的字模,画出来就行了。所有的核心思想皆源于此。

继续阅读“UEFI开发探索15 – 图形模式下文字显示”

2,586 total views, no views today

UEFI开发探索14 – 访问PCI/PCI-E设备2

(请保留->发布地址: http://yiiyee.cn/blog/author/luobing/ )

(关于PCI访问,其中一些内容来自网上,找不到出处了)

PCI规范使用从0CF8H~0CFFH 这8个I/O地址来访问所有设备的PCI配置空间。这8个字节实际上构成了两个32位寄存器:0CF8H寄存器叫做“配置地址寄存器”;0CFCH叫做“配置数据寄存器”。

当要访问配置空间的寄存器时,先向地址寄存器写上目标地址,然后就可以从数据寄存器中读写数据了。

PCI配置空间对应于一个PCI逻辑设备,所以要访问一个配置空间的某个寄存器,必须要指定:PCI总线号、PCI设备号、PCI设备功能号和寄存器号。配置地址寄存器的格式如下:

继续阅读“UEFI开发探索14 – 访问PCI/PCI-E设备2”

3,364 total views, no views today

UEFI开发探索13 – 访问PCI/PCI-E设备1

(请保留->发布地址: http://yiiyee.cn/blog/author/luobing/ )

我所用的测试卡是PCI-E设备,公司商用的产品也是PCI-E设备。所以,我很早就“被迫”去读那些PCI spec。

从软件工程师的角度,我觉得只要解决几个问题就行了,其余的细节不妨碍编程。

1)      PCI/PCI-E设备是如何定位的,也即程序如何找到设备;
2)      系统把它认作什么设备;
3)      如何访问设备的内部寄存器(一般要去读所使用的PCI-E芯片的资料);
4)      商用化的产品,需要考虑设备对ACPI的各种电源事件的处理。

继续阅读“UEFI开发探索13 – 访问PCI/PCI-E设备1”

5,892 total views, no views today