首页 > 编程语言 >UEFI原理与编程(二)

UEFI原理与编程(二)

时间:2024-09-11 17:46:09浏览次数:1  
标签:Protocol 服务 Image 编程 EFI UEFI 原理 pointer

系统表

对UEFI应用程序和驱动程序开发人员来讲,系统表是最重要的数据结构之一,它是用户空间通往内核空间的通道。有了它,UEFI应用程序和驱动才可以访问UEFI内核、硬件资源和I/O设备。

  • 1 在应用程序和驱动中访问系统表

计算机系统进入DXE阶段后系统表被初始化,因而系统表只能用于DXE阶段以及以后的应用程序和驱动中。系统表是UEFI内核的一个全局结构体,其指针作为程序映像(Image)入口函数的参数传递到用户空间。程序映像(包括UEFI应用程序、DXE驱动程序以及UEFI驱动程序)的入口函数有统一的格式,其函数原型如下:

typedef
EFI_STATUS
(EFIAPI *EFI_IMAGE_ENTRY_POINT) (
    IN  EFI_HANDLE ImageHandle,        //程序映像(Image)的句柄
    IN  EFI_SYSTEM_TABLE *SystemTable  //系统表指针
);
  • 2 系统表指针从内核传递到用户空间的过程

通常,程序映像的入口函数是_ModuleEntryPoint(当一个Image被启动服务的StartImage服务启动时,执行的就是这个入口函数)。当应用程序或驱动加载到内存形成Image后(ImageHandle是这个Image的句柄),_ModuleEntryPoint函数地址被赋值给Image对象的EntryPoint,然后Image->EntryPoint(ImageHandle,SystemTable)会被执行,最终会从Image的入口函数_ModuleEntryPoint执行到模块的入口函数(模块的入口函数是通过.inf文件中ENTRY_POINT指定的那个函数)

1 系统表的组成

*系统表可分为以下6部分:

表头:包括表的版本号、表的CRC校验码等。
固件信息:包括固件开发商名字的字符串和固件的版本号。
标准输入控制台、标准输出控制台、标准错误控制台。
启动服务表
运行时服务表
系统配置表


//@file path:  MdePkg\Include\Uefi\UefiSpec.h

///
/// EFI System Table
///
typedef struct {
  ///
  /// The table header for the EFI System Table.
  ///
  EFI_TABLE_HEADER                  Hdr;
  ///
  /// A pointer to a null terminated string that identifies the vendor
  /// that produces the system firmware for the platform.
  ///
  CHAR16                            *FirmwareVendor;
  ///
  /// A firmware vendor specific value that identifies the revision
  /// of the system firmware for the platform.
  ///
  UINT32                            FirmwareRevision;
  ///
  /// The handle for the active console input device. This handle must support
  /// EFI_SIMPLE_TEXT_INPUT_PROTOCOL and EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
  ///
  EFI_HANDLE                        ConsoleInHandle;
  ///
  /// A pointer to the EFI_SIMPLE_TEXT_INPUT_PROTOCOL interface that is
  /// associated with ConsoleInHandle.
  ///
  EFI_SIMPLE_TEXT_INPUT_PROTOCOL    *ConIn;
  ///
  /// The handle for the active console output device.
  ///
  EFI_HANDLE                        ConsoleOutHandle;
  ///
  /// A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface
  /// that is associated with ConsoleOutHandle.
  ///
  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL   *ConOut;
  ///
  /// The handle for the active standard error console device.
  /// This handle must support the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.
  ///
  EFI_HANDLE                        StandardErrorHandle;   
  ///
  /// A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL interface
  /// that is associated with StandardErrorHandle.
  ///
  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL   *StdErr;
  ///
  /// A pointer to the EFI Runtime Services Table.
  ///
  EFI_RUNTIME_SERVICES              *RuntimeServices;     // 运行时服务
  ///
  /// A pointer to the EFI Boot Services Table.
  ///
  EFI_BOOT_SERVICES                 *BootServices;       // 启动时服务
  ///
  /// The number of system configuration tables in the buffer ConfigurationTable.
  ///
  UINTN                             NumberOfTableEntries;  // CongratulationTable数组的大小
  ///
  /// A pointer to the system configuration tables.
  /// The number of entries in the table is NumberOfTableEntries.
  ///
  EFI_CONFIGURATION_TABLE           *ConfigurationTable;  //系统配置表数组
} EFI_SYSTEM_TABLE;

表头:

// file :  EdkCompatibilityPkg\Foundation\Efi\Include\EfiTypes.h
typedef struct {
  UINT64  Signature;  
  UINT32  Revision;
  UINT32  HeaderSize;   //是整个表的长度,对系统表来讲,就是sizeof(EFI_SYSTEM_TABLE)
  UINT32  CRC32;        
  UINT32  Reserved;
} EFI_TABLE_HEADER;

系统配置表:

//file : EdkCompatibilityPkg\Foundation\Efi\Include\EfiApi.h
//
// EFI Configuration Table
//
typedef struct {
  EFI_GUID  VendorGuid;     // 配置表标识符
  VOID      *VendorTable;   // 指向配置表的数据
} EFI_CONFIGURATION_TABLE;

启动服务

启动服务也称启动服务表,它由UEFI表头表项组成,表中每一项是一个函数指针,该函数用于提供一项服务。
启动服务是UEFI的核心数据结构,可以分为以下8类:

  • UEFI事件服务

  • 内存管理服务

  • Protocol管理服务

  • 驱动管理服务

  • Image 管理服务

  • ExitBootServices

  • 其他服务。

1 UEFI事件服务

事件是异步操作的基础,使得在 UEFI 系统内可以执行并发操作。UEFI 事件服务包含事件(Event)、定时器(Timer)、任务优先级(TPL)三类服务。

  • 事件服务用于产生、关闭、触发、等待事件和检查事件状态。
  • 定时器服务用于设置定时器属性。
  • 任务优先级服务用于提升、降低当前程序的优先级。
2 内存管理服务

内存管理服务主要提供内存的分配与释放服务、管理系统内存映射。主要包括:AllocatePages、FreePages、GetMemoryMap, AllocatePool、FreePool 5个服务。

3 Protocol管理服务

Protocol 管理服务提供安装与卸载 Protocol 的服务,以及注册 Protocol 通知函书(安装时调用)的服务(详见第八,九章)。

4 Protocol使用类服务

Protocol使用类服务包括 Protocol 的打开与关闭,查找支持 Protocol 的控制器,主要提供 Protocol 使用者使用(详见第四章)

5 驱动管理服务

驱动管理服务包括将驱动安装到控制器的 connect 服务和将驱动从控制器上卸载的 disconnect 服务(详见第九章)。

6 Image 管理服务

Image 管理服务包括加载、卸载、启动、退出 UEFI 应用程序或驱动.

Image 管理服务 作用
LoadImage 加载 .efi 文件至内存并生成 Image
StartImage 启动 Image,调用 Image 的入口函数
Exit 退出Image
UnloadImage 卸载Image
7 ExitBootServices

ExitBootService 用于结束启动服务,该服务成功返回后,系统进入 RT 期。操作系统加载器从启动服务接过对计算机系统的控制权后必须调用该服务

8 其他服务

启动服务中的其他服务

服务名 作用
InstallConfigurationTable 增加、更新、删除系统配置表项
GetNextMonotonicCount 获得系统单调计数器的下一个值
Stall 暂停 CPU 指定的微秒数
SetWatchdogTimer 设置看门狗定时器(指定的时间内若无系统反应,则重启)
CalculateCrc32 计算 CRC32 校验码
CopyMem 复制内存
SetMem 设置指定内存区域的值

运行时服务

从进入DXE阶段运行时服务被初始化,直到操作系统结束,运行时服务都一直存在并向上层(操作系统,操作系统加载器,UEFI应用程序或者UEFI驱动)提供服务。运行时服务主要包括:

  • 时间服务
  • 读写系统变量
  • 虚拟内存服务
  • 其他服务。
1 时间服务

时间服务包括:读取/设置硬件事件、读取/设置唤醒定时器。
GetTime/SetTime
计算机硬件时钟由单独的电池供电,操作系统启动时通过读取硬件时钟获得事件。


//file: MdePkg\Include\Uefi\UefiSpec.h
/**
  Returns the current time and date information, and the time-keeping capabilities
  of the hardware platform.

  @param[out]  Time             A pointer to storage to receive a snapshot of the current time.
  @param[out]  Capabilities     An optional pointer to a buffer to receive the real time clock
                                device's capabilities.

  @retval EFI_SUCCESS           The operation completed successfully.  
  @retval EFI_INVALID_PARAMETER Time is NULL.
  @retval EFI_DEVICE_ERROR      The time could not be retrieved due to hardware error.

**/
typedef
EFI_STATUS
(EFIAPI *EFI_GET_TIME)(
  OUT  EFI_TIME                    *Time,   //当前时间
  OUT  EFI_TIME_CAPABILITIES       *Capabilities OPTIONAL  // 时钟硬件的性能
  );

/**
  Sets the current local time and date information.

  @param[in]  Time              A pointer to the current time.

  @retval EFI_SUCCESS           The operation completed successfully.
  @retval EFI_INVALID_PARAMETER A time field is out of range.
  @retval EFI_DEVICE_ERROR      The time could not be set due due to hardware error.

**/
typedef
EFI_STATUS
(EFIAPI *EFI_SET_TIME)(
  IN  EFI_TIME                     *Time
  );

标签:Protocol,服务,Image,编程,EFI,UEFI,原理,pointer
From: https://www.cnblogs.com/linhaostudy/p/18408639

相关文章

  • 最大熵原理[解释+例题]
    1熵的概念熵是热力学中的一个概念,由香浓引入到信息论中。在信息论中,熵是衡量随机变量不确定性的量度,熵越大表示随机变量的不确定性越大,即随机变量越难以预测。2熵的计算信息熵的计算可以看笔者的博客:点此跳转。3最大熵原理定义最大熵原理是一种选择随机变量统计特性最符......
  • 【PHP编程】PHP闭包函数及函数回调的实现方式
    https://mp.weixin.qq.com/s/ji6hofCun7w7ErRvLuAiuA原创PHP星编程经验共享2023年10月19日08:01广东1.匿名函数在了解回调函数之前我们来了解一下什么是匿名函数?顾名思义,匿名函数就是一个没有确定函数名的函数,PHP将匿名函数和闭包视作相同的概念,所以匿名函数在PHP中......
  • 并发编程 - NSOperation&NSOperationQueue(多线程)
    ​​​​​​​并发编程-概述-CSDN博客并发编程-GCD的任务和队列-CSDN博客并发编程-NSOperation&NSOperationQueue(多线程)-CSDN博客并发编程-NSThread-CSDN博客引言在上篇博客中我们首先介绍了GCD的多线程方案,NSOperation和NSOperationQueue是Apple为我们提供的......
  • Java语言程序设计基础篇_编程练习题*18.10 (字符串中某个指定字符出现的次数)
    目录题目:*18.10(字符串中某个指定字符出现的次数)习题思路代码示例 输出结果题目:*18.10(字符串中某个指定字符出现的次数)  编写一个递归方法,使用下面的方法头给出一个指定字符在字符串中出现的次数。publicstaticintcount(Stringstr,chara) 例如,coun......
  • Java中的元编程:使用反射与代理模式实现代码的动态增强
    Java中的元编程:使用反射与代理模式实现代码的动态增强大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在Java开发中,元编程是指在程序运行时对程序进行修改和扩展的技术。反射和代理模式是实现Java元编程的两种常用技术。本文将探讨如何使用反射与代理......
  • 零基础国产GD32单片机编程入门(十六)DMA详解及ADC-DMA方式采集含源码
    文章目录一.概要二.GD32F103C8T6单片机DMA外设特点三.GD32单片机DMA内部结构图四.DMA各通道请求五.GD32F103C8T6单片机ADC-DMA采集例程六.工程源代码下载七.小结一.概要基本概念:DMA是DirectMemoryAccess的首字母缩写,是一种完全由硬件执行数据交换的工作方式。DM......
  • 编程工具:提升效率的利器
    哪个编程工具让你的工作效率翻倍?在当今快节奏的软件开发环境中,选择合适的编程工具对于提高工作效率至关重要。方向一:工具介绍我常用的编程工具之一是PyCharm。它是一款专为Python开发而设计的集成开发环境(IDE)。其功能特点包括强大的代码自动完成、语法检查、调试工具......
  • ①MODBUS TCP 通信单元(MODBUS TCP 转 RS485)Modbus TCP转Modbus RTU/ASCII网关同步采集
    ModbusTCP转ModbusRTU/ASCII网关同步采集无需编程高速轻松组网MS-A1-50X1系列作为MODBUSTCP通信的服务器进行动作。可通过MODBUSTCP通信,将MS-A1-50X1系列产品通过RS485采集的仪器仪表之类的值作为通信数据输出到PLC,上位机等。系统配置概述使用MS-A1-50X1系......
  • 【高级编程】Java IO流(补)序列化 & 反序列化
    序列化(ObjectOutputStream)&反序列化(ObjectInputStream)Java的序列化和反序列化是用于将对象转换为字节流的过程,以便在网络上传输或保存到磁盘,然后将这些字节流再转换回对象。这个过程是Java中处理对象持久化和传输的常见方法。序列化是将对象的状态转换为字节流的过......
  • 【高级编程】Java IO流(下)字符流 Reader Writer 字节流读取二进制文件
    文章目录ReaderFileReaderBufferedReaderWriterFileWriterBufferedWriter读写二进制文件ReaderReader是一个抽象类,用于读取字符流。它是所有字符输入流的基类。Reader提供了一些基本的方法来读取字符数据intread()//读取单个字符,并返回一个整数。如果到达流......