Step to UEFI (116)CTRL+ALT+DEL输出字符

最近看代码,发现比较有意思的地方,在 Keyboard.c 中有处理 USB键盘 Ctrl+Alt+Del的代码。

    //
    // When encountering Ctrl + Alt + Del, then warm reset.
    //
    if (KeyDescriptor->Modifier == EFI_DELETE_MODIFIER) {
      if ((UsbKeyboardDevice->CtrlOn) && (UsbKeyboardDevice->AltOn)) {
        gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
      }
}

 

修改一下即可实现在 Shell下按下 Ctrl+Alt+Del输出一段字符,暂停5s然后重启的功能。

    //
    // When encountering Ctrl + Alt + Del, then warm reset.
    //
    if (KeyDescriptor->Modifier == EFI_DELETE_MODIFIER) {
      if ((UsbKeyboardDevice->CtrlOn) && (UsbKeyboardDevice->AltOn)) {
		//LABZDebug_Start
		gST->ConOut->OutputString(gST->ConOut,L"www.lab-z.com");
		gBS->Stall(5000000UL);
		// LABZDebug _End
        gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
      }
    }

 

再阅读代码,上面的代码在USBParseKey 函数中。这个函数实现的是解析 USB键盘的功能。函数调用者是EfiKey.c 中的

/**
  Timer handler to convert the key from USB.

  @param  Event                    Indicates the event that invoke this function.
  @param  Context                  Indicates the calling context.
**/
VOID
EFIAPI
USBKeyboardTimerHandler (
  IN  EFI_EVENT                 Event,
  IN  VOID                      *Context
  )

 

从名称上看,这是一个时间中断来调用的函数。具体的安装代码如下:

  Status = gBS->CreateEvent (
                  EVT_TIMER | EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  USBKeyboardTimerHandler,
                  UsbKeyboardDevice,
                  &UsbKeyboardDevice->TimerEvent
                  );

 

就是说USB键盘是通过时间中断来进行检查和处理的.

UEFI编写的迷宫游戏

