VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/StandaloneMmPkg/Library/StandaloneMmMemLib/X86StandaloneMmMemLibInternal.c@ 108794

Last change on this file since 108794 was 108794, checked in by vboxsync, 2 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

  • Property svn:eol-style set to native
File size: 7.5 KB
Line 
1/** @file
2 Internal ARCH Specific file of MM memory check library.
3
4 MM memory check library implementation. This library consumes MM_ACCESS_PROTOCOL
5 to get MMRAM information. In order to use this library instance, the platform should produce
6 all MMRAM range via MM_ACCESS_PROTOCOL, including the range for firmware (like MM Core
7 and MM driver) and/or specific dedicated hardware.
8
9 Copyright (c) 2015 - 2024, Intel Corporation. All rights reserved.<BR>
10 Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
11 Copyright (c) Microsoft Corporation.
12
13 SPDX-License-Identifier: BSD-2-Clause-Patent
14
15**/
16#include "StandaloneMmMemLibInternal.h"
17#include <PiMm.h>
18#include <Library/MemoryAllocationLib.h>
19#include <Library/HobLib.h>
20
21typedef struct {
22 EFI_PHYSICAL_ADDRESS Base;
23 UINT64 Length;
24} NON_MM_MEMORY_RANGE;
25
26NON_MM_MEMORY_RANGE *mValidNonMmramRanges;
27UINTN mValidNonMmramCount;
28
29//
30// Maximum support address used to check input buffer
31//
32extern EFI_PHYSICAL_ADDRESS mMmMemLibInternalMaximumSupportAddress;
33
34/**
35 Calculate and save the maximum support address.
36
37**/
38VOID
39MmMemLibCalculateMaximumSupportAddress (
40 VOID
41 )
42{
43 VOID *Hob;
44 UINT32 RegEax;
45 UINT8 PhysicalAddressBits;
46
47 //
48 // Get physical address bits supported.
49 //
50 Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
51 if (Hob != NULL) {
52 PhysicalAddressBits = ((EFI_HOB_CPU *)Hob)->SizeOfMemorySpace;
53 } else {
54 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
55 if (RegEax >= 0x80000008) {
56 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
57 PhysicalAddressBits = (UINT8)RegEax;
58 } else {
59 PhysicalAddressBits = 36;
60 }
61 }
62
63 //
64 // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.
65 //
66 ASSERT (PhysicalAddressBits <= 52);
67 if (PhysicalAddressBits > 48) {
68 PhysicalAddressBits = 48;
69 }
70
71 //
72 // Save the maximum support address in one global variable
73 //
74 mMmMemLibInternalMaximumSupportAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)(LShiftU64 (1, PhysicalAddressBits) - 1);
75 DEBUG ((DEBUG_INFO, "mMmMemLibInternalMaximumSupportAddress = 0x%lx\n", mMmMemLibInternalMaximumSupportAddress));
76}
77
78/**
79 Merge the overlapped or continuous ranges in input MemoryRange. This function is to optimize
80 the process of checking whether a buffer range belongs to the range reported by resource HOB,
81 since the buffer to be checked may be covered by multi resource HOB.
82
83 @param[in, out] MemoryRange A pointer to the NonMmramRanges reported by resource HOB.
84 @param[in, out] MemoryRangeSize A pointer to the size, in bytes, of the MemoryRange buffer.
85 On input, it is the size of the current memory map.
86 On output, it is the size of new memory map after merge.
87**/
88STATIC
89VOID
90MergeOverlappedOrContinuousRanges (
91 IN OUT NON_MM_MEMORY_RANGE *MemoryRange,
92 IN OUT UINTN *MemoryRangeSize
93 )
94{
95 NON_MM_MEMORY_RANGE *MemoryRangeEntry;
96 NON_MM_MEMORY_RANGE *MemoryRangeEnd;
97 NON_MM_MEMORY_RANGE *NewMemoryRangeEntry;
98 NON_MM_MEMORY_RANGE *NextMemoryRangeEntry;
99 EFI_PHYSICAL_ADDRESS End;
100
101 MemoryRangeEntry = MemoryRange;
102 NewMemoryRangeEntry = MemoryRange;
103 MemoryRangeEnd = (NON_MM_MEMORY_RANGE *)((UINT8 *)MemoryRange + *MemoryRangeSize);
104 while ((UINTN)MemoryRangeEntry < (UINTN)MemoryRangeEnd) {
105 NextMemoryRangeEntry = MemoryRangeEntry + 1;
106
107 do {
108 if (((UINTN)NextMemoryRangeEntry < (UINTN)MemoryRangeEnd) &&
109 ((MemoryRangeEntry->Base + MemoryRangeEntry->Length) >= NextMemoryRangeEntry->Base))
110 {
111 //
112 // Merge the overlapped or continuous ranges.
113 //
114 End = MAX (
115 MemoryRangeEntry->Base + MemoryRangeEntry->Length,
116 NextMemoryRangeEntry->Base + NextMemoryRangeEntry->Length
117 );
118 MemoryRangeEntry->Length = End - MemoryRangeEntry->Base;
119
120 NextMemoryRangeEntry++;
121 continue;
122 } else {
123 //
124 // Copy the processed independent range to the new index location.
125 //
126 CopyMem (NewMemoryRangeEntry, MemoryRangeEntry, sizeof (NON_MM_MEMORY_RANGE));
127 break;
128 }
129 } while (TRUE);
130
131 MemoryRangeEntry = NextMemoryRangeEntry;
132 NewMemoryRangeEntry++;
133 }
134
135 *MemoryRangeSize = (UINTN)NewMemoryRangeEntry - (UINTN)MemoryRange;
136}
137
138/**
139 Function to compare 2 NON_MM_MEMORY_RANGE pointer based on Base.
140
141 @param[in] Buffer1 pointer to NON_MM_MEMORY_RANGE pointer to compare
142 @param[in] Buffer2 pointer to second NON_MM_MEMORY_RANGE pointer to compare
143
144 @retval 0 Buffer1 equal to Buffer2
145 @retval <0 Buffer1 is less than Buffer2
146 @retval >0 Buffer1 is greater than Buffer2
147**/
148INTN
149EFIAPI
150NonMmMapCompare (
151 IN CONST VOID *Buffer1,
152 IN CONST VOID *Buffer2
153 )
154{
155 if (((NON_MM_MEMORY_RANGE *)Buffer1)->Base > ((NON_MM_MEMORY_RANGE *)Buffer2)->Base) {
156 return 1;
157 } else if (((NON_MM_MEMORY_RANGE *)Buffer1)->Base < ((NON_MM_MEMORY_RANGE *)Buffer2)->Base) {
158 return -1;
159 }
160
161 return 0;
162}
163
164/**
165 Initialize valid non-Mmram Ranges from Resource HOB.
166
167**/
168VOID
169MmMemLibInitializeValidNonMmramRanges (
170 VOID
171 )
172{
173 EFI_PEI_HOB_POINTERS Hob;
174 UINTN Count;
175 UINTN Index;
176 UINTN RangeSize;
177 NON_MM_MEMORY_RANGE SortBuffer;
178
179 mValidNonMmramRanges = NULL;
180 mValidNonMmramCount = 0;
181
182 Count = 0;
183 Index = 0;
184 RangeSize = 0;
185
186 //
187 // 1. Get the count.
188 //
189 Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
190 while (Hob.Raw != NULL) {
191 Count++;
192 Hob.Raw = GET_NEXT_HOB (Hob);
193 Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);
194 }
195
196 //
197 // 2. Store the initial data.
198 //
199 RangeSize = sizeof (NON_MM_MEMORY_RANGE) * Count;
200 mValidNonMmramRanges = (NON_MM_MEMORY_RANGE *)AllocateZeroPool (RangeSize);
201 ASSERT (mValidNonMmramRanges != NULL);
202
203 Hob.Raw = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR);
204 while (Hob.Raw != NULL) {
205 mValidNonMmramRanges[Index].Base = Hob.ResourceDescriptor->PhysicalStart;
206 mValidNonMmramRanges[Index].Length = Hob.ResourceDescriptor->ResourceLength;
207 Index++;
208
209 Hob.Raw = GET_NEXT_HOB (Hob);
210 Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw);
211 }
212
213 ASSERT (Index == Count);
214
215 //
216 // 3. Sort the data.
217 //
218 QuickSort (mValidNonMmramRanges, Count, sizeof (NON_MM_MEMORY_RANGE), (BASE_SORT_COMPARE)NonMmMapCompare, &SortBuffer);
219
220 //
221 // 4. Merge the overlapped or continuous ranges.
222 //
223 MergeOverlappedOrContinuousRanges (mValidNonMmramRanges, &RangeSize);
224 mValidNonMmramCount = RangeSize/sizeof (NON_MM_MEMORY_RANGE);
225}
226
227/**
228 Deinitialize cached non-Mmram Ranges.
229
230**/
231VOID
232MmMemLibFreeValidNonMmramRanges (
233 VOID
234 )
235{
236 if (mValidNonMmramRanges != NULL) {
237 FreePool (mValidNonMmramRanges);
238 }
239}
240
241/**
242 This function check if the buffer is valid non-MMRAM memory range.
243
244 @param[in] Buffer The buffer start address to be checked.
245 @param[in] Length The buffer length to be checked.
246
247 @retval TRUE This buffer is valid non-MMRAM memory range.
248 @retval FALSE This buffer is not valid non-MMRAM memory range.
249**/
250BOOLEAN
251MmMemLibIsValidNonMmramRange (
252 IN EFI_PHYSICAL_ADDRESS Buffer,
253 IN UINT64 Length
254 )
255{
256 UINTN Index;
257
258 for (Index = 0; Index < mValidNonMmramCount; Index++) {
259 if ((Buffer >= mValidNonMmramRanges[Index].Base) &&
260 (Buffer + Length <= mValidNonMmramRanges[Index].Base + mValidNonMmramRanges[Index].Length))
261 {
262 return TRUE;
263 }
264 }
265
266 return FALSE;
267}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette