uefi 内存管理

news2025/1/22 18:50:49

PEI 阶段

PEI 阶段最为重要的结构是HOB, 初始化内存服务前,PEI 申请的内存其实是插入到FV 文件

也就是FLASH 里面去运行。

在此状态下,FLASH 可读不可写,所以是不能使用全局变量的。如果有需要模块间共享信息,需要申请HOB.

HOB 拥有以下类型

//
// HobType of EFI_HOB_GENERIC_HEADER.
//
#define EFI_HOB_TYPE_HANDOFF              0x0001
#define EFI_HOB_TYPE_MEMORY_ALLOCATION    0x0002
#define EFI_HOB_TYPE_RESOURCE_DESCRIPTOR  0x0003
#define EFI_HOB_TYPE_GUID_EXTENSION       0x0004
#define EFI_HOB_TYPE_FV                   0x0005
#define EFI_HOB_TYPE_CPU                  0x0006
#define EFI_HOB_TYPE_MEMORY_POOL          0x0007
#define EFI_HOB_TYPE_FV2                  0x0009
#define EFI_HOB_TYPE_LOAD_PEIM_UNUSED     0x000A
#define EFI_HOB_TYPE_UEFI_CAPSULE         0x000B
#define EFI_HOB_TYPE_FV3                  0x000C
#define EFI_HOB_TYPE_UNUSED               0xFFFE
#define EFI_HOB_TYPE_END_OF_HOB_LIST      0xFFFF

HANDOFF 是第一个hob. 我们平常看代码

DXE 阶段就更丰富一些,像

memory allocation acpi 指向黄色区域,一会传到dxe. dxe 就知道pei 用了之方面的内存。

蓝色的空间,比较重要的一个地方, dxe core 优先考虑放DXE CORE.

HOB 是完全连续的,会不断的在free space 里面追加,无法删除。

Allocatepool 函数的本质就是在上面添加类型为efi_hob_type_memory_pool 的hob.

GCD 

global coherency domain, 中文译名为全局一致域。它管理pei 通过hob 传递过来的系统资源。从功能 上讲,分为管理存储空间的gcd memory space 和管理io 两部分服务。通过这两种服务,系统资源可以被添加,删除,使用。

GCD 初始化

在DXE 阶段刚刚开始时,dxe 主函数调用coreinitiallizegcdservices 函数初始始化gcd 视图

根据cpu hob 信息,初始gcd mem 视图与Io 视图的初始化空间

根据resource descriptor hob 信息, 细化视图结构

将已经使用的内存和dxe 即将使用的内存设置为已经分配状态

调用coregetmemoryspacemap 获得所有gcd 存储空间描述符,遍历它,将剩下的,没分配的系统内存申请出来,作为内存管理中的可分配内存。

/**
  Internal function.  Inserts a new descriptor into a sorted list

  @param  Link                   The linked list to insert the range BaseAddress
                                 and Length into
  @param  Entry                  A pointer to the entry that is inserted
  @param  BaseAddress            The base address of the new range
  @param  Length                 The length of the new range in bytes
  @param  TopEntry               Top pad entry to insert if needed.
  @param  BottomEntry            Bottom pad entry to insert if needed.

  @retval EFI_SUCCESS            The new range was inserted into the linked list

**/
EFI_STATUS
CoreInsertGcdMapEntry (
  IN LIST_ENTRY           *Link,
  IN EFI_GCD_MAP_ENTRY     *Entry,
  IN EFI_PHYSICAL_ADDRESS  BaseAddress,
  IN UINT64                Length,
  IN EFI_GCD_MAP_ENTRY     *TopEntry,
  IN EFI_GCD_MAP_ENTRY     *BottomEntry
  )
{
  ASSERT (Length != 0);

  if (BaseAddress > Entry->BaseAddress) {
    ASSERT (BottomEntry->Signature == 0);

    CopyMem (BottomEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY));
    Entry->BaseAddress      = BaseAddress;
    BottomEntry->EndAddress = BaseAddress - 1;
    InsertTailList (Link, &BottomEntry->Link);
  }

  if ((BaseAddress + Length - 1) < Entry->EndAddress) {
    ASSERT (TopEntry->Signature == 0);

    CopyMem (TopEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY));
    TopEntry->BaseAddress = BaseAddress + Length;
    Entry->EndAddress     = BaseAddress + Length - 1;
    InsertHeadList (Link, &TopEntry->Link);
  }

  return EFI_SUCCESS;
}

