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