本文根据《软件调试(第2版)》卷1:硬件基础“第七章 JTAG 调试”编写。建议有兴趣的朋友购买一本来学习。对于 Firmware 工程师来说,从底向上学习是一个很好的方向。

现在的X86变得日益复杂,如何进行有效的Debug 也日渐成为一个难题。为此 Intel 在芯片组或者 CPU 上预留了一个称作DCI (Intel® Direct Connect Interface)的Debug 接口。这个接口使用 USB 3.0一模一样的外部连接。CPU 内部有切换器,当Chipset 发现外部有设备和他握手,就将原本的USB信号切换为DCI 的信号。这样无需额外的预留就能实现Debug。

在DCI 出现之前,Intel 使用J-Tag 接口。当时的 Debug 盒子是下面这样,叫做 In-Target Proble,简称 ITP。  当年价格在 3000刀,现在好像没有这么贵了。之前我在的公司买了一个,老板恨不得把它供起来,一年也用不到几次。最后不知道什么原因它的适配器坏掉了。我去询问价格,得到的答案是适配器90刀,然后90天发货........当然对方也很nice 的告诉我可以去中关村配一个电压相同功率差不多的也能用。后来回报上去之后老板左右不定,不想花钱和时间又怕损坏.........最终这个设备束之高阁了。

图片来自【参考1】

为了Debug,主板上同时必须预留下面这样的 J Tag 接口。显而易见,说服HW工程师在主板上预留这样的接口需要花费极大的口舌,至于说服老板在量产板子上焊接这样的接口几乎是不可能的事情。因此,串口一直是BIOS工程师的最爱。

通常情况下,一台电脑不止一个 IP,因此需要考虑枚举出所有的 IP.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;

