]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/PiSmmCore/MemoryAttributesTable.c
MdeModulePkg/PiSmmCore: Add MemoryAttributes support.
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / MemoryAttributesTable.c
CommitLineData
285a682c
JY
1/** @file\r
2 PI SMM MemoryAttributes support\r
3\r
4Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include <PiDxe.h>\r
16#include <Library/BaseLib.h>\r
17#include <Library/BaseMemoryLib.h>\r
18#include <Library/MemoryAllocationLib.h>\r
19#include <Library/UefiBootServicesTableLib.h>\r
20#include <Library/SmmServicesTableLib.h>\r
21#include <Library/DebugLib.h>\r
22#include <Library/PcdLib.h>\r
23\r
24#include <Library/PeCoffLib.h>\r
25#include <Library/PeCoffGetEntryPointLib.h>\r
26\r
27#include <Guid/PiSmmMemoryAttributesTable.h>\r
28\r
29#include "PiSmmCore.h"\r
30\r
31#define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \\r
32 ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))\r
33\r
34#define IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE SIGNATURE_32 ('I','P','R','C')\r
35\r
36typedef struct {\r
37 UINT32 Signature;\r
38 LIST_ENTRY Link;\r
39 EFI_PHYSICAL_ADDRESS CodeSegmentBase;\r
40 UINT64 CodeSegmentSize;\r
41} IMAGE_PROPERTIES_RECORD_CODE_SECTION;\r
42\r
43#define IMAGE_PROPERTIES_RECORD_SIGNATURE SIGNATURE_32 ('I','P','R','D')\r
44\r
45typedef struct {\r
46 UINT32 Signature;\r
47 LIST_ENTRY Link;\r
48 EFI_PHYSICAL_ADDRESS ImageBase;\r
49 UINT64 ImageSize;\r
50 UINTN CodeSegmentCount;\r
51 LIST_ENTRY CodeSegmentList;\r
52} IMAGE_PROPERTIES_RECORD;\r
53\r
54#define IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('I','P','P','D')\r
55\r
56typedef struct {\r
57 UINT32 Signature;\r
58 UINTN ImageRecordCount;\r
59 UINTN CodeSegmentCountMax;\r
60 LIST_ENTRY ImageRecordList;\r
61} IMAGE_PROPERTIES_PRIVATE_DATA;\r
62\r
63IMAGE_PROPERTIES_PRIVATE_DATA mImagePropertiesPrivateData = {\r
64 IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE,\r
65 0,\r
66 0,\r
67 INITIALIZE_LIST_HEAD_VARIABLE (mImagePropertiesPrivateData.ImageRecordList)\r
68};\r
69\r
70#define EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA BIT0\r
71\r
72UINT64 mMemoryProtectionAttribute = EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA;\r
73\r
74//\r
75// Below functions are for MemoryMap\r
76//\r
77\r
78/**\r
79 Converts a number of EFI_PAGEs to a size in bytes.\r
80\r
81 NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only.\r
82\r
83 @param[in] Pages The number of EFI_PAGES.\r
84\r
85 @return The number of bytes associated with the number of EFI_PAGEs specified\r
86 by Pages.\r
87**/\r
88STATIC\r
89UINT64\r
90EfiPagesToSize (\r
91 IN UINT64 Pages\r
92 )\r
93{\r
94 return LShiftU64 (Pages, EFI_PAGE_SHIFT);\r
95}\r
96\r
97/**\r
98 Converts a size, in bytes, to a number of EFI_PAGESs.\r
99\r
100 NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only.\r
101\r
102 @param[in] Size A size in bytes.\r
103\r
104 @return The number of EFI_PAGESs associated with the number of bytes specified\r
105 by Size.\r
106\r
107**/\r
108STATIC\r
109UINT64\r
110EfiSizeToPages (\r
111 IN UINT64 Size\r
112 )\r
113{\r
114 return RShiftU64 (Size, EFI_PAGE_SHIFT) + ((((UINTN)Size) & EFI_PAGE_MASK) ? 1 : 0);\r
115}\r
116\r
117/**\r
118 Check the consistency of Smm memory attributes table.\r
119\r
120 @param[in] MemoryAttributesTable PI SMM memory attributes table\r
121**/\r
122VOID\r
123SmmMemoryAttributesTableConsistencyCheck (\r
124 IN EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable\r
125 )\r
126{\r
127 EFI_MEMORY_DESCRIPTOR *MemoryMap;\r
128 UINTN MemoryMapEntryCount;\r
129 UINTN DescriptorSize;\r
130 UINTN Index;\r
131 UINT64 Address;\r
132\r
133 Address = 0;\r
134 MemoryMapEntryCount = MemoryAttributesTable->NumberOfEntries;\r
135 DescriptorSize = MemoryAttributesTable->DescriptorSize;\r
136 MemoryMap = (EFI_MEMORY_DESCRIPTOR *)(MemoryAttributesTable + 1);\r
137 for (Index = 0; Index < MemoryMapEntryCount; Index++) {\r
138 if (Address != 0) {\r
139 ASSERT (Address == MemoryMap->PhysicalStart);\r
140 }\r
141 Address = MemoryMap->PhysicalStart + EFI_PAGES_TO_SIZE(MemoryMap->NumberOfPages);\r
142 MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize);\r
143 }\r
144}\r
145\r
146/**\r
147 Sort memory map entries based upon PhysicalStart, from low to high.\r
148\r
149 @param[in] MemoryMap A pointer to the buffer in which firmware places\r
150 the current memory map.\r
151 @param[in] MemoryMapSize Size, in bytes, of the MemoryMap buffer.\r
152 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.\r
153**/\r
154STATIC\r
155VOID\r
156SortMemoryMap (\r
157 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,\r
158 IN UINTN MemoryMapSize,\r
159 IN UINTN DescriptorSize\r
160 )\r
161{\r
162 EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;\r
163 EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry;\r
164 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;\r
165 EFI_MEMORY_DESCRIPTOR TempMemoryMap;\r
166\r
167 MemoryMapEntry = MemoryMap;\r
168 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
169 MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize);\r
170 while (MemoryMapEntry < MemoryMapEnd) {\r
171 while (NextMemoryMapEntry < MemoryMapEnd) {\r
172 if (MemoryMapEntry->PhysicalStart > NextMemoryMapEntry->PhysicalStart) {\r
173 CopyMem (&TempMemoryMap, MemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR));\r
174 CopyMem (MemoryMapEntry, NextMemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR));\r
175 CopyMem (NextMemoryMapEntry, &TempMemoryMap, sizeof(EFI_MEMORY_DESCRIPTOR));\r
176 }\r
177\r
178 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);\r
179 }\r
180\r
181 MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
182 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
183 }\r
184\r
185 return ;\r
186}\r
187\r
188/**\r
189 Merge continous memory map entries whose have same attributes.\r
190\r
191 @param[in, out] MemoryMap A pointer to the buffer in which firmware places\r
192 the current memory map.\r
193 @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the\r
194 MemoryMap buffer. On input, this is the size of\r
195 the current memory map. On output,\r
196 it is the size of new memory map after merge.\r
197 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.\r
198**/\r
199STATIC\r
200VOID\r
201MergeMemoryMap (\r
202 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,\r
203 IN OUT UINTN *MemoryMapSize,\r
204 IN UINTN DescriptorSize\r
205 )\r
206{\r
207 EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;\r
208 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;\r
209 UINT64 MemoryBlockLength;\r
210 EFI_MEMORY_DESCRIPTOR *NewMemoryMapEntry;\r
211 EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry;\r
212\r
213 MemoryMapEntry = MemoryMap;\r
214 NewMemoryMapEntry = MemoryMap;\r
215 MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + *MemoryMapSize);\r
216 while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {\r
217 CopyMem (NewMemoryMapEntry, MemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR));\r
218 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
219\r
220 do {\r
221 MemoryBlockLength = (UINT64) (EfiPagesToSize (MemoryMapEntry->NumberOfPages));\r
222 if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) &&\r
223 (MemoryMapEntry->Type == NextMemoryMapEntry->Type) &&\r
224 (MemoryMapEntry->Attribute == NextMemoryMapEntry->Attribute) &&\r
225 ((MemoryMapEntry->PhysicalStart + MemoryBlockLength) == NextMemoryMapEntry->PhysicalStart)) {\r
226 MemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;\r
227 if (NewMemoryMapEntry != MemoryMapEntry) {\r
228 NewMemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;\r
229 }\r
230\r
231 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);\r
232 continue;\r
233 } else {\r
234 MemoryMapEntry = PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);\r
235 break;\r
236 }\r
237 } while (TRUE);\r
238\r
239 MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
240 NewMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry, DescriptorSize);\r
241 }\r
242\r
243 *MemoryMapSize = (UINTN)NewMemoryMapEntry - (UINTN)MemoryMap;\r
244\r
245 return ;\r
246}\r
247\r
248/**\r
249 Enforce memory map attributes.\r
250 This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP.\r
251\r
252 @param[in, out] MemoryMap A pointer to the buffer in which firmware places\r
253 the current memory map.\r
254 @param[in] MemoryMapSize Size, in bytes, of the MemoryMap buffer.\r
255 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.\r
256**/\r
257STATIC\r
258VOID\r
259EnforceMemoryMapAttribute (\r
260 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,\r
261 IN UINTN MemoryMapSize,\r
262 IN UINTN DescriptorSize\r
263 )\r
264{\r
265 EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;\r
266 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;\r
267\r
268 MemoryMapEntry = MemoryMap;\r
269 MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize);\r
270 while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {\r
271 switch (MemoryMapEntry->Type) {\r
272 case EfiRuntimeServicesCode:\r
273 MemoryMapEntry->Attribute |= EFI_MEMORY_RO;\r
274 break;\r
275 case EfiRuntimeServicesData:\r
276 MemoryMapEntry->Attribute |= EFI_MEMORY_XP;\r
277 break;\r
278 }\r
279\r
280 MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
281 }\r
282\r
283 return ;\r
284}\r
285\r
286/**\r
287 Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].\r
288\r
289 @param[in] Buffer Start Address\r
290 @param[in] Length Address length\r
291\r
292 @return first image record covered by [buffer, length]\r
293**/\r
294STATIC\r
295IMAGE_PROPERTIES_RECORD *\r
296GetImageRecordByAddress (\r
297 IN EFI_PHYSICAL_ADDRESS Buffer,\r
298 IN UINT64 Length\r
299 )\r
300{\r
301 IMAGE_PROPERTIES_RECORD *ImageRecord;\r
302 LIST_ENTRY *ImageRecordLink;\r
303 LIST_ENTRY *ImageRecordList;\r
304\r
305 ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;\r
306\r
307 for (ImageRecordLink = ImageRecordList->ForwardLink;\r
308 ImageRecordLink != ImageRecordList;\r
309 ImageRecordLink = ImageRecordLink->ForwardLink) {\r
310 ImageRecord = CR (\r
311 ImageRecordLink,\r
312 IMAGE_PROPERTIES_RECORD,\r
313 Link,\r
314 IMAGE_PROPERTIES_RECORD_SIGNATURE\r
315 );\r
316\r
317 if ((Buffer <= ImageRecord->ImageBase) &&\r
318 (Buffer + Length >= ImageRecord->ImageBase + ImageRecord->ImageSize)) {\r
319 return ImageRecord;\r
320 }\r
321 }\r
322\r
323 return NULL;\r
324}\r
325\r
326/**\r
327 Set the memory map to new entries, according to one old entry,\r
328 based upon PE code section and data section in image record\r
329\r
330 @param[in] ImageRecord An image record whose [ImageBase, ImageSize] covered\r
331 by old memory map entry.\r
332 @param[in, out] NewRecord A pointer to several new memory map entries.\r
333 The caller gurantee the buffer size be 1 +\r
334 (SplitRecordCount * DescriptorSize) calculated\r
335 below.\r
336 @param[in] OldRecord A pointer to one old memory map entry.\r
337 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.\r
338**/\r
339STATIC\r
340UINTN\r
341SetNewRecord (\r
342 IN IMAGE_PROPERTIES_RECORD *ImageRecord,\r
343 IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord,\r
344 IN EFI_MEMORY_DESCRIPTOR *OldRecord,\r
345 IN UINTN DescriptorSize\r
346 )\r
347{\r
348 EFI_MEMORY_DESCRIPTOR TempRecord;\r
349 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;\r
350 LIST_ENTRY *ImageRecordCodeSectionLink;\r
351 LIST_ENTRY *ImageRecordCodeSectionEndLink;\r
352 LIST_ENTRY *ImageRecordCodeSectionList;\r
353 UINTN NewRecordCount;\r
354 UINT64 PhysicalEnd;\r
355 UINT64 ImageEnd;\r
356\r
357 CopyMem (&TempRecord, OldRecord, sizeof(EFI_MEMORY_DESCRIPTOR));\r
358 PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize(TempRecord.NumberOfPages);\r
359 NewRecordCount = 0;\r
360\r
361 ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;\r
362\r
363 ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;\r
364 ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;\r
365 while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {\r
366 ImageRecordCodeSection = CR (\r
367 ImageRecordCodeSectionLink,\r
368 IMAGE_PROPERTIES_RECORD_CODE_SECTION,\r
369 Link,\r
370 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE\r
371 );\r
372 ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;\r
373\r
374 if (TempRecord.PhysicalStart <= ImageRecordCodeSection->CodeSegmentBase) {\r
375 //\r
376 // DATA\r
377 //\r
378 NewRecord->Type = EfiRuntimeServicesData;\r
379 NewRecord->PhysicalStart = TempRecord.PhysicalStart;\r
380 NewRecord->VirtualStart = 0;\r
381 NewRecord->NumberOfPages = EfiSizeToPages(ImageRecordCodeSection->CodeSegmentBase - NewRecord->PhysicalStart);\r
382 NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP;\r
383 if (NewRecord->NumberOfPages != 0) {\r
384 NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);\r
385 NewRecordCount ++;\r
386 }\r
387\r
388 //\r
389 // CODE\r
390 //\r
391 NewRecord->Type = EfiRuntimeServicesCode;\r
392 NewRecord->PhysicalStart = ImageRecordCodeSection->CodeSegmentBase;\r
393 NewRecord->VirtualStart = 0;\r
394 NewRecord->NumberOfPages = EfiSizeToPages(ImageRecordCodeSection->CodeSegmentSize);\r
395 NewRecord->Attribute = (TempRecord.Attribute & (~EFI_MEMORY_XP)) | EFI_MEMORY_RO;\r
396 if (NewRecord->NumberOfPages != 0) {\r
397 NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);\r
398 NewRecordCount ++;\r
399 }\r
400\r
401 TempRecord.PhysicalStart = ImageRecordCodeSection->CodeSegmentBase + EfiPagesToSize (EfiSizeToPages(ImageRecordCodeSection->CodeSegmentSize));\r
402 TempRecord.NumberOfPages = EfiSizeToPages(PhysicalEnd - TempRecord.PhysicalStart);\r
403 if (TempRecord.NumberOfPages == 0) {\r
404 break;\r
405 }\r
406 }\r
407 }\r
408\r
409 ImageEnd = ImageRecord->ImageBase + ImageRecord->ImageSize;\r
410\r
411 //\r
412 // Final DATA\r
413 //\r
414 if (TempRecord.PhysicalStart < ImageEnd) {\r
415 NewRecord->Type = EfiRuntimeServicesData;\r
416 NewRecord->PhysicalStart = TempRecord.PhysicalStart;\r
417 NewRecord->VirtualStart = 0;\r
418 NewRecord->NumberOfPages = EfiSizeToPages (ImageEnd - TempRecord.PhysicalStart);\r
419 NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP;\r
420 NewRecordCount ++;\r
421 }\r
422\r
423 return NewRecordCount;\r
424}\r
425\r
426/**\r
427 Return the max number of new splitted entries, according to one old entry,\r
428 based upon PE code section and data section.\r
429\r
430 @param[in] OldRecord A pointer to one old memory map entry.\r
431\r
432 @retval 0 no entry need to be splitted.\r
433 @return the max number of new splitted entries\r
434**/\r
435STATIC\r
436UINTN\r
437GetMaxSplitRecordCount (\r
438 IN EFI_MEMORY_DESCRIPTOR *OldRecord\r
439 )\r
440{\r
441 IMAGE_PROPERTIES_RECORD *ImageRecord;\r
442 UINTN SplitRecordCount;\r
443 UINT64 PhysicalStart;\r
444 UINT64 PhysicalEnd;\r
445\r
446 SplitRecordCount = 0;\r
447 PhysicalStart = OldRecord->PhysicalStart;\r
448 PhysicalEnd = OldRecord->PhysicalStart + EfiPagesToSize(OldRecord->NumberOfPages);\r
449\r
450 do {\r
451 ImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart);\r
452 if (ImageRecord == NULL) {\r
453 break;\r
454 }\r
455 SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 1);\r
456 PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize;\r
457 } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));\r
458\r
459 if (SplitRecordCount != 0) {\r
460 SplitRecordCount--;\r
461 }\r
462\r
463 return SplitRecordCount;\r
464}\r
465\r
466/**\r
467 Split the memory map to new entries, according to one old entry,\r
468 based upon PE code section and data section.\r
469\r
470 @param[in] OldRecord A pointer to one old memory map entry.\r
471 @param[in, out] NewRecord A pointer to several new memory map entries.\r
472 The caller gurantee the buffer size be 1 +\r
473 (SplitRecordCount * DescriptorSize) calculated\r
474 below.\r
475 @param[in] MaxSplitRecordCount The max number of splitted entries\r
476 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.\r
477\r
478 @retval 0 no entry is splitted.\r
479 @return the real number of splitted record.\r
480**/\r
481STATIC\r
482UINTN\r
483SplitRecord (\r
484 IN EFI_MEMORY_DESCRIPTOR *OldRecord,\r
485 IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord,\r
486 IN UINTN MaxSplitRecordCount,\r
487 IN UINTN DescriptorSize\r
488 )\r
489{\r
490 EFI_MEMORY_DESCRIPTOR TempRecord;\r
491 IMAGE_PROPERTIES_RECORD *ImageRecord;\r
492 IMAGE_PROPERTIES_RECORD *NewImageRecord;\r
493 UINT64 PhysicalStart;\r
494 UINT64 PhysicalEnd;\r
495 UINTN NewRecordCount;\r
496 UINTN TotalNewRecordCount;\r
497\r
498 if (MaxSplitRecordCount == 0) {\r
499 CopyMem (NewRecord, OldRecord, DescriptorSize);\r
500 return 0;\r
501 }\r
502\r
503 TotalNewRecordCount = 0;\r
504\r
505 //\r
506 // Override previous record\r
507 //\r
508 CopyMem (&TempRecord, OldRecord, sizeof(EFI_MEMORY_DESCRIPTOR));\r
509 PhysicalStart = TempRecord.PhysicalStart;\r
510 PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize(TempRecord.NumberOfPages);\r
511\r
512 ImageRecord = NULL;\r
513 do {\r
514 NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart);\r
515 if (NewImageRecord == NULL) {\r
516 //\r
517 // No more image covered by this range, stop\r
518 //\r
519 if ((PhysicalEnd > PhysicalStart) && (ImageRecord != NULL)) {\r
520 //\r
521 // If this is still address in this record, need record.\r
522 //\r
523 NewRecord = PREVIOUS_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);\r
524 if (NewRecord->Type == EfiRuntimeServicesData) {\r
525 //\r
526 // Last record is DATA, just merge it.\r
527 //\r
528 NewRecord->NumberOfPages = EfiSizeToPages(PhysicalEnd - NewRecord->PhysicalStart);\r
529 } else {\r
530 //\r
531 // Last record is CODE, create a new DATA entry.\r
532 //\r
533 NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);\r
534 NewRecord->Type = EfiRuntimeServicesData;\r
535 NewRecord->PhysicalStart = TempRecord.PhysicalStart;\r
536 NewRecord->VirtualStart = 0;\r
537 NewRecord->NumberOfPages = TempRecord.NumberOfPages;\r
538 NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP;\r
539 TotalNewRecordCount ++;\r
540 }\r
541 }\r
542 break;\r
543 }\r
544 ImageRecord = NewImageRecord;\r
545\r
546 //\r
547 // Set new record\r
548 //\r
549 NewRecordCount = SetNewRecord (ImageRecord, NewRecord, &TempRecord, DescriptorSize);\r
550 TotalNewRecordCount += NewRecordCount;\r
551 NewRecord = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + NewRecordCount * DescriptorSize);\r
552\r
553 //\r
554 // Update PhysicalStart, in order to exclude the image buffer already splitted.\r
555 //\r
556 PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize;\r
557 TempRecord.PhysicalStart = PhysicalStart;\r
558 TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart);\r
559 } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));\r
560\r
561 return TotalNewRecordCount - 1;\r
562}\r
563\r
564/**\r
565 Split the original memory map, and add more entries to describe PE code section and data section.\r
566 This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.\r
567 This function will merge entries with same attributes finally.\r
568\r
569 NOTE: It assumes PE code/data section are page aligned.\r
570 NOTE: It assumes enough entry is prepared for new memory map.\r
571\r
572 Split table:\r
573 +---------------+\r
574 | Record X |\r
575 +---------------+\r
576 | Record RtCode |\r
577 +---------------+\r
578 | Record Y |\r
579 +---------------+\r
580 ==>\r
581 +---------------+\r
582 | Record X |\r
583 +---------------+ ----\r
584 | Record RtData | |\r
585 +---------------+ |\r
586 | Record RtCode | |-> PE/COFF1\r
587 +---------------+ |\r
588 | Record RtData | |\r
589 +---------------+ ----\r
590 | Record RtData | |\r
591 +---------------+ |\r
592 | Record RtCode | |-> PE/COFF2\r
593 +---------------+ |\r
594 | Record RtData | |\r
595 +---------------+ ----\r
596 | Record Y |\r
597 +---------------+\r
598\r
599 @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the\r
600 MemoryMap buffer. On input, this is the size of\r
601 old MemoryMap before split. The actual buffer\r
602 size of MemoryMap is MemoryMapSize +\r
603 (AdditionalRecordCount * DescriptorSize) calculated\r
604 below. On output, it is the size of new MemoryMap\r
605 after split.\r
606 @param[in, out] MemoryMap A pointer to the buffer in which firmware places\r
607 the current memory map.\r
608 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.\r
609**/\r
610STATIC\r
611VOID\r
612SplitTable (\r
613 IN OUT UINTN *MemoryMapSize,\r
614 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,\r
615 IN UINTN DescriptorSize\r
616 )\r
617{\r
618 INTN IndexOld;\r
619 INTN IndexNew;\r
620 UINTN MaxSplitRecordCount;\r
621 UINTN RealSplitRecordCount;\r
622 UINTN TotalSplitRecordCount;\r
623 UINTN AdditionalRecordCount;\r
624\r
625 AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 1) * mImagePropertiesPrivateData.ImageRecordCount;\r
626\r
627 TotalSplitRecordCount = 0;\r
628 //\r
629 // Let old record point to end of valid MemoryMap buffer.\r
630 //\r
631 IndexOld = ((*MemoryMapSize) / DescriptorSize) - 1;\r
632 //\r
633 // Let new record point to end of full MemoryMap buffer.\r
634 //\r
635 IndexNew = ((*MemoryMapSize) / DescriptorSize) - 1 + AdditionalRecordCount;\r
636 for (; IndexOld >= 0; IndexOld--) {\r
637 MaxSplitRecordCount = GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize));\r
638 //\r
639 // Split this MemoryMap record\r
640 //\r
641 IndexNew -= MaxSplitRecordCount;\r
642 RealSplitRecordCount = SplitRecord (\r
643 (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize),\r
644 (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexNew * DescriptorSize),\r
645 MaxSplitRecordCount,\r
646 DescriptorSize\r
647 );\r
648 //\r
649 // Adjust IndexNew according to real split.\r
650 //\r
651 CopyMem (\r
652 ((UINT8 *)MemoryMap + (IndexNew + MaxSplitRecordCount - RealSplitRecordCount) * DescriptorSize),\r
653 ((UINT8 *)MemoryMap + IndexNew * DescriptorSize),\r
654 RealSplitRecordCount * DescriptorSize\r
655 );\r
656 IndexNew = IndexNew + MaxSplitRecordCount - RealSplitRecordCount;\r
657 TotalSplitRecordCount += RealSplitRecordCount;\r
658 IndexNew --;\r
659 }\r
660 //\r
661 // Move all records to the beginning.\r
662 //\r
663 CopyMem (\r
664 MemoryMap,\r
665 (UINT8 *)MemoryMap + (AdditionalRecordCount - TotalSplitRecordCount) * DescriptorSize,\r
666 (*MemoryMapSize) + TotalSplitRecordCount * DescriptorSize\r
667 );\r
668\r
669 *MemoryMapSize = (*MemoryMapSize) + DescriptorSize * TotalSplitRecordCount;\r
670\r
671 //\r
672 // Sort from low to high (Just in case)\r
673 //\r
674 SortMemoryMap (MemoryMap, *MemoryMapSize, DescriptorSize);\r
675\r
676 //\r
677 // Set RuntimeData to XP\r
678 //\r
679 EnforceMemoryMapAttribute (MemoryMap, *MemoryMapSize, DescriptorSize);\r
680\r
681 //\r
682 // Merge same type to save entry size\r
683 //\r
684 MergeMemoryMap (MemoryMap, MemoryMapSize, DescriptorSize);\r
685\r
686 return ;\r
687}\r
688\r
689/**\r
690 This function for GetMemoryMap() with memory attributes table.\r
691\r
692 It calls original GetMemoryMap() to get the original memory map information. Then\r
693 plus the additional memory map entries for PE Code/Data seperation.\r
694\r
695 @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the\r
696 MemoryMap buffer. On input, this is the size of\r
697 the buffer allocated by the caller. On output,\r
698 it is the size of the buffer returned by the\r
699 firmware if the buffer was large enough, or the\r
700 size of the buffer needed to contain the map if\r
701 the buffer was too small.\r
702 @param[in, out] MemoryMap A pointer to the buffer in which firmware places\r
703 the current memory map.\r
704 @param[out] MapKey A pointer to the location in which firmware\r
705 returns the key for the current memory map.\r
706 @param[out] DescriptorSize A pointer to the location in which firmware\r
707 returns the size, in bytes, of an individual\r
708 EFI_MEMORY_DESCRIPTOR.\r
709 @param[out] DescriptorVersion A pointer to the location in which firmware\r
710 returns the version number associated with the\r
711 EFI_MEMORY_DESCRIPTOR.\r
712\r
713 @retval EFI_SUCCESS The memory map was returned in the MemoryMap\r
714 buffer.\r
715 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current\r
716 buffer size needed to hold the memory map is\r
717 returned in MemoryMapSize.\r
718 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
719\r
720**/\r
721STATIC\r
722EFI_STATUS\r
723EFIAPI\r
724SmmCoreGetMemoryMapMemoryAttributesTable (\r
725 IN OUT UINTN *MemoryMapSize,\r
726 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,\r
727 OUT UINTN *MapKey,\r
728 OUT UINTN *DescriptorSize,\r
729 OUT UINT32 *DescriptorVersion\r
730 )\r
731{\r
732 EFI_STATUS Status;\r
733 UINTN OldMemoryMapSize;\r
734 UINTN AdditionalRecordCount;\r
735\r
736 //\r
737 // If PE code/data is not aligned, just return.\r
738 //\r
739 if ((mMemoryProtectionAttribute & EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) == 0) {\r
740 return SmmCoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);\r
741 }\r
742\r
743 if (MemoryMapSize == NULL) {\r
744 return EFI_INVALID_PARAMETER;\r
745 }\r
746\r
747 AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 1) * mImagePropertiesPrivateData.ImageRecordCount;\r
748\r
749 OldMemoryMapSize = *MemoryMapSize;\r
750 Status = SmmCoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);\r
751 if (Status == EFI_BUFFER_TOO_SMALL) {\r
752 *MemoryMapSize = *MemoryMapSize + (*DescriptorSize) * AdditionalRecordCount;\r
753 } else if (Status == EFI_SUCCESS) {\r
754 if (OldMemoryMapSize - *MemoryMapSize < (*DescriptorSize) * AdditionalRecordCount) {\r
755 *MemoryMapSize = *MemoryMapSize + (*DescriptorSize) * AdditionalRecordCount;\r
756 //\r
757 // Need update status to buffer too small\r
758 //\r
759 Status = EFI_BUFFER_TOO_SMALL;\r
760 } else {\r
761 //\r
762 // Split PE code/data\r
763 //\r
764 ASSERT(MemoryMap != NULL);\r
765 SplitTable (MemoryMapSize, MemoryMap, *DescriptorSize);\r
766 }\r
767 }\r
768\r
769 return Status;\r
770}\r
771\r
772//\r
773// Below functions are for ImageRecord\r
774//\r
775\r
776/**\r
777 Set MemoryProtectionAttribute accroding to PE/COFF image section alignment.\r
778\r
779 @param[in] SectionAlignment PE/COFF section alignment\r
780**/\r
781STATIC\r
782VOID\r
783SetMemoryAttributesTableSectionAlignment (\r
784 IN UINT32 SectionAlignment\r
785 )\r
786{\r
787 if (((SectionAlignment & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) != 0) &&\r
788 ((mMemoryProtectionAttribute & EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) != 0)) {\r
789 DEBUG ((DEBUG_VERBOSE, "SMM SetMemoryAttributesTableSectionAlignment - Clear\n"));\r
790 mMemoryProtectionAttribute &= ~((UINT64)EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA);\r
791 }\r
792}\r
793\r
794/**\r
795 Swap two code sections in image record.\r
796\r
797 @param[in] FirstImageRecordCodeSection first code section in image record\r
798 @param[in] SecondImageRecordCodeSection second code section in image record\r
799**/\r
800STATIC\r
801VOID\r
802SwapImageRecordCodeSection (\r
803 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *FirstImageRecordCodeSection,\r
804 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *SecondImageRecordCodeSection\r
805 )\r
806{\r
807 IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection;\r
808\r
809 TempImageRecordCodeSection.CodeSegmentBase = FirstImageRecordCodeSection->CodeSegmentBase;\r
810 TempImageRecordCodeSection.CodeSegmentSize = FirstImageRecordCodeSection->CodeSegmentSize;\r
811\r
812 FirstImageRecordCodeSection->CodeSegmentBase = SecondImageRecordCodeSection->CodeSegmentBase;\r
813 FirstImageRecordCodeSection->CodeSegmentSize = SecondImageRecordCodeSection->CodeSegmentSize;\r
814\r
815 SecondImageRecordCodeSection->CodeSegmentBase = TempImageRecordCodeSection.CodeSegmentBase;\r
816 SecondImageRecordCodeSection->CodeSegmentSize = TempImageRecordCodeSection.CodeSegmentSize;\r
817}\r
818\r
819/**\r
820 Sort code section in image record, based upon CodeSegmentBase from low to high.\r
821\r
822 @param[in] ImageRecord image record to be sorted\r
823**/\r
824STATIC\r
825VOID\r
826SortImageRecordCodeSection (\r
827 IN IMAGE_PROPERTIES_RECORD *ImageRecord\r
828 )\r
829{\r
830 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;\r
831 IMAGE_PROPERTIES_RECORD_CODE_SECTION *NextImageRecordCodeSection;\r
832 LIST_ENTRY *ImageRecordCodeSectionLink;\r
833 LIST_ENTRY *NextImageRecordCodeSectionLink;\r
834 LIST_ENTRY *ImageRecordCodeSectionEndLink;\r
835 LIST_ENTRY *ImageRecordCodeSectionList;\r
836\r
837 ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;\r
838\r
839 ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;\r
840 NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;\r
841 ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;\r
842 while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {\r
843 ImageRecordCodeSection = CR (\r
844 ImageRecordCodeSectionLink,\r
845 IMAGE_PROPERTIES_RECORD_CODE_SECTION,\r
846 Link,\r
847 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE\r
848 );\r
849 while (NextImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {\r
850 NextImageRecordCodeSection = CR (\r
851 NextImageRecordCodeSectionLink,\r
852 IMAGE_PROPERTIES_RECORD_CODE_SECTION,\r
853 Link,\r
854 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE\r
855 );\r
856 if (ImageRecordCodeSection->CodeSegmentBase > NextImageRecordCodeSection->CodeSegmentBase) {\r
857 SwapImageRecordCodeSection (ImageRecordCodeSection, NextImageRecordCodeSection);\r
858 }\r
859 NextImageRecordCodeSectionLink = NextImageRecordCodeSectionLink->ForwardLink;\r
860 }\r
861\r
862 ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;\r
863 NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;\r
864 }\r
865}\r
866\r
867/**\r
868 Check if code section in image record is valid.\r
869\r
870 @param[in] ImageRecord image record to be checked\r
871\r
872 @retval TRUE image record is valid\r
873 @retval FALSE image record is invalid\r
874**/\r
875STATIC\r
876BOOLEAN\r
877IsImageRecordCodeSectionValid (\r
878 IN IMAGE_PROPERTIES_RECORD *ImageRecord\r
879 )\r
880{\r
881 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;\r
882 IMAGE_PROPERTIES_RECORD_CODE_SECTION *LastImageRecordCodeSection;\r
883 LIST_ENTRY *ImageRecordCodeSectionLink;\r
884 LIST_ENTRY *ImageRecordCodeSectionEndLink;\r
885 LIST_ENTRY *ImageRecordCodeSectionList;\r
886\r
887 DEBUG ((DEBUG_VERBOSE, "SMM ImageCode SegmentCount - 0x%x\n", ImageRecord->CodeSegmentCount));\r
888\r
889 ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;\r
890\r
891 ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;\r
892 ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;\r
893 LastImageRecordCodeSection = NULL;\r
894 while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {\r
895 ImageRecordCodeSection = CR (\r
896 ImageRecordCodeSectionLink,\r
897 IMAGE_PROPERTIES_RECORD_CODE_SECTION,\r
898 Link,\r
899 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE\r
900 );\r
901 if (ImageRecordCodeSection->CodeSegmentSize == 0) {\r
902 return FALSE;\r
903 }\r
904 if (ImageRecordCodeSection->CodeSegmentBase < ImageRecord->ImageBase) {\r
905 return FALSE;\r
906 }\r
907 if (ImageRecordCodeSection->CodeSegmentBase >= MAX_ADDRESS - ImageRecordCodeSection->CodeSegmentSize) {\r
908 return FALSE;\r
909 }\r
910 if ((ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize) > (ImageRecord->ImageBase + ImageRecord->ImageSize)) {\r
911 return FALSE;\r
912 }\r
913 if (LastImageRecordCodeSection != NULL) {\r
914 if ((LastImageRecordCodeSection->CodeSegmentBase + LastImageRecordCodeSection->CodeSegmentSize) > ImageRecordCodeSection->CodeSegmentBase) {\r
915 return FALSE;\r
916 }\r
917 }\r
918\r
919 LastImageRecordCodeSection = ImageRecordCodeSection;\r
920 ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;\r
921 }\r
922\r
923 return TRUE;\r
924}\r
925\r
926/**\r
927 Swap two image records.\r
928\r
929 @param[in] FirstImageRecord first image record.\r
930 @param[in] SecondImageRecord second image record.\r
931**/\r
932STATIC\r
933VOID\r
934SwapImageRecord (\r
935 IN IMAGE_PROPERTIES_RECORD *FirstImageRecord,\r
936 IN IMAGE_PROPERTIES_RECORD *SecondImageRecord\r
937 )\r
938{\r
939 IMAGE_PROPERTIES_RECORD TempImageRecord;\r
940\r
941 TempImageRecord.ImageBase = FirstImageRecord->ImageBase;\r
942 TempImageRecord.ImageSize = FirstImageRecord->ImageSize;\r
943 TempImageRecord.CodeSegmentCount = FirstImageRecord->CodeSegmentCount;\r
944\r
945 FirstImageRecord->ImageBase = SecondImageRecord->ImageBase;\r
946 FirstImageRecord->ImageSize = SecondImageRecord->ImageSize;\r
947 FirstImageRecord->CodeSegmentCount = SecondImageRecord->CodeSegmentCount;\r
948\r
949 SecondImageRecord->ImageBase = TempImageRecord.ImageBase;\r
950 SecondImageRecord->ImageSize = TempImageRecord.ImageSize;\r
951 SecondImageRecord->CodeSegmentCount = TempImageRecord.CodeSegmentCount;\r
952\r
953 SwapListEntries (&FirstImageRecord->CodeSegmentList, &SecondImageRecord->CodeSegmentList);\r
954}\r
955\r
956/**\r
957 Sort image record based upon the ImageBase from low to high.\r
958**/\r
959STATIC\r
960VOID\r
961SortImageRecord (\r
962 VOID\r
963 )\r
964{\r
965 IMAGE_PROPERTIES_RECORD *ImageRecord;\r
966 IMAGE_PROPERTIES_RECORD *NextImageRecord;\r
967 LIST_ENTRY *ImageRecordLink;\r
968 LIST_ENTRY *NextImageRecordLink;\r
969 LIST_ENTRY *ImageRecordEndLink;\r
970 LIST_ENTRY *ImageRecordList;\r
971\r
972 ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;\r
973\r
974 ImageRecordLink = ImageRecordList->ForwardLink;\r
975 NextImageRecordLink = ImageRecordLink->ForwardLink;\r
976 ImageRecordEndLink = ImageRecordList;\r
977 while (ImageRecordLink != ImageRecordEndLink) {\r
978 ImageRecord = CR (\r
979 ImageRecordLink,\r
980 IMAGE_PROPERTIES_RECORD,\r
981 Link,\r
982 IMAGE_PROPERTIES_RECORD_SIGNATURE\r
983 );\r
984 while (NextImageRecordLink != ImageRecordEndLink) {\r
985 NextImageRecord = CR (\r
986 NextImageRecordLink,\r
987 IMAGE_PROPERTIES_RECORD,\r
988 Link,\r
989 IMAGE_PROPERTIES_RECORD_SIGNATURE\r
990 );\r
991 if (ImageRecord->ImageBase > NextImageRecord->ImageBase) {\r
992 SwapImageRecord (ImageRecord, NextImageRecord);\r
993 }\r
994 NextImageRecordLink = NextImageRecordLink->ForwardLink;\r
995 }\r
996\r
997 ImageRecordLink = ImageRecordLink->ForwardLink;\r
998 NextImageRecordLink = ImageRecordLink->ForwardLink;\r
999 }\r
1000}\r
1001\r
1002/**\r
1003 Dump image record.\r
1004**/\r
1005STATIC\r
1006VOID\r
1007DumpImageRecord (\r
1008 VOID\r
1009 )\r
1010{\r
1011 IMAGE_PROPERTIES_RECORD *ImageRecord;\r
1012 LIST_ENTRY *ImageRecordLink;\r
1013 LIST_ENTRY *ImageRecordList;\r
1014 UINTN Index;\r
1015\r
1016 ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;\r
1017\r
1018 for (ImageRecordLink = ImageRecordList->ForwardLink, Index= 0;\r
1019 ImageRecordLink != ImageRecordList;\r
1020 ImageRecordLink = ImageRecordLink->ForwardLink, Index++) {\r
1021 ImageRecord = CR (\r
1022 ImageRecordLink,\r
1023 IMAGE_PROPERTIES_RECORD,\r
1024 Link,\r
1025 IMAGE_PROPERTIES_RECORD_SIGNATURE\r
1026 );\r
1027 DEBUG ((DEBUG_VERBOSE, "SMM Image[%d]: 0x%016lx - 0x%016lx\n", Index, ImageRecord->ImageBase, ImageRecord->ImageSize));\r
1028 }\r
1029}\r
1030\r
1031/**\r
1032 Insert image record.\r
1033\r
1034 @param[in] DriverEntry Driver information\r
1035**/\r
1036VOID\r
1037SmmInsertImageRecord (\r
1038 IN EFI_SMM_DRIVER_ENTRY *DriverEntry\r
1039 )\r
1040{\r
1041 VOID *ImageAddress;\r
1042 EFI_IMAGE_DOS_HEADER *DosHdr;\r
1043 UINT32 PeCoffHeaderOffset;\r
1044 UINT32 SectionAlignment;\r
1045 EFI_IMAGE_SECTION_HEADER *Section;\r
1046 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
1047 UINT8 *Name;\r
1048 UINTN Index;\r
1049 IMAGE_PROPERTIES_RECORD *ImageRecord;\r
1050 CHAR8 *PdbPointer;\r
1051 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;\r
1052 UINT16 Magic;\r
1053\r
1054 DEBUG ((DEBUG_VERBOSE, "SMM InsertImageRecord - 0x%x\n", DriverEntry));\r
1055 DEBUG ((DEBUG_VERBOSE, "SMM InsertImageRecord - 0x%016lx - 0x%08x\n", DriverEntry->ImageBuffer, DriverEntry->NumberOfPage));\r
1056\r
1057 ImageRecord = AllocatePool (sizeof(*ImageRecord));\r
1058 if (ImageRecord == NULL) {\r
1059 return ;\r
1060 }\r
1061 ImageRecord->Signature = IMAGE_PROPERTIES_RECORD_SIGNATURE;\r
1062\r
1063 DEBUG ((DEBUG_VERBOSE, "SMM ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));\r
1064\r
1065 //\r
1066 // Step 1: record whole region\r
1067 //\r
1068 ImageRecord->ImageBase = DriverEntry->ImageBuffer;\r
1069 ImageRecord->ImageSize = EFI_PAGES_TO_SIZE(DriverEntry->NumberOfPage);\r
1070\r
1071 ImageAddress = (VOID *)(UINTN)DriverEntry->ImageBuffer;\r
1072\r
1073 PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress);\r
1074 if (PdbPointer != NULL) {\r
1075 DEBUG ((DEBUG_VERBOSE, "SMM Image - %a\n", PdbPointer));\r
1076 }\r
1077\r
1078 //\r
1079 // Check PE/COFF image\r
1080 //\r
1081 DosHdr = (EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress;\r
1082 PeCoffHeaderOffset = 0;\r
1083 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
1084 PeCoffHeaderOffset = DosHdr->e_lfanew;\r
1085 }\r
1086\r
1087 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset);\r
1088 if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
1089 DEBUG ((DEBUG_VERBOSE, "SMM Hdr.Pe32->Signature invalid - 0x%x\n", Hdr.Pe32->Signature));\r
1090 goto Finish;\r
1091 }\r
1092\r
1093 //\r
1094 // Get SectionAlignment\r
1095 //\r
1096 if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1097 //\r
1098 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value\r
1099 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the\r
1100 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
1101 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
1102 //\r
1103 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
1104 } else {\r
1105 //\r
1106 // Get the magic value from the PE/COFF Optional Header\r
1107 //\r
1108 Magic = Hdr.Pe32->OptionalHeader.Magic;\r
1109 }\r
1110 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1111 SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment;\r
1112 } else {\r
1113 SectionAlignment = Hdr.Pe32Plus->OptionalHeader.SectionAlignment;\r
1114 }\r
1115\r
1116 SetMemoryAttributesTableSectionAlignment (SectionAlignment);\r
1117 if ((SectionAlignment & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) != 0) {\r
1118 DEBUG ((DEBUG_ERROR, "SMM !!!!!!!! InsertImageRecord - Section Alignment(0x%x) is not %dK !!!!!!!!\n",\r
1119 SectionAlignment, EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT >> 10));\r
1120 PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress);\r
1121 if (PdbPointer != NULL) {\r
1122 DEBUG ((DEBUG_ERROR, "SMM !!!!!!!! Image - %a !!!!!!!!\n", PdbPointer));\r
1123 }\r
1124 goto Finish;\r
1125 }\r
1126\r
1127 Section = (EFI_IMAGE_SECTION_HEADER *) (\r
1128 (UINT8 *) (UINTN) ImageAddress +\r
1129 PeCoffHeaderOffset +\r
1130 sizeof(UINT32) +\r
1131 sizeof(EFI_IMAGE_FILE_HEADER) +\r
1132 Hdr.Pe32->FileHeader.SizeOfOptionalHeader\r
1133 );\r
1134 ImageRecord->CodeSegmentCount = 0;\r
1135 InitializeListHead (&ImageRecord->CodeSegmentList);\r
1136 for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {\r
1137 Name = Section[Index].Name;\r
1138 DEBUG ((\r
1139 DEBUG_VERBOSE,\r
1140 "SMM Section - '%c%c%c%c%c%c%c%c'\n",\r
1141 Name[0],\r
1142 Name[1],\r
1143 Name[2],\r
1144 Name[3],\r
1145 Name[4],\r
1146 Name[5],\r
1147 Name[6],\r
1148 Name[7]\r
1149 ));\r
1150\r
1151 if ((Section[Index].Characteristics & EFI_IMAGE_SCN_CNT_CODE) != 0) {\r
1152 DEBUG ((DEBUG_VERBOSE, "SMM VirtualSize - 0x%08x\n", Section[Index].Misc.VirtualSize));\r
1153 DEBUG ((DEBUG_VERBOSE, "SMM VirtualAddress - 0x%08x\n", Section[Index].VirtualAddress));\r
1154 DEBUG ((DEBUG_VERBOSE, "SMM SizeOfRawData - 0x%08x\n", Section[Index].SizeOfRawData));\r
1155 DEBUG ((DEBUG_VERBOSE, "SMM PointerToRawData - 0x%08x\n", Section[Index].PointerToRawData));\r
1156 DEBUG ((DEBUG_VERBOSE, "SMM PointerToRelocations - 0x%08x\n", Section[Index].PointerToRelocations));\r
1157 DEBUG ((DEBUG_VERBOSE, "SMM PointerToLinenumbers - 0x%08x\n", Section[Index].PointerToLinenumbers));\r
1158 DEBUG ((DEBUG_VERBOSE, "SMM NumberOfRelocations - 0x%08x\n", Section[Index].NumberOfRelocations));\r
1159 DEBUG ((DEBUG_VERBOSE, "SMM NumberOfLinenumbers - 0x%08x\n", Section[Index].NumberOfLinenumbers));\r
1160 DEBUG ((DEBUG_VERBOSE, "SMM Characteristics - 0x%08x\n", Section[Index].Characteristics));\r
1161\r
1162 //\r
1163 // Step 2: record code section\r
1164 //\r
1165 ImageRecordCodeSection = AllocatePool (sizeof(*ImageRecordCodeSection));\r
1166 if (ImageRecordCodeSection == NULL) {\r
1167 return ;\r
1168 }\r
1169 ImageRecordCodeSection->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;\r
1170\r
1171 ImageRecordCodeSection->CodeSegmentBase = (UINTN)ImageAddress + Section[Index].VirtualAddress;\r
1172 ImageRecordCodeSection->CodeSegmentSize = Section[Index].SizeOfRawData;\r
1173\r
1174 DEBUG ((DEBUG_VERBOSE, "SMM ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection->CodeSegmentBase, ImageRecordCodeSection->CodeSegmentSize));\r
1175\r
1176 InsertTailList (&ImageRecord->CodeSegmentList, &ImageRecordCodeSection->Link);\r
1177 ImageRecord->CodeSegmentCount++;\r
1178 }\r
1179 }\r
1180\r
1181 if (ImageRecord->CodeSegmentCount == 0) {\r
1182 SetMemoryAttributesTableSectionAlignment (1);\r
1183 DEBUG ((DEBUG_ERROR, "SMM !!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n"));\r
1184 PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress);\r
1185 if (PdbPointer != NULL) {\r
1186 DEBUG ((DEBUG_ERROR, "SMM !!!!!!!! Image - %a !!!!!!!!\n", PdbPointer));\r
1187 }\r
1188 goto Finish;\r
1189 }\r
1190\r
1191 //\r
1192 // Final\r
1193 //\r
1194 SortImageRecordCodeSection (ImageRecord);\r
1195 //\r
1196 // Check overlap all section in ImageBase/Size\r
1197 //\r
1198 if (!IsImageRecordCodeSectionValid (ImageRecord)) {\r
1199 DEBUG ((DEBUG_ERROR, "SMM IsImageRecordCodeSectionValid - FAIL\n"));\r
1200 goto Finish;\r
1201 }\r
1202\r
1203 InsertTailList (&mImagePropertiesPrivateData.ImageRecordList, &ImageRecord->Link);\r
1204 mImagePropertiesPrivateData.ImageRecordCount++;\r
1205\r
1206 SortImageRecord ();\r
1207\r
1208 if (mImagePropertiesPrivateData.CodeSegmentCountMax < ImageRecord->CodeSegmentCount) {\r
1209 mImagePropertiesPrivateData.CodeSegmentCountMax = ImageRecord->CodeSegmentCount;\r
1210 }\r
1211\r
1212Finish:\r
1213 return ;\r
1214}\r
1215\r
1216/**\r
1217 Find image record accroding to image base and size.\r
1218\r
1219 @param[in] ImageBase Base of PE image\r
1220 @param[in] ImageSize Size of PE image\r
1221\r
1222 @return image record\r
1223**/\r
1224STATIC\r
1225IMAGE_PROPERTIES_RECORD *\r
1226FindImageRecord (\r
1227 IN EFI_PHYSICAL_ADDRESS ImageBase,\r
1228 IN UINT64 ImageSize\r
1229 )\r
1230{\r
1231 IMAGE_PROPERTIES_RECORD *ImageRecord;\r
1232 LIST_ENTRY *ImageRecordLink;\r
1233 LIST_ENTRY *ImageRecordList;\r
1234\r
1235 ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;\r
1236\r
1237 for (ImageRecordLink = ImageRecordList->ForwardLink;\r
1238 ImageRecordLink != ImageRecordList;\r
1239 ImageRecordLink = ImageRecordLink->ForwardLink) {\r
1240 ImageRecord = CR (\r
1241 ImageRecordLink,\r
1242 IMAGE_PROPERTIES_RECORD,\r
1243 Link,\r
1244 IMAGE_PROPERTIES_RECORD_SIGNATURE\r
1245 );\r
1246\r
1247 if ((ImageBase == ImageRecord->ImageBase) &&\r
1248 (ImageSize == ImageRecord->ImageSize)) {\r
1249 return ImageRecord;\r
1250 }\r
1251 }\r
1252\r
1253 return NULL;\r
1254}\r
1255\r
1256/**\r
1257 Remove Image record.\r
1258\r
1259 @param[in] DriverEntry Driver information\r
1260**/\r
1261VOID\r
1262SmmRemoveImageRecord (\r
1263 IN EFI_SMM_DRIVER_ENTRY *DriverEntry\r
1264 )\r
1265{\r
1266 IMAGE_PROPERTIES_RECORD *ImageRecord;\r
1267 LIST_ENTRY *CodeSegmentListHead;\r
1268 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;\r
1269\r
1270 DEBUG ((DEBUG_VERBOSE, "SMM RemoveImageRecord - 0x%x\n", DriverEntry));\r
1271 DEBUG ((DEBUG_VERBOSE, "SMM RemoveImageRecord - 0x%016lx - 0x%016lx\n", DriverEntry->ImageBuffer, DriverEntry->NumberOfPage));\r
1272\r
1273 ImageRecord = FindImageRecord (DriverEntry->ImageBuffer, EFI_PAGES_TO_SIZE(DriverEntry->NumberOfPage));\r
1274 if (ImageRecord == NULL) {\r
1275 DEBUG ((DEBUG_ERROR, "SMM !!!!!!!! ImageRecord not found !!!!!!!!\n"));\r
1276 return ;\r
1277 }\r
1278\r
1279 CodeSegmentListHead = &ImageRecord->CodeSegmentList;\r
1280 while (!IsListEmpty (CodeSegmentListHead)) {\r
1281 ImageRecordCodeSection = CR (\r
1282 CodeSegmentListHead->ForwardLink,\r
1283 IMAGE_PROPERTIES_RECORD_CODE_SECTION,\r
1284 Link,\r
1285 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE\r
1286 );\r
1287 RemoveEntryList (&ImageRecordCodeSection->Link);\r
1288 FreePool (ImageRecordCodeSection);\r
1289 }\r
1290\r
1291 RemoveEntryList (&ImageRecord->Link);\r
1292 FreePool (ImageRecord);\r
1293 mImagePropertiesPrivateData.ImageRecordCount--;\r
1294}\r
1295\r
1296/**\r
1297 Publish MemoryAttributesTable to SMM configuration table.\r
1298**/\r
1299VOID\r
1300PublishMemoryAttributesTable (\r
1301 VOID\r
1302 )\r
1303{\r
1304 UINTN MemoryMapSize;\r
1305 EFI_MEMORY_DESCRIPTOR *MemoryMap;\r
1306 UINTN MapKey;\r
1307 UINTN DescriptorSize;\r
1308 UINT32 DescriptorVersion;\r
1309 UINTN Index;\r
1310 EFI_STATUS Status;\r
1311 UINTN RuntimeEntryCount;\r
1312 EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable;\r
1313 EFI_MEMORY_DESCRIPTOR *MemoryAttributesEntry;\r
1314 UINTN MemoryAttributesTableSize;\r
1315\r
1316 MemoryMapSize = 0;\r
1317 MemoryMap = NULL;\r
1318 Status = SmmCoreGetMemoryMapMemoryAttributesTable (\r
1319 &MemoryMapSize,\r
1320 MemoryMap,\r
1321 &MapKey,\r
1322 &DescriptorSize,\r
1323 &DescriptorVersion\r
1324 );\r
1325 ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
1326\r
1327 do {\r
1328 DEBUG ((DEBUG_INFO, "MemoryMapSize - 0x%x\n", MemoryMapSize));\r
1329 MemoryMap = AllocatePool (MemoryMapSize);\r
1330 ASSERT (MemoryMap != NULL);\r
1331 DEBUG ((DEBUG_INFO, "MemoryMap - 0x%x\n", MemoryMap));\r
1332\r
1333 Status = SmmCoreGetMemoryMapMemoryAttributesTable (\r
1334 &MemoryMapSize,\r
1335 MemoryMap,\r
1336 &MapKey,\r
1337 &DescriptorSize,\r
1338 &DescriptorVersion\r
1339 );\r
1340 if (EFI_ERROR (Status)) {\r
1341 FreePool (MemoryMap);\r
1342 }\r
1343 } while (Status == EFI_BUFFER_TOO_SMALL);\r
1344\r
1345 //\r
1346 // Allocate MemoryAttributesTable\r
1347 //\r
1348 RuntimeEntryCount = MemoryMapSize/DescriptorSize;\r
1349 MemoryAttributesTableSize = sizeof(EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE) + DescriptorSize * RuntimeEntryCount;\r
1350 MemoryAttributesTable = AllocatePool (sizeof(EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE) + DescriptorSize * RuntimeEntryCount);\r
1351 ASSERT (MemoryAttributesTable != NULL);\r
1352 MemoryAttributesTable->Version = EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE_VERSION;\r
1353 MemoryAttributesTable->NumberOfEntries = (UINT32)RuntimeEntryCount;\r
1354 MemoryAttributesTable->DescriptorSize = (UINT32)DescriptorSize;\r
1355 MemoryAttributesTable->Reserved = 0;\r
1356 DEBUG ((DEBUG_INFO, "MemoryAttributesTable:\n"));\r
1357 DEBUG ((DEBUG_INFO, " Version - 0x%08x\n", MemoryAttributesTable->Version));\r
1358 DEBUG ((DEBUG_INFO, " NumberOfEntries - 0x%08x\n", MemoryAttributesTable->NumberOfEntries));\r
1359 DEBUG ((DEBUG_INFO, " DescriptorSize - 0x%08x\n", MemoryAttributesTable->DescriptorSize));\r
1360 MemoryAttributesEntry = (EFI_MEMORY_DESCRIPTOR *)(MemoryAttributesTable + 1);\r
1361 for (Index = 0; Index < MemoryMapSize/DescriptorSize; Index++) {\r
1362 CopyMem (MemoryAttributesEntry, MemoryMap, DescriptorSize);\r
1363 DEBUG ((DEBUG_INFO, "Entry (0x%x)\n", MemoryAttributesEntry));\r
1364 DEBUG ((DEBUG_INFO, " Type - 0x%x\n", MemoryAttributesEntry->Type));\r
1365 DEBUG ((DEBUG_INFO, " PhysicalStart - 0x%016lx\n", MemoryAttributesEntry->PhysicalStart));\r
1366 DEBUG ((DEBUG_INFO, " VirtualStart - 0x%016lx\n", MemoryAttributesEntry->VirtualStart));\r
1367 DEBUG ((DEBUG_INFO, " NumberOfPages - 0x%016lx\n", MemoryAttributesEntry->NumberOfPages));\r
1368 DEBUG ((DEBUG_INFO, " Attribute - 0x%016lx\n", MemoryAttributesEntry->Attribute));\r
1369 MemoryAttributesEntry = NEXT_MEMORY_DESCRIPTOR(MemoryAttributesEntry, DescriptorSize);\r
1370\r
1371 MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize);\r
1372 }\r
1373\r
1374 Status = gSmst->SmmInstallConfigurationTable (gSmst, &gEdkiiPiSmmMemoryAttributesTableGuid, MemoryAttributesTable, MemoryAttributesTableSize);\r
1375 ASSERT_EFI_ERROR (Status);\r
1376}\r
1377\r
1378/**\r
1379 This function returns if image is inside SMRAM.\r
1380\r
1381 @param[in] LoadedImage LoadedImage protocol instance for an image.\r
1382\r
1383 @retval TRUE the image is inside SMRAM.\r
1384 @retval FALSE the image is outside SMRAM.\r
1385**/\r
1386BOOLEAN\r
1387IsImageInsideSmram (\r
1388 IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage\r
1389 )\r
1390{\r
1391 UINTN Index;\r
1392\r
1393 for (Index = 0; Index < mFullSmramRangeCount; Index++) {\r
1394 if ((mFullSmramRanges[Index].PhysicalStart <= (UINTN)LoadedImage->ImageBase)&&\r
1395 (mFullSmramRanges[Index].PhysicalStart + mFullSmramRanges[Index].PhysicalSize >= (UINTN)LoadedImage->ImageBase + LoadedImage->ImageSize)) {\r
1396 return TRUE;\r
1397 }\r
1398 }\r
1399\r
1400 return FALSE;\r
1401}\r
1402\r
1403/**\r
1404 This function installs all SMM image record information.\r
1405**/\r
1406VOID\r
1407SmmInstallImageRecord (\r
1408 VOID\r
1409 )\r
1410{\r
1411 EFI_STATUS Status;\r
1412 UINTN NoHandles;\r
1413 EFI_HANDLE *HandleBuffer;\r
1414 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
1415 UINTN Index;\r
1416 EFI_SMM_DRIVER_ENTRY DriverEntry;\r
1417\r
1418 Status = SmmLocateHandleBuffer (\r
1419 ByProtocol,\r
1420 &gEfiLoadedImageProtocolGuid,\r
1421 NULL,\r
1422 &NoHandles,\r
1423 &HandleBuffer\r
1424 );\r
1425 if (EFI_ERROR (Status)) {\r
1426 return ;\r
1427 }\r
1428\r
1429 for (Index = 0; Index < NoHandles; Index++) {\r
1430 Status = gSmst->SmmHandleProtocol (\r
1431 HandleBuffer[Index],\r
1432 &gEfiLoadedImageProtocolGuid,\r
1433 (VOID **)&LoadedImage\r
1434 );\r
1435 if (EFI_ERROR (Status)) {\r
1436 continue;\r
1437 }\r
1438 DEBUG ((DEBUG_VERBOSE, "LoadedImage - 0x%x 0x%x ", LoadedImage->ImageBase, LoadedImage->ImageSize));\r
1439 {\r
1440 VOID *PdbPointer;\r
1441 PdbPointer = PeCoffLoaderGetPdbPointer (LoadedImage->ImageBase);\r
1442 if (PdbPointer != NULL) {\r
1443 DEBUG ((DEBUG_VERBOSE, "(%a) ", PdbPointer));\r
1444 }\r
1445 }\r
1446 DEBUG ((DEBUG_VERBOSE, "\n"));\r
1447 ZeroMem (&DriverEntry, sizeof(DriverEntry));\r
1448 DriverEntry.ImageBuffer = (UINTN)LoadedImage->ImageBase;\r
1449 DriverEntry.NumberOfPage = EFI_SIZE_TO_PAGES((UINTN)LoadedImage->ImageSize);\r
1450 SmmInsertImageRecord (&DriverEntry);\r
1451 }\r
1452\r
1453 FreePool (HandleBuffer);\r
1454}\r
1455\r
1456/**\r
1457 Install MemoryAttributesTable.\r
1458\r
1459 @param[in] Protocol Points to the protocol's unique identifier.\r
1460 @param[in] Interface Points to the interface instance.\r
1461 @param[in] Handle The handle on which the interface was installed.\r
1462\r
1463 @retval EFI_SUCCESS Notification runs successfully.\r
1464**/\r
1465EFI_STATUS\r
1466EFIAPI\r
1467SmmInstallMemoryAttributesTable (\r
1468 IN CONST EFI_GUID *Protocol,\r
1469 IN VOID *Interface,\r
1470 IN EFI_HANDLE Handle\r
1471 )\r
1472{\r
1473 SmmInstallImageRecord ();\r
1474\r
1475 DEBUG ((DEBUG_INFO, "SMM MemoryProtectionAttribute - 0x%016lx\n", mMemoryProtectionAttribute));\r
1476 if ((mMemoryProtectionAttribute & EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) == 0) {\r
1477 return EFI_SUCCESS;\r
1478 }\r
1479\r
1480 DEBUG ((DEBUG_VERBOSE, "SMM Total Image Count - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));\r
1481 DEBUG ((DEBUG_VERBOSE, "SMM Dump ImageRecord:\n"));\r
1482 DumpImageRecord ();\r
1483\r
1484 PublishMemoryAttributesTable ();\r
1485\r
1486 return EFI_SUCCESS;\r
1487}\r
1488\r
1489/**\r
1490 Initialize MemoryAttributesTable support.\r
1491**/\r
1492VOID\r
1493EFIAPI\r
1494SmmCoreInitializeMemoryAttributesTable (\r
1495 VOID\r
1496 )\r
1497{\r
1498 EFI_STATUS Status;\r
1499 VOID *Registration;\r
1500\r
1501 Status = gSmst->SmmRegisterProtocolNotify (\r
1502 &gEfiSmmEndOfDxeProtocolGuid,\r
1503 SmmInstallMemoryAttributesTable,\r
1504 &Registration\r
1505 );\r
1506 ASSERT_EFI_ERROR (Status);\r
1507\r
1508 return ;\r
1509}\r