WinDBG 读取 RTC 的 Script

WinDBG 支持Script,这样用户可以通过编程来实现一些自动控制。本文介绍的就是一个读取 RTC (CMOS)的 Script。

先介绍一下如何使用,将 Script 文件放在 c:\asl\ 下面,文件名是 cmos.txt。在 WinDBG 停下来目标机之后输入 $><c:\asl\cmos.txt 即可运行【参考1】。 WinDBG端结果如下:

kd> $><c:\asl\cmos.txt

    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 
===================================================
 0| 8  0 47  0 16  0  2  1 12 20 26  2  0 80  0  0 
 1| 0  0 F0  0  E 80  2 FF FF 2F  0  0  0  0  0  4 
 2|FF FF FF FF FF 3F  0  0  0  0  0  0  0  0  8 EB 
 3|FF FF 20  0  0 7F  0 20 20  0  0  0  0 31  0  0 
 4| 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 
 5| 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 
 6| 1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 
 7| 0  0  0  0  0  0  0  0  1  0  0  0  0  0  0  0 
 8|38  0 48  0 16  0  2  1 12 20 26  2  0 80  0  0 
 9| 0  0 F0  0  E 80  2 FF FF 2F  0  0  0  0  0  4 
 A|FF FF FF FF FF 3F  0  0  0  0  0  0  0  0  8 EB 
 B|FF FF 20  0  0 7F  0 20 20  0  0  0  0 31  0  0 
 C| 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 
 D| 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 
 E| 1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 
 F| 0  0  0  0  0  0  0  0  1  0  0  0  0  0  0  0

在虚拟机中使用 RW_Everything 可以看到同样的结果:

RW_EveryThing 读取 CMOS

具体的代码如下:

$$********************************************
$$* WinDBG Script from www.lab-z.com         *
$$*                                          *
$$*   Read CMOS                              *
$$*                           2020 DEC 1st   *
$$********************************************

.printf "   "
.for (r $t0=0; @$t0 &lt; 10;r $t0=$t0+1) {.printf "%2X ",$t0}
.printf "\n"
.for (r $t0=0; @$t0 &lt; 11;r $t0=$t0+1) {.printf "==="}
.printf "\n"

.for (r $t0=0; $t0 &lt; 10;r $t0=$t0+1) {
  .printf "%2X|",$t0
  .for (r $t1=0; $t1 &lt; 10;r $t1=$t1+1) {
     r $t2=$t0*10+$t1
     ob 70 $t2
     .foreach /pS 1 (vv {!ib 71}) {r $t3=${vv}}
     .printf "%2X ",$t3
   }
  .printf "\n"
}

简单介绍一下代码意思:

“$$” 表示注释,所以最开始几行只是用于标记

下面几行是用于输出一个表格头

 “.for (r $t0=0; $t0 < 10;r $t0=$t0+1) ” 这是一个 for 循环,其中使用到了 $t0 这是 WinDBG 内置的虚拟寄存器,在 WinDBG 中有 t0-t19个

计算当前的 Index r $t2=$t0*10+$t1

代码中所有的数值都是十六进制,所以看到 10 意思是0x10, 表示 16(十进制)

 ob 70 $t2 这是 outport 命令,将 $t2 值送到 0x70 Port 中

 前面对 70 Port输出 Index, 接下来需要从 71 Port上读取。端口读取命令是 ib ,但是无法直接取得读到的值。因此这里使用  .foreach 来解析命令返回值。在这里,ib返回值是 00000070:  XXXXXX 这种形式。因为空格的存在,解析结果会分为两次出现在后面的大括号中。/pS 1 的意思是忽略返回值中的第一个,使用这个参数之后我们只能收到 XXXXXX 这个结果,我们将其放入 $t3 中

 .foreach /pS 1 (vv {!ib 71}) {r $t3=${vv}}

8.文件文件使用ASCII 格式,因此文件中最好不要出现中文

上面只是实现了CMOS 的读取,配合 WinDBG 的断电能够实现更多的功能,另外最新的 WinDBG Script 支持 JavaScript 有兴趣的朋友可以更深入的研究。

本文提到的 Script 文件下载:

参考:

  1. https://www.cnblogs.com/softfair/p/windbg-command-ii.html Windbg  脚本命令简介 二, Windbg  script command
  2. https://blog.csdn.net/hgy413/article/details/9073157  50.windbg-.foreach循环输入(windbg script)
  3. https://www.cnblogs.com/awpatp/archive/2010/06/16/1758929.html 在WinDBG中使用foreach
  4. https://www.jianshu.com/p/56ff0bc43d3d Windbg调试笔记

