在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
			

前面介绍了 IDT ,这里继续研究Shell 下是如何处理 Exception的。

同样,前面提到过,Shell下当一个中断发生之后会从 IDT 中查找Vector入口,然后跳转进去执行。

1.代码在\UefiCpuPkg\Library\CpuExceptionHandlerLib\X64\ExceptionHandlerAsm.nasm 可以看作用是在尽量短的代码中跳转到对应的处理代码

AsmIdtVectorBegin:
%rep  32
    db      0x6a        ; push  #VectorNum
    db      ($ - AsmIdtVectorBegin)...								 > Read More
			

前面介绍了静态条件下的分析,下面研究一下EFI 文件加载在内存中的情况。

用一个图来说明情况:

左侧是文件,右侧是加载到内存后的情况,可以看到对于头是照搬到内存中。对于Section 的话,看起来就比较麻烦,一般情况下内存的对齐要求会比PE文件要求的大。比如:PE 中按照 16Bytes对齐,在内存中可能要求按照 64Bytes对齐,相比是因为 PE文件希望紧凑一些,内存的数据希望读取更快所以要做成这样的。

用一个GenCRC32.exe为例:

加载到内存中的是按照 0x1000对齐,数据在文件中存放是按照 0x200对齐。

继续查看 .text Section 可以看到 RVA=0x1000,意思是:当这个PE被加载到内存后,会放在 BaseAddress+0x1000的内存地址;Pointer to Raw Data 给出 0x400意思是这个段在文件中的位置是从 0x400开始的。

2019年10月19-20日,本站会参加位于上海市杨浦区五角场市级副中心国和路 346 号江湾体育场举办的创客嘉年华活动,展位编号 M10。主要展示 Arduino 设计相关内容。

展览中出售的模块如下:

  1. USB Host Mini http://www.lab-z.com/cuhm/
  2. USB Host Shield http://www.lab-z.com/arduinousb1/
  3. Leonardo2UNO Shield http://www.lab-z.com/l2u/
  4. ProtoShield V1 http://www.lab-z.com/prototype-shield-v3/
  5. ProtoShield V3 http://www.lab-z.com/prototype-shield-v3/

欢迎新老朋友前来捧场。

> Read More

很多年前我去 DELL 面试,里面的BIOS工程师问如何实现一个delay。我讲了一些使用硬件Timer的方法来实现精确的delay,他都一直摇头。最后我实在忍不住问他正确答案是什么。他的回答是 90h 也就是 NOP指令。当然,NOP是最简单的方法,但是这种方法密切和CPU速度相关的,在不同的CPU上实现的效果不同。

最近查看UEFI 发现其中实现了一个delay使用的是 PAUSE 指令看起来很有意思,于是做了一番研究。具体代码在 \MdePkg\Library\BaseLib\Ia32\CpuPause.c 和\MdePkg\Library\BaseLib\X64\CpuPause.nasm 中。殊途同归,最终都是通过pause 指令来实现。

PAUSE Spin Loop Hint

Opcode Mnemonic           Description

F3 90     PAUSE   Gives hint to processor that improves performance of spin-wait loops.

Description

Improves the performance of spin-wait loops. When executing a... > Read More

前面的文章“EFI 文件研究(1)”提到了入口地方有一个奇怪的现象,直接从ProcessLibraryConstructorList 函数跳到了ProcessModuleEntryPointList。百思不得其解之后咨询天杀,他提到有编译器有一种优化方式,针对“连续两个函数的调用 ,在优化后可能会将第一个函数的尾部返回优化成对第二个函数的跳转,然后由第二个函数来进行返回”。经过这样的提醒后,我在代码中查找,找到了非常类似的代码。

在\MdePkg\Library\UefiApplicationEntryPoint\ApplicationEntryPoint.c 定义了Application 的入口:

/**
  Entry point to UEFI Application.

  This function is the entry point for a UEFI Application. This function must call
  ProcessLibraryConstructorList(), ProcessModuleEntryPointList(), and ProcessLibraryDestructorList().
  The return value from ProcessModuleEntryPointList() is returned.
  If _gUefiDriverRevision is not zero and...								 > Read More