最近在 GitHub 上看到了一个 UEFI 编写的迷宫游戏(作者 Haodong Liu , https://github.com/liute62/Firmware-UEFI-Maze-Game), 感觉界面不是很漂亮,于是拿过来进行简单的修改:

maze

修改之前的原始代码和资料:
Firmware-UEFI-Maze-Game-master

修改之后的代码
uefimaze

用的按键是上下左右,ECS 还有 PageUp(类似 Enter的功能)。

VS2015 下面编译 SPB 驱动

差不多3年前的这个时候,我写过一篇介绍如何在 VS2013下面编译 Windows Driver Sample的文章【参考1】。今年的这个时候,我再一次尝试在 VS2015下面编译驱动。

For building Windows Sample you need below software

1. Windows 10 RS2: 15063.0.170317-1834.RS2_RELEASE_CLIENTPRO-CORE_OEMRET_X64FRE_EN-US (Note: VS2015 can’t be installed on Windows7)
2. 15063.0.170317-1834.rs2_release_amd64fre_WDK.iso
3. 15063.0.170317-1834.rs2_release_WindowsSDK.iso
4. Visual_Studio_Pro_2015_English.iso

1.Install Windows RS2
2.Install VS2015 (2 Hours),全默认配置

3.Install WDK 到默认的路径下

image001

安装完成后,用 VS2015打开驱动工程文件。编译会出现下面的错误

“—— Build started: Project: SpbTestTool (Exe\SpbTestTool), Configuration: Debug Win32 ——
Building ‘SpbTestTool’ with toolset ‘WindowsApplicationForDrivers10.0’ and the ‘Desktop’ target platform.
TRACKER : error TRK0005: Failed to locate: “CL.exe”. The system cannot find the file specified.

—— Build started: Project: SpbTestTool (Sys\SpbTestTool), Configuration: Debug Win32 ——
Building ‘SpbTestTool’ with toolset ‘WindowsKernelModeDriver10.0’ and the ‘Universal’ target platform.
Stamping .\Debug\\SpbTestTool.inf [Version] section with DriverVer=05/18/2017,18.15.36.668
TRACKER : error TRK0005: Failed to locate: “CL.exe”. The system cannot find the file specified.

========== Build: 0 succeeded, 2 failed, 0 up-to-date, 0 skipped ==========”

根据我的研究,这是因为VS2015默认安装没有带C++编译器(有点莫名其妙)

image002

image003

image004

再进行一次编译:
—— Build started: Project: SpbTestTool (Exe\SpbTestTool), Configuration: Debug x64 ——
Building ‘SpbTestTool’ with toolset ‘WindowsKernelModeDriver10.0’ and the ‘Desktop’ target platform.
command.cpp
command.cpp : fatal error C1083: Cannot open include file: ‘C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\shared\warning.h’: No such file or directory
main.cpp
main.cpp : fatal error C1083: Cannot open include file: ‘C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\shared\warning.h’: No such file or directory
util.cpp
util.cpp : fatal error C1083: Cannot open include file: ‘C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\shared\warning.h’: No such file or directory
Generating Code…
—— Build started: Project: SpbTestTool (Sys\SpbTestTool), Configuration: Debug x64 ——
Building ‘SpbTestTool’ with toolset ‘WindowsKernelModeDriver10.0’ and the ‘Universal’ target platform.
Stamping .\x64\Debug\\SpbTestTool.inf [Version] section with DriverVer=05/18/2017,22.28.17.712
driver.cpp
driver.cpp : fatal error C1083: Cannot open include file: ‘C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\shared\warning.h’: No such file or directory
device.cpp
device.cpp : fatal error C1083: Cannot open include file: ‘C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\shared\warning.h’: No such file or directory
peripheral.cpp
peripheral.cpp : fatal error C1083: Cannot open include file: ‘C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\shared\warning.h’: No such file or directory
Generating Code…
========== Build: 0 succeeded, 2 failed, 0 up-to-date, 0 skipped ==========

这个错误是因为没有安装 SDK 导致的(VS2015自带SDK,但是可能版本和 WDK 的不匹配,所以有问题)。再安装 SDK,之后 Build again
—— Build started: Project: SpbTestTool (Exe\SpbTestTool), Configuration: Debug x64 ——
Building ‘SpbTestTool’ with toolset ‘WindowsKernelModeDriver10.0’ and the ‘Desktop’ target platform.
command.cpp
main.cpp
util.cpp
Generating Code…
SpbTestTool.vcxproj -> C:\spb\SpbTestTool\exe\x64\Debug\SpbTestTool.exe
SpbTestTool.vcxproj -> x64\Debug\SpbTestTool.pdb (Full PDB)
Inf2Cat task was skipped as there were no inf files to process

—— Build started: Project: SpbTestTool (Sys\SpbTestTool), Configuration: Debug x64 ——
Building ‘SpbTestTool’ with toolset ‘WindowsKernelModeDriver10.0’ and the ‘Universal’ target platform.
Stamping .\x64\Debug\\SpbTestTool.inf [Version] section with DriverVer=05/19/2017,0.46.12.487
driver.cpp
device.cpp
peripheral.cpp
Generating Code…
SpbTestTool.vcxproj -> C:\spb\SpbTestTool\sys\x64\Debug\SpbTestTool.sys
SpbTestTool.vcxproj -> x64\Debug\SpbTestTool.pdb (Full PDB)
Done Adding Additional Store
Successfully signed: C:\spb\SpbTestTool\sys\x64\Debug\SpbTestTool.sys

Driver is a Universal Driver.
……………………
Signability test complete.

Errors:
None

Warnings:
None

Catalog generation complete.
C:\spb\SpbTestTool\sys\x64\Debug\SpbTestTool\spbsamples.cat
Done Adding Additional Store
Successfully signed: x64\Debug\SpbTestTool\spbsamples.cat

========== Build: 2 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

成功!

本文提到的驱动是 Windower Driver Sample【参考2】的一部分。

这里我放置一个 SPB 的Driver

SpbTestTool

参考:
1.http://www.lab-z.com/spbtesttool/
2.https://github.com/Microsoft/windows-driver-samples

Shell 下的 I2C 工具

最近写了一个 Shell下的 I2C 访问工具,可以帮助大家进行 Shell下的I2C测试.

image001

主要功能有4个:
1. Read 读取给定的 I2C Bus, Slave Address, Register 的值
2. Write 向指定的 I2C Bus, Slave Address, Register 写入Value
3. Dump 枚举指定的 I2C Bus, Slave Address上面的256 个Register
4. Scan 扫描枚举指定的 I2C Bus,列出所有对于读操作有 act的设备地址(128个)

A. Read 的功能
image002

B. Dump 功能
image003

C. Scan Bus 确定 I2C 设备地址的功能 ( 这是在 KBL-R HDK 板子上接入了一个 I2C Touch 后的扫描结果,可以看到一个设备上有很多个地址)

image004

下载(无 Source Code)

2017年6月17日更新,之前的版本是 0.3 ,当前升级到了 0.4 修改了 write 无法正确写入的问题

zI2c

How to debug ACPI by WinDBG in Winows RS2

自从 Windows 升级到了 RS1 , WinDBG 就无法进行ACPI 的调试了,主要的现象是各种找不到变量函数等等。经过一番研究,终于摸索出来了在 RS2 上进行ACPI 调试的方法。具体步骤如下:
特别注意,第一次实验的时候务必按照顺序进行,否则很可能需要重头再来!
1. Target端安装 Windows RS2, 用户名为ZTX (请使用这个名称,确保后面的操作有参考作用)
image001

2. Target端进入 Windows后,运行 MSConfig

image002image003

3. Target端CMD 串口下(Administrator 权限),运行下面的命令要求系统不检查驱动签名

bcdedit.exe -set TESTSIGNING ON

4. Host 端使用 WinDbg 确保这个步骤能连上,如果连不上请检查USB设定
5. Target端进入 Windows/System32 下搜索 “acpi.sys”,会找到很多结果,我们的目标只是 acpi.sys,需要将系统中的这个文件替换为 checked 版本的。通常系统中会有1个以上的ACPI.SYS,一个是原本的驱动,另外是系统缓存出来的,所有的都需要删除
image004

因为系统保护的缘故,删除动作很满烦,具体操作如下:
5.1 选择第一个 ACPI.SYS,打开 Properties –> Security查看 Users, 注意到是没有Modify 的权限的。
image005

5.2 选择 Advanced, 点击 Owner:TrustedInstaller 后面的Change
image006

输入用户名 ZTX

image007

之后 Owner 会变成 ZTX
image008

返回上一层之后选择 Users
image010

然后使用 edit 按钮,选中 Users 然后再选择 Full Control
image011

出现下面的提示,选择 Yes
image012

之后,你就有权限删除所有的 ACPI.SYS了。然后将 checked 版本的 ACPI.SYS 放置到system32\drivers目录下。
至此就完成了替换,重启 Target端,
重启之后,HOST端的 WinDBG 会出现下面的提示(特别提醒,这里一定要连着WinDBG,否则看到的只能是无尽的BSOD):
image013

输入 g 还会再次停下来
image014
再输入 gh ,即可进入系统。
image015

简单的托盘程序2

基于很早之前(那时候还有 MSN )编写的托盘程序,可以在内存中查找指定的进程(本例中查找的是Notepad.exe),如果找到了就在 memo 中记录当前时间。

编译环境为 Delphi XE2。

totray2

2017/5/30

参考:
1。http://www.lab-z.com/%E3%80%902009%E5%B9%B41%E6%9C%8816%E6%97%A5%E3%80%91delphi-%E5%BD%93%E6%9C%80%E5%B0%8F%E5%8C%96%E6%97%B6%EF%BC%8C%E8%87%AA%E5%8A%A8%E7%BC%A9%E5%87%8F%E5%88%B0%E6%89%98%E7%9B%98%E4%B8%AD/

WDK 提供的 USBView

网上能找到的都是旧的,不支持 usb 3.0。 于是在 MS 的网站上找了一个最新版本的,下面是来自 WDK for Win10, 64位的:

usbview

具体介绍可以看下面:

USBView
USBView (Universal Serial Bus Viewer, Usbview.exe) is a Windows graphical user interface application that enables you to browse all USB controllers and connected USB devices on your computer. USBView works on all versions of Windows.
Where to get USBView

USBView is included in Debugging Tools for Windows.
USBView is also available in the Windows driver samples repository on GitHub.
Using USBView

USBView can enumerate USB host controllers, USB hubs, and attached USB devices. It can also query information about the devices from the registry and through USB requests to the devices.
The main USBView window contains two panes. The left pane displays a connection-oriented tree view, enabling you to select any USB device.
The right pane displays the USB data structures that pertain to the selected USB device. These structures include Device, Configuration, Interface, and Endpoint Descriptors, as well as the current device configuration.

来自:https://msdn.microsoft.com/en-us/library/windows/hardware/ff560019(v=vs.85).aspx

=========================================================
2024年5月28日  更新一个 Win11 的

Leonrado Uno 转接板和修改后的USB Host库

有时候,我们希望在 Leonrado 上使用 Uno 的Shield,但是会发现两者的引脚并不兼容。比如: uno 上的 SPI 位置和 leonrado 不同。

这种情况下就可以使用下面的转接板。
a2u

主要是调整了 i2c 和 spi 使得转接后的能够兼容设计给 uno 的sheild.

a2u2

比如,我直接的应用就是让 USB Host Shield 可以在 Leonrado 上工作。同时,设计上考虑到国内基本上买不到合适的长脚母座,所以使用了母座外加排针的方式, 堆叠之后的样式如下:

a2u3

电路板下载 zLeo2UnoShieldv1.0

之后,我实验编译使用Leonrado 自带USB Keyboard功能的时候遇到奇怪的问题,始终提示没有加入include “keyboard.h”。经过一番研究发现,出现这个问题的原因是:IDE定义USB keyboard的时候定义了HID Class,而USBHost 库在解析USB设备的时候同样定义了一个HID Class,二者存在冲突。
对此,需要修改避免HID Class 的冲突。我选择修改 USB Host库,因为这个毕竟是第三方库。

最终将库中的 HID Class全部修改为 NewHID ,这样我们可以在 Leonrado 同时使用 USB Host 和 模拟键盘鼠标了。

附件是修改之后的版本,亲测有效:

USB_Host_Shield_Library_2.0_Modified

从源代码到 FFS 文件

本文会以 BdsDxe.ffs 的生成为例,介绍一下从 EFI 到 FFS的编译过程。
所有的实验都是建立在UDK2015 NT32Pkg的基础上。
首先,要保证NT32能够正常编译运行。之后,在 build目录中取得生成的BIOS文件:nt32.fd。使用 fmmt –v nt32.fd 查看一下这个BIOS的组成。可以看到其中只有一个 FV , 然后有 BdsDxe的ffs。我们可以在\Build\NT32IA32\DEBUG_VS2013\IA32\MdeModulePkg\Universal\BdsDxe\BdsDxe\OUTPUT\ 目录下,找到编译生成的 BdsDxe.efi。 在 \Build\NT32IA32\DEBUG_VS2013\FV\Ffs\6D33944A-EC75-4855-A54D-809C75241F6CBdsDxe可以看到文件名为6D33944A-EC75-4855-A54D-809C75241F6C.ffs 的文件。就是说我们前面看到的BdsDxe .efi,最终得到了一个ffs文件。
ffs1

ffs2

下面就针对这个过程逐一进行分析。
1. *.PE32 文件的生成。具体的生成命令可以在在6D33944A-EC75-4855-A54D-809C75241F6CSEC2.1.1.1.pe32.txt中看到:
GenSec -s EFI_SECTION_PE32 -o c:\udk2015\Build\NT32IA32\DEBUG_VS2013\FV\Ffs\6D33944A-EC75-4855-A54D-809C75241F6CBdsDxe\6D33944A-EC75-4855-A54D-809C75241F6CSEC2.1.1.1.pe32 c:\udk2015\Build\NT32IA32\DEBUG_VS2013\IA32\MdeModulePkg\Universal\BdsDxe\BdsDxe\OUTPUT\BdsDxe.efi
使用工具比较一下生成前后的文件,可以看到只有头部存在一点差异。
ffs2
再查看 GenSec 的源代码,当指定为 EFI_SECTION_PE32 的时候,头的内容是 EFI_SECTION_PE32(0x10)+Length。所以和之前的EFI 相比,增加的是 0x10 和0x13004 (EFI文件的长度)
2. GUIDED文件的生成,在6D33944A-EC75-4855-A54D-809C75241F6CSEC2.1.guided.txt 可以看到, 使用的是 GenSec 工具,作为输入的是 PE32, UI和 VER文件。
GenSec -s EFI_SECTION_GUID_DEFINED –sectionalign 1 –sectionalign 1 –sectionalign 1 -o c:\udk2015\Build\NT32IA32\DEBUG_VS2013\FV\Ffs\6D33944A-EC75-4855-A54D-809C75241F6CBdsDxe\6D33944A-EC75-4855-A54D-809C75241F6CSEC2.1.guided c:\udk2015\Build\NT32IA32\DEBUG_VS2013\FV\Ffs\6D33944A-EC75-4855-A54D-809C75241F6CBdsDxe\6D33944A-EC75-4855-A54D-809C75241F6CSEC2.1.1.1.pe32 c:\udk2015\Build\NT32IA32\DEBUG_VS2013\FV\Ffs\6D33944A-EC75-4855-A54D-809C75241F6CBdsDxe\6D33944A-EC75-4855-A54D-809C75241F6CSEC2.1.2.ui c:\udk2015\Build\NT32IA32\DEBUG_VS2013\FV\Ffs\6D33944A-EC75-4855-A54D-809C75241F6CBdsDxe\6D33944A-EC75-4855-A54D-809C75241F6CSEC2.1.3.ver
3. 目前我尚不知道 *.UI文件是如何生成的,希望有懂的朋友指导一下,谢谢!
4. 从6D33944A-EC75-4855-A54D-809C75241F6CSEC2.1.3.ver.txt 文件可以得知*.VER 是这样生成的
GenSec -s EFI_SECTION_VERSION -n 1.0 -o c:\udk2015\Build\NT32IA32\DEBUG_VS2013\FV\Ffs\6D33944A-EC75-4855-A54D-809C75241F6CBdsDxe\6D33944A-EC75-4855-A54D-809C75241F6CSEC2.1.3.ver

5. 从6D33944A-EC75-4855-A54D-809C75241F6CSEC2.com.txt 文件可以得知 .COM 的生成方式如下(COM 并非DOS下面的可执行文件,而是 COMPRESS的缩写)。经过了这步,因为压缩的原因,生成的结果比压缩之前小了很多,比较起来也会发现“面目全非”。
GenSec -s EFI_SECTION_COMPRESSION -c PI_STD -o c:\udk2015\Build\NT32IA32\DEBUG_VS2013\FV\Ffs\6D33944A-EC75-4855-A54D-809C75241F6CBdsDxe\6D33944A-EC75-4855-A54D-809C75241F6CSEC2.com c:\udk2015\Build\NT32IA32\DEBUG_VS2013\FV\Ffs\6D33944A-EC75-4855-A54D-809C75241F6CBdsDxe\6D33944A-EC75-4855-A54D-809C75241F6CSEC2.1.guided
6. 从6D33944A-EC75-4855-A54D-809C75241F6C.ffs.txt 可以看到 FFS是如何生成的:
GenFfs -t EFI_FV_FILETYPE_DRIVER -g 6D33944A-EC75-4855-A54D-809C75241F6C -o c:\udk2015\Build\NT32IA32\DEBUG_VS2013\FV\Ffs\6D33944A-EC75-4855-A54D-809C75241F6CBdsDxe\6D33944A-EC75-4855-A54D-809C75241F6C.ffs -i c:\udk2015\Build\NT32IA32\DEBUG_VS2013\FV\Ffs\6D33944A-EC75-4855-A54D-809C75241F6CBdsDxe\6D33944A-EC75-4855-A54D-809C75241F6CSEC1.1.dpx -i c:\udk2015\Build\NT32IA32\DEBUG_VS2013\FV\Ffs\6D33944A-EC75-4855-A54D-809C75241F6CBdsDxe\6D33944A-EC75-4855-A54D-809C75241F6CSEC2.com
7. 从6D33944A-EC75-4855-A54D-809C75241F6CSEC1.1.dpx.txt,可以看到 dpx 文件的生成过程
GenSec -s EFI_SECTION_DXE_DEPEX -o c:\udk2015\Build\NT32IA32\DEBUG_VS2013\FV\Ffs\6D33944A-EC75-4855-A54D-809C75241F6CBdsDxe\6D33944A-EC75-4855-A54D-809C75241F6CSEC1.1.dpx c:\udk2015\Build\NT32IA32\DEBUG_VS2013\IA32\MdeModulePkg\Universal\BdsDxe\BdsDxe\OUTPUT\BdsDxe.depex

8. 接下来是最后一步,使用COM 和 DPX 生成 FFS 文件,从6D33944A-EC75-4855-A54D-809C75241F6C.ffs.txt 文件可以看到操作动作
GenFfs -t EFI_FV_FILETYPE_DRIVER -g 6D33944A-EC75-4855-A54D-809C75241F6C -o c:\udk2015\Build\NT32IA32\DEBUG_VS2013\FV\Ffs\6D33944A-EC75-4855-A54D-809C75241F6CBdsDxe\6D33944A-EC75-4855-A54D-809C75241F6C.ffs -i c:\udk2015\Build\NT32IA32\DEBUG_VS2013\FV\Ffs\6D33944A-EC75-4855-A54D-809C75241F6CBdsDxe\6D33944A-EC75-4855-A54D-809C75241F6CSEC1.1.dpx -i c:\udk2015\Build\NT32IA32\DEBUG_VS2013\FV\Ffs\6D33944A-EC75-4855-A54D-809C75241F6CBdsDxe\6D33944A-EC75-4855-A54D-809C75241F6CSEC2.com

最后生成的 FFS 和 COM 差别很小
ffs3

了解了整体的BIOS结构,做很多事情,比如:编写无需重新编译代码,直接修改ROM的工具等等。本文只是简单的对于FFS的生成进行了研究,希望这篇文章对于需要了解EDK2 Firmware 结构的朋友有所帮助。