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

相关文章

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 阻断

Windows 系统下 Nginx 的配置步骤详解

《Windows系统下Nginx的配置步骤详解》Nginx是一款功能强大的软件,在互联网领域有广泛应用,简单来说,它就像一个聪明的交通指挥员,能让网站运行得更高效、更稳定,:本文主要介绍W... 目录一、为什么要用 Nginx二、Windows 系统下 Nginx 的配置步骤1. 下载 Nginx2. 解压

如何确定哪些软件是Mac系统自带的? Mac系统内置应用查看技巧

《如何确定哪些软件是Mac系统自带的?Mac系统内置应用查看技巧》如何确定哪些软件是Mac系统自带的?mac系统中有很多自带的应用,想要看看哪些是系统自带,该怎么查看呢?下面我们就来看看Mac系统内... 在MAC电脑上,可以使用以下方法来确定哪些软件是系统自带的:1.应用程序文件夹打开应用程序文件夹

windows系统上如何进行maven安装和配置方式

《windows系统上如何进行maven安装和配置方式》:本文主要介绍windows系统上如何进行maven安装和配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录1. Maven 简介2. maven的下载与安装2.1 下载 Maven2.2 Maven安装2.

使用Python实现Windows系统垃圾清理

《使用Python实现Windows系统垃圾清理》Windows自带的磁盘清理工具功能有限,无法深度清理各类垃圾文件,所以本文为大家介绍了如何使用Python+PyQt5开发一个Windows系统垃圾... 目录一、开发背景与工具概述1.1 为什么需要专业清理工具1.2 工具设计理念二、工具核心功能解析2.

Linux系统之stress-ng测压工具的使用

《Linux系统之stress-ng测压工具的使用》:本文主要介绍Linux系统之stress-ng测压工具的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、理论1.stress工具简介与安装2.语法及参数3.具体安装二、实验1.运行8 cpu, 4 fo

Java中的Closeable接口及常见问题

《Java中的Closeable接口及常见问题》Closeable是Java中的一个标记接口,用于表示可以被关闭的对象,它定义了一个标准的方法来释放对象占用的系统资源,下面给大家介绍Java中的Clo... 目录1. Closeable接口概述2. 主要用途3. 实现类4. 使用方法5. 实现自定义Clos

java对接第三方接口的三种实现方式

《java对接第三方接口的三种实现方式》:本文主要介绍java对接第三方接口的三种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录HttpURLConnection调用方法CloseableHttpClient调用RestTemplate调用总结在日常工作