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 - 2014, 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
PerformUpdateOnFirmwareVolume(IN UPDATE_CONFIG_DATA * ConfigData,IN UINT8 * ImageBuffer,IN UINTN ImageSize,IN EFI_FV_FILETYPE FileType,IN EFI_FV_FILE_ATTRIBUTES FileAttributes)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
PerformUpdateOnFlashArea(IN UPDATE_CONFIG_DATA * ConfigData,IN UINT8 * ImageBuffer,IN UINTN ImageSize)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
PerformUpdate(IN EFI_FIRMWARE_VOLUME2_PROTOCOL * FwVolProtocol,IN UPDATE_CONFIG_DATA * ConfigData)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
ProcessUpdateImage(UINT8 * DataBuffer,UINTN BufferSize,EFI_FIRMWARE_VOLUME2_PROTOCOL ** FwVolProtocol)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
InitializeUpdateDriver(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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   ASSERT (ConfigData != NULL);
759 
760   //
761   // Now find the update image. The update image should be put in a FV, and then
762   // encapsulated as a raw FFS file. This is to prevent the update image from
763   // being dispatched. So the raw data we get here should be an FV. We need to
764   // process this FV and read the files that is going to be updated.
765   //
766   FileBuffer        = NULL;
767   FileBufferSize    = 0;
768   Status            = FwVolProtocol->ReadFile (
769                                        FwVolProtocol,
770                                        &gEfiUpdateDataFileGuid,
771                                        (VOID **) &FileBuffer,
772                                        &FileBufferSize,
773                                        &FileType,
774                                        &Attrib,
775                                        &AuthenticationStatus
776                                        );
777   if (EFI_ERROR (Status)) {
778     return Status;
779   }
780   if (FileType != EFI_FV_FILETYPE_RAW) {
781     return EFI_NOT_FOUND;
782   }
783 
784   //
785   // FileBuffer should be an FV. Process the FV
786   //
787   DataFwVolProtocol = NULL;
788   Status            = ProcessUpdateImage (
789                         FileBuffer,
790                         FileBufferSize,
791                         &DataFwVolProtocol
792                         );
793   if (EFI_ERROR (Status)) {
794     FreePool (FileBuffer);
795     return Status;
796   }
797 
798   //
799   // Print on screen
800   //
801   TmpStr  = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_PROCESS_DATA), NULL);
802   if (TmpStr != NULL) {
803     Print (TmpStr);
804     FreePool(TmpStr);
805   }
806 
807   //
808   // Execute the update
809   //
810   Index = 0;
811   UpdateConfigData = ConfigData;
812   while (Index < NumOfUpdates) {
813     Status = PerformUpdate (
814                DataFwVolProtocol,
815                UpdateConfigData
816                );
817     //
818     // Shall updates be serialized so that if an update is not successfully completed,
819     // the remaining updates won't be performed.
820     //
821     if (EFI_ERROR (Status)) {
822       break;
823     }
824 
825     Index++;
826     UpdateConfigData++;
827   }
828 
829   if (EFI_ERROR (Status)) {
830     if (ConfigData != NULL) {
831       FreePool(ConfigData);
832       ConfigData = NULL;
833     }
834     return Status;
835   }
836 
837   //
838   // Call system reset
839   //
840   gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
841 
842   //
843   // Hopefully it won't be reached
844   //
845   return EFI_ABORTED;
846 }
847