Ampere Computing 招聘(202101)

这是一家做ARM 服务器的公司,网站 :

https://amperecomputing.com/#

DescriptionThe Role:

Our PAE will work with ODM to perform technical supports in software area, specifically in UEFI and BMC related.

What the ODM Management Team wants you to know:

ODM Management is the team to deliver the product from NPI to mass production. A critical function team to make sure the design/manufacture tasks at ODM is completed to deliver the platforms to customers.

What you’ll do:

As a member of the ODM management team, you will support design activities of various ODM projects. And work with sales, AE, and engineering teams worldwide to provide software related support.

What you’ll bring:

Experience of UEFI and BMC porting/testing/debugging either AMI code base or opensourceCoding capability of related software of C+, JAVA, HTML, or othersRequired knowledge of CPU and server system architectureSupport ODM experience is required to demonstrate the skills for design supporting, technical service, and problem-solvingCapable of working independently as well as cross different functional teams’ cooperation within company and customers sideHands on experience in the setup and configuration of server systems

Education & Experience:

Bachelor’s degree in computer science, electrical engineering with minimum 9 years of experienceOur CompanyAmpere is designing the future of hyperscale cloud and edge computing with the world’s first cloud native processor. Built for the cloud with a modern 64-bit Arm server-based architecture, Ampere gives customers the freedom to accelerate the delivery of all cloud computing applications. With industry-leading cloud performance, power efficiency and scalability, Ampere processors are tailored for the continued growth of cloud and edge computing.

有兴趣的朋友请联系 jun.chen@amperecomputing.com

QEMU 下 SecureBoot 和 EFI 签名的测试

本文将介绍如何在 QEMU 上实验 Secure Boot 的功能,以及如何对一个 EFI Application 进行签名。

首先,需要编写一个能在QEMU 上运行的,打开 Secure Boot 功能的 BIOS。编译命令如下:

build -a X64 -p OvmfPkg\OvmfPkgx64.dsc -D SECURE_BOOT_ENABLE=TRUE

即可(在 EDK202008 的版本上测试,打开这个功能后需要用到 OpenSSL 提供的函数,因此需要在 EDK2中加入 OpenSSL 的代码)。接下来,根据【参考1】,我们需要生成下面这些文件用于签名。

生成这些文件必须安装Windows SDK,这里使用的是 Windows 10 的 SDK ,工具在C:\Program Files (x86)\Windows Kits\10\bin\x64 下面:

  1. 生成 TestRoot.pvk 和 TestRoot.cer

命令:makecert -n “CN=TestRoot ” -r -sv TestRoot.pvk TestRoot.cer

运行之后会要求你设置一个密码,这里我们使用  labz 作为密码。

之后会再要求你输入一次 labz

2.生成TestSub.pvk 和 TestSub.cer

命令:makecert -n “CN=TestRoot ” -iv TestRoot.pvk -ic TestRoot.cer -sv TestSub.pvk TestSub.cer

这里会要求你设置另外一个密码,这里我们使用 labzpri

输入你设置的 labzpri

再次弹出的对话框输入之前设置的 labz 这个密码

现在我们就有了前面提到的4个文件。

然后准备一个用于测试的EFI 文件,我们使用 Hell.EFI ,它只是在屏幕上输出字符串。同样的,使用 SDK 中的工具对其进行签名,命令如下:

C:\Program Files (x86)\Windows Kits\10\bin\x64>signtool sign /ac TestSub.cer /f TestSub.pfx /p labzpri /fd sha256 Hello.Efi

运行结果:

签名后的文件名称是 Hello-signed.efi 。到现在我们有4个签名相关的文件和2个 EFI 文件,将他们全部copy到U盘上的QEMU目录中(特别注意 U盘必须FAT32格式)。之后使用下面这个 command 启动 QEMU:

qemu-system-x86_64.exe -pflash ovmf_secureboot.fd -hda fat:rw:j:\QEMU -net none

启动后,默认情况下 Secure Boot 是 Disabled,至少需要从 Setup 加入 PK 和 DB 两组 Key【参考1】才能 Enable这个功能:

a.Device Mnager->Secure Boot Configuration切换为 Custom Mode

b.加载 PK 的操作在  Custom Secure Boot Options 中选择 PK Option

c进入之后选择 Enroll PK 通过文件加载 PK

选择盘符

选择 TestRoot.cer 文件

返回后可以看到这个文件已经加载生效了

d.继续加载 DB文件, 操作如下

一个系统中只能有一个 PK,但是可以有多个 DB 文件。这里需要给加载的DB 指定一个 GUID,随便写编一个即可

e.完成设置后返回即可看到 Secure Boot 已经 Enable了。

在 Shell 下测试,因为 Hello.efi 没有签名,所以无法执行,Hello-signed.efi 正确签名了,所以可以运行。

上面就是在 QEMU 下测试 Secure Boot 功能的过程,有兴趣的朋友可以动手试试。

参考:

  1. http://gschwinds.net/cache/SigningUEFIImages-1.31.pdf
  2. https://www.jianshu.com/p/e892733c6f50
  3. 来源同【1】DB和 PK 对于 Secure Boot  Enabling 是必须的

【参考1】的文档,备份一下

ESP32 作为蓝牙音频接收端

具体方法:

1. https://github.com/tierneytim/btAudio 下载并且安装

2.使用UDA1334A I2S 立体声 解码器 I2S Stereo Decoder, 注意:这个是解码器,并不能直接推动喇叭,所以如果在没有音响的情况下只能使用耳机,

如果你想做一个直接带喇叭的播放器,那么还需要一个功放。

原作使用的是“Adafruit I2S Stereo Decoder – UDA1334A” https://learn.adafruit.com/adafr … er-uda1334a/pinouts

我这个是从长江智动买的,一般来说,如果你看到 Adafriut 的板子都可以尝试在这家搜索是否有相同的设计:

CJMCU-1334 UDA334A I2C Decoder

3.将对应的线连接起来, 这里提到的是 D26/D27/D25 这样的Pin:

int bck = 26;
int ws = 27;
int dout = 25;

ESP32 做蓝牙音频接收,之后从 I2S 接口输出给 Codec

4.运行库里面 minimalAudio

5.手机可以搜索到这个设备将 Audio 发送到 ESP32 上

测试视频可以在下面看到:

https://www.bilibili.com/video/BV1B64y1c7H3

sizeof(int)=?

很长一段时间以来,我理所当然的认为 sizeof(int) 是根据编译目标变化的,比如: x86 下应该为 4 Bytes (32-bits),x64 模式下应该为 8 Bytes(64 bits)。但是近日有朋友遇到了问题,我随手实验,用 printf 输出 sizeof(int) 和 sizeof(int *) 结果令我大吃一惊:

x86 下 sizeof(int) ==4 , sizeof(int *)==4

x64 下 sizeof(int) ==4 , sizeof(int *)==8

就是说, x64 下内存指针变成了8Bytes, 但是 int 仍然是 4bytes。无他,规定如此耳。

所以,在编写 UEFI 代码的时候,尽量不要使用 int 类型,因为你在代码中随手写下的赋值可能会因为编译目标不同而导致令人疑惑的错误。作为 Firmware 工程师,需要时刻了解数据的大小。

参考:

1.https://docs.microsoft.com/en-us/cpp/cpp/data-type-ranges?view=msvc-160

2.https://www.geeksforgeeks.org/difference-between-sizeofint-and-sizeofint-in-c-c/

3.https://docs.microsoft.com/en-us/cpp/cpp/fundamental-types-cpp?view=msvc-160

Sizes of built-in types

Most built-in types have implementation-defined sizes. The following table lists the amount of storage required for built-in types in Microsoft C++. In particular, long is 4 bytes even on 64-bit operating systems.

TypeSize
boolcharchar8_tunsigned charsigned char__int81 byte
char16_t__int16shortunsigned shortwchar_t__wchar_t2 bytes
char32_tfloat__int32intunsigned intlongunsigned long4 bytes
double__int64long doublelong longunsigned long long8 bytes

嘉立创 SMT 指南

相信大多数和我一样的非专业玩家在制作自己的作品时经常会受到焊接方面的困扰。比如,经常因为焊接失误导致芯片报废。曾经有哲人说过:“一个人遇到的99%的问题都可以用钱解决,剩下的1%,需要用更多的钱。”同样的,焊接的问题也可以用钱来解决。这次以设计一块CH558芯片的开发板为例,介绍一下如何在嘉立创直接 SMT。

选择嘉立创的主要原因是:他们有PCB 绘制软件,PCB 制作,SMT焊接和元件商城 。这样涵盖了电子制作的全部过程,可以一站式满足需求,这样在最大程度上避免了生产过程不匹配的问题,尽可能节省了设计者的时间。比如,我曾经碰到做主板时贴片二极管符号和实物方向不匹配的问题,第一次遇到问题时,硬件工程师花了很长时间才确定问题。

