说明

UEFI变量在BIOS启动过程中创建。

它们有不同的类型,可以直接看属性:

///
/// Attributes of variable.
///
#define EFI_VARIABLE_NON_VOLATILE                            0x00000001
#define EFI_VARIABLE_BOOTSERVICE_ACCESS                      0x00000002
#define EFI_VARIABLE_RUNTIME_ACCESS                          0x00000004

并不是所有的变量都可以在OS下获取到,比如EFI_VARIABLE_BOOTSERVICE_ACCESS类型的变量当在UEFI下调用了ExitBootServices()之后就不能再使用了。

在《UEFI Spec》中有如下的章节:"Globally Defined Variables",它介绍了UEFI下定义的变量,它们都包含了EFI_VARIABLE_RUNTIME_ACCESS这个属性,因此可以在OS下访问到。

各个变量的使用方式见《UEFI Spec》。

Windows下访问UEFI变量

MSDN中有介绍UEFI变量访问的接口,主要是如下几个:

GetFirmwareEnvironmentVariable

GetFirmwareEnvironmentVariableEx

SetFirmwareEnvironmentVariable

SetFirmwareEnvironmentVariableEx

下面是一个示例:

#include "stdafx.h"
#include "windows.h"
#include "tchar.h"
#include "stdio.h"#define EFI_GLOBAL_VARIABLE     "{8BE4DF61-93CA-11D2-AA0D-00E098032B8C}"
#define ConOut                  "ConOut"
#define MAX_SIZE                200BOOL AdjustToken();int _tmain (int argc, _TCHAR* argv[])
{DWORD dwRet;PVOID pBuffer;DWORD nSize;DWORD index;dwRet = ERROR_SUCCESS;nSize = MAX_SIZE;pBuffer = malloc (nSize);AdjustToken ();//// 首先使用空(Dummy)的变量,来确定是否是在Legacy BIOS上安装的Windows;//dwRet = GetFirmwareEnvironmentVariable (_T (""),_T ("{00000000-0000-0000-0000-000000000000}"),pBuffer,nSize);if (0 == dwRet){//// 返回值是变量的大小,0表示的是没有获取到;//if (GetLastError () == ERROR_INVALID_FUNCTION){//// 如果Windows是装在Legacy BIOS上,返回值是ERROR_INVALID_FUNCTION;//printf ("Windows was installed using legacy BIOS.\n");}else{//// 如果返回998(ERROR_NOACCESS)表示没有这个GUID的变量,这也是正常的,因为访问的是空的变量;//printf ("ErrCode = %ld.\n", GetLastError ());printf ("Windows was installed using UEFI BIOS.\n");dwRet = GetFirmwareEnvironmentVariable (_T (ConOut),_T (EFI_GLOBAL_VARIABLE),pBuffer,100);if (0 == dwRet){printf ("ErrCode = %ld.\n", GetLastError ());}else{printf ("Variable size: %d.\n", dwRet);for (index = 0; index < dwRet; index++){printf ("%02x ", *((BYTE *)pBuffer + index));}printf("\n");}}}free (pBuffer);return ERROR_SUCCESS;
}

这里有几点说明:

1. 上述代码在VS2107 commnity上编译和使用,系统环境是Windows10,运行结果如下:

2. 需要在Administrator打开命令行并运行,这里是一个权限的问题;

3. 这里还需要一个函数AdjustToken(),也是用来处理权限的,代码来自下面的网址:

GetFirmwareEnvironmentVariable失败返回错误码1314_youyudexiaowangzi的专栏-CSDN博客

Linux下访问UEFI变量

要了解Linux下如何获取变量,可以从efibootmgr这个命令开始,下面是一个例子:

efibootmgr命令用来调整UEFI启动顺序,它就是通过操作UEFI变量来完成的。

efibootmgr的源代码可以在GitHub - rhboot/efibootmgr: efibootmgr development tree下载到。

查看源代码就会注意到里面操作变量的接口,下面是efibootmgr中读取启动项顺序的函数:

static int
read_order(const char *name, var_entry_t **order)
{int rc;var_entry_t *new = NULL, *bo = NULL;if (*order == NULL) {new = calloc(1, sizeof (**order));if (!new) {efi_error("calloc(1, %zd) failed",sizeof (**order));return -1;}*order = bo = new;} else {bo = *order;}rc = efi_get_variable(EFI_GLOBAL_GUID, name,&bo->data, &bo->data_size, &bo->attributes);if (rc < 0 && new != NULL) {efi_error("efi_get_variable failed");free(new);*order = NULL;bo = NULL;}if (bo) {/* latest apple firmware sets high bit which appears invalid* to the linux kernel if we write it back so lets zero it out* if it is set since it would be invalid to set it anyway */bo->attributes = bo->attributes & ~(1 << 31);}return rc;
}

