IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> SMBIOS驱动代码分析 -> 正文阅读

[嵌入式]SMBIOS驱动代码分析

1、概述

在主板上电后,UEFI会将HW信息包括, CPU、Memory、FW、PM等信息以SMBIOS table形式上存储到一段内存区域中,进入OS后,OS通过解析该段内存即可获取相关配置。
SMBIOS是通过DXE驱动加载到系统表的,入口函数为SmbiosDriverEntryPoint,该驱动程序生成一个实例。实例包含了增加、更新、移除、获取 SMBIOS的函数,入口函数还初始化数据链表和句柄头部链表。最后实现的实例安装到新的句柄上,在DXE阶段调用。

EFI_STATUS
EFIAPI
SmbiosDriverEntryPoint (
  IN EFI_HANDLE           ImageHandle,
  IN EFI_SYSTEM_TABLE     *SystemTable
  )
{
  EFI_STATUS            Status;

  mPrivateData.Signature                = SMBIOS_INSTANCE_SIGNATURE;
  mPrivateData.Smbios.Add               = SmbiosAdd;
  mPrivateData.Smbios.UpdateString      = SmbiosUpdateString;
  mPrivateData.Smbios.Remove            = SmbiosRemove;
  mPrivateData.Smbios.GetNext           = SmbiosGetNext;
  mPrivateData.Smbios.MajorVersion      = (UINT8) (PcdGet16 (PcdSmbiosVersion) >> 8);
  mPrivateData.Smbios.MinorVersion      = (UINT8) (PcdGet16 (PcdSmbiosVersion) & 0x00ff);

  InitializeListHead (&mPrivateData.DataListHead);
  InitializeListHead (&mPrivateData.AllocatedHandleListHead);
  EfiInitializeLock (&mPrivateData.DataLock, TPL_NOTIFY);
  
  //
  // Make a new handle and install the protocol
  //
  mPrivateData.Handle = NULL;
  Status = gBS->InstallProtocolInterface (
                  &mPrivateData.Handle,
                  &gEfiSmbiosProtocolGuid,
                  EFI_NATIVE_INTERFACE,
                  &mPrivateData.Smbios
                  );

  return Status;
}

2、创建表结构

SmbiosCreateTable (
  OUT VOID    **TableEntryPointStructure
  )
  {
  .....
  EntryPointStructureData.MajorVersion  = mPrivateData.Smbios.MajorVersion;
  EntryPointStructureData.MinorVersion  = mPrivateData.Smbios.MinorVersion;
  EntryPointStructureData.SmbiosBcdRevision = (UINT8) ((PcdGet16 (PcdSmbiosVersion) >> 4) & 0xf0) | (UINT8) (PcdGet16 (PcdSmbiosVersion) & 0x0f);
  PhysicalAddress = 0xffffffff;
  Status = gBS->AllocatePages (
                    AllocateMaxAddress,
                    EfiRuntimeServicesData,
                    EFI_SIZE_TO_PAGES (sizeof (SMBIOS_TABLE_ENTRY_POINT)),
                    &PhysicalAddress
                    );
  ....
  }

创建表结构的主要功能为
1、根据EPS表结构填充字段

位置名称长度描述
00H关键字4BYTE固定是”SM
04H校验和1BYTE用于校验数据
05H表结构长度1BYTEEntry Point Structure 表的长度
06HMajor 版本号1BYTE用于判断SMBIOS 版本
07HMinor 版本号1BYTE用于判断SMBIOS 版本
08H表结构大小2BYTE用于即插即用接口方法获得数据表结构长度
0AHEPS 修正1BYTE
0B-0FH格式区域5BYTE存放解释EPS 修正的信息
10H关键字5BYTE固定为“DMI
15H校验和1BYTEIntermediate Entry Point Structure (IEPS)的校验和
16H结构表长度2BYTESMBIOS 结构表的长度
18H结构表地址4BYTESMBIOS 结构表的真实内存位置
1CH结构表个数2BYTESMBIOS 结构表数目
1EHSmbios BCD 修正1BYTE

与SMBIOS的SMBIOS_TABLE_ENTRY_POINT结构体对应起来

typedef struct {
  UINT8   AnchorString[4];
  UINT8   EntryPointStructureChecksum;
  UINT8   EntryPointLength;
  UINT8   MajorVersion;
  UINT8   MinorVersion;
  UINT16  MaxStructureSize;
  UINT8   EntryPointRevision;
  UINT8   FormattedArea[5];
  UINT8   IntermediateAnchorString[5];
  UINT8   IntermediateChecksum;
  UINT16  TableLength;
  UINT32  TableAddress;
  UINT16  NumberOfSmbiosStructures;
  UINT8   SmbiosBcdRevision;
} SMBIOS_TABLE_ENTRY_POINT;

2、创建表头部

位置名称长度描述
00HTYPE 号1BYTE结构的TYPE 号
01H长度1BYTE本结构的长度,就此TYPE 号的结构而言
02H句柄2BYTE用于获得本SMBIOS 结构,其值不定
 EndStructure.Header.Type = SMBIOS_TYPE_END_OF_TABLE;
  EndStructure.Header.Length = (UINT8) sizeof (EFI_SMBIOS_TABLE_HEADER);
  EndStructure.Header.Handle = SmbiosHandle;

3 增加SMBIOS表

mPrivateData.Smbios.Add = SmbiosAdd;

EFI_STATUS
EFIAPI
SmbiosAdd (
  IN CONST EFI_SMBIOS_PROTOCOL  *This,
  IN EFI_HANDLE                 ProducerHandle, OPTIONAL
  IN OUT EFI_SMBIOS_HANDLE      *SmbiosHandle,
  IN EFI_SMBIOS_TABLE_HEADER    *Record
  )
   Add an SMBIOS record.

  @param  This                  The EFI_SMBIOS_PROTOCOL instance.
  @param  ProducerHandle        The handle of the controller or driver associated with the SMBIOS information. NULL
                                means no handle.
  @param  SmbiosHandle          On entry, the handle of the SMBIOS record to add. If FFFEh, then a unique handle
                                will be assigned to the SMBIOS record. If the SMBIOS handle is already in use,
                                EFI_ALREADY_STARTED is returned and the SMBIOS record is not updated.
  @param  Record                The data for the fixed portion of the SMBIOS record. The format of the record is
                                determined by EFI_SMBIOS_TABLE_HEADER.Type. The size of the formatted area is defined 
                                by EFI_SMBIOS_TABLE_HEADER.Length and either followed by a double-null (0x0000) or 
                                a set of null terminated strings and a null.

  @retval EFI_SUCCESS           Record was added.
  @retval EFI_OUT_OF_RESOURCES  Record was not added due to lack of system resources.
  @retval EFI_ALREADY_STARTED   The SmbiosHandle passed in was already in use.

1、核实SmbiosHandle是否在使用中
2、计算record的大小和字符数字
找到1个0,是一个字段的长度
找到两个0,就是一条record的大小
3、分配record的内存空间
TotalSize = sizeof (EFI_SMBIOS_ENTRY) + sizeof (EFI_SMBIOS_RECORD_HEADER) + StructureSize;
4、构建句柄入口并且增加到链表中

 HandleEntry->Signature     = SMBIOS_HANDLE_ENTRY_SIGNATURE;
  HandleEntry->SmbiosHandle  = *SmbiosHandle;
  InsertTailList(&Private->AllocatedHandleListHead, &HandleEntry->Link);

5、构建record 的头结构并且增加到内部的链表中

InternalRecord->Version     = EFI_SMBIOS_RECORD_HEADER_VERSION;
  InternalRecord->HeaderSize  = (UINT16) sizeof (EFI_SMBIOS_RECORD_HEADER);
  InternalRecord->RecordSize  = RecordSize;
  InternalRecord->ProducerHandle = ProducerHandle;
  InternalRecord->NumberOfStrings = NumberOfStrings;
  SmbiosEntry->Signature    = EFI_SMBIOS_ENTRY_SIGNATURE;
  SmbiosEntry->RecordHeader = InternalRecord;
  SmbiosEntry->RecordSize   = TotalSize;
  SmbiosEntry->Smbios32BitTable = Smbios32BitTable;
  SmbiosEntry->Smbios64BitTable = Smbios64BitTable;
  InsertTailList (&Private->DataListHead, &SmbiosEntry->Link);

6、安装SMBIOS表到系统表中

typedef
EFI_STATUS
(EFIAPI *EFI_INSTALL_CONFIGURATION_TABLE)(
  IN EFI_GUID                 *Guid,
  IN VOID                     *Table
  );
  Adds, updates, or removes a configuration table entry from the EFI System Table.

  @param[in]  Guid              A pointer to the GUID for the entry to add, update, or remove.
  @param[in]  Table             A pointer to the configuration table for the entry to add, update, or
                                remove. May be NULL.

  @retval EFI_SUCCESS           The (Guid, Table) pair was added, updated, or removed.
  @retval EFI_NOT_FOUND         An attempt was made to delete a nonexistent entry.
  @retval EFI_INVALID_PARAMETER Guid is NULL.
  @retval EFI_OUT_OF_RESOURCES  There is not enough memory available to complete the operation.

4、获得SMBIOS Record

mPrivateData.Smbios.GetNext = SmbiosGetNext;

EFI_STATUS
EFIAPI
GetNextSmbiosRecord (
  IN CONST EFI_SMBIOS_PROTOCOL         *This,
  IN OUT EFI_SMBIOS_ENTRY              **CurrentSmbiosEntry,
  OUT EFI_SMBIOS_TABLE_HEADER          **Record
  )

1、CurrentSmbiosEntry,在退出时,指针指向包含SMBIOS记录信息的入口地址,如果CurrentSmbiosEntry指针在入口时为空,第一个smbios 的入口地址将被返回。
2、Record,在退出时,指向SMBIOS记录,该记录由格式化区域组成,然后是
无格式的区域。 无格式区域可选地包含文本字符串。
通过链表遍历的方法获得SMBIOS record

5、更新或移除SMBIOS Record

mPrivateData.Smbios.UpdateString = SmbiosUpdateString;
mPrivateData.Smbios.Remove = SmbiosRemove;

更新:重新构建InternalRecord,再加载到系统表

6、增加一条SMBIOS table记录

smbios 驱动加载完成,怎样实际增加一条type0/type1/type2…记录
1、先根据gEfiSmbiosProtocolGuid 获得mSmbios接口
Status = gBS->LocateProtocol(&gEfiSmbiosProtocolGuid, NULL, (VOID **)&mSmbios);
2、再通过接口中add 函数加载到系统表中
EFI_SMBIOS_PROTOCOL *mSmbios;
Status = mSmbios->Add (
mSmbios,
NULL,
&SmbiosHandle,
(EFI_SMBIOS_TABLE_HEADER *)SmbiosRecord
);

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-09-08 10:53:52  更:2021-09-08 10:56:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 0:37:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码