从这个过程可以看出两点,一是GCD使用链表管理,二是这个链表是严格按从高地址到低地址的方式排列的。

根据这个特性,根据地址和长度寻找对应资源节点时(CoreSearchGcdMapEntry函数),可以按记录的base 顺序查找,当然,由于长度没有限制,可以横跨多个节点,返回它们的头切点和尾节点。

基于这个函数构成了以下的GCD 管理函数。

coreconvertspace : 对GCD 视图中指定区域进行添加,删除和修改属性。

coreallocatespace: 分配新的gcd 结点。

内存服务:

内存类型

/// Enumeration of memory types introduced in UEFI.
///
typedef enum {
  ///
  /// Not used.
  ///
  EfiReservedMemoryType,
  ///
  /// The code portions of a loaded application.
  /// (Note that UEFI OS loaders are UEFI applications.)
  ///
  EfiLoaderCode,
  ///
  /// The data portions of a loaded application and the default data allocation
  /// type used by an application to allocate pool memory.
  ///
  EfiLoaderData,
  ///
  /// The code portions of a loaded Boot Services Driver.
  ///
  EfiBootServicesCode,
  ///
  /// The data portions of a loaded Boot Serves Driver, and the default data
  /// allocation type used by a Boot Services Driver to allocate pool memory.
  ///
  EfiBootServicesData,
  ///
  /// The code portions of a loaded Runtime Services Driver.
  ///
  EfiRuntimeServicesCode,
  ///
  /// The data portions of a loaded Runtime Services Driver and the default
  /// data allocation type used by a Runtime Services Driver to allocate pool memory.
  ///
  EfiRuntimeServicesData,
  ///
  /// Free (unallocated) memory.
  ///
  EfiConventionalMemory,
  ///
  /// Memory in which errors have been detected.
  ///
  EfiUnusableMemory,
  ///
  /// Memory that holds the ACPI tables.
  ///
  EfiACPIReclaimMemory,
  ///
  /// Address space reserved for use by the firmware.
  ///
  EfiACPIMemoryNVS,
  ///
  /// Used by system firmware to request that a memory-mapped IO region
  /// be mapped by the OS to a virtual address so it can be accessed by EFI runtime services.
  ///
  EfiMemoryMappedIO,
  ///
  /// System memory-mapped IO region that is used to translate memory
  /// cycles to IO cycles by the processor.
  ///
  EfiMemoryMappedIOPortSpace,
  ///
  /// Address space reserved by the firmware for code that is part of the processor.
  ///
  EfiPalCode,
  ///
  /// A memory region that operates as EfiConventionalMemory,
  /// however it happens to also support byte-addressable non-volatility.
  ///
  EfiPersistentMemory,
  EfiMaxMemoryType
} EFI_MEMORY_TYPE;

POOL

与PEI 类似, DXE 中管理内存用的也是pool 和page.

pool

申请空间的碎片化资源,每个类型有一长串的pool 头节点,代表粒度从低到高,后面再跟着可使用的节点,类似于一个二次链表

每次要申请空间都会去找对应长度和对应类型的pool 是否有free 的节点。有就用,没有就申请一页内存把它拆成Pool, 被用的直接用掉,没被用的送进free.

//
// Each element is the sum of the 2 previous ones: this allows us to migrate
// blocks between bins by splitting them up, while not wasting too much memory
// as we would in a strict power-of-2 sequence
//
STATIC CONST UINT16 mPoolSizeTable[] = {
  128, 256, 384, 640, 1024, 1664, 2688, 4352, 7040, 11392, 18432, 29824
};

这个是pool 的粒度。每一数都是前两个数的和。

page 

与pool 对应,page 是被申请出来的整页内存,按uefi 规范,一页的大小为4k.

内存预分配

在内核初始化时,内核通过配置表拿到bios的内存布局,根据内存布局完成内核的初始始内存配置。

对于rt 类内存,内核认为bios 可能会使用,将其标记为保留

对于bs 类内存,内核认为bios 不会使用,将其收入可使用空间

比较特殊的是efiacpireclaimmemory类型内存,此段内存用于存储bios 传给内核的acpi表,在内核初始化acpi 后,将此段空间释放。

内存预分配如何实现

1 在 PEI 阶段,构造GUI HOB(HOB 内容可来自PCD 或VARIABLE 变量区)

2 DXE 初始化内存状态,调用COREADDMEMROYDESCRIPTOR 函数,如果此函数是第一次被调用,进入内存预分配流程。

