]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
UefiCpuPkg/PiSmmCpuDxeSmm: Add support for PCD PcdPteMemoryEncryptionAddressOrMask
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / SmmCpuMemoryManagement.c
CommitLineData
717fb604
JY
1/** @file\r
2\r
3Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
4This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12**/\r
13\r
14#include "PiSmmCpuDxeSmm.h"\r
15\r
16#define NEXT_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \\r
17 ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) + (Size)))\r
18\r
d2fc7711
JY
19#define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \\r
20 ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))\r
21\r
22EFI_MEMORY_DESCRIPTOR *mUefiMemoryMap;\r
23UINTN mUefiMemoryMapSize;\r
24UINTN mUefiDescriptorSize;\r
25\r
717fb604
JY
26PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] = {\r
27 {Page4K, SIZE_4KB, PAGING_4K_ADDRESS_MASK_64},\r
28 {Page2M, SIZE_2MB, PAGING_2M_ADDRESS_MASK_64},\r
29 {Page1G, SIZE_1GB, PAGING_1G_ADDRESS_MASK_64},\r
30};\r
31\r
32/**\r
33 Return page table base.\r
34\r
35 @return page table base.\r
36**/\r
37UINTN\r
38GetPageTableBase (\r
39 VOID\r
40 )\r
41{\r
42 return (AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64);\r
43}\r
44\r
45/**\r
46 Return length according to page attributes.\r
47\r
48 @param[in] PageAttributes The page attribute of the page entry.\r
49\r
50 @return The length of page entry.\r
51**/\r
52UINTN\r
53PageAttributeToLength (\r
54 IN PAGE_ATTRIBUTE PageAttribute\r
55 )\r
56{\r
57 UINTN Index;\r
58 for (Index = 0; Index < sizeof(mPageAttributeTable)/sizeof(mPageAttributeTable[0]); Index++) {\r
59 if (PageAttribute == mPageAttributeTable[Index].Attribute) {\r
60 return (UINTN)mPageAttributeTable[Index].Length;\r
61 }\r
62 }\r
63 return 0;\r
64}\r
65\r
66/**\r
67 Return address mask according to page attributes.\r
68\r
69 @param[in] PageAttributes The page attribute of the page entry.\r
70\r
71 @return The address mask of page entry.\r
72**/\r
73UINTN\r
74PageAttributeToMask (\r
75 IN PAGE_ATTRIBUTE PageAttribute\r
76 )\r
77{\r
78 UINTN Index;\r
79 for (Index = 0; Index < sizeof(mPageAttributeTable)/sizeof(mPageAttributeTable[0]); Index++) {\r
80 if (PageAttribute == mPageAttributeTable[Index].Attribute) {\r
81 return (UINTN)mPageAttributeTable[Index].AddressMask;\r
82 }\r
83 }\r
84 return 0;\r
85}\r
86\r
87/**\r
88 Return page table entry to match the address.\r
89\r
90 @param[in] Address The address to be checked.\r
91 @param[out] PageAttributes The page attribute of the page entry.\r
92\r
93 @return The page entry.\r
94**/\r
95VOID *\r
96GetPageTableEntry (\r
97 IN PHYSICAL_ADDRESS Address,\r
98 OUT PAGE_ATTRIBUTE *PageAttribute\r
99 )\r
100{\r
101 UINTN Index1;\r
102 UINTN Index2;\r
103 UINTN Index3;\r
104 UINTN Index4;\r
105 UINT64 *L1PageTable;\r
106 UINT64 *L2PageTable;\r
107 UINT64 *L3PageTable;\r
108 UINT64 *L4PageTable;\r
109\r
110 Index4 = ((UINTN)RShiftU64 (Address, 39)) & PAGING_PAE_INDEX_MASK;\r
111 Index3 = ((UINTN)Address >> 30) & PAGING_PAE_INDEX_MASK;\r
112 Index2 = ((UINTN)Address >> 21) & PAGING_PAE_INDEX_MASK;\r
113 Index1 = ((UINTN)Address >> 12) & PAGING_PAE_INDEX_MASK;\r
114\r
115 if (sizeof(UINTN) == sizeof(UINT64)) {\r
116 L4PageTable = (UINT64 *)GetPageTableBase ();\r
117 if (L4PageTable[Index4] == 0) {\r
118 *PageAttribute = PageNone;\r
119 return NULL;\r
120 }\r
121\r
241f9149 122 L3PageTable = (UINT64 *)(UINTN)(L4PageTable[Index4] & ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64);\r
717fb604
JY
123 } else {\r
124 L3PageTable = (UINT64 *)GetPageTableBase ();\r
125 }\r
126 if (L3PageTable[Index3] == 0) {\r
127 *PageAttribute = PageNone;\r
128 return NULL;\r
129 }\r
130 if ((L3PageTable[Index3] & IA32_PG_PS) != 0) {\r
131 // 1G\r
132 *PageAttribute = Page1G;\r
133 return &L3PageTable[Index3];\r
134 }\r
135\r
241f9149 136 L2PageTable = (UINT64 *)(UINTN)(L3PageTable[Index3] & ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64);\r
717fb604
JY
137 if (L2PageTable[Index2] == 0) {\r
138 *PageAttribute = PageNone;\r
139 return NULL;\r
140 }\r
141 if ((L2PageTable[Index2] & IA32_PG_PS) != 0) {\r
142 // 2M\r
143 *PageAttribute = Page2M;\r
144 return &L2PageTable[Index2];\r
145 }\r
146\r
147 // 4k\r
241f9149 148 L1PageTable = (UINT64 *)(UINTN)(L2PageTable[Index2] & ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64);\r
717fb604
JY
149 if ((L1PageTable[Index1] == 0) && (Address != 0)) {\r
150 *PageAttribute = PageNone;\r
151 return NULL;\r
152 }\r
153 *PageAttribute = Page4K;\r
154 return &L1PageTable[Index1];\r
155}\r
156\r
157/**\r
158 Return memory attributes of page entry.\r
159\r
160 @param[in] PageEntry The page entry.\r
161\r
162 @return Memory attributes of page entry.\r
163**/\r
164UINT64\r
165GetAttributesFromPageEntry (\r
166 IN UINT64 *PageEntry\r
167 )\r
168{\r
169 UINT64 Attributes;\r
170 Attributes = 0;\r
171 if ((*PageEntry & IA32_PG_P) == 0) {\r
172 Attributes |= EFI_MEMORY_RP;\r
173 }\r
174 if ((*PageEntry & IA32_PG_RW) == 0) {\r
175 Attributes |= EFI_MEMORY_RO;\r
176 }\r
177 if ((*PageEntry & IA32_PG_NX) != 0) {\r
178 Attributes |= EFI_MEMORY_XP;\r
179 }\r
180 return Attributes;\r
181}\r
182\r
183/**\r
184 Modify memory attributes of page entry.\r
185\r
186 @param[in] PageEntry The page entry.\r
187 @param[in] Attributes The bit mask of attributes to modify for the memory region.\r
188 @param[in] IsSet TRUE means to set attributes. FALSE means to clear attributes.\r
189 @param[out] IsModified TRUE means page table modified. FALSE means page table not modified.\r
190**/\r
191VOID\r
192ConvertPageEntryAttribute (\r
193 IN UINT64 *PageEntry,\r
194 IN UINT64 Attributes,\r
195 IN BOOLEAN IsSet,\r
196 OUT BOOLEAN *IsModified\r
197 )\r
198{\r
199 UINT64 CurrentPageEntry;\r
200 UINT64 NewPageEntry;\r
201\r
202 CurrentPageEntry = *PageEntry;\r
203 NewPageEntry = CurrentPageEntry;\r
204 if ((Attributes & EFI_MEMORY_RP) != 0) {\r
205 if (IsSet) {\r
206 NewPageEntry &= ~(UINT64)IA32_PG_P;\r
207 } else {\r
208 NewPageEntry |= IA32_PG_P;\r
209 }\r
210 }\r
211 if ((Attributes & EFI_MEMORY_RO) != 0) {\r
212 if (IsSet) {\r
213 NewPageEntry &= ~(UINT64)IA32_PG_RW;\r
214 } else {\r
215 NewPageEntry |= IA32_PG_RW;\r
216 }\r
217 }\r
218 if ((Attributes & EFI_MEMORY_XP) != 0) {\r
750ec4ca
JY
219 if (mXdSupported) {\r
220 if (IsSet) {\r
221 NewPageEntry |= IA32_PG_NX;\r
222 } else {\r
223 NewPageEntry &= ~IA32_PG_NX;\r
224 }\r
717fb604
JY
225 }\r
226 }\r
227 *PageEntry = NewPageEntry;\r
228 if (CurrentPageEntry != NewPageEntry) {\r
229 *IsModified = TRUE;\r
230 DEBUG ((DEBUG_VERBOSE, "ConvertPageEntryAttribute 0x%lx", CurrentPageEntry));\r
231 DEBUG ((DEBUG_VERBOSE, "->0x%lx\n", NewPageEntry));\r
232 } else {\r
233 *IsModified = FALSE;\r
234 }\r
235}\r
236\r
237/**\r
238 This function returns if there is need to split page entry.\r
239\r
240 @param[in] BaseAddress The base address to be checked.\r
241 @param[in] Length The length to be checked.\r
242 @param[in] PageEntry The page entry to be checked.\r
243 @param[in] PageAttribute The page attribute of the page entry.\r
244\r
245 @retval SplitAttributes on if there is need to split page entry.\r
246**/\r
247PAGE_ATTRIBUTE\r
248NeedSplitPage (\r
249 IN PHYSICAL_ADDRESS BaseAddress,\r
250 IN UINT64 Length,\r
251 IN UINT64 *PageEntry,\r
252 IN PAGE_ATTRIBUTE PageAttribute\r
253 )\r
254{\r
255 UINT64 PageEntryLength;\r
256\r
257 PageEntryLength = PageAttributeToLength (PageAttribute);\r
258\r
259 if (((BaseAddress & (PageEntryLength - 1)) == 0) && (Length >= PageEntryLength)) {\r
260 return PageNone;\r
261 }\r
262\r
263 if (((BaseAddress & PAGING_2M_MASK) != 0) || (Length < SIZE_2MB)) {\r
264 return Page4K;\r
265 }\r
266\r
267 return Page2M;\r
268}\r
269\r
270/**\r
271 This function splits one page entry to small page entries.\r
272\r
273 @param[in] PageEntry The page entry to be splitted.\r
274 @param[in] PageAttribute The page attribute of the page entry.\r
275 @param[in] SplitAttribute How to split the page entry.\r
276\r
277 @retval RETURN_SUCCESS The page entry is splitted.\r
278 @retval RETURN_UNSUPPORTED The page entry does not support to be splitted.\r
279 @retval RETURN_OUT_OF_RESOURCES No resource to split page entry.\r
280**/\r
281RETURN_STATUS\r
282SplitPage (\r
283 IN UINT64 *PageEntry,\r
284 IN PAGE_ATTRIBUTE PageAttribute,\r
285 IN PAGE_ATTRIBUTE SplitAttribute\r
286 )\r
287{\r
288 UINT64 BaseAddress;\r
289 UINT64 *NewPageEntry;\r
290 UINTN Index;\r
291\r
292 ASSERT (PageAttribute == Page2M || PageAttribute == Page1G);\r
293\r
294 if (PageAttribute == Page2M) {\r
295 //\r
296 // Split 2M to 4K\r
297 //\r
298 ASSERT (SplitAttribute == Page4K);\r
299 if (SplitAttribute == Page4K) {\r
300 NewPageEntry = AllocatePageTableMemory (1);\r
301 DEBUG ((DEBUG_VERBOSE, "Split - 0x%x\n", NewPageEntry));\r
302 if (NewPageEntry == NULL) {\r
303 return RETURN_OUT_OF_RESOURCES;\r
304 }\r
305 BaseAddress = *PageEntry & PAGING_2M_ADDRESS_MASK_64;\r
306 for (Index = 0; Index < SIZE_4KB / sizeof(UINT64); Index++) {\r
241f9149 307 NewPageEntry[Index] = (BaseAddress + SIZE_4KB * Index) | mAddressEncMask | ((*PageEntry) & PAGE_PROGATE_BITS);\r
717fb604 308 }\r
241f9149 309 (*PageEntry) = (UINT64)(UINTN)NewPageEntry | mAddressEncMask | PAGE_ATTRIBUTE_BITS;\r
717fb604
JY
310 return RETURN_SUCCESS;\r
311 } else {\r
312 return RETURN_UNSUPPORTED;\r
313 }\r
314 } else if (PageAttribute == Page1G) {\r
315 //\r
316 // Split 1G to 2M\r
317 // No need support 1G->4K directly, we should use 1G->2M, then 2M->4K to get more compact page table.\r
318 //\r
319 ASSERT (SplitAttribute == Page2M || SplitAttribute == Page4K);\r
320 if ((SplitAttribute == Page2M || SplitAttribute == Page4K)) {\r
321 NewPageEntry = AllocatePageTableMemory (1);\r
322 DEBUG ((DEBUG_VERBOSE, "Split - 0x%x\n", NewPageEntry));\r
323 if (NewPageEntry == NULL) {\r
324 return RETURN_OUT_OF_RESOURCES;\r
325 }\r
326 BaseAddress = *PageEntry & PAGING_1G_ADDRESS_MASK_64;\r
327 for (Index = 0; Index < SIZE_4KB / sizeof(UINT64); Index++) {\r
241f9149 328 NewPageEntry[Index] = (BaseAddress + SIZE_2MB * Index) | mAddressEncMask | IA32_PG_PS | ((*PageEntry) & PAGE_PROGATE_BITS);\r
717fb604 329 }\r
241f9149 330 (*PageEntry) = (UINT64)(UINTN)NewPageEntry | mAddressEncMask | PAGE_ATTRIBUTE_BITS;\r
717fb604
JY
331 return RETURN_SUCCESS;\r
332 } else {\r
333 return RETURN_UNSUPPORTED;\r
334 }\r
335 } else {\r
336 return RETURN_UNSUPPORTED;\r
337 }\r
338}\r
339\r
340/**\r
341 This function modifies the page attributes for the memory region specified by BaseAddress and\r
342 Length from their current attributes to the attributes specified by Attributes.\r
343\r
344 Caller should make sure BaseAddress and Length is at page boundary.\r
345\r
346 @param[in] BaseAddress The physical address that is the start address of a memory region.\r
347 @param[in] Length The size in bytes of the memory region.\r
348 @param[in] Attributes The bit mask of attributes to modify for the memory region.\r
349 @param[in] IsSet TRUE means to set attributes. FALSE means to clear attributes.\r
350 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.\r
351 @param[out] IsModified TRUE means page table modified. FALSE means page table not modified.\r
352\r
353 @retval RETURN_SUCCESS The attributes were modified for the memory region.\r
354 @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by\r
355 BaseAddress and Length cannot be modified.\r
356 @retval RETURN_INVALID_PARAMETER Length is zero.\r
357 Attributes specified an illegal combination of attributes that\r
358 cannot be set together.\r
359 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of\r
360 the memory resource range.\r
361 @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the memory\r
362 resource range specified by BaseAddress and Length.\r
363 The bit mask of attributes is not support for the memory resource\r
364 range specified by BaseAddress and Length.\r
365**/\r
366RETURN_STATUS\r
367EFIAPI\r
368ConvertMemoryPageAttributes (\r
369 IN PHYSICAL_ADDRESS BaseAddress,\r
370 IN UINT64 Length,\r
371 IN UINT64 Attributes,\r
372 IN BOOLEAN IsSet,\r
373 OUT BOOLEAN *IsSplitted, OPTIONAL\r
374 OUT BOOLEAN *IsModified OPTIONAL\r
375 )\r
376{\r
377 UINT64 *PageEntry;\r
378 PAGE_ATTRIBUTE PageAttribute;\r
379 UINTN PageEntryLength;\r
380 PAGE_ATTRIBUTE SplitAttribute;\r
381 RETURN_STATUS Status;\r
382 BOOLEAN IsEntryModified;\r
383\r
384 ASSERT (Attributes != 0);\r
385 ASSERT ((Attributes & ~(EFI_MEMORY_RP | EFI_MEMORY_RO | EFI_MEMORY_XP)) == 0);\r
386\r
387 ASSERT ((BaseAddress & (SIZE_4KB - 1)) == 0);\r
388 ASSERT ((Length & (SIZE_4KB - 1)) == 0);\r
389\r
390 if (Length == 0) {\r
391 return RETURN_INVALID_PARAMETER;\r
392 }\r
393\r
394// DEBUG ((DEBUG_ERROR, "ConvertMemoryPageAttributes(%x) - %016lx, %016lx, %02lx\n", IsSet, BaseAddress, Length, Attributes));\r
395\r
396 if (IsSplitted != NULL) {\r
397 *IsSplitted = FALSE;\r
398 }\r
399 if (IsModified != NULL) {\r
400 *IsModified = FALSE;\r
401 }\r
402\r
403 //\r
404 // Below logic is to check 2M/4K page to make sure we donot waist memory.\r
405 //\r
406 while (Length != 0) {\r
407 PageEntry = GetPageTableEntry (BaseAddress, &PageAttribute);\r
408 if (PageEntry == NULL) {\r
409 return RETURN_UNSUPPORTED;\r
410 }\r
411 PageEntryLength = PageAttributeToLength (PageAttribute);\r
412 SplitAttribute = NeedSplitPage (BaseAddress, Length, PageEntry, PageAttribute);\r
413 if (SplitAttribute == PageNone) {\r
414 ConvertPageEntryAttribute (PageEntry, Attributes, IsSet, &IsEntryModified);\r
415 if (IsEntryModified) {\r
416 if (IsModified != NULL) {\r
417 *IsModified = TRUE;\r
418 }\r
419 }\r
420 //\r
421 // Convert success, move to next\r
422 //\r
423 BaseAddress += PageEntryLength;\r
424 Length -= PageEntryLength;\r
425 } else {\r
426 Status = SplitPage (PageEntry, PageAttribute, SplitAttribute);\r
427 if (RETURN_ERROR (Status)) {\r
428 return RETURN_UNSUPPORTED;\r
429 }\r
430 if (IsSplitted != NULL) {\r
431 *IsSplitted = TRUE;\r
432 }\r
433 if (IsModified != NULL) {\r
434 *IsModified = TRUE;\r
435 }\r
436 //\r
437 // Just split current page\r
438 // Convert success in next around\r
439 //\r
440 }\r
441 }\r
442\r
443 return RETURN_SUCCESS;\r
444}\r
445\r
446/**\r
447 FlushTlb on current processor.\r
448\r
449 @param[in,out] Buffer Pointer to private data buffer.\r
450**/\r
451VOID\r
452EFIAPI\r
453FlushTlbOnCurrentProcessor (\r
454 IN OUT VOID *Buffer\r
455 )\r
456{\r
457 CpuFlushTlb ();\r
458}\r
459\r
460/**\r
461 FlushTlb for all processors.\r
462**/\r
463VOID\r
464FlushTlbForAll (\r
465 VOID\r
466 )\r
467{\r
468 UINTN Index;\r
469\r
470 FlushTlbOnCurrentProcessor (NULL);\r
471\r
472 for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {\r
473 if (Index != gSmst->CurrentlyExecutingCpu) {\r
474 // Force to start up AP in blocking mode,\r
475 SmmBlockingStartupThisAp (FlushTlbOnCurrentProcessor, Index, NULL);\r
476 // Do not check return status, because AP might not be present in some corner cases.\r
477 }\r
478 }\r
479}\r
480\r
481/**\r
482 This function sets the attributes for the memory region specified by BaseAddress and\r
483 Length from their current attributes to the attributes specified by Attributes.\r
484\r
485 @param[in] BaseAddress The physical address that is the start address of a memory region.\r
486 @param[in] Length The size in bytes of the memory region.\r
487 @param[in] Attributes The bit mask of attributes to set for the memory region.\r
488 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.\r
489\r
490 @retval EFI_SUCCESS The attributes were set for the memory region.\r
491 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by\r
492 BaseAddress and Length cannot be modified.\r
493 @retval EFI_INVALID_PARAMETER Length is zero.\r
494 Attributes specified an illegal combination of attributes that\r
495 cannot be set together.\r
496 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of\r
497 the memory resource range.\r
498 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory\r
499 resource range specified by BaseAddress and Length.\r
500 The bit mask of attributes is not support for the memory resource\r
501 range specified by BaseAddress and Length.\r
502\r
503**/\r
504EFI_STATUS\r
505EFIAPI\r
506SmmSetMemoryAttributesEx (\r
507 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
508 IN UINT64 Length,\r
509 IN UINT64 Attributes,\r
510 OUT BOOLEAN *IsSplitted OPTIONAL\r
511 )\r
512{\r
513 EFI_STATUS Status;\r
514 BOOLEAN IsModified;\r
515\r
516 Status = ConvertMemoryPageAttributes (BaseAddress, Length, Attributes, TRUE, IsSplitted, &IsModified);\r
517 if (!EFI_ERROR(Status)) {\r
518 if (IsModified) {\r
519 //\r
520 // Flush TLB as last step\r
521 //\r
522 FlushTlbForAll();\r
523 }\r
524 }\r
525\r
526 return Status;\r
527}\r
528\r
529/**\r
530 This function clears the attributes for the memory region specified by BaseAddress and\r
531 Length from their current attributes to the attributes specified by Attributes.\r
532\r
533 @param[in] BaseAddress The physical address that is the start address of a memory region.\r
534 @param[in] Length The size in bytes of the memory region.\r
535 @param[in] Attributes The bit mask of attributes to clear for the memory region.\r
536 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.\r
537\r
538 @retval EFI_SUCCESS The attributes were cleared for the memory region.\r
539 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by\r
540 BaseAddress and Length cannot be modified.\r
541 @retval EFI_INVALID_PARAMETER Length is zero.\r
542 Attributes specified an illegal combination of attributes that\r
543 cannot be set together.\r
544 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of\r
545 the memory resource range.\r
546 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory\r
547 resource range specified by BaseAddress and Length.\r
548 The bit mask of attributes is not support for the memory resource\r
549 range specified by BaseAddress and Length.\r
550\r
551**/\r
552EFI_STATUS\r
553EFIAPI\r
554SmmClearMemoryAttributesEx (\r
555 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
556 IN UINT64 Length,\r
557 IN UINT64 Attributes,\r
558 OUT BOOLEAN *IsSplitted OPTIONAL\r
559 )\r
560{\r
561 EFI_STATUS Status;\r
562 BOOLEAN IsModified;\r
563\r
564 Status = ConvertMemoryPageAttributes (BaseAddress, Length, Attributes, FALSE, IsSplitted, &IsModified);\r
565 if (!EFI_ERROR(Status)) {\r
566 if (IsModified) {\r
567 //\r
568 // Flush TLB as last step\r
569 //\r
570 FlushTlbForAll();\r
571 }\r
572 }\r
573\r
574 return Status;\r
575}\r
576\r
577/**\r
578 This function sets the attributes for the memory region specified by BaseAddress and\r
579 Length from their current attributes to the attributes specified by Attributes.\r
580\r
581 @param[in] BaseAddress The physical address that is the start address of a memory region.\r
582 @param[in] Length The size in bytes of the memory region.\r
583 @param[in] Attributes The bit mask of attributes to set for the memory region.\r
584\r
585 @retval EFI_SUCCESS The attributes were set for the memory region.\r
586 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by\r
587 BaseAddress and Length cannot be modified.\r
588 @retval EFI_INVALID_PARAMETER Length is zero.\r
589 Attributes specified an illegal combination of attributes that\r
590 cannot be set together.\r
591 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of\r
592 the memory resource range.\r
593 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory\r
594 resource range specified by BaseAddress and Length.\r
595 The bit mask of attributes is not support for the memory resource\r
596 range specified by BaseAddress and Length.\r
597\r
598**/\r
599EFI_STATUS\r
600EFIAPI\r
601SmmSetMemoryAttributes (\r
602 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
603 IN UINT64 Length,\r
604 IN UINT64 Attributes\r
605 )\r
606{\r
607 return SmmSetMemoryAttributesEx (BaseAddress, Length, Attributes, NULL);\r
608}\r
609\r
610/**\r
611 This function clears the attributes for the memory region specified by BaseAddress and\r
612 Length from their current attributes to the attributes specified by Attributes.\r
613\r
614 @param[in] BaseAddress The physical address that is the start address of a memory region.\r
615 @param[in] Length The size in bytes of the memory region.\r
616 @param[in] Attributes The bit mask of attributes to clear for the memory region.\r
617\r
618 @retval EFI_SUCCESS The attributes were cleared for the memory region.\r
619 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by\r
620 BaseAddress and Length cannot be modified.\r
621 @retval EFI_INVALID_PARAMETER Length is zero.\r
622 Attributes specified an illegal combination of attributes that\r
623 cannot be set together.\r
624 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of\r
625 the memory resource range.\r
626 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory\r
627 resource range specified by BaseAddress and Length.\r
628 The bit mask of attributes is not support for the memory resource\r
629 range specified by BaseAddress and Length.\r
630\r
631**/\r
632EFI_STATUS\r
633EFIAPI\r
634SmmClearMemoryAttributes (\r
635 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
636 IN UINT64 Length,\r
637 IN UINT64 Attributes\r
638 )\r
639{\r
640 return SmmClearMemoryAttributesEx (BaseAddress, Length, Attributes, NULL);\r
641}\r
642\r
643\r
644\r
645/**\r
646 Retrieves a pointer to the system configuration table from the SMM System Table\r
647 based on a specified GUID.\r
648\r
649 @param[in] TableGuid The pointer to table's GUID type.\r
650 @param[out] Table The pointer to the table associated with TableGuid in the EFI System Table.\r
651\r
652 @retval EFI_SUCCESS A configuration table matching TableGuid was found.\r
653 @retval EFI_NOT_FOUND A configuration table matching TableGuid could not be found.\r
654\r
655**/\r
656EFI_STATUS\r
657EFIAPI\r
658SmmGetSystemConfigurationTable (\r
659 IN EFI_GUID *TableGuid,\r
660 OUT VOID **Table\r
661 )\r
662{\r
663 UINTN Index;\r
664\r
665 ASSERT (TableGuid != NULL);\r
666 ASSERT (Table != NULL);\r
667\r
668 *Table = NULL;\r
669 for (Index = 0; Index < gSmst->NumberOfTableEntries; Index++) {\r
670 if (CompareGuid (TableGuid, &(gSmst->SmmConfigurationTable[Index].VendorGuid))) {\r
671 *Table = gSmst->SmmConfigurationTable[Index].VendorTable;\r
672 return EFI_SUCCESS;\r
673 }\r
674 }\r
675\r
676 return EFI_NOT_FOUND;\r
677}\r
678\r
679/**\r
680 This function sets SMM save state buffer to be RW and XP.\r
681**/\r
682VOID\r
683PatchSmmSaveStateMap (\r
684 VOID\r
685 )\r
686{\r
687 UINTN Index;\r
688 UINTN TileCodeSize;\r
689 UINTN TileDataSize;\r
690 UINTN TileSize;\r
691\r
692 TileCodeSize = GetSmiHandlerSize ();\r
693 TileCodeSize = ALIGN_VALUE(TileCodeSize, SIZE_4KB);\r
f12367a0 694 TileDataSize = (SMRAM_SAVE_STATE_MAP_OFFSET - SMM_PSD_OFFSET) + sizeof (SMRAM_SAVE_STATE_MAP);\r
717fb604
JY
695 TileDataSize = ALIGN_VALUE(TileDataSize, SIZE_4KB);\r
696 TileSize = TileDataSize + TileCodeSize - 1;\r
697 TileSize = 2 * GetPowerOfTwo32 ((UINT32)TileSize);\r
698\r
699 DEBUG ((DEBUG_INFO, "PatchSmmSaveStateMap:\n"));\r
700 for (Index = 0; Index < mMaxNumberOfCpus - 1; Index++) {\r
701 //\r
702 // Code\r
703 //\r
704 SmmSetMemoryAttributes (\r
705 mCpuHotPlugData.SmBase[Index] + SMM_HANDLER_OFFSET,\r
706 TileCodeSize,\r
707 EFI_MEMORY_RO\r
708 );\r
709 SmmClearMemoryAttributes (\r
710 mCpuHotPlugData.SmBase[Index] + SMM_HANDLER_OFFSET,\r
711 TileCodeSize,\r
712 EFI_MEMORY_XP\r
713 );\r
714\r
715 //\r
716 // Data\r
717 //\r
718 SmmClearMemoryAttributes (\r
719 mCpuHotPlugData.SmBase[Index] + SMM_HANDLER_OFFSET + TileCodeSize,\r
720 TileSize - TileCodeSize,\r
721 EFI_MEMORY_RO\r
722 );\r
723 SmmSetMemoryAttributes (\r
724 mCpuHotPlugData.SmBase[Index] + SMM_HANDLER_OFFSET + TileCodeSize,\r
725 TileSize - TileCodeSize,\r
726 EFI_MEMORY_XP\r
727 );\r
728 }\r
729\r
730 //\r
731 // Code\r
732 //\r
733 SmmSetMemoryAttributes (\r
734 mCpuHotPlugData.SmBase[mMaxNumberOfCpus - 1] + SMM_HANDLER_OFFSET,\r
735 TileCodeSize,\r
736 EFI_MEMORY_RO\r
737 );\r
738 SmmClearMemoryAttributes (\r
739 mCpuHotPlugData.SmBase[mMaxNumberOfCpus - 1] + SMM_HANDLER_OFFSET,\r
740 TileCodeSize,\r
741 EFI_MEMORY_XP\r
742 );\r
743\r
744 //\r
745 // Data\r
746 //\r
747 SmmClearMemoryAttributes (\r
748 mCpuHotPlugData.SmBase[mMaxNumberOfCpus - 1] + SMM_HANDLER_OFFSET + TileCodeSize,\r
749 SIZE_32KB - TileCodeSize,\r
750 EFI_MEMORY_RO\r
751 );\r
752 SmmSetMemoryAttributes (\r
753 mCpuHotPlugData.SmBase[mMaxNumberOfCpus - 1] + SMM_HANDLER_OFFSET + TileCodeSize,\r
754 SIZE_32KB - TileCodeSize,\r
755 EFI_MEMORY_XP\r
756 );\r
757}\r
758\r
717fb604
JY
759/**\r
760 This function sets memory attribute according to MemoryAttributesTable.\r
761**/\r
762VOID\r
763SetMemMapAttributes (\r
764 VOID\r
765 )\r
766{\r
767 EFI_MEMORY_DESCRIPTOR *MemoryMap;\r
768 EFI_MEMORY_DESCRIPTOR *MemoryMapStart;\r
769 UINTN MemoryMapEntryCount;\r
770 UINTN DescriptorSize;\r
771 UINTN Index;\r
772 EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable;\r
773\r
774 SmmGetSystemConfigurationTable (&gEdkiiPiSmmMemoryAttributesTableGuid, (VOID **)&MemoryAttributesTable);\r
775 if (MemoryAttributesTable == NULL) {\r
776 DEBUG ((DEBUG_INFO, "MemoryAttributesTable - NULL\n"));\r
777 return ;\r
778 }\r
779\r
780 DEBUG ((DEBUG_INFO, "MemoryAttributesTable:\n"));\r
781 DEBUG ((DEBUG_INFO, " Version - 0x%08x\n", MemoryAttributesTable->Version));\r
782 DEBUG ((DEBUG_INFO, " NumberOfEntries - 0x%08x\n", MemoryAttributesTable->NumberOfEntries));\r
783 DEBUG ((DEBUG_INFO, " DescriptorSize - 0x%08x\n", MemoryAttributesTable->DescriptorSize));\r
784\r
785 MemoryMapEntryCount = MemoryAttributesTable->NumberOfEntries;\r
786 DescriptorSize = MemoryAttributesTable->DescriptorSize;\r
787 MemoryMapStart = (EFI_MEMORY_DESCRIPTOR *)(MemoryAttributesTable + 1);\r
788 MemoryMap = MemoryMapStart;\r
789 for (Index = 0; Index < MemoryMapEntryCount; Index++) {\r
790 DEBUG ((DEBUG_INFO, "Entry (0x%x)\n", MemoryMap));\r
791 DEBUG ((DEBUG_INFO, " Type - 0x%x\n", MemoryMap->Type));\r
792 DEBUG ((DEBUG_INFO, " PhysicalStart - 0x%016lx\n", MemoryMap->PhysicalStart));\r
793 DEBUG ((DEBUG_INFO, " VirtualStart - 0x%016lx\n", MemoryMap->VirtualStart));\r
794 DEBUG ((DEBUG_INFO, " NumberOfPages - 0x%016lx\n", MemoryMap->NumberOfPages));\r
795 DEBUG ((DEBUG_INFO, " Attribute - 0x%016lx\n", MemoryMap->Attribute));\r
796 MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize);\r
797 }\r
798\r
799 MemoryMap = MemoryMapStart;\r
800 for (Index = 0; Index < MemoryMapEntryCount; Index++) {\r
801 DEBUG ((DEBUG_VERBOSE, "SetAttribute: Memory Entry - 0x%lx, 0x%x\n", MemoryMap->PhysicalStart, MemoryMap->NumberOfPages));\r
802 switch (MemoryMap->Type) {\r
803 case EfiRuntimeServicesCode:\r
804 SmmSetMemoryAttributes (\r
805 MemoryMap->PhysicalStart,\r
806 EFI_PAGES_TO_SIZE((UINTN)MemoryMap->NumberOfPages),\r
807 EFI_MEMORY_RO\r
808 );\r
809 break;\r
810 case EfiRuntimeServicesData:\r
811 SmmSetMemoryAttributes (\r
812 MemoryMap->PhysicalStart,\r
813 EFI_PAGES_TO_SIZE((UINTN)MemoryMap->NumberOfPages),\r
814 EFI_MEMORY_XP\r
815 );\r
816 break;\r
817 default:\r
818 SmmSetMemoryAttributes (\r
819 MemoryMap->PhysicalStart,\r
820 EFI_PAGES_TO_SIZE((UINTN)MemoryMap->NumberOfPages),\r
821 EFI_MEMORY_XP\r
822 );\r
823 break;\r
824 }\r
825 MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize);\r
826 }\r
827\r
828 PatchSmmSaveStateMap ();\r
829 PatchGdtIdtMap ();\r
830\r
831 return ;\r
832}\r
d2fc7711
JY
833\r
834/**\r
835 Sort memory map entries based upon PhysicalStart, from low to high.\r
836\r
837 @param MemoryMap A pointer to the buffer in which firmware places\r
838 the current memory map.\r
839 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.\r
840 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.\r
841**/\r
842STATIC\r
843VOID\r
844SortMemoryMap (\r
845 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,\r
846 IN UINTN MemoryMapSize,\r
847 IN UINTN DescriptorSize\r
848 )\r
849{\r
850 EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;\r
851 EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry;\r
852 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;\r
853 EFI_MEMORY_DESCRIPTOR TempMemoryMap;\r
854\r
855 MemoryMapEntry = MemoryMap;\r
856 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
857 MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize);\r
858 while (MemoryMapEntry < MemoryMapEnd) {\r
859 while (NextMemoryMapEntry < MemoryMapEnd) {\r
860 if (MemoryMapEntry->PhysicalStart > NextMemoryMapEntry->PhysicalStart) {\r
861 CopyMem (&TempMemoryMap, MemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR));\r
862 CopyMem (MemoryMapEntry, NextMemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR));\r
863 CopyMem (NextMemoryMapEntry, &TempMemoryMap, sizeof(EFI_MEMORY_DESCRIPTOR));\r
864 }\r
865\r
866 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);\r
867 }\r
868\r
869 MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
870 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
871 }\r
872}\r
873\r
874/**\r
875 Return if a UEFI memory page should be marked as not present in SMM page table.\r
876 If the memory map entries type is\r
877 EfiLoaderCode/Data, EfiBootServicesCode/Data, EfiConventionalMemory,\r
878 EfiUnusableMemory, EfiACPIReclaimMemory, return TRUE.\r
879 Or return FALSE.\r
880\r
881 @param[in] MemoryMap A pointer to the memory descriptor.\r
882\r
883 @return TRUE The memory described will be marked as not present in SMM page table.\r
884 @return FALSE The memory described will not be marked as not present in SMM page table.\r
885**/\r
886BOOLEAN\r
887IsUefiPageNotPresent (\r
888 IN EFI_MEMORY_DESCRIPTOR *MemoryMap\r
889 )\r
890{\r
891 switch (MemoryMap->Type) {\r
892 case EfiLoaderCode:\r
893 case EfiLoaderData:\r
894 case EfiBootServicesCode:\r
895 case EfiBootServicesData:\r
896 case EfiConventionalMemory:\r
897 case EfiUnusableMemory:\r
898 case EfiACPIReclaimMemory:\r
899 return TRUE;\r
900 default:\r
901 return FALSE;\r
902 }\r
903}\r
904\r
905/**\r
906 Merge continous memory map entries whose type is\r
907 EfiLoaderCode/Data, EfiBootServicesCode/Data, EfiConventionalMemory,\r
908 EfiUnusableMemory, EfiACPIReclaimMemory, because the memory described by\r
909 these entries will be set as NOT present in SMM page table.\r
910\r
911 @param[in, out] MemoryMap A pointer to the buffer in which firmware places\r
912 the current memory map.\r
913 @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the\r
914 MemoryMap buffer. On input, this is the size of\r
915 the current memory map. On output,\r
916 it is the size of new memory map after merge.\r
917 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.\r
918**/\r
919STATIC\r
920VOID\r
921MergeMemoryMapForNotPresentEntry (\r
922 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,\r
923 IN OUT UINTN *MemoryMapSize,\r
924 IN UINTN DescriptorSize\r
925 )\r
926{\r
927 EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;\r
928 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;\r
929 UINT64 MemoryBlockLength;\r
930 EFI_MEMORY_DESCRIPTOR *NewMemoryMapEntry;\r
931 EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry;\r
932\r
933 MemoryMapEntry = MemoryMap;\r
934 NewMemoryMapEntry = MemoryMap;\r
935 MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + *MemoryMapSize);\r
936 while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {\r
937 CopyMem (NewMemoryMapEntry, MemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR));\r
938 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
939\r
940 do {\r
941 MemoryBlockLength = (UINT64) (EFI_PAGES_TO_SIZE((UINTN)MemoryMapEntry->NumberOfPages));\r
942 if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) &&\r
943 IsUefiPageNotPresent(MemoryMapEntry) && IsUefiPageNotPresent(NextMemoryMapEntry) &&\r
944 ((MemoryMapEntry->PhysicalStart + MemoryBlockLength) == NextMemoryMapEntry->PhysicalStart)) {\r
945 MemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;\r
946 if (NewMemoryMapEntry != MemoryMapEntry) {\r
947 NewMemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;\r
948 }\r
949\r
950 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);\r
951 continue;\r
952 } else {\r
953 MemoryMapEntry = PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);\r
954 break;\r
955 }\r
956 } while (TRUE);\r
957\r
958 MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
959 NewMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry, DescriptorSize);\r
960 }\r
961\r
962 *MemoryMapSize = (UINTN)NewMemoryMapEntry - (UINTN)MemoryMap;\r
963\r
964 return ;\r
965}\r
966\r
967/**\r
968 This function caches the UEFI memory map information.\r
969**/\r
970VOID\r
971GetUefiMemoryMap (\r
972 VOID\r
973 )\r
974{\r
975 EFI_STATUS Status;\r
976 UINTN MapKey;\r
977 UINT32 DescriptorVersion;\r
978 EFI_MEMORY_DESCRIPTOR *MemoryMap;\r
979 UINTN UefiMemoryMapSize;\r
980\r
981 DEBUG ((DEBUG_INFO, "GetUefiMemoryMap\n"));\r
982\r
983 UefiMemoryMapSize = 0;\r
984 MemoryMap = NULL;\r
985 Status = gBS->GetMemoryMap (\r
986 &UefiMemoryMapSize,\r
987 MemoryMap,\r
988 &MapKey,\r
989 &mUefiDescriptorSize,\r
990 &DescriptorVersion\r
991 );\r
992 ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
993\r
994 do {\r
995 Status = gBS->AllocatePool (EfiBootServicesData, UefiMemoryMapSize, (VOID **)&MemoryMap);\r
996 ASSERT (MemoryMap != NULL);\r
997 if (MemoryMap == NULL) {\r
998 return ;\r
999 }\r
1000\r
1001 Status = gBS->GetMemoryMap (\r
1002 &UefiMemoryMapSize,\r
1003 MemoryMap,\r
1004 &MapKey,\r
1005 &mUefiDescriptorSize,\r
1006 &DescriptorVersion\r
1007 );\r
1008 if (EFI_ERROR (Status)) {\r
1009 gBS->FreePool (MemoryMap);\r
1010 MemoryMap = NULL;\r
1011 }\r
1012 } while (Status == EFI_BUFFER_TOO_SMALL);\r
1013\r
403f5476
HW
1014 if (MemoryMap == NULL) {\r
1015 return ;\r
1016 }\r
1017\r
d2fc7711
JY
1018 SortMemoryMap (MemoryMap, UefiMemoryMapSize, mUefiDescriptorSize);\r
1019 MergeMemoryMapForNotPresentEntry (MemoryMap, &UefiMemoryMapSize, mUefiDescriptorSize);\r
1020\r
1021 mUefiMemoryMapSize = UefiMemoryMapSize;\r
1022 mUefiMemoryMap = AllocateCopyPool (UefiMemoryMapSize, MemoryMap);\r
1023 ASSERT (mUefiMemoryMap != NULL);\r
1024\r
1025 gBS->FreePool (MemoryMap);\r
1026}\r
1027\r
1028/**\r
1029 This function sets UEFI memory attribute according to UEFI memory map.\r
1030\r
1031 The normal memory region is marked as not present, such as\r
1032 EfiLoaderCode/Data, EfiBootServicesCode/Data, EfiConventionalMemory,\r
1033 EfiUnusableMemory, EfiACPIReclaimMemory.\r
1034**/\r
1035VOID\r
1036SetUefiMemMapAttributes (\r
1037 VOID\r
1038 )\r
1039{\r
1040 EFI_MEMORY_DESCRIPTOR *MemoryMap;\r
1041 UINTN MemoryMapEntryCount;\r
1042 UINTN Index;\r
1043\r
1044 DEBUG ((DEBUG_INFO, "SetUefiMemMapAttributes\n"));\r
1045\r
1046 if (mUefiMemoryMap == NULL) {\r
1047 DEBUG ((DEBUG_INFO, "UefiMemoryMap - NULL\n"));\r
1048 return ;\r
1049 }\r
1050\r
1051 MemoryMapEntryCount = mUefiMemoryMapSize/mUefiDescriptorSize;\r
1052 MemoryMap = mUefiMemoryMap;\r
1053 for (Index = 0; Index < MemoryMapEntryCount; Index++) {\r
1054 if (IsUefiPageNotPresent(MemoryMap)) {\r
1055 DEBUG ((DEBUG_INFO, "UefiMemory protection: 0x%lx - 0x%lx\n", MemoryMap->PhysicalStart, MemoryMap->PhysicalStart + (UINT64)EFI_PAGES_TO_SIZE((UINTN)MemoryMap->NumberOfPages)));\r
1056 SmmSetMemoryAttributes (\r
1057 MemoryMap->PhysicalStart,\r
1058 EFI_PAGES_TO_SIZE((UINTN)MemoryMap->NumberOfPages),\r
1059 EFI_MEMORY_RP\r
1060 );\r
1061 }\r
1062 MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, mUefiDescriptorSize);\r
1063 }\r
1064\r
1065 //\r
1066 // Do free mUefiMemoryMap, it will be checked in IsSmmCommBufferForbiddenAddress().\r
1067 //\r
1068}\r
1069\r
1070/**\r
1071 Return if the Address is forbidden as SMM communication buffer.\r
1072\r
1073 @param[in] Address the address to be checked\r
1074\r
1075 @return TRUE The address is forbidden as SMM communication buffer.\r
1076 @return FALSE The address is allowed as SMM communication buffer.\r
1077**/\r
1078BOOLEAN\r
1079IsSmmCommBufferForbiddenAddress (\r
1080 IN UINT64 Address\r
1081 )\r
1082{\r
1083 EFI_MEMORY_DESCRIPTOR *MemoryMap;\r
1084 UINTN MemoryMapEntryCount;\r
1085 UINTN Index;\r
1086\r
403f5476
HW
1087 if (mUefiMemoryMap == NULL) {\r
1088 return FALSE;\r
1089 }\r
1090\r
d2fc7711
JY
1091 MemoryMap = mUefiMemoryMap;\r
1092 MemoryMapEntryCount = mUefiMemoryMapSize/mUefiDescriptorSize;\r
1093 for (Index = 0; Index < MemoryMapEntryCount; Index++) {\r
1094 if (IsUefiPageNotPresent (MemoryMap)) {\r
1095 if ((Address >= MemoryMap->PhysicalStart) &&\r
1096 (Address < MemoryMap->PhysicalStart + EFI_PAGES_TO_SIZE((UINTN)MemoryMap->NumberOfPages)) ) {\r
1097 return TRUE;\r
1098 }\r
1099 }\r
1100 MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, mUefiDescriptorSize);\r
1101 }\r
1102 return FALSE;\r
1103}\r