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