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