]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Library/DxeCapsuleLib/DxeCapsuleLib.c
IntelFrameworkModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / IntelFrameworkModulePkg / Library / DxeCapsuleLib / DxeCapsuleLib.c
CommitLineData
cf7958f7 1/** @file\r
566771b0 2 Capsule Library instance to process capsule images.\r
cf7958f7 3\r
0a6f4824 4 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
cf7958f7 5\r
c0a00b14 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
cf7958f7 7\r
8**/\r
9#include <PiDxe.h>\r
566771b0 10\r
cf7958f7 11#include <Guid/Capsule.h>\r
566771b0 12#include <Guid/FmpCapsule.h>\r
13\r
cf7958f7 14#include <Library/DebugLib.h>\r
15#include <Library/BaseMemoryLib.h>\r
16#include <Library/DxeServicesTableLib.h>\r
17#include <Library/MemoryAllocationLib.h>\r
18#include <Library/CapsuleLib.h>\r
566771b0 19#include <Library/GenericBdsLib.h>\r
20#include <Library/UefiBootServicesTableLib.h>\r
21#include <Library/BaseLib.h>\r
22#include <Library/DevicePathLib.h>\r
23\r
24#include <Protocol/FirmwareManagement.h>\r
25#include <Protocol/DevicePath.h>\r
26\r
27\r
28/**\r
29 Function indicate the current completion progress of the firmware\r
30 update. Platform may override with own specific progress function.\r
31\r
32 @param Completion A value between 1 and 100 indicating the current completion progress of the firmware update\r
33\r
34 @retval EFI_SUCESS Input capsule is a correct FMP capsule.\r
35**/\r
36EFI_STATUS\r
37EFIAPI\r
38Update_Image_Progress (\r
39 IN UINTN Completion\r
40)\r
41{\r
42 return EFI_SUCCESS;\r
43}\r
44\r
45\r
46/**\r
47 Validate Fmp capsules layout.\r
48\r
49 @param CapsuleHeader Points to a capsule header.\r
50\r
51 @retval EFI_SUCESS Input capsule is a correct FMP capsule.\r
52 @retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.\r
53**/\r
54EFI_STATUS\r
55ValidateFmpCapsule (\r
56 IN EFI_CAPSULE_HEADER *CapsuleHeader\r
57 )\r
58{\r
59 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;\r
60 UINT8 *EndOfCapsule;\r
61 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;\r
62 UINT8 *EndOfPayload;\r
63 UINT64 *ItemOffsetList;\r
64 UINT32 ItemNum;\r
65 UINTN Index;\r
66\r
67 FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);\r
68 EndOfCapsule = (UINT8 *) CapsuleHeader + CapsuleHeader->CapsuleImageSize;\r
69\r
70 if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {\r
71 return EFI_INVALID_PARAMETER;\r
72 }\r
73 ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);\r
74\r
75 ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;\r
76\r
77 if (ItemNum == FmpCapsuleHeader->EmbeddedDriverCount) {\r
78 //\r
0a6f4824 79 // No payload element\r
566771b0 80 //\r
81 if (((UINT8 *)FmpCapsuleHeader + ItemOffsetList[ItemNum - 1]) < EndOfCapsule) {\r
82 return EFI_SUCCESS;\r
83 } else {\r
84 return EFI_INVALID_PARAMETER;\r
85 }\r
86 }\r
87\r
88 if (FmpCapsuleHeader->PayloadItemCount != 0) {\r
89 //\r
90 // Check if the last payload is within capsule image range\r
91 //\r
92 ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[ItemNum - 1]);\r
93 EndOfPayload = (UINT8 *)(ImageHeader + 1) + ImageHeader->UpdateImageSize + ImageHeader->UpdateVendorCodeSize;\r
94 } else {\r
95 //\r
96 // No driver & payload element in FMP\r
97 //\r
98 EndOfPayload = (UINT8 *)(FmpCapsuleHeader + 1);\r
99 }\r
100\r
101 if (EndOfPayload != EndOfCapsule) {\r
102 return EFI_INVALID_PARAMETER;\r
103 }\r
104\r
105 //\r
106 // All the address in ItemOffsetList must be stored in ascending order\r
107 //\r
108 if (ItemNum >= 2) {\r
109 for (Index = 0; Index < ItemNum - 1; Index++) {\r
110 if (ItemOffsetList[Index] >= ItemOffsetList[Index + 1]) {\r
111 return EFI_INVALID_PARAMETER;\r
112 }\r
113 }\r
114 }\r
115\r
116 return EFI_SUCCESS;\r
117}\r
118\r
119/**\r
0a6f4824 120 Process Firmware management protocol data capsule.\r
566771b0 121\r
122 @param CapsuleHeader Points to a capsule header.\r
123\r
124 @retval EFI_SUCESS Process Capsule Image successfully.\r
125 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.\r
126 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.\r
127 @retval EFI_OUT_OF_RESOURCES Not enough memory.\r
128**/\r
129EFI_STATUS\r
130ProcessFmpCapsuleImage (\r
131 IN EFI_CAPSULE_HEADER *CapsuleHeader\r
132 )\r
133{\r
134 EFI_STATUS Status;\r
135 EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;\r
566771b0 136 EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;\r
137 EFI_HANDLE ImageHandle;\r
138 UINT64 *ItemOffsetList;\r
139 UINT32 ItemNum;\r
140 UINTN Index;\r
141 UINTN ExitDataSize;\r
142 EFI_HANDLE *HandleBuffer;\r
143 EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
144 UINTN NumberOfHandles;\r
145 UINTN DescriptorSize;\r
146 UINT8 FmpImageInfoCount;\r
147 UINT32 FmpImageInfoDescriptorVer;\r
148 UINTN ImageInfoSize;\r
149 UINT32 PackageVersion;\r
150 CHAR16 *PackageVersionName;\r
151 CHAR16 *AbortReason;\r
152 EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;\r
153 EFI_FIRMWARE_IMAGE_DESCRIPTOR *TempFmpImageInfo;\r
154 UINTN DriverLen;\r
155 UINTN Index1;\r
156 UINTN Index2;\r
157 MEMMAP_DEVICE_PATH MemMapNode;\r
158 EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath;\r
159\r
160 Status = EFI_SUCCESS;\r
161 HandleBuffer = NULL;\r
162 ExitDataSize = 0;\r
163 DriverDevicePath = NULL;\r
164\r
165 FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);\r
566771b0 166\r
167 if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {\r
168 return EFI_INVALID_PARAMETER;\r
169 }\r
170 ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);\r
171\r
172 ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;\r
173\r
174 //\r
175 // capsule in which driver count and payload count are both zero is not processed.\r
176 //\r
177 if (ItemNum == 0) {\r
178 return EFI_SUCCESS;\r
179 }\r
180\r
181 //\r
0a6f4824
LG
182 // 1. ConnectAll to ensure\r
183 // All the communication protocol required by driver in capsule installed\r
566771b0 184 // All FMP protocols are installed\r
185 //\r
186 BdsLibConnectAll();\r
187\r
188\r
189 //\r
0a6f4824 190 // 2. Try to load & start all the drivers within capsule\r
566771b0 191 //\r
192 SetDevicePathNodeLength (&MemMapNode.Header, sizeof (MemMapNode));\r
193 MemMapNode.Header.Type = HARDWARE_DEVICE_PATH;\r
194 MemMapNode.Header.SubType = HW_MEMMAP_DP;\r
195 MemMapNode.MemoryType = EfiBootServicesCode;\r
5f727329 196 MemMapNode.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CapsuleHeader;\r
197 MemMapNode.EndingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)((UINT8 *)CapsuleHeader + CapsuleHeader->CapsuleImageSize - 1);\r
566771b0 198\r
199 DriverDevicePath = AppendDevicePathNode (NULL, &MemMapNode.Header);\r
200 if (DriverDevicePath == NULL) {\r
201 return EFI_OUT_OF_RESOURCES;\r
202 }\r
203\r
204 for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {\r
5f727329 205 if (FmpCapsuleHeader->PayloadItemCount == 0 && Index == (UINTN)FmpCapsuleHeader->EmbeddedDriverCount - 1) {\r
566771b0 206 //\r
207 // When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER\r
208 //\r
5f727329 209 DriverLen = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize - (UINTN)ItemOffsetList[Index];\r
566771b0 210 } else {\r
5f727329 211 DriverLen = (UINTN)ItemOffsetList[Index + 1] - (UINTN)ItemOffsetList[Index];\r
566771b0 212 }\r
213\r
214 Status = gBS->LoadImage(\r
215 FALSE,\r
216 gImageHandle,\r
217 DriverDevicePath,\r
218 (UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index],\r
219 DriverLen,\r
220 &ImageHandle\r
221 );\r
222 if (EFI_ERROR(Status)) {\r
223 goto EXIT;\r
224 }\r
225\r
226 Status = gBS->StartImage(\r
0a6f4824
LG
227 ImageHandle,\r
228 &ExitDataSize,\r
566771b0 229 NULL\r
230 );\r
231 if (EFI_ERROR(Status)) {\r
232 DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));\r
233 goto EXIT;\r
234 }\r
235 }\r
236\r
237 //\r
0a6f4824 238 // Connnect all again to connect drivers within capsule\r
566771b0 239 //\r
240 if (FmpCapsuleHeader->EmbeddedDriverCount > 0) {\r
241 BdsLibConnectAll();\r
242 }\r
243\r
244 //\r
245 // 3. Route payload to right FMP instance\r
246 //\r
247 Status = gBS->LocateHandleBuffer (\r
248 ByProtocol,\r
249 &gEfiFirmwareManagementProtocolGuid,\r
250 NULL,\r
251 &NumberOfHandles,\r
252 &HandleBuffer\r
253 );\r
254\r
255 if (!EFI_ERROR(Status)) {\r
256 for(Index1 = 0; Index1 < NumberOfHandles; Index1++) {\r
257 Status = gBS->HandleProtocol(\r
258 HandleBuffer[Index1],\r
259 &gEfiFirmwareManagementProtocolGuid,\r
5f727329 260 (VOID **)&Fmp\r
566771b0 261 );\r
262 if (EFI_ERROR(Status)) {\r
263 continue;\r
264 }\r
265\r
266 ImageInfoSize = 0;\r
267 Status = Fmp->GetImageInfo (\r
268 Fmp,\r
269 &ImageInfoSize,\r
270 NULL,\r
271 NULL,\r
272 NULL,\r
273 NULL,\r
274 NULL,\r
275 NULL\r
276 );\r
277 if (Status != EFI_BUFFER_TOO_SMALL) {\r
278 continue;\r
279 }\r
280\r
281 FmpImageInfoBuf = NULL;\r
282 FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);\r
283 if (FmpImageInfoBuf == NULL) {\r
284 Status = EFI_OUT_OF_RESOURCES;\r
285 goto EXIT;\r
286 }\r
287\r
288 PackageVersionName = NULL;\r
289 Status = Fmp->GetImageInfo (\r
290 Fmp,\r
291 &ImageInfoSize, // ImageInfoSize\r
292 FmpImageInfoBuf, // ImageInfo\r
293 &FmpImageInfoDescriptorVer, // DescriptorVersion\r
294 &FmpImageInfoCount, // DescriptorCount\r
295 &DescriptorSize, // DescriptorSize\r
296 &PackageVersion, // PackageVersion\r
297 &PackageVersionName // PackageVersionName\r
298 );\r
299\r
300 //\r
301 // If FMP GetInformation interface failed, skip this resource\r
302 //\r
303 if (EFI_ERROR(Status)) {\r
304 FreePool(FmpImageInfoBuf);\r
305 continue;\r
306 }\r
307\r
308 if (PackageVersionName != NULL) {\r
309 FreePool(PackageVersionName);\r
310 }\r
311\r
312 TempFmpImageInfo = FmpImageInfoBuf;\r
313 for (Index2 = 0; Index2 < FmpImageInfoCount; Index2++) {\r
314 //\r
0a6f4824 315 // Check all the payload entry in capsule payload list\r
566771b0 316 //\r
317 for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {\r
318 ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);\r
319 if (CompareGuid(&ImageHeader->UpdateImageTypeId, &TempFmpImageInfo->ImageTypeId) &&\r
320 ImageHeader->UpdateImageIndex == TempFmpImageInfo->ImageIndex) {\r
321 AbortReason = NULL;\r
322 if (ImageHeader->UpdateVendorCodeSize == 0) {\r
323 Status = Fmp->SetImage(\r
324 Fmp,\r
325 TempFmpImageInfo->ImageIndex, // ImageIndex\r
326 (UINT8 *)(ImageHeader + 1), // Image\r
327 ImageHeader->UpdateImageSize, // ImageSize\r
328 NULL, // VendorCode\r
329 Update_Image_Progress, // Progress\r
330 &AbortReason // AbortReason\r
331 );\r
332 } else {\r
333 Status = Fmp->SetImage(\r
334 Fmp,\r
335 TempFmpImageInfo->ImageIndex, // ImageIndex\r
336 (UINT8 *)(ImageHeader + 1), // Image\r
337 ImageHeader->UpdateImageSize, // ImageSize\r
338 (UINT8 *)((UINT8 *) (ImageHeader + 1) + ImageHeader->UpdateImageSize), // VendorCode\r
339 Update_Image_Progress, // Progress\r
340 &AbortReason // AbortReason\r
341 );\r
342 }\r
343 if (AbortReason != NULL) {\r
344 DEBUG ((EFI_D_ERROR, "%s\n", AbortReason));\r
345 FreePool(AbortReason);\r
346 }\r
347 }\r
348 }\r
349 //\r
350 // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version\r
351 //\r
352 TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSize);\r
353 }\r
354 FreePool(FmpImageInfoBuf);\r
355 }\r
356 }\r
357\r
358EXIT:\r
359\r
360 if (HandleBuffer != NULL) {\r
361 FreePool(HandleBuffer);\r
362 }\r
363\r
364 if (DriverDevicePath != NULL) {\r
365 FreePool(DriverDevicePath);\r
366 }\r
367\r
368 return Status;\r
369}\r
cf7958f7 370\r
371/**\r
372 Those capsules supported by the firmwares.\r
373\r
374 @param CapsuleHeader Points to a capsule header.\r
375\r
376 @retval EFI_SUCESS Input capsule is supported by firmware.\r
377 @retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.\r
566771b0 378 @retval EFI_INVALID_PARAMETER Input capsule layout is not correct\r
cf7958f7 379**/\r
380EFI_STATUS\r
381EFIAPI\r
382SupportCapsuleImage (\r
383 IN EFI_CAPSULE_HEADER *CapsuleHeader\r
384 )\r
385{\r
386 if (CompareGuid (&gEfiCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {\r
387 return EFI_SUCCESS;\r
388 }\r
389\r
566771b0 390 if (CompareGuid (&gEfiFmpCapsuleGuid, &CapsuleHeader->CapsuleGuid)) {\r
391 //\r
392 // Check layout of FMP capsule\r
393 //\r
394 return ValidateFmpCapsule(CapsuleHeader);\r
395 }\r
396\r
cf7958f7 397 return EFI_UNSUPPORTED;\r
398}\r
399\r
400/**\r
401 The firmware implements to process the capsule image.\r
402\r
403 @param CapsuleHeader Points to a capsule header.\r
404\r
405 @retval EFI_SUCESS Process Capsule Image successfully.\r
406 @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.\r
407 @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.\r
408 @retval EFI_OUT_OF_RESOURCES Not enough memory.\r
409**/\r
410EFI_STATUS\r
411EFIAPI\r
412ProcessCapsuleImage (\r
413 IN EFI_CAPSULE_HEADER *CapsuleHeader\r
414 )\r
415{\r
416 UINT32 Length;\r
417 EFI_FIRMWARE_VOLUME_HEADER *FvImage;\r
418 EFI_FIRMWARE_VOLUME_HEADER *ProcessedFvImage;\r
419 EFI_STATUS Status;\r
420 EFI_HANDLE FvProtocolHandle;\r
421 UINT32 FvAlignment;\r
422\r
423 FvImage = NULL;\r
424 ProcessedFvImage = NULL;\r
425 Status = EFI_SUCCESS;\r
426\r
427 if (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS) {\r
428 return EFI_UNSUPPORTED;\r
429 }\r
430\r
566771b0 431 //\r
432 // Check FMP capsule layout\r
433 //\r
434 if (CompareGuid (&gEfiFmpCapsuleGuid, &CapsuleHeader->CapsuleGuid)){\r
435 Status = ValidateFmpCapsule(CapsuleHeader);\r
436 if (EFI_ERROR(Status)) {\r
437 return Status;\r
438 }\r
439\r
440 //\r
441 // Press EFI FMP Capsule\r
442 //\r
443 return ProcessFmpCapsuleImage(CapsuleHeader);\r
444 }\r
445\r
cf7958f7 446 //\r
447 // Skip the capsule header, move to the Firware Volume\r
448 //\r
449 FvImage = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);\r
450 Length = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize;\r
451\r
452 while (Length != 0) {\r
453 //\r
454 // Point to the next firmware volume header, and then\r
455 // call the DXE service to process it.\r
456 //\r
457 if (FvImage->FvLength > (UINTN) Length) {\r
458 //\r
459 // Notes: need to stuff this status somewhere so that the\r
460 // error can be detected at OS runtime\r
461 //\r
462 Status = EFI_VOLUME_CORRUPTED;\r
463 break;\r
464 }\r
465\r
466 FvAlignment = 1 << ((FvImage->Attributes & EFI_FVB2_ALIGNMENT) >> 16);\r
467 //\r
468 // FvAlignment must be more than 8 bytes required by FvHeader structure.\r
469 //\r
470 if (FvAlignment < 8) {\r
471 FvAlignment = 8;\r
472 }\r
473 //\r
474 // Check FvImage Align is required.\r
475 //\r
476 if (((UINTN) FvImage % FvAlignment) == 0) {\r
477 ProcessedFvImage = FvImage;\r
478 } else {\r
479 //\r
480 // Allocate new aligned buffer to store FvImage.\r
481 //\r
a661e27f 482 ProcessedFvImage = (EFI_FIRMWARE_VOLUME_HEADER *) AllocateAlignedPages ((UINTN) EFI_SIZE_TO_PAGES ((UINTN) FvImage->FvLength), (UINTN) FvAlignment);\r
cf7958f7 483 if (ProcessedFvImage == NULL) {\r
484 Status = EFI_OUT_OF_RESOURCES;\r
485 break;\r
486 }\r
487 CopyMem (ProcessedFvImage, FvImage, (UINTN) FvImage->FvLength);\r
488 }\r
489\r
490 Status = gDS->ProcessFirmwareVolume (\r
491 (VOID *) ProcessedFvImage,\r
492 (UINTN) ProcessedFvImage->FvLength,\r
493 &FvProtocolHandle\r
494 );\r
495 if (EFI_ERROR (Status)) {\r
496 break;\r
497 }\r
498 //\r
499 // Call the dispatcher to dispatch any drivers from the produced firmware volume\r
500 //\r
501 gDS->Dispatch ();\r
502 //\r
503 // On to the next FV in the capsule\r
504 //\r
505 Length -= (UINT32) FvImage->FvLength;\r
506 FvImage = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) FvImage + FvImage->FvLength);\r
507 }\r
508\r
509 return Status;\r
510}\r
511\r
afaa44c3
JY
512/**\r
513\r
514 This routine is called to process capsules.\r
515\r
516 Caution: This function may receive untrusted input.\r
517\r
518 The capsules reported in EFI_HOB_UEFI_CAPSULE are processed.\r
519 If there is no EFI_HOB_UEFI_CAPSULE, this routine does nothing.\r
520\r
521 This routine should be called twice in BDS.\r
522 1) The first call must be before EndOfDxe. The system capsules is processed.\r
523 If device capsule FMP protocols are exposted at this time and device FMP\r
524 capsule has zero EmbeddedDriverCount, the device capsules are processed.\r
525 Each individual capsule result is recorded in capsule record variable.\r
526 System may reset in this function, if reset is required by capsule and\r
527 all capsules are processed.\r
528 If not all capsules are processed, reset will be defered to second call.\r
529\r
530 2) The second call must be after EndOfDxe and after ConnectAll, so that all\r
531 device capsule FMP protocols are exposed.\r
532 The system capsules are skipped. If the device capsules are NOT processed\r
533 in first call, they are processed here.\r
534 Each individual capsule result is recorded in capsule record variable.\r
535 System may reset in this function, if reset is required by capsule\r
536 processed in first call and second call.\r
537\r
538 @retval EFI_SUCCESS There is no error when processing capsules.\r
539 @retval EFI_OUT_OF_RESOURCES No enough resource to process capsules.\r
540\r
541**/\r
542EFI_STATUS\r
543EFIAPI\r
544ProcessCapsules (\r
545 VOID\r
546 )\r
547{\r
548 return EFI_UNSUPPORTED;\r
549}\r
cf7958f7 550\r