]>
Commit | Line | Data |
---|---|---|
4184aabd MK |
1 | /** @file\r |
2 | Publishes ESRT table from Firmware Management Protocol instances\r | |
3 | \r | |
4 | Copyright (c) 2016, Microsoft Corporation\r | |
e314132f | 5 | Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>\r |
4184aabd MK |
6 | \r |
7 | All rights reserved.\r | |
9d510e61 | 8 | SPDX-License-Identifier: BSD-2-Clause-Patent\r |
4184aabd MK |
9 | \r |
10 | **/\r | |
11 | \r | |
12 | #include <Uefi.h>\r | |
13 | #include <Library/BaseLib.h>\r | |
14 | #include <Library/BaseMemoryLib.h>\r | |
15 | #include <Library/MemoryAllocationLib.h>\r | |
16 | #include <Library/UefiBootServicesTableLib.h>\r | |
17 | #include <Library/DebugLib.h>\r | |
18 | #include <Library/PcdLib.h>\r | |
19 | #include <Library/UefiLib.h>\r | |
20 | #include <Protocol/FirmwareManagement.h>\r | |
21 | #include <Guid/EventGroup.h>\r | |
22 | #include <Guid/SystemResourceTable.h>\r | |
23 | \r | |
e314132f JE |
24 | ///\r |
25 | /// Structure for array of unique GUID/HardwareInstance pairs from the\r | |
26 | /// current set of EFI_FIRMWARE_IMAGE_DESCRIPTORs from all FMP Protocols.\r | |
27 | ///\r | |
28 | typedef struct {\r | |
29 | ///\r | |
30 | /// A unique GUID identifying the firmware image type.\r | |
31 | ///\r | |
1436aea4 | 32 | EFI_GUID ImageTypeGuid;\r |
e314132f JE |
33 | ///\r |
34 | /// An optional number to identify the unique hardware instance within the\r | |
35 | /// system for devices that may have multiple instances whenever possible.\r | |
36 | ///\r | |
1436aea4 | 37 | UINT64 HardwareInstance;\r |
e314132f JE |
38 | } GUID_HARDWAREINSTANCE_PAIR;\r |
39 | \r | |
ae38c976 DB |
40 | /**\r |
41 | Print ESRT to debug console.\r | |
42 | \r | |
43 | @param[in] Table Pointer to the ESRT table.\r | |
44 | \r | |
45 | **/\r | |
4184aabd MK |
46 | VOID\r |
47 | EFIAPI\r | |
48 | PrintTable (\r | |
49 | IN EFI_SYSTEM_RESOURCE_TABLE *Table\r | |
50 | );\r | |
51 | \r | |
4184aabd MK |
52 | /**\r |
53 | Install EFI System Resource Table into the UEFI Configuration Table\r | |
54 | \r | |
6ec4d300 SZ |
55 | @param[in] Table Pointer to the ESRT.\r |
56 | \r | |
4184aabd MK |
57 | @return Status code.\r |
58 | \r | |
59 | **/\r | |
60 | EFI_STATUS\r | |
61 | InstallEfiSystemResourceTableInUefiConfigurationTable (\r | |
1436aea4 | 62 | IN EFI_SYSTEM_RESOURCE_TABLE *Table\r |
4184aabd MK |
63 | )\r |
64 | {\r | |
1436aea4 | 65 | EFI_STATUS Status;\r |
4184aabd MK |
66 | \r |
67 | Status = EFI_SUCCESS;\r | |
6ec4d300 SZ |
68 | if (Table->FwResourceCount == 0) {\r |
69 | DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Can't install ESRT table because it has zero Entries. \n"));\r | |
70 | Status = EFI_UNSUPPORTED;\r | |
71 | } else {\r | |
72 | //\r | |
73 | // Install the pointer into config table\r | |
74 | //\r | |
75 | Status = gBS->InstallConfigurationTable (&gEfiSystemResourceTableGuid, Table);\r | |
76 | if (EFI_ERROR (Status)) {\r | |
77 | DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Can't install ESRT table. Status: %r. \n", Status));\r | |
4184aabd | 78 | } else {\r |
6ec4d300 | 79 | DEBUG ((DEBUG_INFO, "EsrtFmpDxe: Installed ESRT table. \n"));\r |
4184aabd MK |
80 | }\r |
81 | }\r | |
1436aea4 | 82 | \r |
4184aabd MK |
83 | return Status;\r |
84 | }\r | |
85 | \r | |
86 | /**\r | |
87 | Return if this FMP is a system FMP or a device FMP, based upon FmpImageInfo.\r | |
88 | \r | |
89 | @param[in] FmpImageInfo A pointer to EFI_FIRMWARE_IMAGE_DESCRIPTOR\r | |
90 | \r | |
91 | @return TRUE It is a system FMP.\r | |
92 | @return FALSE It is a device FMP.\r | |
93 | **/\r | |
94 | BOOLEAN\r | |
95 | IsSystemFmp (\r | |
96 | IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfo\r | |
97 | )\r | |
98 | {\r | |
99 | GUID *Guid;\r | |
100 | UINTN Count;\r | |
101 | UINTN Index;\r | |
102 | \r | |
103 | Guid = PcdGetPtr (PcdSystemFmpCapsuleImageTypeIdGuid);\r | |
1436aea4 | 104 | Count = PcdGetSize (PcdSystemFmpCapsuleImageTypeIdGuid) / sizeof (GUID);\r |
4184aabd MK |
105 | \r |
106 | for (Index = 0; Index < Count; Index++, Guid++) {\r | |
107 | if (CompareGuid (&FmpImageInfo->ImageTypeId, Guid)) {\r | |
108 | return TRUE;\r | |
109 | }\r | |
110 | }\r | |
111 | \r | |
112 | return FALSE;\r | |
113 | }\r | |
114 | \r | |
115 | /**\r | |
e314132f JE |
116 | Function to create a single ESRT Entry and add it to the ESRT with\r |
117 | a given FMP descriptor. If the GUID is already in the ESRT, then the ESRT\r | |
118 | entry is updated.\r | |
119 | \r | |
120 | @param[in,out] Table Pointer to the ESRT Table.\r | |
121 | @param[in,out] HardwareInstances Pointer to the GUID_HARDWAREINSTANCE_PAIR.\r | |
122 | @param[in,out] NumberOfDescriptors The number of EFI_FIRMWARE_IMAGE_DESCRIPTORs.\r | |
123 | @param[in] FmpImageInfoBuf Pointer to the EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r | |
124 | @param[in] FmpVersion FMP Version.\r | |
125 | \r | |
126 | @retval EFI_SUCCESS FmpImageInfoBuf was use to fill in a new ESRT entry\r | |
127 | in Table.\r | |
128 | @retval EFI_SUCCESS The ImageTypeId GUID in FmpImageInfoBuf matches an\r | |
129 | existing ESRT entry in Table, and the information\r | |
130 | from FmpImageInfoBuf was merged into the the existing\r | |
131 | ESRT entry.\r | |
132 | @retval EFI_UNSPOORTED The GUID/HardareInstance in FmpImageInfoBuf has is a\r | |
133 | duplicate.\r | |
4184aabd MK |
134 | \r |
135 | **/\r | |
136 | EFI_STATUS\r | |
4184aabd | 137 | CreateEsrtEntry (\r |
e314132f JE |
138 | IN OUT EFI_SYSTEM_RESOURCE_TABLE *Table,\r |
139 | IN OUT GUID_HARDWAREINSTANCE_PAIR *HardwareInstances,\r | |
140 | IN OUT UINT32 *NumberOfDescriptors,\r | |
141 | IN EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf,\r | |
142 | IN UINT32 FmpVersion\r | |
4184aabd MK |
143 | )\r |
144 | {\r | |
145 | UINTN Index;\r | |
146 | EFI_SYSTEM_RESOURCE_ENTRY *Entry;\r | |
e314132f | 147 | UINT64 FmpHardwareInstance;\r |
4184aabd | 148 | \r |
e314132f JE |
149 | FmpHardwareInstance = 0;\r |
150 | if (FmpVersion >= 3) {\r | |
151 | FmpHardwareInstance = FmpImageInfoBuf->HardwareInstance;\r | |
152 | }\r | |
4184aabd | 153 | \r |
4184aabd | 154 | //\r |
e314132f | 155 | // Check to see of FmpImageInfoBuf GUID/HardwareInstance is unique\r |
090642db | 156 | // Skip if HardwareInstance is 0 as this is the case if FmpVersion < 3\r |
157 | // or the device can not create a unique ID per UEFI specification\r | |
4184aabd | 158 | //\r |
090642db | 159 | if (FmpHardwareInstance != 0) {\r |
160 | for (Index = 0; Index < *NumberOfDescriptors; Index++) {\r | |
161 | if (CompareGuid (&HardwareInstances[Index].ImageTypeGuid, &FmpImageInfoBuf->ImageTypeId)) {\r | |
162 | if (HardwareInstances[Index].HardwareInstance == FmpHardwareInstance) {\r | |
163 | DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Duplicate firmware image descriptor with GUID %g HardwareInstance:0x%x\n", &FmpImageInfoBuf->ImageTypeId, FmpHardwareInstance));\r | |
164 | ASSERT (\r | |
165 | !CompareGuid (&HardwareInstances[Index].ImageTypeGuid, &FmpImageInfoBuf->ImageTypeId) ||\r | |
166 | HardwareInstances[Index].HardwareInstance != FmpHardwareInstance\r | |
167 | );\r | |
168 | return EFI_UNSUPPORTED;\r | |
169 | }\r | |
e314132f | 170 | }\r |
4184aabd | 171 | }\r |
4184aabd MK |
172 | }\r |
173 | \r | |
174 | //\r | |
e314132f | 175 | // Record new GUID/HardwareInstance pair\r |
4184aabd | 176 | //\r |
e314132f JE |
177 | CopyGuid (&HardwareInstances[*NumberOfDescriptors].ImageTypeGuid, &FmpImageInfoBuf->ImageTypeId);\r |
178 | HardwareInstances[*NumberOfDescriptors].HardwareInstance = FmpHardwareInstance;\r | |
1436aea4 | 179 | *NumberOfDescriptors = *NumberOfDescriptors + 1;\r |
e314132f JE |
180 | \r |
181 | DEBUG ((DEBUG_INFO, "EsrtFmpDxe: Add new image descriptor with GUID %g HardwareInstance:0x%x\n", &FmpImageInfoBuf->ImageTypeId, FmpHardwareInstance));\r | |
182 | \r | |
183 | //\r | |
184 | // Check to see if GUID is already in the ESRT table\r | |
185 | //\r | |
186 | Entry = (EFI_SYSTEM_RESOURCE_ENTRY *)(Table + 1);\r | |
187 | for (Index = 0; Index < Table->FwResourceCount; Index++, Entry++) {\r | |
188 | if (!CompareGuid (&Entry->FwClass, &FmpImageInfoBuf->ImageTypeId)) {\r | |
189 | continue;\r | |
4184aabd | 190 | }\r |
1436aea4 | 191 | \r |
e314132f JE |
192 | DEBUG ((DEBUG_INFO, "EsrtFmpDxe: ESRT Entry already exists for FMP Instance with GUID %g\n", &Entry->FwClass));\r |
193 | \r | |
4184aabd | 194 | //\r |
e314132f | 195 | // Set ESRT FwVersion to the smaller of the two values\r |
4184aabd | 196 | //\r |
e314132f JE |
197 | Entry->FwVersion = MIN (FmpImageInfoBuf->Version, Entry->FwVersion);\r |
198 | \r | |
4184aabd | 199 | //\r |
e314132f | 200 | // VERSION 2 has Lowest Supported\r |
4184aabd | 201 | //\r |
e314132f JE |
202 | if (FmpVersion >= 2) {\r |
203 | //\r | |
204 | // Set ESRT LowestSupportedFwVersion to the smaller of the two values\r | |
205 | //\r | |
206 | Entry->LowestSupportedFwVersion =\r | |
207 | MIN (\r | |
208 | FmpImageInfoBuf->LowestSupportedImageVersion,\r | |
209 | Entry->LowestSupportedFwVersion\r | |
210 | );\r | |
211 | }\r | |
212 | \r | |
4184aabd | 213 | //\r |
e314132f | 214 | // VERSION 3 supports last attempt values\r |
4184aabd | 215 | //\r |
e314132f JE |
216 | if (FmpVersion >= 3) {\r |
217 | //\r | |
218 | // Update the ESRT entry with the last attempt status and last attempt\r | |
219 | // version from the first FMP instance whose last attempt status is not\r | |
220 | // SUCCESS. If all FMP instances are SUCCESS, then set version to the\r | |
221 | // smallest value from all FMP instances.\r | |
222 | //\r | |
223 | if (Entry->LastAttemptStatus == LAST_ATTEMPT_STATUS_SUCCESS) {\r | |
224 | if (FmpImageInfoBuf->LastAttemptStatus != LAST_ATTEMPT_STATUS_SUCCESS) {\r | |
1436aea4 | 225 | Entry->LastAttemptStatus = FmpImageInfoBuf->LastAttemptStatus;\r |
e314132f JE |
226 | Entry->LastAttemptVersion = FmpImageInfoBuf->LastAttemptVersion;\r |
227 | } else {\r | |
228 | Entry->LastAttemptVersion =\r | |
229 | MIN (\r | |
230 | FmpImageInfoBuf->LastAttemptVersion,\r | |
231 | Entry->LastAttemptVersion\r | |
232 | );\r | |
233 | }\r | |
234 | }\r | |
235 | }\r | |
236 | \r | |
237 | return EFI_SUCCESS;\r | |
4184aabd MK |
238 | }\r |
239 | \r | |
240 | //\r | |
e314132f | 241 | // Add a new ESRT Table Entry\r |
4184aabd | 242 | //\r |
e314132f | 243 | Entry = (EFI_SYSTEM_RESOURCE_ENTRY *)(Table + 1) + Table->FwResourceCount;\r |
4184aabd MK |
244 | \r |
245 | CopyGuid (&Entry->FwClass, &FmpImageInfoBuf->ImageTypeId);\r | |
246 | \r | |
247 | if (IsSystemFmp (FmpImageInfoBuf)) {\r | |
248 | DEBUG ((DEBUG_INFO, "EsrtFmpDxe: Found an ESRT entry for a System Device.\n"));\r | |
249 | Entry->FwType = (UINT32)(ESRT_FW_TYPE_SYSTEMFIRMWARE);\r | |
250 | } else {\r | |
251 | Entry->FwType = (UINT32)(ESRT_FW_TYPE_DEVICEFIRMWARE);\r | |
252 | }\r | |
253 | \r | |
e314132f | 254 | Entry->FwVersion = FmpImageInfoBuf->Version;\r |
4184aabd | 255 | Entry->LowestSupportedFwVersion = 0;\r |
e314132f JE |
256 | Entry->CapsuleFlags = 0;\r |
257 | Entry->LastAttemptVersion = 0;\r | |
258 | Entry->LastAttemptStatus = 0;\r | |
4184aabd MK |
259 | \r |
260 | //\r | |
261 | // VERSION 2 has Lowest Supported\r | |
262 | //\r | |
263 | if (FmpVersion >= 2) {\r | |
264 | Entry->LowestSupportedFwVersion = FmpImageInfoBuf->LowestSupportedImageVersion;\r | |
265 | }\r | |
266 | \r | |
267 | //\r | |
268 | // VERSION 3 supports last attempt values\r | |
269 | //\r | |
270 | if (FmpVersion >= 3) {\r | |
271 | Entry->LastAttemptVersion = FmpImageInfoBuf->LastAttemptVersion;\r | |
e314132f | 272 | Entry->LastAttemptStatus = FmpImageInfoBuf->LastAttemptStatus;\r |
4184aabd MK |
273 | }\r |
274 | \r | |
e314132f JE |
275 | //\r |
276 | // Increment the number of active ESRT Table Entries\r | |
277 | //\r | |
278 | Table->FwResourceCount++;\r | |
279 | \r | |
4184aabd MK |
280 | return EFI_SUCCESS;\r |
281 | }\r | |
282 | \r | |
e314132f JE |
283 | /**\r |
284 | Function to retrieve the EFI_FIRMWARE_IMAGE_DESCRIPTOR from an FMP Instance.\r | |
285 | The returned buffer is allocated using AllocatePool() and must be freed by the\r | |
286 | caller using FreePool().\r | |
287 | \r | |
288 | @param[in] Fmp Pointer to an EFI_FIRMWARE_MANAGEMENT_PROTOCOL.\r | |
289 | @param[out] FmpImageInfoDescriptorVer Pointer to the version number associated\r | |
290 | with the returned EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r | |
291 | @param[out] FmpImageInfoCount Pointer to the number of the returned\r | |
292 | EFI_FIRMWARE_IMAGE_DESCRIPTORs.\r | |
293 | @param[out] DescriptorSize Pointer to the size, in bytes, of each\r | |
294 | returned EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r | |
295 | \r | |
296 | @return Pointer to the retrieved EFI_FIRMWARE_IMAGE_DESCRIPTOR. If the\r | |
297 | descriptor can not be retrieved, then NULL is returned.\r | |
298 | \r | |
299 | **/\r | |
300 | EFI_FIRMWARE_IMAGE_DESCRIPTOR *\r | |
301 | FmpGetFirmwareImageDescriptor (\r | |
302 | IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp,\r | |
303 | OUT UINT32 *FmpImageInfoDescriptorVer,\r | |
304 | OUT UINT8 *FmpImageInfoCount,\r | |
305 | OUT UINTN *DescriptorSize\r | |
306 | )\r | |
307 | {\r | |
308 | EFI_STATUS Status;\r | |
309 | UINTN ImageInfoSize;\r | |
310 | UINT32 PackageVersion;\r | |
311 | CHAR16 *PackageVersionName;\r | |
312 | EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;\r | |
313 | \r | |
314 | ImageInfoSize = 0;\r | |
1436aea4 MK |
315 | Status = Fmp->GetImageInfo (\r |
316 | Fmp, // FMP Pointer\r | |
317 | &ImageInfoSize, // Buffer Size (in this case 0)\r | |
318 | NULL, // NULL so we can get size\r | |
319 | FmpImageInfoDescriptorVer, // DescriptorVersion\r | |
320 | FmpImageInfoCount, // DescriptorCount\r | |
321 | DescriptorSize, // DescriptorSize\r | |
322 | &PackageVersion, // PackageVersion\r | |
323 | &PackageVersionName // PackageVersionName\r | |
324 | );\r | |
e314132f JE |
325 | if (Status != EFI_BUFFER_TOO_SMALL) {\r |
326 | DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Unexpected Failure in GetImageInfo. Status = %r\n", Status));\r | |
327 | return NULL;\r | |
328 | }\r | |
329 | \r | |
330 | FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);\r | |
331 | if (FmpImageInfoBuf == NULL) {\r | |
332 | DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to get memory for FMP descriptor.\n"));\r | |
333 | return NULL;\r | |
334 | }\r | |
335 | \r | |
336 | PackageVersionName = NULL;\r | |
1436aea4 MK |
337 | Status = Fmp->GetImageInfo (\r |
338 | Fmp, // FMP Pointer\r | |
339 | &ImageInfoSize, // ImageInfoSize\r | |
340 | FmpImageInfoBuf, // ImageInfo\r | |
341 | FmpImageInfoDescriptorVer, // DescriptorVersion\r | |
342 | FmpImageInfoCount, // DescriptorCount\r | |
343 | DescriptorSize, // DescriptorSize\r | |
344 | &PackageVersion, // PackageVersion\r | |
345 | &PackageVersionName // PackageVersionName\r | |
346 | );\r | |
e314132f JE |
347 | if (PackageVersionName != NULL) {\r |
348 | FreePool (PackageVersionName);\r | |
349 | }\r | |
1436aea4 | 350 | \r |
e314132f JE |
351 | if (EFI_ERROR (Status)) {\r |
352 | DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failure in GetImageInfo. Status = %r\n", Status));\r | |
353 | FreePool (FmpImageInfoBuf);\r | |
354 | return NULL;\r | |
355 | }\r | |
356 | \r | |
357 | return FmpImageInfoBuf;\r | |
358 | }\r | |
359 | \r | |
4184aabd | 360 | /**\r |
6ec4d300 SZ |
361 | Function to create ESRT based on FMP Instances.\r |
362 | Create ESRT table, get the descriptors from FMP Instance and\r | |
363 | create ESRT entries (ESRE).\r | |
4184aabd | 364 | \r |
6ec4d300 | 365 | @return Pointer to the ESRT created.\r |
4184aabd MK |
366 | \r |
367 | **/\r | |
6ec4d300 SZ |
368 | EFI_SYSTEM_RESOURCE_TABLE *\r |
369 | CreateFmpBasedEsrt (\r | |
370 | VOID\r | |
4184aabd MK |
371 | )\r |
372 | {\r | |
e314132f JE |
373 | EFI_STATUS Status;\r |
374 | UINTN NoProtocols;\r | |
375 | VOID **Buffer;\r | |
376 | UINTN Index;\r | |
377 | UINT32 FmpImageInfoDescriptorVer;\r | |
378 | UINT8 FmpImageInfoCount;\r | |
379 | UINTN DescriptorSize;\r | |
380 | UINT32 NumberOfDescriptors;\r | |
381 | EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;\r | |
382 | EFI_FIRMWARE_IMAGE_DESCRIPTOR *OrgFmpImageInfoBuf;\r | |
383 | EFI_SYSTEM_RESOURCE_TABLE *Table;\r | |
384 | GUID_HARDWAREINSTANCE_PAIR *HardwareInstances;\r | |
4184aabd MK |
385 | \r |
386 | Status = EFI_SUCCESS;\r | |
6ec4d300 SZ |
387 | NoProtocols = 0;\r |
388 | Buffer = NULL;\r | |
4184aabd | 389 | FmpImageInfoBuf = NULL;\r |
e314132f JE |
390 | OrgFmpImageInfoBuf = NULL;\r |
391 | Table = NULL;\r | |
392 | HardwareInstances = NULL;\r | |
4184aabd | 393 | \r |
6ec4d300 SZ |
394 | Status = EfiLocateProtocolBuffer (\r |
395 | &gEfiFirmwareManagementProtocolGuid,\r | |
396 | &NoProtocols,\r | |
397 | &Buffer\r | |
398 | );\r | |
1436aea4 | 399 | if (EFI_ERROR (Status) || (Buffer == NULL)) {\r |
6ec4d300 SZ |
400 | return NULL;\r |
401 | }\r | |
4184aabd | 402 | \r |
6ec4d300 | 403 | //\r |
e314132f JE |
404 | // Count the total number of EFI_FIRMWARE_IMAGE_DESCRIPTORs\r |
405 | //\r | |
406 | for (Index = 0, NumberOfDescriptors = 0; Index < NoProtocols; Index++) {\r | |
407 | FmpImageInfoBuf = FmpGetFirmwareImageDescriptor (\r | |
1436aea4 | 408 | (EFI_FIRMWARE_MANAGEMENT_PROTOCOL *)Buffer[Index],\r |
e314132f JE |
409 | &FmpImageInfoDescriptorVer,\r |
410 | &FmpImageInfoCount,\r | |
411 | &DescriptorSize\r | |
412 | );\r | |
413 | if (FmpImageInfoBuf != NULL) {\r | |
414 | NumberOfDescriptors += FmpImageInfoCount;\r | |
415 | FreePool (FmpImageInfoBuf);\r | |
416 | }\r | |
417 | }\r | |
418 | \r | |
419 | //\r | |
420 | // Allocate ESRT Table and GUID/HardwareInstance table\r | |
6ec4d300 SZ |
421 | //\r |
422 | Table = AllocateZeroPool (\r | |
1436aea4 MK |
423 | (NumberOfDescriptors * sizeof (EFI_SYSTEM_RESOURCE_ENTRY)) + sizeof (EFI_SYSTEM_RESOURCE_TABLE)\r |
424 | );\r | |
6ec4d300 SZ |
425 | if (Table == NULL) {\r |
426 | DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to allocate memory for ESRT.\n"));\r | |
e314132f | 427 | FreePool (Buffer);\r |
6ec4d300 SZ |
428 | return NULL;\r |
429 | }\r | |
430 | \r | |
e314132f JE |
431 | HardwareInstances = AllocateZeroPool (NumberOfDescriptors * sizeof (GUID_HARDWAREINSTANCE_PAIR));\r |
432 | if (HardwareInstances == NULL) {\r | |
433 | DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to allocate memory for HW Instance Table.\n"));\r | |
434 | FreePool (Table);\r | |
435 | FreePool (Buffer);\r | |
436 | return NULL;\r | |
437 | }\r | |
438 | \r | |
439 | //\r | |
440 | // Initialize ESRT Table\r | |
441 | //\r | |
6ec4d300 | 442 | Table->FwResourceCount = 0;\r |
e314132f | 443 | Table->FwResourceCountMax = NumberOfDescriptors;\r |
4a76d9b9 | 444 | Table->FwResourceVersion = EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION;\r |
4184aabd | 445 | \r |
e314132f | 446 | NumberOfDescriptors = 0;\r |
6ec4d300 | 447 | for (Index = 0; Index < NoProtocols; Index++) {\r |
e314132f | 448 | FmpImageInfoBuf = FmpGetFirmwareImageDescriptor (\r |
1436aea4 | 449 | (EFI_FIRMWARE_MANAGEMENT_PROTOCOL *)Buffer[Index],\r |
e314132f JE |
450 | &FmpImageInfoDescriptorVer,\r |
451 | &FmpImageInfoCount,\r | |
452 | &DescriptorSize\r | |
453 | );\r | |
4184aabd | 454 | if (FmpImageInfoBuf == NULL) {\r |
6ec4d300 | 455 | continue;\r |
4184aabd MK |
456 | }\r |
457 | \r | |
458 | //\r | |
459 | // Check each descriptor and read from the one specified\r | |
460 | //\r | |
e314132f | 461 | OrgFmpImageInfoBuf = FmpImageInfoBuf;\r |
4184aabd MK |
462 | while (FmpImageInfoCount > 0) {\r |
463 | //\r | |
464 | // If the descriptor has the IN USE bit set, create ESRT entry otherwise ignore.\r | |
465 | //\r | |
466 | if ((FmpImageInfoBuf->AttributesSetting & FmpImageInfoBuf->AttributesSupported & IMAGE_ATTRIBUTE_IN_USE) == IMAGE_ATTRIBUTE_IN_USE) {\r | |
467 | //\r | |
468 | // Create ESRT entry\r | |
469 | //\r | |
e314132f | 470 | CreateEsrtEntry (Table, HardwareInstances, &NumberOfDescriptors, FmpImageInfoBuf, FmpImageInfoDescriptorVer);\r |
4184aabd | 471 | }\r |
1436aea4 | 472 | \r |
4184aabd MK |
473 | FmpImageInfoCount--;\r |
474 | //\r | |
475 | // Increment the buffer pointer ahead by the size of the descriptor\r | |
476 | //\r | |
477 | FmpImageInfoBuf = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)(((UINT8 *)FmpImageInfoBuf) + DescriptorSize);\r | |
478 | }\r | |
479 | \r | |
e314132f JE |
480 | FreePool (OrgFmpImageInfoBuf);\r |
481 | OrgFmpImageInfoBuf = NULL;\r | |
4184aabd | 482 | }\r |
6ec4d300 | 483 | \r |
e314132f JE |
484 | FreePool (Buffer);\r |
485 | FreePool (HardwareInstances);\r | |
6ec4d300 | 486 | return Table;\r |
4184aabd MK |
487 | }\r |
488 | \r | |
489 | /**\r | |
490 | Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used to\r | |
491 | install the Efi System Resource Table.\r | |
492 | \r | |
493 | @param[in] Event The Event that is being processed.\r | |
494 | @param[in] Context The Event Context.\r | |
495 | \r | |
496 | **/\r | |
497 | VOID\r | |
498 | EFIAPI\r | |
499 | EsrtReadyToBootEventNotify (\r | |
500 | IN EFI_EVENT Event,\r | |
501 | IN VOID *Context\r | |
502 | )\r | |
503 | {\r | |
6ec4d300 SZ |
504 | EFI_STATUS Status;\r |
505 | EFI_SYSTEM_RESOURCE_TABLE *Table;\r | |
506 | \r | |
507 | Table = CreateFmpBasedEsrt ();\r | |
508 | if (Table != NULL) {\r | |
509 | //\r | |
510 | // Print table on debug builds\r | |
511 | //\r | |
512 | DEBUG_CODE_BEGIN ();\r | |
513 | PrintTable (Table);\r | |
514 | DEBUG_CODE_END ();\r | |
515 | \r | |
516 | Status = InstallEfiSystemResourceTableInUefiConfigurationTable (Table);\r | |
517 | if (EFI_ERROR (Status)) {\r | |
518 | FreePool (Table);\r | |
519 | }\r | |
520 | } else {\r | |
521 | DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Can't install ESRT table because it is NULL. \n"));\r | |
522 | }\r | |
4184aabd MK |
523 | \r |
524 | //\r | |
6ec4d300 | 525 | // Close the event to prevent it be signalled again.\r |
4184aabd | 526 | //\r |
6ec4d300 | 527 | gBS->CloseEvent (Event);\r |
4184aabd MK |
528 | }\r |
529 | \r | |
530 | /**\r | |
531 | The module Entry Point of the Efi System Resource Table DXE driver.\r | |
532 | \r | |
533 | @param[in] ImageHandle The firmware allocated handle for the EFI image.\r | |
534 | @param[in] SystemTable A pointer to the EFI System Table.\r | |
535 | \r | |
536 | @retval EFI_SUCCESS The entry point is executed successfully.\r | |
537 | @retval Other Some error occurs when executing this entry point.\r | |
538 | \r | |
539 | **/\r | |
540 | EFI_STATUS\r | |
541 | EFIAPI\r | |
542 | EsrtFmpEntryPoint (\r | |
543 | IN EFI_HANDLE ImageHandle,\r | |
544 | IN EFI_SYSTEM_TABLE *SystemTable\r | |
545 | )\r | |
546 | {\r | |
547 | EFI_STATUS Status;\r | |
6ec4d300 | 548 | EFI_EVENT EsrtReadyToBootEvent;\r |
4184aabd MK |
549 | \r |
550 | //\r | |
551 | // Register notify function to install ESRT on ReadyToBoot Event.\r | |
552 | //\r | |
553 | Status = EfiCreateEventReadyToBootEx (\r | |
554 | TPL_CALLBACK,\r | |
555 | EsrtReadyToBootEventNotify,\r | |
556 | NULL,\r | |
6ec4d300 | 557 | &EsrtReadyToBootEvent\r |
4184aabd MK |
558 | );\r |
559 | \r | |
560 | ASSERT_EFI_ERROR (Status);\r | |
561 | if (EFI_ERROR (Status)) {\r | |
562 | DEBUG ((DEBUG_ERROR, "EsrtFmpDxe: Failed to register for ready to boot\n"));\r | |
563 | }\r | |
564 | \r | |
565 | return Status;\r | |
566 | }\r |