系统表

对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
);

UEFI原理与编程(二)的更多相关文章

  1. 【读书笔记】UEFI原理与编程(1)概述及开发环境的搭建

    一.概述: 0.为什么会有这篇文章 说实在的,在2016初的时候,我就萌生了写一个操作系统的念头,但是这对于我一个菜鸟来说,犹如登天. 既然想了就去写,即使最后做不完,也不后悔. 抱着这样的念头,我开 ...

  2. 【原创】高性能网络编程(二):上一个10年,著名的C10K并发连接问题

    1.前言 对于高性能即时通讯技术(或者说互联网编程)比较关注的开发者,对C10K问题(即单机1万个并发连接问题)应该都有所了解."C10K"概念最早由Dan Kegel发布于其个人 ...

  3. trident原理及编程指南

    目录 trident原理及编程指南 一.理论介绍 1.trident是什么? 2.trident处理单位 3.事务类型 二.编程指南 1.定义输入流 2.统计单词数量 3.输出统计结果 4.split ...

  4. Spring事务原理分析-部分二

    Spring事务原理分析-部分二 说明:这是我在蚂蚁课堂学习了余老师Spring手写框架的课程的一些笔记,部分代码代码会用到余老师的课件代码.这不是广告,是我听了之后觉得很好. 课堂链接:Spring ...

  5. 超级干货:动态防御WAF技术原理及编程实战!

    本文带给大家的内容是动态防御WAF的技术原理及编程实战. 将通过介绍ShareWAF的核心技术点,向大家展示动态防御的优势.实现思路,并以编程实战的方式向大家展示如何在WAF产品开发过程中应用动态防御 ...

  6. Linux shell脚本编程(二)

    Linux shell脚本编程(二) 练习:求100以内所有偶数之和; 使用至少三种方法实现; 示例1: #!/bin/bash # declare -i sum=0 #声明一个变量求和,初始值为0 ...

  7. Java并发编程二三事

    Java并发编程二三事 转自我的Github 近日重新翻了一下<Java Concurrency in Practice>故以此文记之. 我觉得Java的并发可以从下面三个点去理解: * ...

  8. Python进阶之面向对象编程(二)

    Python面向对象编程(二) .note-content {font-family: "Helvetica Neue",Arial,"Hiragino Sans GB& ...

  9. Linux网络编程(二)

    Linux网络编程(二) 使用多进程实现服务器并发访问. 采用多进程的方式实现服务器的并发访问的经典范例. 程序实现功能: 1.客户端从标准输入读入一行文字,发送到服务器. 2.服务器接收到客户端发来 ...

  10. java GUI编程二

    java基础学习总结--GUI编程(二) 一.事件监听 测试代码一: 1 package cn.javastudy.summary; 2 3 import java.awt.*; 4 import j ...

随机推荐

  1. Python和RPA网页自动化-让非标准下拉框选择指定文本的方法

    以下方"节点审批"下拉框为例 该下拉框没有<select>标签,而是<div><ul><li>标签.分别使用Python和RPA网页 ...

  2. 【RabbitMQ】06 Spring整合RabbitMQ

    首先生产者和消费者需要的Maven依赖是一样的 <?xml version="1.0" encoding="UTF-8"?> <project ...

  3. PVE linux_VM 扩容分区

    页面 调整磁盘大小 手动分区 fdisk -l fdisk /dev/sda 对该磁盘进行分区, 输入n并回车,n是"new"新建分区 [root@localhost ~]# fd ...

  4. LVGL btn组件

    /************************************************* * * file name:widget_line.c * author :momolyl@126 ...

  5. java如何保证一个方法只能执行一次

    我们经常会遇到一些情况需要某一个方法或者操作只执行一次,比如说配置信息加载,如果配置信息需要动态刷新,这个不在适用范围.下面列举几种方式 第一种 如果是web容器,可以使用servlet或者Liste ...

  6. Linux信号量(1)-SYSTEM V

    ​ 信号量概念 信号量本质上是一个计数器(不设置全局变量是因为进程间是相互独立的,而这不一定能看到,看到也不能保证++引用计数为原子操作),用于多进程对共享数据对象的读取,它和管道有所不同,它不以传送 ...

  7. WCF实例管理

    实例管理是对WCF使用的一系列技术的总称,通过它可以将客户端的请求绑定到服务实例上,并根据客户端请求的类型以确定服务实例的管理方式.由于应用程序在可扩展,性能,吞吐量,事物与对垒调用等方面存在巨大的差 ...

  8. WIN32下的模拟时钟

    #include <Windows.h> #include <math.h> #include <tchar.h> #include "resource. ...

  9. Python的OpenCV转换图像大小

    在Python中,使用OpenCV库来转换图像大小是一个常见的操作,它可以帮助你调整图像到特定的尺寸,以适应不同的应用场景,比如图像预处理.模型输入等.下面是一个详细的代码示例,展示了如何使用Open ...

  10. Elementui 给输入框加上单位

    效果图: 具体代码: <el-input class="el-col-12" v-model="value.projectLevel" :disabled ...