里面可以看到读取UEFI变量的接口:efi_get_variable。

它的声明在头文件<efivar.h>中,而它的实现也可以在Github上找到:

GitHub - rhboot/efivar: Tools and libraries to work with EFI variables

具体的实现和例子就不用多说了,主要还是要看代码。

【UEFI实战】如何在OS下获取UEFI变量相关推荐

  1. 如何在firefox下获取下列框选中option的text

    Firefox下面没有innerText,所以我们想在firefox下获取下列框选中option的text(注意不是value)时会比较吃力.笔者结合自己在项目中的解决方案和代码总结一下,请大家指教. ...

  2. python os.environ windows_python 获取系统环境变量 os.environ and os.putenv

    从一段code说起 "if "BATCH_CONFIG_INI" in os.environ:" 判断环境变量的值有没有定义 如果定义的话就去环境变量的值,否则 ...

  3. 【UEFI实战】OS下如何查看系统相关信息

    说明 本文主要介绍OS下如何来查看系统信息,这些系统信息大多是通过BIOS上传的.这里的OS主要分为Linux和Windows两个部分来说明,前者使用的发行版系统是Ubuntu18.04,后者使用的是 ...

  4. 【UEFI实战】EDK的编译流程说明

    前言 使用EDK进行UEFI开发,开始的时候很容易遇到的问题就是编译不过,并非代码的问题,而是编译环境存在异常. 本文主要介绍EDK是如何进行编译的,使用的平台是Windows.这里还想说一点,事实上 ...

  5. 【UEFI实战】Redfish的BIOS实现1

    Redfish的BIOS实现 EDK2提供了Redfish框架,用来实现带外的BIOS配置,其基本框架如下: 通过RedfishPkg中提供的Driver,可以实现BIOS与BMC或者其它的软件进行通 ...

  6. 【UEFI实战】UART的初始化

    说明 UART全称是Universal Asynchronous Receiver/Transmitter,这里它表示的是一种实现串口通信的芯片,在整个串口系统中它的位置如下图所示: RS232 +- ...

  7. 【UEFI实战】Secure Boot

    说明 Secure Boot,顾名思义就是用来保证启动安全的一套措施. Secure Boot是一个比较普通的说法,使用的场景也很多,所以这里要特别说明一下,这里指的是UEFI BIOS下的,用来启动 ...

  8. 如何获取UEFI开源资源?

    1.认识TianoCore 2004 年 6 月,英特尔宣布将在开源许可下发布其可扩展固件接口 (EFI) 的"基础代码",这是 16 位 x86"传统"PC ...

  9. 【UEFI实战】LinuxBoot

    综述 LinuxBoot是一个开源的固件,用来替代UEFI BIOS加载Linux的系统. 官网是LinuxBoot. 对应的代码库位于LinuxBoot · GitHub. 另外,本文是在[UEFI ...

最新文章

  1. 异步化,高并发大杀器
  2. C++类的使用(五)—— 多态
  3. 戴尔新鲜空气制冷的研究:在数据中心里面,让我们脱掉厚夹克换上一件夏威夷衬衫!...
  4. 4-5:TCP协议之连接管理机制(三次握手、四次挥手详解)
  5. Flink的累加器(Accumulator)应用
  6. fragment的懒加载
  7. 后 5G 时代,路在何方?
  8. C++使函数返回多个数组
  9. 如何在NEO区块链上实现信息加密
  10. 验证码的旋转与放缩代码
  11. 用文本文档写的代码怎么运行?
  12. Stata+R: 一文读懂中介效应分析
  13. python中del的用法
  14. 你需要的iPhoneX适配
  15. 谷歌创始人拉里·佩奇不为人知的故事
  16. 世界观、价值观和人生观三者之间的关系
  17. C# 图形处理-缩略图,图片合并,图片写文字,图片调整
  18. [转]Sqlite中文排序研究
  19. 【C#懒蛋编程——5分钟经验分享】02使用partial关键字,分离代码
  20. 25张漂亮的微距摄影作品欣赏

热门文章

  1. LBP+SVM 活体识别
  2. 抖音视频审核不通过,可能你触碰以下红线丨国仁网络
  3. AppEmit解决Chrome浏览器自2020年12月开始不再支持Flash Player
  4. java软件发布_发布简单java程序
  5. Wireshark网络抓包工具
  6. 重温历史:Palm OS经典游戏于发布20年后公开源代码
  7. python怎么输入文件路径_python怎么打开文件的路径?
  8. 【认证绕过】NACOS身份认证绕过漏洞分析
  9. ERROR: cannot download default sources list from
  10. PCB设计中容易忽视的小细节 一分钟帮你总结