UEFI开发探索101 – PCD探究

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

从《UEFI编程实践》出版后,一系列的事情接踵而来,终于在今天,算是告一段落了。

这段时间,有不少机会和业内人员讨论UEFI和BIOS。反思自己对这个领域的理解,深感自己理论的不足。

看过《UEFI编程实践》的网友,应该能了解,书中对于概念的理论部分,阐述得相对较少。我一般都是遵循“提出问题-介绍UEFI相关知识-提供实例”的框架,围绕某一课题进行研究。

其中的一个原因,是因为我本来就是奔着实践为目的,将平时开发中所遇到的课题逐渐展开讨论。另一个原因,是没有深入到EDK2的具体实现去。

因此,从UEFI开发探索第101篇开始,我想逐渐转向对EDK2的代码研究了。如之前研究PCI Option ROM开发一样,这次设立的目标包括:

  1. 对OvmfPkg源代码进行研究,搞清楚固件架构、编译过程、各阶段代码实现等;
  2. 了解Qemu怎么使用固件启动的,以及如何启动操作系统;
  3. 了解Ovmf固件如何提供操作系统所需要的各种Table、Runtime Services,甚至SMI Handler等。搞清楚一个UEFI操作系统如何与BIOS结合的。

我了解这是一个不小的目标,会遇到不少的困难,兴趣所在,倒不是特别畏惧。本来的想法,是在树莓派上进行实验,在lab-z(博客:https://www.lab-z.com/)的建议下,觉得OvmfPkg做实验更方便些。

主题确定,后续想到哪里不熟就补足哪里的知识。嗯,先从EDK2全局配置的关键核心-PCD开始研究。

1 PCD简介

Platform Configuration Database(PCD)是EDK2用来进行全局配置的机制,可在代码复用、模块化方面发挥巨大作用。

PCD是把代码里面的可配置选项抽取出来,在platform需要修改的时候,可以不用去修改源代码。其参数的配置,可以在编译过程中、运行时中都可以配置,甚至在二进制文件中也可以配置。

这种设计方式就比较让人着迷,这也使得定制化更为容易,代码更容易维护。

早期我一直以为PCD如同C/C++中的宏,用来提取公用代码,这是错误的。它提供的功能更为广泛,也更复杂。

首先直观地看下平常程序中用到的PCD,以前几篇中的Diskdump工程为例,使用如下命令编译,提取出其所用的PCD信息:

C:\vUDK2018\edk2>build -Y PCD -y pcd.log -p RobinPkg\RobinPkg.dsc -m RobinPkg\Applications\Diskdump\Diskdump.inf -a IA32

输出的信息,存在了pcd.log中。查看下log信息:

图1 Diskdump中用到的PCD
继续阅读“UEFI开发探索101 – PCD探究”

349 total views, 3 views today

UEFI开发探索100 – 《UEFI编程实践》发布啦

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

经过四百多天的奋斗,新书终于上市了(京东官方书店 https://item.jd.com/13406126.html):

每天晚上9点,在安排好孩子睡觉后,就坐在书桌前敲打键盘;每个周末,都逼迫自己进入代码和Spec的海洋,一句句调试,一点点查询。

看到书稿成型的那一刻,感觉一切的付出都值得了!

封面以红色色调为主,占据视觉中心的芯片,周边的器件和数字0、1,表明这是本计算机底层实践的书。在各种器件间专心走着的漫画小人,让我想起每个专心调试的日日夜夜。我很喜欢这个封面的感觉,工程师的文化感扑面而来。

书中提供了33个UEFI应用和驱动示例,以及多个用来配合实验的Windows程序、Linux程序和嵌入式程序。涵盖了构建程序架构、调试方法、构建GUI、各种总线外设的访问、网络应用开发、UEFI驱动和Option ROM开发等内容,特别介绍了国产计算机下的UEFI开发,是偏实战操作的技术性书籍。

继续阅读“UEFI开发探索100 – 《UEFI编程实践》发布啦”

594 total views, 7 views today

UEFI开发探索99 – UEFI Shell下截屏工具

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

最近有些程序,只能在实际机器的UEFI Shell下进行测试。比如上一篇的diskdump程序,在模拟器下是没法运行的。

模拟器上运行,可以直接使用各种截屏软件截图,图像还是比较清晰的。在实际机器上运行,只能使用手机录像或者拍照。自己的拍照技术有多糟糕,我还是很清楚的。所拍出的照片,只能勉强看清楚程序的运行情况。因此,后期还得在电脑上用PS处理一下。

这种情况遇到多了,总得想个办法解决一下。

今天早上上班的路上,冒出一个想法,何不写个UEFI Shell下截屏的软件?

需要解决的问题不多,主要包括以下几个:
1) 截屏程序要能常驻内存,以允许其他程序在运行的时候唤出;
2) 设置键盘热键,可以随时唤出后台运行的截屏程序;
3) 将整个屏幕以bmp图像的格式,存储在硬盘或者U盘上。

有点类似以前DOS系统下的常驻内存程序TSR一样,早期的DOS中有大量这样的程序存在。

想了一下实现方法,觉得应该可以在UEFI下把这个截屏软件实现出来。常驻内存应该可以通过UEFI驱动的方式实现,屏幕获取和存取BMP图像比较简单,之前写的图像处理代码稍微修改就可以了。

不过,越深入思考,越觉得在哪看过这样的想法。

查了下平常的开发日志,果然,微软的Github库中,提供了同样功能的软件。很久以前我就看过了,只是一直没有去编译测试。

这个UEFI程序存在于微软在Github上的mu_plus库中,库的地址为:https://github.com/microsoft/mu_plus.git。

截图软件位于mu_plus的MsGraphicsPkg中,名称为PrintScreenLogger。

既然已经有了,就没必要再写了,本篇试着了解其实现原理,并在实际环境中测试一下。

1 PrintScreenLogger的代码结构

从整体设计上来看,与想象的差不多。PrintScreenLogger采用了UEFI驱动的形式,让程序可以常驻内存。

其代码结构如图1所示。

图1 PrintScreenLogger程序结构图
继续阅读“UEFI开发探索99 – UEFI Shell下截屏工具”

460 total views, 5 views today

UEFI开发探索98 – 硬盘访问Diskdump

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

之前在CSDN上建了一个专栏,名字为汇编语言探索,准备聊一些用汇编写的小项目。大概写了十几篇关于Foxdisk运行原理的文章,后面还会不定期的写写,特别是最近看到一个俄罗斯程序员用FASM写的KolibriOS,贼有意思了,找时间读一读。

Foxdisk本来是我为自己写的一个多操作系统引导的软件,类似于Grub。核心点在于,在Foxdisk内可以将硬盘分成若干区域,每个区域装一个操作系统,各操作系统间可以通过共享的分区分享数据。而提供的图形界面,比单调的Grub让我舒服些。

这是一个很好的想法,能满足我使用多个操作系统的开发习惯。Foxdisk开发了3代,前两代是纯粹用汇编语言写的,3.0则使用了C语言嵌汇编。再然后,我迷上了UEFI,对于在Legacy BIOS下开发的Foxdisk,就这么抛弃了。

Foxdisk 3.0中,内置了对硬盘分区的功能(相当于Fdisk或spfdisk之类的工具)。实际上,Foxdisk大部分的工作,都是在和硬盘打交道。

进入UEFI后,一直不怎么想去研究硬盘访问。总觉得UEFI本身已经将硬盘访问封装得很好了,没什么必要再去开发分区、格式化之类的软件了。

刚好在近期的项目中,需要在Option ROM中查看某几个扇区的数据。为了比对Option ROM的代码,需要开发一个UEFI小程序,实现类似功能。

1 UEFI的存储介质访问栈

UEFI规范中提供了大量的存储介质Protocol(Media Protocol),甚至包括内存虚拟盘(RAM Disk)都支持了。

Legacy BIOS下是通过Int 0x13进行硬盘访问的,由寄存器AH标识各种功能号,供程序员调用。习惯了这种思维,再看UEFI的访问方式,总是有点别扭。

首先需要找出类似功能的访问接口,UEFI提供了从硬盘协议层的Protocol,一直到文件系统的Protocol,非常完善,其架构如图1所示。

图1 UEFI的存储介质访问栈
继续阅读“UEFI开发探索98 – 硬盘访问Diskdump”

309 total views, no views today

UEFI开发探索97 – EDK2模拟器搭建网络环境

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

最近一段时间,很多网友问的问题都是和网络相关的。讨论的问题大部分是关于网络环境的搭建,有些现象我也没有遇到过。

在UEFI开发探索49中,介绍过在Nt32模拟器和真实环境中搭建UEFI网络环境。当时我使用的EDK2是UDK2018的版本。

随着EDK2版本的升级,原有的NT32模拟器(使用Nt32Pkg编译)已经取消了,随之替代的是EmulatorPkg。后者提供的功能更为全面,提供了32位和64位的模拟器,之前的博客中也曾经介绍过。

因此,本篇准备用EmulatorPkg编译的模拟器重新搭建网络测试环境。之前的模拟器使用Nt32Pkg编译,所以我取名为Nt32模拟器;现在的EmulatorPkg名字太长了,为方便行文,称之为EDK2模拟器了。

1 搭建EDK2开发环境

详细的搭建过程,可以参考UEFI开发探索22和57,这里简单描述本次的搭建过程。步骤如下:

1)工具安装

安装必要的开发工具,包括Visual Studio、Python、ASL和Nasm;

2)下载代码库

使用Git将EDK2的代码和StdLib的代码下载到本地。

在C盘新建目录edk202011,使用如下命令下载:

robin@robin-PC MINGW64 /c/edk202011
$ git clone --branch stable/202011 https://gitee.com/luobing4365/edk2.git
$ git clone https://gitee.com/luobing4365/edk2-libc.git

请注意,这里下载的地址是我的私有仓库,我把github上的edk2和edk2-libc的仓库同步到我在gitee上的仓库中了,方便自己下载。

不要按照我给的命令去下载,原始的仓库为https://github.com/tianocore/edk2.git 和https://github.com/tianocore/edk2-libc.git,可以使用如下命令去下载:

$ git clone --branch stable/202011 https://github.com/tianocore/edk2.git
$ git clone https://github.com/tianocore/edk2-libc.git

当然,取决于你所在地方的网速,下载速度会很慢。建议使用同样的方法,将github上的仓库同步到gitee上,或者直接在gitee上找到同样的仓库再下载。

本篇使用的分支为stable/202011,后续的实验结果均是基于此版本得出的。

3)更新子模块

修改edk2中的.gitmodules,更子模块。

如果能使用github直接下载,可以不用修改.gitmodules,直接运行后续的更新命令就可以了。我修改的内容如下:

[submodule "CryptoPkg/Library/OpensslLib/openssl"]
	path = CryptoPkg/Library/OpensslLib/openssl
	url = https://gitee.com/luobing4365/openssl.git
[submodule "SoftFloat"]
	path = ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3
	url = https://gitee.com/luobing4365/berkeley-softfloat-3.git
[submodule "UnitTestFrameworkPkg/Library/CmockaLib/cmocka"]
	path = UnitTestFrameworkPkg/Library/CmockaLib/cmocka
	url = https://gitee.com/luobing4365/cmocka.git
[submodule "MdeModulePkg/Universal/RegularExpressionDxe/oniguruma"]
	path = MdeModulePkg/Universal/RegularExpressionDxe/oniguruma
	url = https://gitee.com/luobing4365/oniguruma.git
[submodule "MdeModulePkg/Library/BrotliCustomDecompressLib/brotli"]
	path = MdeModulePkg/Library/BrotliCustomDecompressLib/brotli
	url = https://gitee.com/luobing4365/brotli.git
[submodule "BaseTools/Source/C/BrotliCompress/brotli"]
	path = BaseTools/Source/C/BrotliCompress/brotli
	url = https://gitee.com/luobing4365/brotli.git
ignore = untracked

再次提醒,上述的子模块给出的地址,均是我将子模块在github上的仓库,导到gitee上的地址。可以参考我的方法,但是不要直接使用,这些都是我的私有地址,没法直接用。

具体的导入方法,可以参考UEFI开发探索57的内容。

继续阅读“UEFI开发探索97 – EDK2模拟器搭建网络环境”

294 total views, 1 views today

UEFI开发探索96 – 温度计小游戏

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

syslibforuefi中,还有几个小程序。从我的角度来看,最值得学习的是他将图像变为HII资源的方式,其他图形图像的知识,在很久以前的博客中,已经研究了很多了。

早上打开CSDN,让我吃了一惊:

图1 CSDN的评价

悄没声息地跑到了游戏领域内容榜的第2名了!

上次我就说过,我这是UEFI开发的博客啊,又不是介绍游戏开发的。这奇怪的评价,让我都不知道从哪里吐槽了。

我是不是转行去开发游戏比较好?

继续阅读“UEFI开发探索96 – 温度计小游戏”

255 total views, 1 views today

UEFI开发探索95 – 弹跳小游戏

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

昨天闲暇的时候,把Tim Lewis的迷宫游戏编译了一下,自娱自乐在UEFI下玩了一把。

奇怪的是,CSDN竟然给我发了“入选《游戏领域内容榜》第27名”,如下图:

图1 CSDN奇怪的评选

嗯,虽然从理论上来说,这篇博客也算写了个游戏,可我主要写的是UEFI程序啊。除了这篇博客的名字外,在关键字里我也没有设置“游戏”字样。

实在搞不懂CSDN的评判算法。

继续阅读“UEFI开发探索95 – 弹跳小游戏”

232 total views, no views today

UEFI开发探索94 – 迷宫小游戏

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

最近一直在写YIE002开发探索的博客,偶尔看看其他人写的和BIOS开发相关的博客。

经常看的博客有Tim Lewis、Vincent Zimmer等,总是能学到一些东西。

今天下班后,可能是因为最近公司的事情比较繁杂,精神有点不振。虽然计划了近期要写的嵌入式代码,可是怎么也提不起劲,开发工具都不想打开。

我无聊地翻阅着常看的几位作者的博客,Tim Lewis有个关于UEFI和C++的议题,稍微有点兴趣,就点进去看了。

他的代码放在了sourceforge上,地址为:https://sourceforge.net/projects/syslibforuefi/。下载了之后,我浏览了目录结构,发现几个有意思的程序。其中有些是可以在UEFI下玩的小游戏,看来程序员的想法很类似啊,我之前也开发了UEFI下的贪吃蛇游戏。

今天休息一下,拜读下顶级BIOS程序员写的UEFI程序。

1 Maze程序结构分析

源程序在文末给出了,可以试玩一下。

整个迷宫程序的主要实现目标包括:
1) 自动生成迷宫;
2) 通过方向键,控制角色通过迷宫。

实现的目标比较简单,从代码结构来看,主要包含如下函数,如图1所示。

图1 Maze程序架构图
继续阅读“UEFI开发探索94 – 迷宫小游戏”

171 total views, no views today

UEFI开发探索93 – UEFI下使用YIE002随机数发生器

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

在UEFI开发探索72中,曾经规划过YIE002的开发板计划。当时的主要目标是使用YIE002做USB HID的双向通信设备,并在Windows、Linux和UEFI下都实现上位机访问程序。

如今,这些目标都已经实现了。特别是Windows下的测试程序UsbHID,现在成为我专用的测试工具了。

当时的开发计划中,还有一项目前还没有完成,那就是让YIE002开发板提供生成随机数的功能,使得在各个系统下都能通过USB通道得到生成的随机数,包括UEFI系统。

这个目标的灵感来源于国外工程师开发的ChaosKey,是以前学习UEFI开发时,在网上搜寻资料时偶然遇到的。一个小小的产生随机数的设备(U盘大小),作者花了不少心思来制作,让我觉得很有意思。因此,在设计YIE002的时候,就预留了生成随机数的机制。

周末的时候,花了一点时间,终于把这个随机数生成器做成了。具体的过程,请见我的另外一篇博客:YIE002开发探索10-随机数生成器。

今天就来UEFI下使用下这个小设备。

1 代码编写

代码编写的过程实际非常简单,借用了UEFI开发探索88篇的工程HelloHID,稍微修改了下其中的函数,就实现了需要的功能。

将HelloHID改为RngUEFI,包括INF文件和源文件名,都修改下。然后在RobinPkg.dsc中,添加对RngUEFI工程的编译支持,就完成了框架调整。

由于YIE002随机数生成器提供了三种USB HID通信能力,可以使用任意一种方式与之通信。因此,我就直接用Feature Report通信的方式来编写代码了。

继续阅读“UEFI开发探索93 – UEFI下使用YIE002随机数发生器”

210 total views, 1 views today

UEFI开发探索92 – 调试使用了StdLib的64位程序

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

昨天有位名为“sam bing”的网友,提到用VS2015和EmulatorPkg调试UEFI程序。调试方法在之前的博客中讨论过,他是参照博客去操作的。

问题在于,他发现在工程中使用C标准库函数,也即StdLib后,在EmulatorPkg中无法编译通过,也就无法通过EmulatorPkg进行64位C标准库工程的调试了。

这个问题我也觉得奇怪,理论上不应该啊。

上午处理完项目相关的事情后,正好有点时间,就着手进行这个问题的分析了。

1 搭建开发环境

我日常都是在vUDK2018下进行开发,主要是因为它还支持Nt32Pkg,方便我随时使用模拟器进行调试。

为了分析这个问题,我得用一个相对较新的版本来测试。正好前段时间整理书稿的时候,搭建了一个开发环境,看了下版本:

robin@DESKTOP-083AISO:/mnt/c/srcEDKx/edk2$ git log
commit ca407c7246bf405da6d9b1b9d93e5e7f17b4b1f9 (HEAD, tag: edk2-stable202005)
Author: Ard Biesheuvel <ard.biesheuvel@arm.com>
Date:   Wed May 20 13:44:48 2020 +0200

ArmPkg/CompilerIntrinsicsLib: provide atomics intrinsics
…..//后略

robin@DESKTOP-083AISO:/mnt/c/srcEDKx/edk2$ ls
AppPkg          DynamicTablesPkg     License.txt      RobinPkg             StdLibPrivateInternalFiles
ArmPkg          EmbeddedPkg          Maintainers.txt  RobinPkg1            UefiCpuPkg
ArmPlatformPkg  EmulatorPkg          MdeModulePkg     SecurityPkg          UefiPayloadPkg
ArmVirtPkg      FatPkg               MdePkg           ShellPkg             UnitTestFrameworkPkg
BaseTools       FmpDevicePkg         NetworkPkg       SignedCapsulePkg     edksetup.bat
Build           IntelFsp2Pkg         OvmfPkg          SourceLevelDebugPkg  edksetup.sh
Conf            IntelFsp2WrapperPkg  PcAtChipsetPkg   StandaloneMmPkg      pip-requirements.txt
CryptoPkg       License-History.txt  ReadMe.rst       StdLib

使用的是2020年的5月版,为了方便使用,我把StdLib、AppPkg等包,以及我自己的包RobinPkg一股脑都放在了edk2的同一目录下了。

继续阅读“UEFI开发探索92 – 调试使用了StdLib的64位程序”

804 total views, 2 views today

UEFI开发探索91- 类型强制转换引起的问题

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

最近有个项目开发,我需要构建几个UEFI图形对话框,用来接受用户的密码修改和输入。大致的样子是这样的:

图1 UEFI下的密码对话框

开发过程中,发现使用VS编译和GCC编译的结果不同。一番折腾后,了解到是强制转换引起的问题。

之前有个问题集的博客,本想把这个问题也扔到那边去,不过在寻找问题原因的过程中,使用了各种调试手段,我觉得有必要记录下来,作为未来开发的参考。

因此有了这篇博客。

继续阅读“UEFI开发探索91- 类型强制转换引起的问题”

547 total views, 1 views today

UEFI开发探索90- YIE002USB开发板(13 Linux编程)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

上一篇使用hidapi的hidraw方式,实现了Linux上位机与USB HID设备通信的测试程序。不过,只实现了三种通信方式中的两种。本篇将使用hidapi的libusb方式,将三种通信方式全部实现。

