ACPI之 系统地址映射接口

2023-10-10 20:18

本文主要是介绍ACPI之 系统地址映射接口,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目前有三种方法将内存映射告诉OSPM,

1 . 通过 BIOS INT 15.

2. UEFI 通过GetMemoryMap()  boot service 告诉OS loader, 然后OS loader 告诉OSPM.

3. 如果内存资源被动态的增加或删除,我们可以通过定义在ACPI 名字空间里的内存设备去表达出来。


ACPI 定义了五种范围: AdddressRangeMemory, AddressRangeACPI, AddressRangeNVS, 

AddressRangeUnusable, AddressRangeReserved.


valueMnemonic  助记符Description
1AddressRangeMemory这一段内存是可以供操作系统使用的
2AddressRangeReserved这一段内存已经被用了,或者保留起来的,不被OS的memory manager去分配
3AddressRangeACPI当OS 读过ACPI 表之后,就可使用的一段范围
4AddressRangeNVSACPI NVS 内存,这一段内存已经被用了或者保留起来,是不能被OS去用的
5AddressRangeUnusuable这是一段不能有的地址,因为检测到了错误
6AddressRangeDisabled一段没有被enabled的地址, 也是ospm 不可以用的
其他Undefined未定义,保留或者将来用。

BIOS 用AddressRangeReserved 把某些地址屏蔽起来,不给可编程器件去用,出于下列这些原因:

 1  这段地址包含了system BIOS.

 2 The address range contains RAM in use by the ROM.

 3. 这段地址被memory-mapped device 使用了

  4. 出于其他任何一种原因,不适合给standard device 作为memory space 用

  5. 这一段地址范围位于NVRAM device里面,往这些设备去读写,不一定成功

   5. The address range is within an NVRAM device where reads and writes to memory locations are

        no longer successful, that is, the deice was worn out.



UEFI GetMemoryMap() Boot Service Function

EFI 使用 GetMemoryMap() boot services 这个函数将内存资源的情况告诉OS loader,  后续OS loader 一定要将这个信息传给OSPM.


GetMemoryMap 这个函数只存在于boot service 这段时间,boot time service 和 run time service 之间的界限在于ExitBootServices()  函数的执行。


GetMemoryMap() 返回一个数组,里面放着内存描述符。 这些内存描述符定义了所有安装在板子上的RAM.


每一个描述符,有这么一个成员,去标示(dictate) OS 应该怎么对待这段区域。