3 BDS 结束后,会调用函数统一具体内存使用情况,将估算后的值填回VARIABLE(为保证S4, 应设置更新内容后重启)。

gMemoryMap

gMemoryMap 链表是内存管理的另一重要结构

这个结构有些类似于GCD, 甚至插入删除的写法都与GCD类似,可以直观的看出当前系统内存的情况和属性

GCD 和内存管理有什么关系呢?

PromoteMemoryResource

转换GCD已初始化但未测试的部分转换进动态存储空间

找到属性为EfiGcdMemoryTypeReserver, 已经初始化但未测试的部分,修改它的节点属性,调用CoreAddRange将资源放入mMapStack空间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/414086.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

gtkmm给组件添加css

设置方式 使用CSS分为两步&#xff0c;1:为组件设这css名称&#xff0c;2:加载样式表。 样式表我们写在文件中就行&#xff08;似乎也可以从字符串加载&#xff0c;不过不推荐&#xff09;。 1. 设置css名称 使用gtk的接口&#xff1a;gtk_widget_class_set_css_name()。 这…

rk3568点亮E-ink

rk3568 Android11/12 适配 E-ink “EINK”是英语ElectronicInk的缩写。翻译成中文为“电子墨水”。电子墨水由数百万个微胶囊(Microcapsules)所构成&#xff0c;微胶囊的大小约等同于人类头发的直径。每个微胶囊里含有电泳粒子──带负电荷的白色以及带正电荷的黑色粒子&#…

Ubuntu 交叉编译Windows 版本的ffmpeg最佳实践

之前介绍在Windows上采用msys2+minGW或者cygwin在Windows编译方法。很多读者觉得在Windows搭建一个类Linux比较麻烦或者说方法不够通用,本文就介绍在流行的Linux发行版Ubuntu上编译window版本的ffmpeg。即介绍一种通用办法来编译Windows版本ffmpeg,该方法可以推广到android,…

算法 贪心4 || 860.柠檬水找零 406.根据身高重建队列 452. 用最少数量的箭引爆气球

860.柠檬水找零 很简单的一题&#xff0c;完全是常识题 class Solution { public:bool lemonadeChange(vector<int>& bills) {unordered_map<int,int> map;for(int i 0; i < bills.size(); i){map[bills[i]];if(bills[i] ! 5){if(map[5] 0) return fals…

【Linux】程序中获取和设置cpu和mem相关信息

这里是目录一、CPU和MEM信息1.1、CPU信息1.1.1、CPU核心数1.1.2、CPU频率读取和调整1.1.3、CPU温度1.2、MEM信息二、C程序读取CPU和MEM信息三、测试写在前面&#xff1a; 记录一下日常&#xff0c;之前有做过相关工作&#xff0c;但是没有记录下来&#xff0c;因此写一写文章。…

使用hbuilder连接夜神模拟器调试app

1. Hbuilder设置 这里端口号随便用一个没有被占用的&#xff1b; 路径夜神模拟器的安装路径下的nox_adb.exe的路径。 2. 夜神模拟器设置 设置如下&#xff1a; 工具&#xff0c;设置&#xff0c;关于平板电脑&#xff08;这里应该没有开发者模式选项&#xff0c;这是我配好之…

【LeetCode】剑指 Offer 53. 在排序数组中查找数字 p263 -- Java Version

1. 题目介绍&#xff08;53. 在排序数组中查找数字&#xff09; 面试题53&#xff1a;在排序数组中查找数字 一共分为三小题&#xff1a; 题目一&#xff1a;数字在排序数组中出现的次数题目二&#xff1a;0 ~ n-1 中缺失的数字题目三&#xff1a;数组中数值和下标相等的元素 2…

【创作赢红包】面向对象基础概念

什么是面向对象 面向对象&#xff08;Object Oriented&#xff09;是软件开发方法&#xff0c;一种编程范式&#xff0c;它是一种对现实世界理解和抽象的方法&#xff0c;是计算机编程技术发展到一定阶段后的产物。 早期的计算机编程是基于面向过程的方法&#xff0c;如实现算…

前端工程化:环境准备—NodeJs安装-Vue项目开发流程

一、前端工程化-Yapi 介绍&#xff1a;YApi 是高效、易用、功能强大的 api 管理平台&#xff0c;旨在为开发、产品、测试人员提供更优雅的接口管理服务 地址&#xff1a; http://yapi.smart-xwork.cn/ 具体操作步骤&#xff1a; 1、添加项目 2、添加接口&#xff1a;根据ID查…