1 建立开发目录

与上一篇一样,首先建立开发用的目录。新建文件夹hidlibusb,将以下文件拷贝进去:

libusb/hid.c
hidapi/hidapi.h
hidtest/test.c

为目前的代码编写Makefile,内容如下:

继续阅读“UEFI开发探索90- YIE002USB开发板(13 Linux编程)”

403 total views, 1 views today

UEFI开发探索89- YIE002USB开发板(12 Linux编程)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

对于USB HID的编程,在YIE002USB开篇时,就已经讨论过:

  1. 下位机是使用YIE002制作的USB HID设备,这是嵌入式开发;
  2. 上位机包括了Windows系统、UEFI系统和Linux系统。

上位机软件中,没有把Mac OSX包含进来,主要是因为我较少在苹果的系统上开发,而且也可以将其等同于Linux系统看待(同属于类Unix系)。

至今为止,Windows系统和UEFI系统,我们都已经完成了上位机的软件编写,下面该进入Linux的USB HID上位机软件开发了。

1 概述

对于Linux下的HID,网站“The Linux Kernel”上有非常详细的描述,值得仔细阅读,网址为:
https://www.kernel.org/doc/html/latest/hid/index.html。

我们所要访问的设备,是USB HID设备。在Linux系统中,常用的USB开源库,是libusb。这是一个用C语言开发的,跨平台的USB设备访问接口库。

在Github上找到这个开源库后,通读了一遍其文档。理论上使用它,可以完整地实现我们所需要的功能。不过,文档中也建议,如果是访问HID设备的话,可以使用hidapi。

hidapi是一个开源的操作HID设备的C语言库,适用于Windows、Linux和Mac OSX平台。它是针对HID设备的,对于其他USB设备不合适。

其源码仓库为:https://github.com/libusb/hidapi,主要目录如下:

hidapi: 头文件(所有平台共用一份头文件)hidapi.h
libusb:Linux系统实现源码文件hid.c,使用libusb库实现的方式
linux:Linux系统实现源码文件hid.c,使用内核接口(hidraw)实现方式
windows:Windows系统实现源码文件hid.c
mac:Mac OSX 系统实现源码文件hid.c
hidtest:测试代码 test.c
继续阅读“UEFI开发探索89- YIE002USB开发板(12 Linux编程)”

353 total views, 1 views today

UEFI开发探索88- YIE002USB开发板(11 UEFI下访问HID设备)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

通过前面几个篇章的博客,制作好了USB HID设备,并使用Windows下的上位机工具UsbHID,测试了设备的工作状态。

终于,可以在UEFI系统下构建访问USB HID设备的工程了。

我们所制作的USB HID设备,在Windows系统下可以成功通信,这也意味着,在UEFI环境下,我们也可以与之通信。

首先,使用linux下的lsusb工具,查看下我们之前实现的USB HID设备:

robin@robin-virtual-machine:~$ sudo lsusb -v -d 0x8765:4321
Bus 002 Device 004: ID 8765:4321  
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x8765 
  idProduct          0x4321 
  bcdDevice            2.00
  iManufacturer           1 Robin
  iProduct                2 Robin's UEFI Explorer
  iSerial                 3 My123
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           41
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xe0
      Self Powered
      Remote Wakeup
    MaxPower              100mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 No Subclass
      bInterfaceProtocol      0 None
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.10
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      33
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval              32
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval              32
Device Status:     0x0003
  Self Powered
  Remote Wakeup Enabled

从中可以看出,自制的USB HID设备,端点1可以使用中断传输的方式进行通信。另外,在上述的信息中没有列出报表描述符,此设备支持通过Output report& Input report、Feature report的方式进行通信,传输字节为16字节。

本篇介绍如何在UEFI系统下,实现对应这三种通信方式的代码,主要实现步骤如下。

继续阅读“UEFI开发探索88- YIE002USB开发板(11 UEFI下访问HID设备)”

378 total views, 1 views today

UEFI开发探索87- YIE002USB开发板(10 UEFI对USB的支持2)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

3 EFI_USB_IO_PROTOCOL

EFI_USB_IO_PROTOCOL由USB总线驱动产生,可由UEFI应用和驱动使用,用来访问各种USB设备,比如USB键盘、鼠标和大容量存储设备等。EFI_USB_IO_PROTOCOL所提供的接口,可提供四种类型的传输方式与USB设备通信,即之前介绍过的控制传输、中断传输、批量传输和实时传输。

EFI_USB_IO_PROTOCOL的函数接口如下所示:

typedef struct _EFI_USB_IO_PROTOCOL {
  EFI_USB_IO_CONTROL_TRANSFER UsbControlTransfer;   //控制传输
  EFI_USB_IO_BULK_TRANSFER UsbBulkTransfer;          //批量传输
  EFI_USB_IO_ASYNC_INTERRUPT_TRANSFER  \
                          UsbAsyncInterruptTransfer;   //异步中断传输
  EFI_USB_IO_SYNC_INTERRPUT_TRANSFER UsbSyncInterruptTransfer //同步中断传输
  EFI_USB_IO_ISOCHRONOUS_TRANSFER UsbIsochronousTransfer;      //实时传输
  EFI_USB_IO_ASYNC_ISOCHRONOUS_TRANSFER \
                          UsbAsyncIsochronousTransfer; //异步实时传输
  EFI_USB_IO_GET_DEVICE_DESCRIPTOR UsbGetDeviceDescriptor; //获取设备描述符
  EFI_USB_IO_GET_CONFIG_DESCRIPTOR UsbGetConfigDescriptor; //获取配置描述符
  EFI_USB_IO_GET_INTERFACE_DESCRIPTOR \
                        UsbGetInterfaceDescriptor;               //获取接口描述符
EFI_USB_IO_GET_ENDPOINT_DESCRIPTOR UsbGetEndpointDescriptor;
//获取端点描述符
  EFI_USB_IO_GET_STRING_DESCRIPTOR UsbGetStringDescriptor;//获取字符串描述符
  EFI_USB_IO_GET_SUPPORTED_LANGUAGES UsbGetSupportedLanguages;//获取支持语言
  EFI_USB_IO_PORT_RESET UsbPortReset;                        //重启USB控制器
} EFI_USB_IO_PROTOCOL;

对照之前介绍过的USB协议的知识,很容易理解EFI_USB_IO_PROTOCOL所提供的各类接口函数。下面主要介绍下常用的两个接口函数,UsbGetDeviceDescriptor()和UsbControlTransfer(),其他接口函数的说明,请查询UEFI Spec。

继续阅读“UEFI开发探索87- YIE002USB开发板(10 UEFI对USB的支持2)”

274 total views, 1 views today

UEFI开发探索86- YIE002USB开发板(09 UEFI对USB的支持1)

请保留-> 【原文:  https://blog.csdn.net/luobing4365 和 http://yiiyee.cn/blog/author/luobing/】

通过前面几篇博客,我们制作了具备通信能力的USB HID设备。使用之前写的Windows下的测试工具,设备工作得很好。

同样的,UEFI环境下,也可以编写上位机程序,访问USB HID设备。本篇主要介绍UEFI对USB的支持,包括UEFI的USB驱动架构和提供的USB Protocol。

1 UEFI下的USB驱动协议架构

在UEFI系统中,包含USB主控制器驱动、USB总线驱动和USB设备驱动,它们共同工作构建了UEFI平台的USB驱动协议栈。USB驱动协议栈的模型如图1所示,图中演示了USB驱动的关系和使用的Protocol。

图1 UEFI中的USB驱动协议栈

平台硬件的PCI总线上,提供了一个单独的USB控制器。PCI总线驱动为USB主控制器句柄安装Protocol,包括EFI_DEVICE_PATH_PROTOCOL和EFI_PCI_IO_PROTOCOL。而USB主控制器则使用EFI_PCI_IO_PROTOCOL,在其句柄上安装EFI_USB2_HC_PROTOCOL。

继续阅读“UEFI开发探索86- YIE002USB开发板(09 UEFI对USB的支持1)”

300 total views, 1 views today