]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/FirmwareVolume/UpdateDriverDxe/UpdateDispatcher.c
aaab24921df1f86abd815429bd1e7f757ecc688c
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / FirmwareVolume / UpdateDriverDxe / UpdateDispatcher.c
1 /** @file
2 Functions in this file will mainly focus on looking through the capsule
3 for the image to be programmed, and the flash area that is going to be
4 programed.
5
6 Copyright (c) 2002 - 2018, Intel Corporation. All rights reserved.<BR>
7
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10 **/
11
12 #include "UpdateDriver.h"
13
14 EFI_HII_HANDLE gHiiHandle;
15
16 /**
17 Update the whole FV, or certain files in the FV.
18
19 @param ConfigData Pointer to the config data on updating file.
20 @param ImageBuffer Image buffer to be updated.
21 @param ImageSize Image size.
22 @param FileType FFS file type.
23 @param FileAttributes FFS file attribute.
24
25 @retval EFI_NOT_FOUND The matched FVB protocol is not found.
26 @retval EFI_SUCCESS The image buffer is updated into FV.
27
28 **/
29 EFI_STATUS
30 PerformUpdateOnFirmwareVolume (
31 IN UPDATE_CONFIG_DATA *ConfigData,
32 IN UINT8 *ImageBuffer,
33 IN UINTN ImageSize,
34 IN EFI_FV_FILETYPE FileType,
35 IN EFI_FV_FILE_ATTRIBUTES FileAttributes
36 )
37 {
38 EFI_STATUS Status;
39 BOOLEAN Found;
40 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;
41 UINTN Index;
42 UINTN NumOfHandles;
43 EFI_HANDLE *HandleBuffer;
44 EFI_PHYSICAL_ADDRESS BaseAddress;
45 EFI_FVB_ATTRIBUTES_2 Attributes;
46
47 //
48 // Locate all Fvb protocol
49 //
50 HandleBuffer = NULL;
51 Status = gBS->LocateHandleBuffer (
52 ByProtocol,
53 &gEfiFirmwareVolumeBlockProtocolGuid,
54 NULL,
55 &NumOfHandles,
56 &HandleBuffer
57 );
58 if ((EFI_ERROR (Status)) || (NumOfHandles == 0) || (HandleBuffer == NULL)) {
59 if (HandleBuffer != NULL) {
60 FreePool (HandleBuffer);
61 }
62 return EFI_NOT_FOUND;
63 }
64
65 //
66 // Check the FVB protocol one by one
67 //
68 Found = FALSE;
69 FvbProtocol = NULL;
70 for (Index = 0; Index < NumOfHandles; Index++) {
71 Status = gBS->HandleProtocol (
72 HandleBuffer[Index],
73 &gEfiFirmwareVolumeBlockProtocolGuid,
74 (VOID **) &FvbProtocol
75 );
76 if (EFI_ERROR (Status)) {
77 break;
78 }
79
80 //
81 // Ensure this FVB protocol supported Write operation.
82 //
83 Status = FvbProtocol->GetAttributes (FvbProtocol, &Attributes);
84 if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {
85 continue;
86 }
87
88 Status = FvbProtocol->GetPhysicalAddress (
89 FvbProtocol,
90 &BaseAddress
91 );
92 if (EFI_ERROR (Status)) {
93 break;
94 }
95 if (BaseAddress == ConfigData->BaseAddress) {
96 Found = TRUE;
97 break;
98 }
99 }
100
101 if (!Found) {
102 if (HandleBuffer != NULL) {
103 FreePool (HandleBuffer);
104 HandleBuffer = NULL;
105 }
106 return EFI_NOT_FOUND;
107 }
108
109 //
110 // Now we have got the corresponding FVB protocol. Use the FVB protocol
111 // to update the whole FV, or certain files in the FV.
112 //
113 if (ConfigData->UpdateType == UpdateWholeFV) {
114 if (FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
115 Status = EFI_INVALID_PARAMETER;
116 } else {
117 Status = PerformUpdateOnWholeFv (
118 HandleBuffer[Index],
119 FvbProtocol,
120 ConfigData,
121 ImageBuffer,
122 ImageSize
123 );
124 }
125 } else if (ConfigData->UpdateType == UpdateFvFile) {
126 Status = PerformUpdateOnFvFile (
127 HandleBuffer[Index],
128 FvbProtocol,
129 ConfigData,
130 ImageBuffer,
131 ImageSize,
132 FileType,
133 FileAttributes
134 );
135 }
136
137 if (HandleBuffer != NULL) {
138 FreePool (HandleBuffer);
139 HandleBuffer = NULL;
140 }
141
142 return Status;
143 }
144
145 /**
146 Update the file directly into flash area.
147
148 @param ConfigData Pointer to the config data on updating file.
149 @param ImageBuffer Image buffer to be updated.
150 @param ImageSize Image size.
151
152 @retval EFI_SUCCESS The file is updated into flash area.
153 @retval EFI_NOT_FOUND The FVB protocol for the updated flash area is not found.
154
155 **/
156 EFI_STATUS
157 PerformUpdateOnFlashArea (
158 IN UPDATE_CONFIG_DATA *ConfigData,
159 IN UINT8 *ImageBuffer,
160 IN UINTN ImageSize
161 )
162 {
163 EFI_STATUS Status;
164 UINTN SizeLeft;
165 EFI_PHYSICAL_ADDRESS FlashAddress;
166 UINT8 *PtrImage;
167 BOOLEAN Found;
168 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;
169 UINTN Index;
170 UINTN NumOfHandles;
171 EFI_HANDLE *HandleBuffer;
172 EFI_PHYSICAL_ADDRESS BaseAddress;
173 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
174 EFI_HANDLE FvbHandle;
175 UINTN SizeUpdated;
176 CHAR16 *TmpStr;
177 EFI_FVB_ATTRIBUTES_2 Attributes;
178
179 SizeLeft = ImageSize;
180 PtrImage = ImageBuffer;
181 FlashAddress = ConfigData->BaseAddress;
182 Status = EFI_SUCCESS;
183 HandleBuffer = NULL;
184
185 //
186 // Print on screen
187 //
188 TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_FLASH_RANGE), NULL);
189 if (TmpStr != NULL) {
190 Print (TmpStr, FlashAddress, ((UINT64)SizeLeft + FlashAddress));
191 FreePool (TmpStr);
192 }
193
194 //
195 // Locate all Fvb protocol
196 //
197 Status = gBS->LocateHandleBuffer (
198 ByProtocol,
199 &gEfiFirmwareVolumeBlockProtocolGuid,
200 NULL,
201 &NumOfHandles,
202 &HandleBuffer
203 );
204 if ((EFI_ERROR (Status)) || (NumOfHandles == 0) || (HandleBuffer == NULL)) {
205 if (HandleBuffer != NULL) {
206 FreePool (HandleBuffer);
207 }
208 return EFI_NOT_FOUND;
209 }
210
211 while (SizeLeft > 0) {
212 //
213 // First get the FVB protocols. If the flash area is a FV, or sub FV,
214 // we can directly locate all the FVB protocol. Otherwise we should use
215 // implementation specific method to get the alternate FVB protocol
216 //
217 Found = FALSE;
218 FvbProtocol = NULL;
219
220 //
221 // Check the FVB protocol one by one
222 //
223 for (Index = 0; Index < NumOfHandles; Index++) {
224 Status = gBS->HandleProtocol (
225 HandleBuffer[Index],
226 &gEfiFirmwareVolumeBlockProtocolGuid,
227 (VOID **) &FvbProtocol
228 );
229 if (EFI_ERROR (Status)) {
230 break;
231 }
232
233 //
234 // Ensure this FVB protocol supported Write operation.
235 //
236 Status = FvbProtocol->GetAttributes (FvbProtocol, &Attributes);
237 if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {
238 continue;
239 }
240
241 Status = FvbProtocol->GetPhysicalAddress (
242 FvbProtocol,
243 &BaseAddress
244 );
245 if (EFI_ERROR (Status)) {
246 break;
247 }
248 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress;
249
250 //
251 // This sub area entry falls in the range of the FV
252 //
253 if ((FlashAddress >= BaseAddress) && (FlashAddress < (BaseAddress + FwVolHeader->FvLength))) {
254 Found = TRUE;
255 break;
256 }
257 }
258
259 if (!Found) {
260 if (HandleBuffer != NULL) {
261 FreePool (HandleBuffer);
262 HandleBuffer = NULL;
263 }
264 return EFI_NOT_FOUND;
265 }
266
267 FvbHandle = HandleBuffer[Index];
268 SizeUpdated = 0;
269
270 //
271 // If the flash area is boot required, the update must be fault tolerant
272 //
273 if (ConfigData->FaultTolerant) {
274 //
275 // Finally we are here. We have got the corresponding FVB protocol. Now
276 // we need to convert the physical address to LBA and offset and call
277 // FTW write. Also check if the flash range is larger than the FV.
278 //
279 Status = FaultTolerantUpdateOnPartFv (
280 PtrImage,
281 SizeLeft,
282 &SizeUpdated,
283 ConfigData,
284 FlashAddress,
285 FvbProtocol,
286 FvbHandle
287 );
288 } else {
289 //
290 // Finally we are here. We have got the corresponding FVB protocol. Now
291 // we need to convert the physical address to LBA and offset and call
292 // FVB write. Also check if the flash range is larger than the FV.
293 //
294 Status = NonFaultTolerantUpdateOnPartFv (
295 PtrImage,
296 SizeLeft,
297 &SizeUpdated,
298 FlashAddress,
299 FvbProtocol,
300 FvbHandle
301 );
302 }
303
304 if (EFI_ERROR (Status)) {
305 return Status;
306 }
307
308 //
309 // As part of the FV has been replaced, the FV driver shall re-parse
310 // the firmware volume. So re-install FVB protocol here
311 //
312 Status = gBS->ReinstallProtocolInterface (
313 FvbHandle,
314 &gEfiFirmwareVolumeBlockProtocolGuid,
315 FvbProtocol,
316 FvbProtocol
317 );
318
319 if (EFI_ERROR (Status)) {
320 return Status;
321 }
322
323 //
324 // Check if we are done with the update
325 //
326 SizeLeft = SizeLeft - SizeUpdated;
327 FlashAddress = FlashAddress + SizeUpdated;
328 PtrImage = PtrImage + SizeUpdated;
329 }
330
331 if (HandleBuffer != NULL) {
332 FreePool (HandleBuffer);
333 HandleBuffer = NULL;
334 }
335
336 return Status;
337 }
338
339 /**
340 Find the updated file, and program it into the flash area based on the config data.
341
342 @param FwVolProtocol Pointer to FV protocol that contains the updated file.
343 @param ConfigData Pointer to the Config Data on updating file.
344
345 @retval EFI_INVALID_PARAMETER The update operation is not valid.
346 @retval EFI_NOT_FOUND The updated file is not found.
347 @retval EFI_SUCCESS The file is updated into the flash area.
348
349 **/
350 EFI_STATUS
351 PerformUpdate (
352 IN EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVolProtocol,
353 IN UPDATE_CONFIG_DATA *ConfigData
354 )
355 {
356 EFI_STATUS Status;
357 UINT8 *FileBuffer;
358 UINTN FileBufferSize;
359 EFI_FV_FILETYPE FileType;
360 EFI_FV_FILE_ATTRIBUTES Attrib;
361 EFI_SECTION_TYPE SectionType;
362 UINT32 AuthenticationStatus;
363 CHAR16 *TmpStr;
364 BOOLEAN StartToUpdate;
365
366 Status = EFI_SUCCESS;
367 FileBuffer = NULL;
368 FileBufferSize = 0;
369 Status = FwVolProtocol->ReadFile (
370 FwVolProtocol,
371 &(ConfigData->FileGuid),
372 (VOID **) &FileBuffer,
373 &FileBufferSize,
374 &FileType,
375 &Attrib,
376 &AuthenticationStatus
377 );
378 if (EFI_ERROR (Status)) {
379 return Status;
380 }
381
382 StartToUpdate = FALSE;
383
384 //
385 // Check if the update image is the one we require
386 // and then perform the update
387 //
388 switch (ConfigData->UpdateType) {
389
390 case UpdateWholeFV:
391
392 //
393 // For UpdateWholeFv, the update file shall be a firmware volume
394 // image file.
395 //
396 if (FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
397 DEBUG ((EFI_D_UPDATE, "UpdateDriver: Data file should be of TYPE EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n"));
398 Status = EFI_INVALID_PARAMETER;
399 } else {
400 if (FileBuffer != NULL) {
401 FreePool (FileBuffer);
402 }
403 SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
404 FileBuffer = NULL;
405 FileBufferSize = 0;
406 Status = FwVolProtocol->ReadSection (
407 FwVolProtocol,
408 &(ConfigData->FileGuid),
409 SectionType,
410 0,
411 (VOID **) &FileBuffer,
412 &FileBufferSize,
413 &AuthenticationStatus
414 );
415 if (!EFI_ERROR (Status)) {
416 //
417 // Execute the update. For UpdateWholeFv, the update
418 // will always execute on a whole FV
419 //
420 StartToUpdate = TRUE;
421 Status = PerformUpdateOnFirmwareVolume (
422 ConfigData,
423 FileBuffer,
424 FileBufferSize,
425 FileType,
426 Attrib
427 );
428
429 } else {
430 DEBUG ((EFI_D_UPDATE, "UpdateDriver: Data file should be sectioned with TYPE EFI_SECTION_FIRMWARE_VOLUME_IMAGE\n"));
431 }
432 }
433 break;
434
435 case UpdateFvRange:
436
437 //
438 // For UpdateFvRange, the update file shall be a raw file
439 // which does not contain any sections. The contents of the file
440 // will be directly programmed.
441 //
442 if (FileType != EFI_FV_FILETYPE_RAW) {
443 DEBUG ((EFI_D_UPDATE, "UpdateDriver: Data file should of TYPE EFI_FV_FILETYPE_RAW\n"));
444 Status = EFI_INVALID_PARAMETER;
445 } else {
446 //
447 // For UpdateFvRange, the update may be performed on a sub area
448 // of a certain FV, or a flash area that is not FV, or part of FV.
449 // The update may also go across more than one FVs.
450 //
451 StartToUpdate = TRUE;
452 Status = PerformUpdateOnFlashArea (
453 ConfigData,
454 FileBuffer,
455 FileBufferSize
456 );
457 }
458 break;
459
460 case UpdateFvFile:
461
462 //
463 // No check will be done the the file got. The contents of the file
464 // will be directly programmed.
465 // Though UpdateFvFile will only update a single file, but the update
466 // will always execute on a FV
467 //
468 StartToUpdate = TRUE;
469 Status = PerformUpdateOnFirmwareVolume (
470 ConfigData,
471 FileBuffer,
472 FileBufferSize,
473 FileType,
474 Attrib
475 );
476 break;
477
478 default:
479 Status = EFI_INVALID_PARAMETER;
480 }
481
482 if (StartToUpdate) {
483 if (EFI_ERROR (Status)) {
484 TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_DRIVER_ABORTED), NULL);
485 } else {
486 TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_DRIVER_DONE), NULL);
487 }
488 if (TmpStr != NULL) {
489 Print (TmpStr);
490 FreePool (TmpStr);
491 }
492 }
493
494 if (FileBuffer != NULL) {
495 FreePool(FileBuffer);
496 FileBuffer = NULL;
497 }
498
499 return Status;
500 }
501
502 /**
503 Process the input firmware volume by using DXE service ProcessFirmwareVolume.
504
505 @param DataBuffer Point to the FV image to be processed.
506 @param BufferSize Size of the FV image buffer.
507 @param FwVolProtocol Point to the installed FV protocol for the input FV image.
508
509 @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.
510 @retval EFI_VOLUME_CORRUPTED FV image is corrupted.
511 @retval EFI_SUCCESS FV image is processed and FV protocol is installed.
512
513 **/
514 EFI_STATUS
515 ProcessUpdateImage (
516 UINT8 *DataBuffer,
517 UINTN BufferSize,
518 EFI_FIRMWARE_VOLUME2_PROTOCOL **FwVolProtocol
519 )
520 {
521 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
522 EFI_HANDLE FwVolHandle;
523 EFI_STATUS Status;
524 UINT8 *ProcessedDataBuffer;
525 UINT32 FvAlignment;
526
527 ProcessedDataBuffer = NULL;
528 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DataBuffer;
529 if (FwVolHeader->FvLength != BufferSize) {
530 return EFI_VOLUME_CORRUPTED;
531 }
532
533 FvAlignment = 1 << ((FwVolHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16);
534 //
535 // FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value.
536 //
537 if (FvAlignment < 8) {
538 FvAlignment = 8;
539 }
540 //
541 // Check FvImage Align is required.
542 //
543 if (((UINTN) FwVolHeader % FvAlignment) == 0) {
544 ProcessedDataBuffer = DataBuffer;
545 } else {
546 //
547 // Allocate new aligned buffer to store DataBuffer.
548 //
549 ProcessedDataBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), (UINTN) FvAlignment);
550 if (ProcessedDataBuffer == NULL) {
551 return EFI_OUT_OF_RESOURCES;
552 }
553 CopyMem (ProcessedDataBuffer, DataBuffer, BufferSize);
554 }
555 //
556 // Process the firmware volume
557 //
558 gDS->ProcessFirmwareVolume (
559 ProcessedDataBuffer,
560 BufferSize,
561 &FwVolHandle
562 );
563
564 //
565 // Get the FwVol protocol
566 //
567 Status = gBS->HandleProtocol (
568 FwVolHandle,
569 &gEfiFirmwareVolume2ProtocolGuid,
570 (VOID **) FwVolProtocol
571 );
572
573 return Status;
574 }
575
576 /**
577 Find the image in the same FV and program it in a target Firmware Volume device.
578 After update image, it will reset system and no return.
579
580 @param ImageHandle A handle for the image that is initializing this driver
581 @param SystemTable A pointer to the EFI system table
582
583 @retval EFI_ABORTED System reset failed.
584 @retval EFI_NOT_FOUND The updated image is not found in the same FV.
585
586 **/
587 EFI_STATUS
588 EFIAPI
589 InitializeUpdateDriver (
590 IN EFI_HANDLE ImageHandle,
591 IN EFI_SYSTEM_TABLE *SystemTable
592 )
593 {
594 EFI_STATUS Status;
595 EFI_LOADED_IMAGE_PROTOCOL *LoadedImageProtocol;
596 EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVolProtocol;
597 EFI_FIRMWARE_VOLUME2_PROTOCOL *DataFwVolProtocol;
598 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FwVolFilePathNode;
599 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *AlignedDevPathNode;
600 EFI_DEVICE_PATH_PROTOCOL *FilePathNode;
601 EFI_SECTION_TYPE SectionType;
602 UINT8 *FileBuffer;
603 UINTN FileBufferSize;
604 EFI_FV_FILETYPE FileType;
605 EFI_FV_FILE_ATTRIBUTES Attrib;
606 UINT32 AuthenticationStatus;
607 UPDATE_CONFIG_DATA *ConfigData;
608 UPDATE_CONFIG_DATA *UpdateConfigData;
609 UINTN NumOfUpdates;
610 UINTN Index;
611 CHAR16 *TmpStr;
612
613 //
614 // Clear screen
615 //
616 if (gST->ConOut != NULL) {
617 gST->ConOut->ClearScreen (gST->ConOut);
618 gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);
619 gST->ConOut->EnableCursor (gST->ConOut, FALSE);
620 }
621
622 gHiiHandle = HiiAddPackages (
623 &gEfiCallerIdGuid,
624 NULL,
625 UpdateDriverDxeStrings,
626 NULL
627 );
628 ASSERT (gHiiHandle != NULL);
629
630 //
631 // In order to look for the update data file and programmed image file
632 // from the same volume which this driver is dispatched from, we need
633 // to get the device path of this driver image. It is done by first
634 // locate the LoadedImageProtocol and then get its device path
635 //
636 Status = gBS->OpenProtocol (
637 ImageHandle,
638 &gEfiLoadedImageProtocolGuid,
639 (VOID **)&LoadedImageProtocol,
640 ImageHandle,
641 NULL,
642 EFI_OPEN_PROTOCOL_GET_PROTOCOL
643 );
644 if (EFI_ERROR (Status)) {
645 return Status;
646 }
647 //
648 // Get the firmware volume protocol where this file resides
649 //
650 Status = gBS->HandleProtocol (
651 LoadedImageProtocol->DeviceHandle,
652 &gEfiFirmwareVolume2ProtocolGuid,
653 (VOID **) &FwVolProtocol
654 );
655 if (EFI_ERROR (Status)) {
656 return EFI_NOT_FOUND;
657 }
658
659 //
660 // Shall do some extra check to see if it is really contained in the FV?
661 // Should be able to find the section of this driver in the the FV.
662 //
663 FilePathNode = LoadedImageProtocol->FilePath;
664 FwVolFilePathNode = NULL;
665 while (!IsDevicePathEnd (FilePathNode)) {
666 if (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)FilePathNode)!= NULL) {
667 FwVolFilePathNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) FilePathNode;
668 break;
669 }
670 FilePathNode = NextDevicePathNode (FilePathNode);
671 }
672
673 if (FwVolFilePathNode != NULL) {
674 AlignedDevPathNode = AllocateCopyPool (DevicePathNodeLength (FwVolFilePathNode), FwVolFilePathNode);
675
676 SectionType = EFI_SECTION_PE32;
677 FileBuffer = NULL;
678 FileBufferSize = 0;
679 Status = FwVolProtocol->ReadSection (
680 FwVolProtocol,
681 &(AlignedDevPathNode->FvFileName),
682 SectionType,
683 0,
684 (VOID **) &FileBuffer,
685 &FileBufferSize,
686 &AuthenticationStatus
687 );
688 if (EFI_ERROR (Status)) {
689 FreePool (AlignedDevPathNode);
690 return Status;
691 }
692
693 if (FileBuffer != NULL) {
694 FreePool(FileBuffer);
695 FileBuffer = NULL;
696 }
697
698 //
699 // Check the NameGuid of the udpate driver so that it can be
700 // used as the CallerId in fault tolerant write protocol
701 //
702 if (!CompareGuid (&gEfiCallerIdGuid, &(AlignedDevPathNode->FvFileName))) {
703 FreePool (AlignedDevPathNode);
704 return EFI_NOT_FOUND;
705 }
706 FreePool (AlignedDevPathNode);
707 } else {
708 return EFI_NOT_FOUND;
709 }
710
711 //
712 // Now try to find the script file. The script file is usually
713 // a raw data file which does not contain any sections.
714 //
715 FileBuffer = NULL;
716 FileBufferSize = 0;
717 Status = FwVolProtocol->ReadFile (
718 FwVolProtocol,
719 &gEfiConfigFileNameGuid,
720 (VOID **) &FileBuffer,
721 &FileBufferSize,
722 &FileType,
723 &Attrib,
724 &AuthenticationStatus
725 );
726 if (EFI_ERROR (Status)) {
727 return Status;
728 }
729 if (FileType != EFI_FV_FILETYPE_RAW) {
730 return EFI_NOT_FOUND;
731 }
732
733 //
734 // Parse the configuration file.
735 //
736 ConfigData = NULL;
737 NumOfUpdates = 0;
738 Status = ParseUpdateDataFile (
739 FileBuffer,
740 FileBufferSize,
741 &NumOfUpdates,
742 &ConfigData
743 );
744 if (FileBuffer != NULL) {
745 FreePool (FileBuffer);
746 FileBuffer = NULL;
747 }
748 if (EFI_ERROR (Status)) {
749 return Status;
750 }
751 ASSERT (ConfigData != NULL);
752
753 //
754 // Now find the update image. The update image should be put in a FV, and then
755 // encapsulated as a raw FFS file. This is to prevent the update image from
756 // being dispatched. So the raw data we get here should be an FV. We need to
757 // process this FV and read the files that is going to be updated.
758 //
759 FileBuffer = NULL;
760 FileBufferSize = 0;
761 Status = FwVolProtocol->ReadFile (
762 FwVolProtocol,
763 &gEfiUpdateDataFileGuid,
764 (VOID **) &FileBuffer,
765 &FileBufferSize,
766 &FileType,
767 &Attrib,
768 &AuthenticationStatus
769 );
770 if (EFI_ERROR (Status)) {
771 return Status;
772 }
773 if (FileType != EFI_FV_FILETYPE_RAW) {
774 return EFI_NOT_FOUND;
775 }
776
777 //
778 // FileBuffer should be an FV. Process the FV
779 //
780 DataFwVolProtocol = NULL;
781 Status = ProcessUpdateImage (
782 FileBuffer,
783 FileBufferSize,
784 &DataFwVolProtocol
785 );
786 if (EFI_ERROR (Status)) {
787 FreePool (FileBuffer);
788 return Status;
789 }
790
791 //
792 // Print on screen
793 //
794 TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_PROCESS_DATA), NULL);
795 if (TmpStr != NULL) {
796 Print (TmpStr);
797 FreePool(TmpStr);
798 }
799
800 //
801 // Execute the update
802 //
803 Index = 0;
804 UpdateConfigData = ConfigData;
805 while (Index < NumOfUpdates) {
806 Status = PerformUpdate (
807 DataFwVolProtocol,
808 UpdateConfigData
809 );
810 //
811 // Shall updates be serialized so that if an update is not successfully completed,
812 // the remaining updates won't be performed.
813 //
814 if (EFI_ERROR (Status)) {
815 break;
816 }
817
818 Index++;
819 UpdateConfigData++;
820 }
821
822 if (EFI_ERROR (Status)) {
823 if (ConfigData != NULL) {
824 FreePool(ConfigData);
825 ConfigData = NULL;
826 }
827 return Status;
828 }
829
830 //
831 // Call system reset
832 //
833 gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
834
835 //
836 // Hopefully it won't be reached
837 //
838 return EFI_ABORTED;
839 }