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