第一个目标时是完成电路图和 PCB 的绘制,这个步骤结束后会产生有三个用于生产的文件:

  1. Gerber File (用于制作PCB。电路的设计软件很多,比如 PROTEL, Eagle, Allegro 等等。PCB 生产厂家通常 “不认可”你提交的源文件,但是 Gerber 格式是通用的。)
  2. BOM (元件列表,用于告诉准备SMT的人需要为你的板子准备什么元件。订阅《无线电》杂志的朋友应该看过上面对于波峰焊机的介绍。在SMT准备过程中,工程师就是根据BOM 将需要焊接的元件料盘放置在机器中。)
  3. 坐标文件(告诉贴片机在什么位置贴什么元件。)

前面提到立创有一条龙服务,这里使用的软件是立创EDA。主要优点是支持在线编辑绘制电路图和PCB,这样有网络能打开网页就可以画图,上班摸鱼下班回家后可以继续绘制。缺点主要是:自动布线不太成熟,经常抽风,官方建议手工布线。

绘制电路的过程需要选择元件。诸如USB公头这样的插接件,强烈建议选用商城中的元件,因为这样的元件有对应的元件库,这样能够尽可能避免引脚差异导致的无法使用。

这次绘制的是 CH558的开发板,更具体可以说是将 CH558的封装转成 DIP 封装。电路图很简单,外围元件只有几个电阻,主要工作是将芯片引到排插上,设计如下:

PCB设计如下,特别注意图中的2个USB引脚需要通过差分布线来实现(主要是保证等长):

上述设计完成后即可生成准备用于制造的文件。

在PCB编辑界面上(注意,电路图编辑界面没有这个选项,必须是 PCB编辑界面),选择下面“生成制造文件(Gerber)”;或者在菜单中选择“制造àPCB制版文件(Gerber)”:

在弹出的对话框中使用按钮下载生成的 Gerber package。这样我们就有了 Gerber File有了这样的文件可以提交给 PCB 厂家进行生产。

同样的,可以在菜单—> 制造—>物料清单(BOM)生成物料清单表。

列表如下,使用下面的“导出BOM ”即可生成生产所需 BOM 表

接下来是坐标文件,在同样的位置

我们是单板,在嘉立创生产所以都无须勾选:

选择“导出”后,我们就有了坐标文件。下面就可以提交进行生产了。

有了上面的文件就可以准备生产了,SMT 的目标可以分解为2个小目标:一个是PCB 的制作,另一个是在这个 PCB 上进行SMT。

小目标1:提交嘉立生产PCB

1.1使用嘉立创下单助手(这个软件有网页版和PC版,二者界面是相同的。目前在推广期,建议使用PC版提交生产,有优惠价格)。选择左侧 PCB订单管理à在线下单/计价

1.2 点击 “上传PCB文件” 选中刚才的Gerber Packag-e 文件:

1.3 自动解析,生成预览。可以看到PCB的预览图,建议认真观察过孔位置等等:

1.4 在上面的界面选择“板子数量”,最少5块。建议第一次打选择5块这样最节省。

1.5 续设定参数,如果没有特别要求大部分使用默认值即可。具体尺寸可以在立创 EDA 菜单 ――> 制作 ――> PCB 信息 中看到。目前嘉立创有优惠,用户每个月有两次机会,可以以5元价格制作10x10cm以内的PCB,非常实惠。

如果你是第一次打板子,建议选择“确认生产稿”(多3元),这样可以避免一些问题(比如线距太窄导致PCB 打出来就无法使用这样的问题):

下面的工艺信息中,阻焊颜色决定了 PCB板子的颜色,绿色的打板速度最快,其他颜色加工时间稍微长一点(绿色通常是24小时;我个人比较喜欢红色,承诺交货时间是72小时)。我们打的板子没有拼板(这个可以理解为一个稿件中同时包含了多块板子)。我们打的样板没有拼板(拼版可以理解为一个稿件中同时包含了多块板子,在以面积计算价格的情况下可以节省成本)。

下面这些选项保持默认即可:

我们要求 SMT 因此,这里选择“需要”:

点击后会弹出要求确认,再点需要。

我们这次打的是单片:

选择了 SMT 之后只能选择不需要钢网,另h外也不需要发票

交期根据自己需要选择最快的:

目前的优惠每个用户每个月有两次机会,可以以5元价格制作10x10cm以内的PCB

1.5提交订单,等待审核。建议耐心一点等待审核结果。

1.6上述选择后,在右侧填写地址信息。至此,PCB 的提交已经完成。如果你只是制作PCB 没有 SMT 的要求,在付款之后等待PCB到家即可。

下面是提交 SMT的过程

  1. 审核结束之后,点击确认。会提示继续下 SMT 订单。

2.建议第一次打板选择 2片贴3片不贴

3.接下来继续填写表格,这里需要前面BOM 和 坐标文件,选择文件后即可进行下一步:

