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