理论上写中文注释是没问题的,因为 VS 是支持中文的。但是,很多用于 Build 的工具并没有考虑这种情况,因此会导致稀奇古怪的问题。最近我遇到了一个编译错误

C:\BuildBs\201903>build -a X64
Build environment: Windows-10-10.0.16299-SP0
Build start time: 09:15:25, Jun.02 2019

WORKSPACE        = c:\buildbs\201903
EDK_TOOLS_PATH   = c:\buildbs\201903\basetools
EDK_TOOLS_BIN    = c:\buildbs\201903\basetools\bin\win32
CONF_PATH        = c:\buildbs\201903\conf
PYTHON_COMMAND   = py -3


Architecture(s)  = X64
Build target  ...								 > Read More
			

BaseLib 提供了一些计算CheckSum 的函数,用这些可以让我们方便的计算一些协议要求的校验码。

下面编写一个简单的例子:

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

extern  EFI_SYSTEM_TABLE    *gST;
extern  EFI_BOOT_SERVICES   *gBS;

UINT8   Buffer={1,2,3,4,5};

/***
  Print a welcoming message.

  Establishes the main...								 > Read More
			

目前市面上能够测量心率的设备很多。有腕带腕表式的,也有夹在耳朵或者手指末端的。从准确性上来说,腕带式的容易松动因此没有胸带式的准确。同时,胸带式的对于运动统计来说也是最好的选择。

前一段入手了三根心率带和一个接收模块。其中的心率带是带有编码的,因此在接收端可以很容易的区分数据来源。当然,与之对应的还有不带编码的心率带,无法在多个的情况下使用。

先说说心率带模块:

  1. 内部使用 CR2032 纽扣电池,据说每天工作1小时可以撑9个月;
  2. 发送频率为 2.4Ghz;
  3. 平时处于睡眠模式,戴上之后才开始发送数据
  4. 发射数据每次 4 Bytes,3 Bytes ID+ 1 Byte 心率。

接收模块:

  1. 模块三个引脚,GND  VCC (特别强调是 3.3V供电) TX 。使用串口通讯。波特率 9600 bps。比如:DD 20 03 04 50(个人感觉有点低,设想如果很多根在同一个空间内使用不知道会有什么问题);
  2. 上面有一个LED,当收到有效数据后会闪动一次;
  3. 板子上的孔间距是 2.0mm 不是 2.54,使用杜邦线会很别扭,我直接焊接上导线来使用;

最近在编写一个需要随机生成数值的代码,使用之前的 rand 函数【参考1】发现每次生成的随机数是相同的,忽然意识到这是因为代码里面的随机种子是固定值导致的,如果使用当前时间作为随机种子那么每次生成的数值将会是不同的。

可以使用 Runtime Service 中的 GetTime 来取得时间作为种子,返回的时间格式如下:

//
// EFI Time Abstraction:
//  Year:       2000 - 20XX
//  Month:      1 - 12
//  Day:        1 - 31
//  Hour: ...								 > Read More
			

当我们使用 RW Everything 这样的软件时,会自动请求管理员权限。

相比之下,我们使用批处理文件调用FITW 刷写 BIOS工具的时候不会出现这样的提示,又忘记使用管理员权限打开 CMD 窗口,这样会导致执行失败。最近看到了一个好用的批处理,可以在批处理文件中直接像 RW 这样来请求管理员权限,这样能够避免忘记使用管理员权限打开的问题。

批处理来自 “在批处理中提升权限 (UAC开启状态下)”【参考1】,根据作者的原文应该是翻译自https://sites.google.com/site/eneerge/home/BatchGotAdmin

@echo off

:: BatchGotAdmin
:-------------------------------------
REM  --> Check for permissions
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"

REM --> If error flag set, we do not have admin.
if...								 > Read More
			

之前的《Shell 下读取 VBT》【参考1】给出了一个读取VBT 的方法。Simon 留言表示可以使用 PLATFORM_GOP_POLICY_PROTOCOL提供的 GetVbtData 。可以在\Vlv2DeviceRefCodePkg\ValleyView2Soc\NorthCluster\Include\Protocol\PlatformGopPolicy.h 中看到如下定义:

#define EFI_PLATFORM_GOP_POLICY_PROTOCOL_GUID \
  { 0xec2e931b, 0x3281, 0x48a5, 0x81, 0x7, 0xdf, 0x8a, 0x8b, 0xed, 0x3c, 0x5d }
#define PLATFORM_GOP_POLICY_PROTOCOL_REVISION_01 0x01
#define PLATFORM_GOP_POLICY_PROTOCOL_REVISION_02 x0222
#pragma pack(1)

typedef enum {
  LidClosed,
  LidOpen,
  LidStatusMax
} LID_STATUS;

typedef enum {
  Docked,
  UnDocked,
  DockStatusMax
} DOCK_STATUS;

typedef
EFI_STATUS
(EFIAPI *GET_PLATFORM_LID_STATUS) (
  OUT LID_STATUS *CurrentLidStatus
 ...								 > Read More
			

之前介绍过,现在的 VS 不支持直接在代码中嵌入汇编,因此需要单独将汇编语句写在独立的 Asm 中然后在编译过程中会 Link 到生成的 EFI 文件中。最近碰到了一个奇怪的问题:明明写好的 Asm 在编译的 Link 过程中会提示无法找到对应的函数。经过研究最终确定是因为Asm 文件的名称导致的。

例如,之前的 “新指令 RDRAND”【参考1】文章中 INF 定义如下

[Sources.IA32]
  IA32/RdRandWord.c
  IA32/AsmRdRand.asm

[Sources.X64]
  X64/RdRandWord.c
  X64/AsmRdRand.asm

如果你手抖,命名成 X64/RdRandWord.asm 就会出现前面提到的问题。并且根据错误提示一直无法确定原因。

> Read More

本文根据《软件调试(第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