4.勾选需要进行贴片的文件,我们这里只贴嘉立创有库存的元件,余下的等板子回来自己手工贴。这里需要注意目前嘉立创无法贴需要手工摆放的元件,比如:USB公头,12MHz晶振这样的东西:

5.接下来会有简单的预览,我们的元件在正面(T层)

6.提示要求确认:

7.继续后需要确认主要芯片的Pin1 ,以及由极性元件的方向。确定后继续

8.最后就是交钱的过程了

经过一段的等待后板子就会飞越千山万水来到你的手中,入下:两片打芯片,三片不打。

板子到手之后即可着手进行检查,可能出现的问题是元件库和实物不符,比如:WS2811 搞错了 Pin1, 这种情况下可以去论坛提出问题,然后会有 PCB 和 EDA 方面的人和你进行接洽。

Vs2015 Source Level Debug WinHost

前面提到过,EDK2 后面更换了模拟器,每次编译的结果是 WinHost.exe。最近偶然发现,之前给出来的调试方法无效【参考1和2】。具体现象是运行之后遇到 DebugBreak会自动退出不会出现VS2015调试界面。经过研究,可以用下面的方法来实现源码调试:

  1. 编译 EmulatorPkg ,然后运行起来 WinHost.exe
  2. 打开 VS2015(需要管理员权限运行),选择 Debug -> Attach to Process
VS2015 Attach to Process

 3.在出现的界面中选择 WinHost.exe

找到当前模拟器的 WinHost.exe 进程

4.在WinHost 模拟器中发出 Break ,比如,使用【参考2】的代码,运行 rim 程序:

在 WinHost.exe 中 Trigger DebugBreak

5.使用 F10 跳过中断,可以看到 Image.c 的代码:

参考:

  1. http://www.lab-z.com/stu204nt32day/
  2. http://www.lab-z.com/stu205/

===============================================

2025年2月,验证了上述方法在 EDK2 202411 + VS2019 上仍然可以使用

推荐一个三极管仿真软件

在使用 Arduino 驱动一些元件工作的时候需要特别留意元件的功耗,如果元件需要的电流超过了 Arduino 引脚的共给能力就需要想办法进行“扩流”。最简单的方法就是使用三极管。但是三极管工作状态计算是一个麻烦的事情,在我上学的时候老师就曾经讲过“数字电路的搞不赢模拟电路”,时至今日,我的模拟电路知识更是早已归还给了老师。好在近日找到一个好用的在线计算工具在 https://www.falstad.com/circuit/e-pnp.html 这对于设计一个三极管驱动电路是最合适不过的:

首先,放置一个我们需要的三极管(PNP,NPN)。然后设定它工作的放大参数。

例如,Import 我们之前设计的电路(在 File 菜单中选择保存和加载你的设计):

通过修改 “Base Voltage” 的电压,可以模拟Arduino GPIO ,可以看到,当Arduino GPIO 为5V 时,8欧电阻(实际上我想放置于此的是蜂鸣器)上的电流为 0.1pa,相当于没有驱动电流:

当Arduino Pin 为0 时,300Ω电阻上电流时 14.126ma, 8欧姆电阻上电流为 (625.4-14.126)ma,此时蜂鸣器可以工作

本文提到的设计,三极管放大倍数为 120 (对应三极管SS8050),电路文件如下:

$ 1 0.000005 89.03963197220334 33 2 50
172 208 176 176 176 0 7 5 5 0 0 0.5 Base Voltage
w 320 160 320 112 1
t 272 176 320 176 0 -1 4.9999999999683995 -3.000089066063083e-11 120
R 320 112 320 80 0 0 40 5 0 0 0.5
172 320 240 320 272 0 7 0 2 0 0 0.5 Collector Voltage
r 224 176 256 176 0 300
w 224 176 208 176 0
w 256 176 272 176 0
r 320 208 320 240 0 8
w 320 192 320 208 0

UEFI下的 NTFS 驱动

最近研究了一下rufus,这是一款Windows 下的启动 U盘制作工具【参考1】。更难能可贵的是该项目是开源的。同时它提供了UEFI 的 NTFS 和 exFat32 分区的驱动。这次我测试了前者。

1.首先检查一下,系统中有2个 Shell 下可见的分区:U盘的一个和硬盘上的启动分区

2.加载 NTFS 驱动

3. map -r 之后可以看到能识别更多的分区

4. fs1 应该是系统的 recovery 分区

5.这是安装 Windows的分区

本文提到的ntfs 和 exFat32 驱动下载

参考:

1.https://rufus.ie/

2.https://github.com/pbatard/rufus/tree/master/res