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 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 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