UEFI——Shell下读取SMBIOS信息

2024-09-06 08:04
文章标签 读取 shell 信息 uefi smbios

本文主要是介绍UEFI——Shell下读取SMBIOS信息,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、SMBIOS简介

SMBIOS的全称为System Management BIOS,它不是一个BIOS,只是与BIOS相关。它是一个规范,定义了BIOS传递给操作系统的系统管理信息。它也表示了一系列的数据结构,包含了各类信息,由BIOS启动过程中创建并放在特定的内存,之后操作系统可以拿来用。

整个 SMBIOS_STRUCTURE 结构体定义了 SMBIOS 表中的一个基本单元。每个 SMBIOS 结构都包含一个类型、长度和句柄,后面跟着与该类型相关的特定数据。这些结构体被组织成一个链表,可以在系统启动时由系统固件、操作系统或管理工具读取,以获取系统的硬件配置和管理信息。

typedef struct {SMBIOS_TYPE      Type;UINT8            Length;SMBIOS_HANDLE    Handle;
} SMBIOS_STRUCTURE;

二、Shell下读取SMBIOS信息

首先介绍结构体_EFI_SMBIOS_PROTOCOL,用于定义在EFI应用程序和驱动程序中管理SMBIOS表的接口。其代码原型为:

struct _EFI_SMBIOS_PROTOCOL {EFI_SMBIOS_ADD              Add; //添加SMBIOS记录EFI_SMBIOS_UPDATE_STRING    UpdateString;EFI_SMBIOS_REMOVE           Remove;EFI_SMBIOS_GET_NEXT         GetNext;UINT8                       MajorVersion; ///< The major revision of the SMBIOS specification supported.UINT8                       MinorVersion; ///< The minor revision of the SMBIOS specification supported.
};

其中添加SMBIOS记录的为EFI_SMBIOS_ADD,