/**This function returns a copy of the current memory map. The map is an array ofmemory descriptors, each of which describes a contiguous block of memory.@param  MemoryMapSize          A pointer to the size, in bytes, of theMemoryMap buffer. On input, this is the size ofthe buffer allocated by the caller.  On output,it is the size of the buffer returned by thefirmware  if the buffer was large enough, or thesize of the buffer needed  to contain the map ifthe buffer was too small.@param  MemoryMap              A pointer to the buffer in which firmware placesthe current memory map.@param  MapKey                 A pointer to the location in which firmwarereturns the key for the current memory map.@param  DescriptorSize         A pointer to the location in which firmwarereturns the size, in bytes, of an individualEFI_MEMORY_DESCRIPTOR.@param  DescriptorVersion      A pointer to the location in which firmwarereturns the version number associated with theEFI_MEMORY_DESCRIPTOR.@retval EFI_SUCCESS            The memory map was returned in the MemoryMapbuffer.@retval EFI_BUFFER_TOO_SMALL   The MemoryMap buffer was too small. The currentbuffer size needed to hold the memory map isreturned in MemoryMapSize.@retval EFI_INVALID_PARAMETER  One of the parameters has an invalid value.**/
EFI_STATUS
EFIAPI
CoreGetMemoryMap (IN OUT UINTN                  *MemoryMapSize,IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,OUT UINTN                     *MapKey,OUT UINTN                     *DescriptorSize,OUT UINT32                    *DescriptorVersion)
{EFI_STATUS                        Status;UINTN                             Size;UINTN                             BufferSize;UINTN                             NumberOfEntries;LIST_ENTRY                        *Link;MEMORY_MAP                        *Entry;EFI_GCD_MAP_ENTRY                 *GcdMapEntry;EFI_MEMORY_TYPE                   Type;EFI_MEMORY_DESCRIPTOR             *MemoryMapStart;//// Make sure the parameters are valid//if (MemoryMapSize == NULL) {return EFI_INVALID_PARAMETER;}CoreAcquireGcdMemoryLock ();//// Count the number of Reserved and runtime MMIO entries// And, count the number of Persistent entries.//NumberOfEntries = 0;for (Link = mGcdMemorySpaceMap.ForwardLink; Link != &mGcdMemorySpaceMap; Link = Link->ForwardLink) {GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);if ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypePersistentMemory) || (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) ||((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) &&((GcdMapEntry->Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME))) {NumberOfEntries ++;}}Size = sizeof (EFI_MEMORY_DESCRIPTOR);//// Make sure Size != sizeof(EFI_MEMORY_DESCRIPTOR). This will// prevent people from having pointer math bugs in their code.// now you have to use *DescriptorSize to make things work.//Size += sizeof(UINT64) - (Size % sizeof (UINT64));if (DescriptorSize != NULL) {*DescriptorSize = Size;}if (DescriptorVersion != NULL) {*DescriptorVersion = EFI_MEMORY_DESCRIPTOR_VERSION;}CoreAcquireMemoryLock ();//// Compute the buffer size needed to fit the entire map//BufferSize = Size * NumberOfEntries;for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {BufferSize += Size;}if (*MemoryMapSize < BufferSize) {Status = EFI_BUFFER_TOO_SMALL;goto Done;}if (MemoryMap == NULL) {Status = EFI_INVALID_PARAMETER;goto Done;}//// Build the map//ZeroMem (MemoryMap, BufferSize);MemoryMapStart = MemoryMap;for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) {Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);ASSERT (Entry->VirtualStart == 0);//// Convert internal map into an EFI_MEMORY_DESCRIPTOR//MemoryMap->Type           = Entry->Type;MemoryMap->PhysicalStart  = Entry->Start;MemoryMap->VirtualStart   = Entry->VirtualStart;MemoryMap->NumberOfPages  = RShiftU64 (Entry->End - Entry->Start + 1, EFI_PAGE_SHIFT);//// If the memory type is EfiConventionalMemory, then determine if the range is part of a// memory type bin and needs to be converted to the same memory type as the rest of the// memory type bin in order to minimize EFI Memory Map changes across reboots.  This// improves the chances for a successful S4 resume in the presence of minor page allocation// differences across reboots.//if (MemoryMap->Type == EfiConventionalMemory) {for (Type = (EFI_MEMORY_TYPE) 0; Type < EfiMaxMemoryType; Type++) {if (mMemoryTypeStatistics[Type].Special                        &&mMemoryTypeStatistics[Type].NumberOfPages > 0              &&Entry->Start >= mMemoryTypeStatistics[Type].BaseAddress    &&Entry->End   <= mMemoryTypeStatistics[Type].MaximumAddress) {MemoryMap->Type = Type;}}}MemoryMap->Attribute = Entry->Attribute;if (MemoryMap->Type < EfiMaxMemoryType) {if (mMemoryTypeStatistics[MemoryMap->Type].Runtime) {MemoryMap->Attribute |= EFI_MEMORY_RUNTIME;}}//// Check to see if the new Memory Map Descriptor can be merged with an // existing descriptor if they are adjacent and have the same attributes//MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size);}for (Link = mGcdMemorySpaceMap.ForwardLink; Link != &mGcdMemorySpaceMap; Link = Link->ForwardLink) {GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);if ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) ||((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) &&((GcdMapEntry->Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME))) {// // Create EFI_MEMORY_DESCRIPTOR for every Reserved and runtime MMIO GCD entries//MemoryMap->PhysicalStart = GcdMapEntry->BaseAddress;MemoryMap->VirtualStart  = 0;MemoryMap->NumberOfPages = RShiftU64 ((GcdMapEntry->EndAddress - GcdMapEntry->BaseAddress + 1), EFI_PAGE_SHIFT);MemoryMap->Attribute     = GcdMapEntry->Attributes & ~EFI_MEMORY_PORT_IO;if (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) {MemoryMap->Type = EfiReservedMemoryType;} else if (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) {if ((GcdMapEntry->Attributes & EFI_MEMORY_PORT_IO) == EFI_MEMORY_PORT_IO) {MemoryMap->Type = EfiMemoryMappedIOPortSpace;} else {MemoryMap->Type = EfiMemoryMappedIO;}}//// Check to see if the new Memory Map Descriptor can be merged with an // existing descriptor if they are adjacent and have the same attributes//MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size);}if (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypePersistentMemory) {// // Create EFI_MEMORY_DESCRIPTOR for every Persistent GCD entries//MemoryMap->PhysicalStart = GcdMapEntry->BaseAddress;MemoryMap->VirtualStart  = 0;MemoryMap->NumberOfPages = RShiftU64 ((GcdMapEntry->EndAddress - GcdMapEntry->BaseAddress + 1), EFI_PAGE_SHIFT);MemoryMap->Attribute     = GcdMapEntry->Attributes | EFI_MEMORY_NV;MemoryMap->Type          = EfiPersistentMemory;//// Check to see if the new Memory Map Descriptor can be merged with an // existing descriptor if they are adjacent and have the same attributes//MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size);}}//// Compute the size of the buffer actually used after all memory map descriptor merge operations//BufferSize = ((UINT8 *)MemoryMap - (UINT8 *)MemoryMapStart);Status = EFI_SUCCESS;Done://// Update the map key finally//if (MapKey != NULL) {*MapKey = mMemoryMapKey;}CoreReleaseMemoryLock ();CoreReleaseGcdMemoryLock ();*MemoryMapSize = BufferSize;return Status;
}