namespace tmpshowip
{
    class Program
    {
        static void Main(string args)
        {
            string...								 > Read More
			

最近工作需要在 UEFI  Shell 下Check EC Ram 的设定,发现手上只有 Windows 下的读取工具(RW Everything)。于是研究了一下如何在Shell 读取 EC Ram。

 根据【参考1】读取的流程如下:

Port 66 Commands

There are also some EC commands that use ports 0x66 and 0x62. Some of these are standard ACPI commands as defined in the external ACPI spec, others are custom.

The... > Read More

电子的巨大魅力在于无限的可能性。比如说用3个IO端口驱动6个 LED 或者用三极管、电感、电阻制作能榨干电池剩余电力的“焦耳小偷”。百思不得其解之后看到最终的解决方案总会有醍醐灌顶的感觉,也会非常钦佩第一个想到这样用法的人。和解决数学问题之后的快乐不同,因为电子和生活息息相关,学会了这样的招数转头也可以用在自己的设计上。

本文的起因是某天在网上看到有人用 Teensy 2.X 制作的摄像头【参考1】,2.0版本使用32u4也是Leonardo同款主控芯片,因此,这个项目完全可以使用在Leonardo上。

Arduino Leonardo 是很常见的Arduino开发板,它使用了 32U4 的主控芯片,其中带有了USB Device,因此我们有机会将视频直接投送到PC上,而具体的方法就是将设备报告为 USB Camera,再将要显示的内容生成视频发送出去。Windows 内置了 USB Mass Storage 驱动,因此用户可以直接使用 U盘而无需额外安装驱动。同样的,目前的 Win10 内置了 UVC(USB video device class)的驱动,对于符合这个协议定义的USB 设备可以直接在“摄像头”程序中显示出来。

上面介绍了基本原理,接下来就是具体的实验。为了能够更好的展现内容,实验的目标是滚动显示“祝新年快乐”字样。在实验验证上有很多经验之谈,比如:不要用4个字做实验,因为4刚好是2的2倍,同时也是2的平方。很多适用于此的技巧实际上只是巧合。因此,这次使用5个字。另外还有就是测试音频设备尽量不要使用纯音乐而要使用歌曲,后者更容易让测试人员得知当前的音调是否正常。

先研究一下字模的问题。为了将汉字的字形显示输出,汉字信息处理系统还需要配有汉字字模库,也称字形库,它集中了全部汉字的字形信息。需要显示汉字时,根据汉字内码向字模库检索出该汉字的字形信息,然后输出,再从输出设备得到汉字。汉字点阵字模有16*16点、24*24点、32*32点,48*48点几种,每个汉字字模分别需要32、72、128、288个字节存放,点数愈多,输出的汉字愈美观。从经验上来说,16x16是普通人能够接受的最小字形,虽然这个尺寸的字形信息也有缺少笔画的问题(比如:“量”字,在这个尺寸下会丢掉上面 “曰”的最下面一横),但是少于16X16的汉字字形信息会让观看者有明显的缺少笔画的的观感,有如“第二次简化字”死灰复燃。24x24 的字形信息则是完全不丢失笔画的最小尺寸。但是缺点很明显,每个汉字要比16x16的字形多花1倍的空间来进行存储。这对于内存和处理能力有限的单片机来说,着实是一个负担。因此,大多数情况下,单片机使用最多的是 16x16的自字形库HZK16。这个字库是符合GB2312国家标准的16×16点阵字库,HZK16的GB2312-80支持的汉字有6763个,符号682个。其中一级汉字有 3755个,按声序排列,二级汉字有3008个,按偏旁部首排列。取得字形的过程如下:

  1. 取得欲查询汉字的GB2312编码,每个汉字由2个Byte 进行编码,第一个字节被称作              “区码”;第二个字节被称作“位码”;
  2. 接下来计算汉字在HZK16中的绝对偏移位置:offset = (94*(区码-1)+(位码-1))*32
  3. 读取 HZK16 中 offset 给出的位置连续 32 Bytes... > Read More

人类常用权威的话语来证明自己的观点,这种方式可以说是一种签名。当然,这种方式存在一个严重的缺陷:无法证明那个生成的名人确实说过这句话。


同样的,在互联网上,我们需要用一种方式来验证确认身份信息。其中的一个方法就是数字签名。

前面介绍过 RSA 算法,因为它能够实现非对称的加密所以还可以用来进行数字签名。比如:我在网站上公布了自己的公钥,然后每次发送消息的时候会附上使用私钥对这个消息签名结果。这样,别人就无法冒充我发布消息。这次展示使用 OpenSSL 实现UEFI下面的签名和验证。

第一步,生成RSA密钥对(我不清楚为什么文章都喜欢将这个直接称作“私钥”,实际上这样生成的结果是包括公钥部分的,索性这里我称之为密钥包)。

openssl genrsa -out rsa_private_key.pem 1024

生成的密钥包内容如下:

-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDTiExu8F6X/VWPqPmzBc3mqUfMvOB0xtaTZAQbSfyt+uqxu7GN
aStGpdJvCuOFL7+FFXSFLJfmZsiYRaiOSpPDDuQLBkG0m/ABk8pLtobEy6UgJPpS
6Oiku1618+uwYKcZpPj2Ftu5d+FFMiS23SCI8zhLcF3fM2J7/IXudCOErQIDAQAB
AoGABbgtuOIu7JUg9x1ugvSpOI9jLZn9x6qIqruNkN9TQbEDH4Mfrd8mGGbrZa05
saQ03XhTCjbGdKhazCM2B4Lks9jb0ovA2CUvuX+sxUHXdgEFekEv/VVIzem3qt0F
kMV+lSX76F/CkV4XXOO4H1rYja7BObl/jFMjTpRgPh0g4AECQQD3MCGCwqqQvGBV
Lw8cJHj7E9bMK8NWauONJfYL0D+9/ylas+xS73iqLcSpWcchWDjbM3T2tYAeZLrf
i0VmHm4BAkEA2xLFKytC9dbIDJS+0316jZvK/AWsSDbKo+Fn+DnO9x6ZhstX062t
7WEDRHT3ZR0vQTS7f9SayxN3MMwSB88urQJBAOI2ofRQwleCjYZncqSGnFDqbwCa
bEGBwI1D2FAnXK47/VSMpBGiJgNXr0psZtgVLLMt/DRrFby64moBwpkZ8AECQQC3
7zWOfj81S8UhEw55YYQxO1odaeHxq9dN62Yw+tBzmcSLcVVnTA6ZHPfyVUaWJf/T
/qNiu63PzaMoXF7TIbftAkBcpDvw4T3kynR1mXyuC1jmvenYZGtfdhtCgqBRt4Z2
MFeMsqkFNDzuJbHdq1vdDUl2Oh4XyVyOGNc5hxiFrx8a
-----END RSA PRIVATE KEY-----

第二步,从这个密钥包分离出来公钥。

最近在 Teensy 3.2 上使用 ILI9341 的液晶屏,在编译的时候出现关于 _NOP 的错误。经过搜索,在 https://github.com/olikraus/ucglib/issues/65 找到有人解决过这样的问题。原帖写的是:

Ucglib.cpp, line 786 - change the ...defined(__arm__)... to ...defined(__NOT_arm__)...
Ucglib.cpp, line 833, add the following:

#ifndef __NOP
#define __NOP __asm__ __volatile__("NOP");
#endif

有可能是因为版本的差别,我在Ucglib.cpp 中修改如下:

Line783:

#if defined(__PIC32MX) || defined(__NOT_arm__) || defined(ESP8266) || defined(ARDUINO_ARCH_ESP8266) || defined(ESP_PLATFORM)...								 > Read More
			

之前的文章“哪里来的的 memset”【参考1】提到过因为编译器擅作主张使用memset优化引起了很诡异的问题。可以通过关闭编译优化来避免错误,这里从代码的角度分析 EDK2 是如何实现 memset 功能的。

  1. \MdePkg\Library\BaseMemoryLib\MemLibGeneric.c 提供了三个函数

InternalMemSetMem16

 InternalMemSetMem32

InternalMemSetMem64

以 InternalMemSetMem16  为例:

/**
  Fills a target buffer with a 16-bit value, and returns the target buffer.

  @param  Buffer ...								 > Read More
			

野史看起来永远比正事更加精彩,最近偶然间知乎上看到王知先生编写的《纪念英特尔成立五十周年》。感觉很有意思。因为作者禁止转载,所以这里给出链接。有兴趣的朋友可以上去直接看看。

《纪念英特尔成立五十周年》 引言,讲述了 Intel 的成立过程

https://zhuanlan.zhihu.com/p/39805025

《篇一 阴差阳错》
https://zhuanlan.zhihu.com/p/39804154

《篇二 失而复得》

https://zhuanlan.zhihu.com/p/39805356

《篇三 力挽狂澜》
https://zhuanlan.zhihu.com/p/39806179

> Read More

最近看到一篇文章“Intel ACPI IGD OpRegion Spec, and IntelSiliconPkg added to Tianocore”【参考1】,介绍的是Intel Jiewen Yao在开源项目 Tianocore 中加入了关于 IGD OpRegion相关内容。与这个文件相关有一份名为“Intel Integrated Graphics Device OpRegion Specification Driver Programmer’s Reference Manual” 的 datasheet【参考2】。简单的说这是介绍 Intel IGD 显卡控制接口的资料。上面提到的下面这个表格引起了我的兴趣:

就是说,如果我们能在内存中找到OpRegion 那么是有机会找到 VBT 的。如果能找到 VBT 那么就有机会 Dump 出来。更出人意料的是,这份Datasheet 直接给出了获得 OpRegion 的方法: