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