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
PerformUpdateOnFirmwareVolume(IN UPDATE_CONFIG_DATA * ConfigData,IN UINT8 * ImageBuffer,IN UINTN ImageSize,IN EFI_FV_FILETYPE FileType,IN EFI_FV_FILE_ATTRIBUTES FileAttributes)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
PerformUpdateOnFlashArea(IN UPDATE_CONFIG_DATA * ConfigData,IN UINT8 * ImageBuffer,IN UINTN ImageSize)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
PerformUpdate(IN EFI_FIRMWARE_VOLUME2_PROTOCOL * FwVolProtocol,IN UPDATE_CONFIG_DATA * ConfigData)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
ProcessUpdateImage(UINT8 * DataBuffer,UINTN BufferSize,EFI_FIRMWARE_VOLUME2_PROTOCOL ** FwVolProtocol)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
InitializeUpdateDriver(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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 }
840