这篇关于ACPI之 系统地址映射接口的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

golang程序打包成脚本部署到Linux系统方式

《golang程序打包成脚本部署到Linux系统方式》Golang程序通过本地编译(设置GOOS为linux生成无后缀二进制文件),上传至Linux服务器后赋权执行,使用nohup命令实现后台运行,完... 目录本地编译golang程序上传Golang二进制文件到linux服务器总结本地编译Golang程序

Linux系统性能检测命令详解

《Linux系统性能检测命令详解》本文介绍了Linux系统常用的监控命令(如top、vmstat、iostat、htop等)及其参数功能,涵盖进程状态、内存使用、磁盘I/O、系统负载等多维度资源监控,... 目录toppsuptimevmstatIOStatiotopslabtophtopdstatnmon

linux重启命令有哪些? 7个实用的Linux系统重启命令汇总

《linux重启命令有哪些?7个实用的Linux系统重启命令汇总》Linux系统提供了多种重启命令,常用的包括shutdown-r、reboot、init6等,不同命令适用于不同场景,本文将详细... 在管理和维护 linux 服务器时,完成系统更新、故障排查或日常维护后,重启系统往往是必不可少的步骤。本文

SpringBoot+Redis防止接口重复提交问题

《SpringBoot+Redis防止接口重复提交问题》:本文主要介绍SpringBoot+Redis防止接口重复提交问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录前言实现思路代码示例测试总结前言在项目的使用使用过程中,经常会出现某些操作在短时间内频繁提交。例

Mac系统下卸载JAVA和JDK的步骤

《Mac系统下卸载JAVA和JDK的步骤》JDK是Java语言的软件开发工具包,它提供了开发和运行Java应用程序所需的工具、库和资源,:本文主要介绍Mac系统下卸载JAVA和JDK的相关资料,需... 目录1. 卸载系统自带的 Java 版本检查当前 Java 版本通过命令卸载系统 Java2. 卸载自定

springboot下载接口限速功能实现

《springboot下载接口限速功能实现》通过Redis统计并发数动态调整每个用户带宽,核心逻辑为每秒读取并发送限定数据量,防止单用户占用过多资源,确保整体下载均衡且高效,本文给大家介绍spring... 目录 一、整体目标 二、涉及的主要类/方法✅ 三、核心流程图解(简化) 四、关键代码详解1️⃣ 设置

spring中的ImportSelector接口示例详解

《spring中的ImportSelector接口示例详解》Spring的ImportSelector接口用于动态选择配置类,实现条件化和模块化配置,关键方法selectImports根据注解信息返回... 目录一、核心作用二、关键方法三、扩展功能四、使用示例五、工作原理六、应用场景七、自定义实现Impor

MybatisPlus service接口功能介绍

《MybatisPlusservice接口功能介绍》:本文主要介绍MybatisPlusservice接口功能介绍,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录Service接口基本用法进阶用法总结:Lambda方法Service接口基本用法MyBATisP

基于Python实现一个简单的题库与在线考试系统

《基于Python实现一个简单的题库与在线考试系统》在当今信息化教育时代,在线学习与考试系统已成为教育技术领域的重要组成部分,本文就来介绍一下如何使用Python和PyQt5框架开发一个名为白泽题库系... 目录概述功能特点界面展示系统架构设计类结构图Excel题库填写格式模板题库题目填写格式表核心数据结构

Linux系统中的firewall-offline-cmd详解(收藏版)

《Linux系统中的firewall-offline-cmd详解(收藏版)》firewall-offline-cmd是firewalld的一个命令行工具,专门设计用于在没有运行firewalld服务的... 目录主要用途基本语法选项1. 状态管理2. 区域管理3. 服务管理4. 端口管理5. ICMP 阻断