1 /** @file
2 
3 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
5 
6 **/
7 
8 #include <Uefi.h>
9 #include <PiDxe.h>
10 #include <Library/UefiBootServicesTableLib.h>
11 #include <Library/TestPointCheckLib.h>
12 #include <Library/TestPointLib.h>
13 #include <Library/DebugLib.h>
14 #include <Library/PrintLib.h>
15 #include <Library/UefiLib.h>
16 #include <Library/BaseMemoryLib.h>
17 #include <Library/MemoryAllocationLib.h>
18 
19 CHAR8 *mMemoryTypeShortName[] = {
20   "Reserved  ",
21   "LoaderCode",
22   "LoaderData",
23   "BS_Code   ",
24   "BS_Data   ",
25   "RT_Code   ",
26   "RT_Data   ",
27   "Available ",
28   "Unusable  ",
29   "ACPI_Recl ",
30   "ACPI_NVS  ",
31   "MMIO      ",
32   "MMIO_Port ",
33   "PalCode   ",
34   "Persistent",
35 };
36 
37 STATIC CHAR8 mUnknownStr[11];
38 
39 CHAR8 *
40 ShortNameOfMemoryType(
41   IN UINT32 Type
42   )
43 {
44   if (Type < sizeof(mMemoryTypeShortName) / sizeof(mMemoryTypeShortName[0])) {
45     return mMemoryTypeShortName[Type];
46   } else {
47     AsciiSPrint(mUnknownStr, sizeof(mUnknownStr), "[%08x]", Type);
48     return mUnknownStr;
49   }
50 }
51 
52 
53 /**
54   Dump memory map.
55 
56   @param  MemoryMap              A pointer to the buffer in which firmware places
57                                  the current memory map.
58   @param  MemoryMapSize          Size, in bytes, of the MemoryMap buffer.
59   @param  DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
60 **/
61 VOID
62 TestPointDumpMemoryMap (
63   IN EFI_MEMORY_DESCRIPTOR  *MemoryMap,
64   IN UINTN                  MemoryMapSize,
65   IN UINTN                  DescriptorSize
66   )
67 {
68   EFI_MEMORY_DESCRIPTOR *Entry;
69   UINTN                 NumberOfEntries;
70   UINTN                 Index;
71   UINT64                Pages[EfiMaxMemoryType];
72 
73   ZeroMem (Pages, sizeof(Pages));
74 
75   DEBUG ((EFI_D_INFO, "MemoryMap:\n"));
76 
77   Entry = MemoryMap;
78   NumberOfEntries = MemoryMapSize / DescriptorSize;
79   DEBUG ((DEBUG_INFO, "Type       Start            End              # Pages          Attributes\n"));
80   for (Index = 0; Index < NumberOfEntries; Index++) {
81     DEBUG ((DEBUG_INFO, ShortNameOfMemoryType(Entry->Type)));
82     DEBUG ((DEBUG_INFO, " %016LX-%016LX %016LX %016LX\n",
83       Entry->PhysicalStart,
84       Entry->PhysicalStart+MultU64x64 (SIZE_4KB,Entry->NumberOfPages) - 1,
85       Entry->NumberOfPages,
86       Entry->Attribute
87       ));
88     if (Entry->Type < EfiMaxMemoryType) {
89       Pages[Entry->Type] += Entry->NumberOfPages;
90     }
91     Entry = NEXT_MEMORY_DESCRIPTOR (Entry, DescriptorSize);
92   }
93 
94   DEBUG ((DEBUG_INFO, "\n"));
95   DEBUG ((DEBUG_INFO, "  Reserved  : %14ld Pages (%ld Bytes)\n", Pages[EfiReservedMemoryType],      MultU64x64(SIZE_4KB, Pages[EfiReservedMemoryType])));
96   DEBUG ((DEBUG_INFO, "  LoaderCode: %14ld Pages (%ld Bytes)\n", Pages[EfiLoaderCode],              MultU64x64(SIZE_4KB, Pages[EfiLoaderCode])));
97   DEBUG ((DEBUG_INFO, "  LoaderData: %14ld Pages (%ld Bytes)\n", Pages[EfiLoaderData],              MultU64x64(SIZE_4KB, Pages[EfiLoaderData])));
98   DEBUG ((DEBUG_INFO, "  BS_Code   : %14ld Pages (%ld Bytes)\n", Pages[EfiBootServicesCode],        MultU64x64(SIZE_4KB, Pages[EfiBootServicesCode])));
99   DEBUG ((DEBUG_INFO, "  BS_Data   : %14ld Pages (%ld Bytes)\n", Pages[EfiBootServicesData],        MultU64x64(SIZE_4KB, Pages[EfiBootServicesData])));
100   DEBUG ((DEBUG_INFO, "  RT_Code   : %14ld Pages (%ld Bytes)\n", Pages[EfiRuntimeServicesCode],     MultU64x64(SIZE_4KB, Pages[EfiRuntimeServicesCode])));
101   DEBUG ((DEBUG_INFO, "  RT_Data   : %14ld Pages (%ld Bytes)\n", Pages[EfiRuntimeServicesData],     MultU64x64(SIZE_4KB, Pages[EfiRuntimeServicesData])));
102   DEBUG ((DEBUG_INFO, "  ACPI_Recl : %14ld Pages (%ld Bytes)\n", Pages[EfiACPIReclaimMemory],       MultU64x64(SIZE_4KB, Pages[EfiACPIReclaimMemory])));
103   DEBUG ((DEBUG_INFO, "  ACPI_NVS  : %14ld Pages (%ld Bytes)\n", Pages[EfiACPIMemoryNVS],           MultU64x64(SIZE_4KB, Pages[EfiACPIMemoryNVS])));
104   DEBUG ((DEBUG_INFO, "  MMIO      : %14ld Pages (%ld Bytes)\n", Pages[EfiMemoryMappedIO],          MultU64x64(SIZE_4KB, Pages[EfiMemoryMappedIO])));
105   DEBUG ((DEBUG_INFO, "  MMIO_Port : %14ld Pages (%ld Bytes)\n", Pages[EfiMemoryMappedIOPortSpace], MultU64x64(SIZE_4KB, Pages[EfiMemoryMappedIOPortSpace])));
106   DEBUG ((DEBUG_INFO, "  PalCode   : %14ld Pages (%ld Bytes)\n", Pages[EfiPalCode],                 MultU64x64(SIZE_4KB, Pages[EfiPalCode])));
107   DEBUG ((DEBUG_INFO, "  Available : %14ld Pages (%ld Bytes)\n", Pages[EfiConventionalMemory],      MultU64x64(SIZE_4KB, Pages[EfiConventionalMemory])));
108   DEBUG ((DEBUG_INFO, "  Persistent: %14ld Pages (%ld Bytes)\n", Pages[EfiPersistentMemory],        MultU64x64(SIZE_4KB, Pages[EfiPersistentMemory])));
109   DEBUG ((DEBUG_INFO, "              -------------- \n"));
110 }
111 
112 BOOLEAN
113 TestPointCheckUefiMemoryMapEntry (
114   IN EFI_MEMORY_DESCRIPTOR  *MemoryMap,
115   IN UINTN                  MemoryMapSize,
116   IN UINTN                  DescriptorSize
117   )
118 {
119   EFI_MEMORY_DESCRIPTOR *Entry;
120   UINTN                 NumberOfEntries;
121   UINTN                 Index;
122   UINT64                EntryCount[EfiMaxMemoryType];
123 
124   ZeroMem (EntryCount, sizeof(EntryCount));
125 
126   Entry = MemoryMap;
127   NumberOfEntries = MemoryMapSize / DescriptorSize;
128   for (Index = 0; Index < NumberOfEntries; Index++) {
129     if (Entry->Type < EfiMaxMemoryType) {
130       EntryCount[Entry->Type] ++;
131     }
132     Entry = NEXT_MEMORY_DESCRIPTOR (Entry, DescriptorSize);
133   }
134   if (EntryCount[EfiRuntimeServicesCode] > 1) {
135     DEBUG ((DEBUG_ERROR, "EfiRuntimeServicesCode entry - %d\n", EntryCount[EfiRuntimeServicesCode]));
136   }
137   if (EntryCount[EfiRuntimeServicesData] > 1) {
138     DEBUG ((DEBUG_ERROR, "EfiRuntimeServicesData entry - %d\n", EntryCount[EfiRuntimeServicesCode]));
139   }
140   if (EntryCount[EfiACPIMemoryNVS] > 1) {
141     DEBUG ((DEBUG_ERROR, "EfiACPIMemoryNVS entry - %d\n", EntryCount[EfiACPIMemoryNVS]));
142   }
143   if (EntryCount[EfiACPIReclaimMemory] > 1) {
144     DEBUG ((DEBUG_ERROR, "EfiACPIReclaimMemory entry - %d\n", EntryCount[EfiACPIReclaimMemory]));
145   }
146   if ((EntryCount[EfiRuntimeServicesCode] > 1) ||
147       (EntryCount[EfiRuntimeServicesData] > 1) ||
148       (EntryCount[EfiACPIReclaimMemory] > 1) ||
149       (EntryCount[EfiACPIMemoryNVS] > 1) ) {
150     return FALSE;
151   } else {
152     return TRUE;
153   }
154 }
155 
156 VOID
157 TestPointDumpUefiMemoryMap (
158   OUT EFI_MEMORY_DESCRIPTOR **UefiMemoryMap, OPTIONAL
159   OUT UINTN                 *UefiMemoryMapSize, OPTIONAL
160   OUT UINTN                 *UefiDescriptorSize, OPTIONAL
161   IN  BOOLEAN               DumpPrint
162   )
163 {
164   EFI_STATUS            Status;
165   UINTN                 MapKey;
166   UINT32                DescriptorVersion;
167   EFI_MEMORY_DESCRIPTOR *MemoryMap;
168   UINTN                 MemoryMapSize;
169   UINTN                 DescriptorSize;
170 
171   if (UefiMemoryMap != NULL) {
172     *UefiMemoryMap = NULL;
173     *UefiMemoryMapSize = 0;
174     *UefiDescriptorSize = 0;
175   }
176 
177   if (DumpPrint) {
178     DEBUG ((DEBUG_INFO, "==== TestPointDumpUefiMemoryMap - Enter\n"));
179   }
180   MemoryMapSize = 0;
181   MemoryMap = NULL;
182   Status = gBS->GetMemoryMap (
183                   &MemoryMapSize,
184                   MemoryMap,
185                   &MapKey,
186                   &DescriptorSize,
187                   &DescriptorVersion
188                   );
189   ASSERT (Status == EFI_BUFFER_TOO_SMALL);
190 
191   do {
192     Status = gBS->AllocatePool (EfiBootServicesData, MemoryMapSize, (VOID **)&MemoryMap);
193     ASSERT (MemoryMap != NULL);
194     if (MemoryMap == NULL) {
195       goto Done ;
196     }
197 
198     Status = gBS->GetMemoryMap (
199                     &MemoryMapSize,
200                     MemoryMap,
201                     &MapKey,
202                     &DescriptorSize,
203                     &DescriptorVersion
204                     );
205     if (EFI_ERROR (Status)) {
206       gBS->FreePool (MemoryMap);
207       MemoryMap = NULL;
208     }
209   } while (Status == EFI_BUFFER_TOO_SMALL);
210 
211   if (MemoryMap == NULL) {
212     goto Done ;
213   }
214 
215   if (DumpPrint) {
216     TestPointDumpMemoryMap (MemoryMap, MemoryMapSize, DescriptorSize);
217   }
218 
219   if (UefiMemoryMap != NULL) {
220     *UefiMemoryMap = AllocateCopyPool (MemoryMapSize, MemoryMap);
221     *UefiMemoryMapSize = MemoryMapSize;
222     *UefiDescriptorSize = DescriptorSize;
223   }
224   gBS->FreePool (MemoryMap);
225 
226 Done:
227   if (DumpPrint) {
228     DEBUG ((DEBUG_INFO, "==== TestPointDumpUefiMemoryMap - Exit\n"));
229   }
230   return ;
231 }
232 
233 EFI_STATUS
234 TestPointCheckUefiMemoryMap (
235   VOID
236   )
237 {
238   EFI_STATUS            Status;
239   UINTN                 MapKey;
240   UINT32                DescriptorVersion;
241   EFI_MEMORY_DESCRIPTOR *MemoryMap;
242   UINTN                 UefiMemoryMapSize;
243   UINTN                 UefiDescriptorSize;
244   BOOLEAN               Result;
245 
246   DEBUG ((DEBUG_INFO, "==== TestPointCheckUefiMemoryMap - Enter\n"));
247   UefiMemoryMapSize = 0;
248   MemoryMap = NULL;
249   Status = gBS->GetMemoryMap (
250                   &UefiMemoryMapSize,
251                   MemoryMap,
252                   &MapKey,
253                   &UefiDescriptorSize,
254                   &DescriptorVersion
255                   );
256   ASSERT (Status == EFI_BUFFER_TOO_SMALL);
257 
258   do {
259     Status = gBS->AllocatePool (EfiBootServicesData, UefiMemoryMapSize, (VOID **)&MemoryMap);
260     ASSERT (MemoryMap != NULL);
261     if (MemoryMap == NULL) {
262       Status = EFI_OUT_OF_RESOURCES;
263       goto Done ;
264     }
265 
266     Status = gBS->GetMemoryMap (
267                     &UefiMemoryMapSize,
268                     MemoryMap,
269                     &MapKey,
270                     &UefiDescriptorSize,
271                     &DescriptorVersion
272                     );
273     if (EFI_ERROR (Status)) {
274       gBS->FreePool (MemoryMap);
275       MemoryMap = NULL;
276     }
277   } while (Status == EFI_BUFFER_TOO_SMALL);
278 
279   if (MemoryMap == NULL) {
280     Status = EFI_OUT_OF_RESOURCES;
281     goto Done ;
282   }
283 
284   Result = TestPointCheckUefiMemoryMapEntry (MemoryMap, UefiMemoryMapSize, UefiDescriptorSize);
285   if (!Result) {
286     TestPointLibAppendErrorString (
287       PLATFORM_TEST_POINT_ROLE_PLATFORM_IBV,
288       NULL,
289       TEST_POINT_BYTE4_READY_TO_BOOT_MEMORY_TYPE_INFORMATION_FUNCTIONAL_ERROR_CODE \
290         TEST_POINT_READY_TO_BOOT \
291         TEST_POINT_BYTE4_READY_TO_BOOT_MEMORY_TYPE_INFORMATION_FUNCTIONAL_ERROR_STRING
292       );
293     Status = EFI_INVALID_PARAMETER;
294   } else {
295     Status = EFI_SUCCESS;
296   }
297 
298   gBS->FreePool (MemoryMap);
299 
300 Done:
301   DEBUG ((DEBUG_INFO, "==== TestPointCheckUefiMemoryMap - Exit\n"));
302   return Status;
303 }