typedef
EFI_STATUS
(EFIAPI *EFI_SMBIOS_ADD)(IN CONST      EFI_SMBIOS_PROTOCOL     *This, //手动添加的This指针,始终指向当前的EFI_SMBIOS_PROTOCOL实例IN            EFI_HANDLE              ProducerHandle OPTIONAL, //与 SMBIOS 信息关联的控制器或驱动程序的句柄。NULL 表示没有句柄。IN OUT        EFI_SMBIOS_HANDLE       *SmbiosHandle, //输出参数,要添加的 SMBIOS 记录的句柄。如果为 FFFEh,则将为 SMBIOS 记录分配唯一句柄。如果 SMBIOS 句柄已在使用中,则会返回 EFI_ALREADY_STARTED,并且不会更新 SMBIOS 记录。IN            EFI_SMBIOS_TABLE_HEADER *Record //SMBIOS记录的固定部分的数据);

更新SMBIOS信息字符串用EFI_SMBIOS_UPDATE_STRING

typedef
EFI_STATUS
(EFIAPI *EFI_SMBIOS_UPDATE_STRING)(IN CONST EFI_SMBIOS_PROTOCOL *This, //EFI_SMBIOS_PROTOCOL实例IN       EFI_SMBIOS_HANDLE   *SmbiosHandle, //要更新字符串的SMBIOS句柄IN       UINTN               *StringNumber, //要更新的字符串IN       CHAR8               *String //用于更新的字符串);

删除SMBIOS记录用EFI_SMBIOS_REMOVE

typedef
EFI_STATUS
(EFIAPI *EFI_SMBIOS_REMOVE)(IN CONST EFI_SMBIOS_PROTOCOL *This,IN       EFI_SMBIOS_HANDLE   SmbiosHandle //要删除的SMBIOS记录的句柄);

允许调用者查找全部或部分SMBIOS记录用EFI_SMBIOS_GET_NEXT

typedef
EFI_STATUS
(EFIAPI *EFI_SMBIOS_GET_NEXT)(IN     CONST EFI_SMBIOS_PROTOCOL     *This,IN OUT       EFI_SMBIOS_HANDLE       *SmbiosHandle, //进入时,指向 SMBIOS 记录的上一个句柄。退出时,指向下一个 SMBIOS 记录句柄。如果输入时为 FFFEh,则将返回第一个 SMBIOS 记录句柄。如果它在退出时返回 FFFEh,则没有更多的 SMBIOS 记录。IN           EFI_SMBIOS_TYPE         *Type              OPTIONAL, //进入时,它指向要返回的下一条 SMBIOS 记录的类型。如果为 NULL,则表示将返回任何类型的下一条记录。此函数不会修改 Type。OUT          EFI_SMBIOS_TABLE_HEADER **Record, //输出参数,退出时,指向指向 SMBIOS 记录的指针,该记录由格式化区域和未格式化区域组成。未格式化区域(可选)包含文本字符串。OUT          EFI_HANDLE              *ProducerHandle    OPTIONAL //输出参数,带有 SmbiosHandle 的 SMBIOS 记录是最后一条可用记录。);

 在使用SMBIOSProtocol的时候,首先通过LocateProtocol找到实例

  Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, //gEfiSmbiosProtocolGuid是一个全局变量,用于唯一标识EFI_SMBIOS_PROTOCOLNULL,(VOID**)&Smbios //输出参数,指向找到的EFI_SMBIOS_PROCOTOL实例);

宏定义SMBIOS_HANDLE_PI_RESERVED设定了一个特定的值0xFFFE,这个值在SMBIOS协议中被保留用于特定的目的,SMBIOS_HANDLE通常是一个唯一标识符,用在SMBIOS表中引起特定的SMBIOS结构

//根据SMBIOS 2.7版本的6.1.2章节,以及UEFI平台初始化规范,宏定义SMBIOS_HANDLE_PI_RESERVED 设置为 0xFFFE,当 EFI_SMBIOS_PROTOCOL.Add() 函数的 Handle 参数被设置为 0xFFFE 时,它指示固件自动分配一个未被使用的句柄号给新的 SMBIOS 结构。这意味着调用者不需要指定具体的句柄号,而是由固件来选择一个合适的、未被占用的句柄号。
//0xFFFE这个值不会被用作任何其他目的,它专门用作自动分配句柄号
#define SMBIOS_HANDLE_PI_RESERVED  0xFFFE

 完整代码如下:

#include <uefi.h> 
#include <Library/UefiLib.h> 
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/Smbios.h>EFI_STATUS
EFIAPI
MyHelloWorldSmbiosAppEntry(IN EFI_HANDLE        ImageHandle,IN EFI_SYSTEM_TABLE  *SystemTable
)
{ EFI_STATUS  Status = EFI_SUCCESS;EFI_SMBIOS_PROTOCOL           *Smbios;EFI_SMBIOS_HANDLE             SmbiosHandle;EFI_SMBIOS_TABLE_HEADER       *Record;DEBUG ((EFI_D_ERROR , "[MyHelloWorldSmbios] MyHelloWorldSmbiosAppEntry Start..\n"));//// Find the SMBIOS protocol//Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid,NULL,(VOID**)&Smbios);if (EFI_ERROR (Status)) { //需要注意的是EFI_SUCCESS通常被定义为0,即成功为0,不成功为非0return Status;}SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL);while (!EFI_ERROR(Status)) {DEBUG ((EFI_D_ERROR, "[MyHelloWorldSmbios] %d ..\n", Record->Type));// if (Record->Type == SMBIOS_TYPE_BIOS_INFORMATION) {// Type0Record = (SMBIOS_TABLE_TYPE0 *) Record;// StrIndex = Type0Record->BiosVersion;// GetOptionalStringByIndex ((CHAR8*)((UINT8*)Type0Record + Type0Record->Hdr.Length), StrIndex, &NewString);// FirmwareVersionString = (CHAR16 *) PcdGetPtr (PcdFirmwareVersionString);// if (*FirmwareVersionString != 0x0000 ) {// FreePool (NewString);// NewString = (CHAR16 *) PcdGetPtr (PcdFirmwareVersionString);// UiCustomizeFrontPageBanner (3, TRUE, &NewString);// HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION), NewString, NULL);// } else {// UiCustomizeFrontPageBanner (3, TRUE, &NewString);// HiiSetString (gFrontPagePrivate.HiiHandle, STRING_TOKEN (STR_FRONT_PAGE_BIOS_VERSION), NewString, NULL);// FreePool (NewString);// }// }Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL);}DEBUG ((EFI_D_ERROR, "[MyHelloWorldSmbios] MyHelloWorldSmbiosAppEntry End..\n"));return Status;
}

这篇关于UEFI——Shell下读取SMBIOS信息的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1141457

相关文章

Java实现远程执行Shell指令

《Java实现远程执行Shell指令》文章介绍使用JSch在SpringBoot项目中实现远程Shell操作,涵盖环境配置、依赖引入及工具类编写,详解分号和双与号执行多指令的区别... 目录软硬件环境说明编写执行Shell指令的工具类总结jsch(Java Secure Channel)是SSH2的一个纯J

使用Java读取本地文件并转换为MultipartFile对象的方法

《使用Java读取本地文件并转换为MultipartFile对象的方法》在许多JavaWeb应用中,我们经常会遇到将本地文件上传至服务器或其他系统的需求,在这种场景下,MultipartFile对象非... 目录1. 基本需求2. 自定义 MultipartFile 类3. 实现代码4. 代码解析5. 自定

MySQL 数据库表操作完全指南:创建、读取、更新与删除实战

《MySQL数据库表操作完全指南:创建、读取、更新与删除实战》本文系统讲解MySQL表的增删查改(CURD)操作,涵盖创建、更新、查询、删除及插入查询结果,也是贯穿各类项目开发全流程的基础数据交互原... 目录mysql系列前言一、Create(创建)并插入数据1.1 单行数据 + 全列插入1.2 多行数据

shell脚本批量导出redis key-value方式

《shell脚本批量导出rediskey-value方式》为避免keys全量扫描导致Redis卡顿,可先通过dump.rdb备份文件在本地恢复,再使用scan命令渐进导出key-value,通过CN... 目录1 背景2 详细步骤2.1 本地docker启动Redis2.2 shell批量导出脚本3 附录总

SpringBoot多环境配置数据读取方式

《SpringBoot多环境配置数据读取方式》SpringBoot通过环境隔离机制,支持properties/yaml/yml多格式配置,结合@Value、Environment和@Configura... 目录一、多环境配置的核心思路二、3种配置文件格式详解2.1 properties格式(传统格式)1.

SQL Server跟踪自动统计信息更新实战指南

《SQLServer跟踪自动统计信息更新实战指南》本文详解SQLServer自动统计信息更新的跟踪方法,推荐使用扩展事件实时捕获更新操作及详细信息,同时结合系统视图快速检查统计信息状态,重点强调修... 目录SQL Server 如何跟踪自动统计信息更新:深入解析与实战指南 核心跟踪方法1️⃣ 利用系统目录

解决pandas无法读取csv文件数据的问题

《解决pandas无法读取csv文件数据的问题》本文讲述作者用Pandas读取CSV文件时因参数设置不当导致数据错位,通过调整delimiter和on_bad_lines参数最终解决问题,并强调正确参... 目录一、前言二、问题复现1. 问题2. 通过 on_bad_lines=‘warn’ 跳过异常数据3

linux下shell脚本启动jar包实现过程

《linux下shell脚本启动jar包实现过程》确保APP_NAME和LOG_FILE位于目录内,首次启动前需手动创建log文件夹,否则报错,此为个人经验,供参考,欢迎支持脚本之家... 目录linux下shell脚本启动jar包样例1样例2总结linux下shell脚本启动jar包样例1#!/bin

Python使用openpyxl读取Excel的操作详解

《Python使用openpyxl读取Excel的操作详解》本文介绍了使用Python的openpyxl库进行Excel文件的创建、读写、数据操作、工作簿与工作表管理,包括创建工作簿、加载工作簿、操作... 目录1 概述1.1 图示1.2 安装第三方库2 工作簿 workbook2.1 创建:Workboo

一文详解如何使用Java获取PDF页面信息

《一文详解如何使用Java获取PDF页面信息》了解PDF页面属性是我们在处理文档、内容提取、打印设置或页面重组等任务时不可或缺的一环,下面我们就来看看如何使用Java语言获取这些信息吧... 目录引言一、安装和引入PDF处理库引入依赖二、获取 PDF 页数三、获取页面尺寸(宽高)四、获取页面旋转角度五、判断