最近在研究 UEFI Application结构相关的内容。除了静态的分析,还需要找到一种观察和调试加载到内存后EFI文件的方法。经过比较和研究, NT32 模拟器是很好的选择。通过它能够方便的进行观察和反编译。

需要解决的第一个问题是:找到跳转到Application Entry Point 处的代码。经过研究入口位于  \MdeModulePkg\Core\Dxe\Image\Image.c  文件中下面这个函数:

EFI_STATUS
EFIAPI
CoreStartImage (
  IN EFI_HANDLE  ImageHandle,
  OUT UINTN      *ExitDataSize,
  OUT CHAR16     **ExitData  OPTIONAL
  )

前面准备妥当后,在下面的语句中跳转到Application Entry来开始执行:

最近需要进行memory stress 测试,于是到 MemTest86 网站上进行查看:

https://www.memtest86.com/index.html

目前他们提供了几个版本供下载,具体区别如下:

来自 https://www.memtest86.com/features.htm

可以看出对于普通测试,免费版已经足够。当然,如果有条件还是建议购买 Pro 版本。

运行测试的方法是:

1.从 https://www.memtest86.com/download.htm 下载免费版

2.解压之后的 Boot 目录内容就是可以在 UEFI Shell 下运行的Application

继续研究基础的X86 寄存器。这次研究一下 CR0。在【参考1】可以看到 CR0 的简单介绍如下:

这里我第一次听说 MSW 寄存器,特地去搜索了一下“ Intel在80286 CPU中引入了一个16位的机器状态字寄存器MSW。在80386及其后续的CPU中已经把MSW扩展为4个32位控制寄存器CR0、CR1、CR2和CR3,原来的MSW功能由CR0的低16位来实现。”【参考2】简单的说就是一个历史遗留下来的寄存器,功能已经被 CR0 取代了。

接下来介绍每一个Bit(这部分根据《x86/x64 体系探索及编程》第六章 处理器的控制寄存器,编写),只是大概的介绍,如果想进一步了解推荐购买这本书。

参考:

Ru 是AMI 的 James Wang(个人主页http://ruexe.blogspot.tw/)推出的系列工具,其中包括IA32 X64版本的Ru.EFI和一个 Windows 版本的 RU.EXE。最新版本可以在https://github.com/JamesAmiTw/ru-uefi 下载到。

本文简单介绍它的功能和使用。

UEFI X64 版本初始界面如下:

  1. File 菜单,提供了 Load Save 和 Compare 功能,可以保存和读取当前页面的数据,一般情况下不会使用,主要原因是操作没有 Windows 下方便。

2.Config 菜单用来进行寄存器的访问。

当我还是一个孩子的时候,荧幕上充斥的还是史泰龙施瓦辛格这样的硬汉,他们用肌肉而不是今天这样的小鲜肉那样用兰花指打败敌人,看起来非常过瘾。一次偶然的机会,在父亲的朋友家看了电视台播出的《铁血战士》。这部影片给我留下很深的印象,神秘的丛林,还有影片中拥有着高科技武器的外星人。譬如说,大反派的铁血战士有一个很酷的带在手腕上能显示当前心率的个人电脑。还有就是他可以切换到红外线模式,看到人类无法看到的红外线。这样的功能在夜战中尽占便宜。最后施瓦辛格州长大人凭借主角光环发现了对手这一特性,用泥巴将自己包裹起来阻挡身体上的红外线躲过搜查实现反杀。

最近发现市面上有一种红外阵列传感器:MLX90640 ,分辨率可以达到 32*24。忽发奇想尝试用它DIY一个简易的热成像仪。MLX90640对内存要求比较高,普通的 Arduino 无法胜任。最终选用  Teensy 3.2 作为主控,主要原因是它性能远超 Arduino ,主频可以达到 120Mhz (Overclock状态)。为了实现在液晶屏上面的显示,需要主控能够快速的将数据发送到屏幕上,否则刷新速度慢非常影响效果。此外,Teensy 3.2内存有 64KB,取得数据和处理数据需要在足够的内存中进行,因此大内存必不可少。之后,从淘宝入手了 320*240 分辨率的SPI 接口的液晶屏作为显示界面。硬件方案确定之后即可着手进行代码编写。

从整体上来说,代码操作需要三部分:第一步,获得传感器数据;第二步,处理数据(因为屏幕明显比传感器大,因此,需要将少量数据变换成大量数据,这里使用的是双线性插值算法);第三步,将数据显示在屏幕上。下面就是详细步骤:

第一步:传感器数据的获得。MLX90640 有对应的 Arduino 库,这使得用户能够方便的获得红外数据。特别需要注意的取得的数据是从右上到左下排列的。

这部分代码很简单,配合调用库函数即可:

  for (byte x = 0 ; x < 2 ; x++){
 ...								 > Read More
			

IO Port 的访问是对硬件的最基本操作,在 UEFI Shell 下我们通过 IoLib 中的IoRead8 IoRead16 IoRead32 这样的来进行读取。本文介绍Shell 下的 IoRead8 的具体实现。

首先编写一个代码用于测试:

#include  <Uefi.h>
#include  <Library/UefiLib.h>
#include  <Library/ShellCEntryLib.h>
#include  <Library/IoLib.h>

extern  EFI_SYSTEM_TABLE    *gST;
extern  EFI_BOOT_SERVICES   *gBS;

/***
  Print a welcoming message.

  Establishes the main structure of the application.

...								 > Read More
			

在64位模式下,Microsoft Visual Studio 不支持内嵌汇编。但是编译器本身支持一些intrinsic 预定义的指令,这次就研究一下_AddressOfReturnAddress。他的作用是“提供保存当前函数的返回地址的内存位置的地址。 此地址不能用于访问其他内存位置 (例如, 函数的参数)。”【参考1】

编写一个简单的Application 验证之:

#include  <Uefi.h>
#include  <Library/BaseLib.h>
#include  <Library/UefiLib.h>
#include  <Library/ShellCEntryLib.h>
#include  <Library/IoLib.h>

/**
  Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics.
**/

void* _AddressOfReturnAddress (VOID);

#pragma intrinsic(_AddressOfReturnAddress)

void func() {
   void* pvAddressOfReturnAddress = _AddressOfReturnAddress();
   Print(L"%lx\n", pvAddressOfReturnAddress);
   Print(L"%lx\n", *((void**)...								 > Read More
			

这篇文章其实和BIOS关系不大,之所以放在这里更关键的是给大家提供一种Windows 下针对IRQ, Interrupt Vector 的分析方法。

我有一台 WHL HDK ,上面有4个实体按键,分别是 Power Button ,Volume Up, Volume Down 和Reset。从电路图上来看,Volume Up 和 Down 是直接连接进入EC的。起初我以为按下时会产生Q Event,但始终无法在 ASL 中触发对应的 Event。后来仔细琢磨:所谓“条条大路通罗马”,抓不到的原因非常可能是EC 并不是通过 Q_Event 的方式来通知的系统,很可能是通过多媒体按键的键值方式传递这个消息的。为此,进行下面的实验:

1.打开设备管理器查看一下 PS2 键盘,上面给出的 IRQ1:

当我们在 cmd 窗口下输入一个命令后,首先Windows会在当前目录中查找,之后会在 Path 指定的路径下查找。我们在编译过程中经常会遇到:输入一个可执行文件,但是又不知道是从哪里执行的。特别是当系统中有很多个同名文件的时候。最近发现Windows下有一个命令能够帮助我们很快完成查找的工作,就是 Where 命令。

例如,我想知道当前 python 执行的是哪个,可以输入 where python

WHERE.exe【参考1】

Locate and display files in a directory tree.

The WHERE command is roughly equivalent to the UNIX 'which' command. By default, the search is done in... > Read More

很多年前的BIOS Setup中通常存在 Disable  Cache的选项。时至今日这个选项已经消失的无影无踪,而当你提出这个问题时,人们第一个反应是“为什么要 Disable 它”?不过最近我遇到客户提出这样的需求,只得进行一番研究。

在 “Intel® 64 and IA-32 Architectures Software Developer’s Manual”【参考1】对此有明确表述:

上文提到的操作就是设置 CR0的2个 Bits ,再用 WBINVD 清除缓冲队列,最后Disable MTRR即可,具体代码如下:

AsmDisableCache();        //这个函数自带 WBINVD指令,所以这里无需再写一次
       ...								 > Read More