技术分享 | observer 资源水位介绍

作者&#xff1a;郭斌斌 爱可生 DBA 团队成员&#xff0c;负责项目日常问题处理及公司平台问题排查。 本文来源&#xff1a;原创投稿 *爱可生开源社区出品&#xff0c;原创内容未经授权不得随意使用&#xff0c;转载请联系小编并注明来源。 OceanBase 集群界面会展示 Observer …

MATLAB绘制柱状/饼图填充图

MATLAB绘制柱状填充图方法1&#xff1a;hatchfill2工具1.1 案例1&#xff1a;柱状图填充1.2 案例2&#xff1a;饼图填充方法2&#xff1a;applyhatch函数2.1 案例1&#xff1a;柱状图填充2.2 案例2&#xff1a;饼图填充方法3&#xff1a; applyhatch_plusC函数3.1 案例1&#x…

Python 小型项目大全 31~35

三十一、猜数字 原文&#xff1a;http://inventwithpython.com/bigbookpython/project31.html 猜数字是初学者练习基本编程技术的经典游戏。在这个游戏中&#xff0c;电脑会想到一个介于 1 到 100 之间的随机数。玩家有 10 次机会猜出数字。每次猜中后&#xff0c;电脑会告诉玩…

Java实现ArrayList和底层源码讲解

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了 博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点!人生格言&#xff1a;当你的才华撑不起你的野心的时候,你就应该静下心来学习! 欢迎志同道合的朋友一起加油喔&#x1f9be;&am…

Centos7安装MySQL5.7.30

文章目录1. 环境准备1.1 卸载mariadb1.2 下载MySQL 5.7.301.3 安装MySQL依赖项1.4 创建目录1.5 创建用户和用户组1.6 修改Mysql用户权限2. 安装MySQL2.1 解压2.2 修改解压目录名称2.3 初始化2.4 添加my.cnf异常找不到Sock文件2.5 启动MySQL服务2.5.1 建立软连接2.5.2 启动2.6 设…

TCP协议工作机制二(滑动窗口,流量控制,拥塞控制,延时应答,捎带应答等)

目录 滑动窗口 流量控制 拥塞控制 延时应答 捎带应答 面向字节流 异常情况 UDP和TCP对比 滑动窗口 由于TCP是可靠传输,有确认应答,超时重传,连接管理等机制,发送消息时需要等待接收方返回的ack.因此会消耗大量等待ack的时间,我们引入滑动窗口的机制来竭尽可能提高TCP的…

基于支持向量机的Digits手写数字识别

基于支持向量机的Digits手写数字识别 描述 支持向量机&#xff08;Support Vector Machine&#xff0c;简称SVM&#xff09;模型既可以用于分类也可以用于回归。手写数字识别是一个多分类问题&#xff08;判断一张手写数字图片是0~9中的哪一个&#xff09;&#xff0c;数据集…

图片英文翻译成中文转换器-中文翻译英文软件

您正在准备一份重要的英文资料或文件&#xff0c;但是您还不是很熟练地掌握英文&#xff0c;需要翻译才能完成您的任务吗&#xff1f;哪个软件能够免费把英文文档翻译成中文&#xff1f;让我们带您了解如何使用我们的翻译软件来免费翻译英文文档为中文。 我们的翻译软件是一款功…

C风格的字符串赋值方式

文章目录&#xff08;1&#xff09;C语言中&#xff0c;没有字符串类型但可以用字符数组模拟字符串。&#xff08;2&#xff09;C语言中&#xff0c;字符串是以’\0’作结尾字符。&#xff08;3&#xff09;C语言中&#xff0c;字符串常量本质上是一个无名的字符数组。C风格的字…

使用Spring JDBC中的JdbcTemplate对数据进行增删改查操作教程~

jdbcTemplate实现添加数据功能&#xff1a; spring框架对jdbc框架进行封装&#xff0c;使用jdbcTemplate方便实现对数据库的操作 数据库准备工作&#xff1a; 在已有数据库中创建新的表&#xff1a; create table t_user (id int,username varchar(20),password varchar(20…

搜索词分析工具-网站关键词挖掘

怎么能找到行业的关键词 以下是如何找到行业关键词的建议&#xff1a; 了解行业&#xff1a;要找到与行业相关的关键词&#xff0c;首先需要了解行业。了解行业以及核心目标&#xff0c;从而更好地理解行业中的主题和词汇。 找到竞争对手网站&#xff1a;搜索竞争对手的网站&…