+++ /dev/null
-/** @file\r
- Functions in this file will mainly focus on looking through the capsule\r
- for the image to be programmed, and the flash area that is going to be\r
- programed.\r
-\r
- Copyright (c) 2002 - 2018, Intel Corporation. All rights reserved.<BR>\r
-\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "UpdateDriver.h"\r
-\r
-EFI_HII_HANDLE gHiiHandle;\r
-\r
-/**\r
- Update the whole FV, or certain files in the FV.\r
-\r
- @param ConfigData Pointer to the config data on updating file.\r
- @param ImageBuffer Image buffer to be updated.\r
- @param ImageSize Image size.\r
- @param FileType FFS file type.\r
- @param FileAttributes FFS file attribute.\r
-\r
- @retval EFI_NOT_FOUND The matched FVB protocol is not found.\r
- @retval EFI_SUCCESS The image buffer is updated into FV.\r
-\r
-**/\r
-EFI_STATUS\r
-PerformUpdateOnFirmwareVolume (\r
- IN UPDATE_CONFIG_DATA *ConfigData,\r
- IN UINT8 *ImageBuffer,\r
- IN UINTN ImageSize,\r
- IN EFI_FV_FILETYPE FileType,\r
- IN EFI_FV_FILE_ATTRIBUTES FileAttributes\r
- )\r
-{\r
- EFI_STATUS Status;\r
- BOOLEAN Found;\r
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;\r
- UINTN Index;\r
- UINTN NumOfHandles;\r
- EFI_HANDLE *HandleBuffer;\r
- EFI_PHYSICAL_ADDRESS BaseAddress;\r
- EFI_FVB_ATTRIBUTES_2 Attributes;\r
-\r
- //\r
- // Locate all Fvb protocol\r
- //\r
- HandleBuffer = NULL;\r
- Status = gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiFirmwareVolumeBlockProtocolGuid,\r
- NULL,\r
- &NumOfHandles,\r
- &HandleBuffer\r
- );\r
- if ((EFI_ERROR (Status)) || (NumOfHandles == 0) || (HandleBuffer == NULL)) {\r
- if (HandleBuffer != NULL) {\r
- FreePool (HandleBuffer);\r
- }\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- //\r
- // Check the FVB protocol one by one\r
- //\r
- Found = FALSE;\r
- FvbProtocol = NULL;\r
- for (Index = 0; Index < NumOfHandles; Index++) {\r
- Status = gBS->HandleProtocol (\r
- HandleBuffer[Index],\r
- &gEfiFirmwareVolumeBlockProtocolGuid,\r
- (VOID **) &FvbProtocol\r
- );\r
- if (EFI_ERROR (Status)) {\r
- break;\r
- }\r
-\r
- //\r
- // Ensure this FVB protocol supported Write operation.\r
- //\r
- Status = FvbProtocol->GetAttributes (FvbProtocol, &Attributes);\r
- if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {\r
- continue;\r
- }\r
-\r
- Status = FvbProtocol->GetPhysicalAddress (\r
- FvbProtocol,\r
- &BaseAddress\r
- );\r
- if (EFI_ERROR (Status)) {\r
- break;\r
- }\r
- if (BaseAddress == ConfigData->BaseAddress) {\r
- Found = TRUE;\r
- break;\r
- }\r
- }\r
-\r
- if (!Found) {\r
- if (HandleBuffer != NULL) {\r
- FreePool (HandleBuffer);\r
- HandleBuffer = NULL;\r
- }\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- //\r
- // Now we have got the corresponding FVB protocol. Use the FVB protocol\r
- // to update the whole FV, or certain files in the FV.\r
- //\r
- if (ConfigData->UpdateType == UpdateWholeFV) {\r
- if (FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
- Status = EFI_INVALID_PARAMETER;\r
- } else {\r
- Status = PerformUpdateOnWholeFv (\r
- HandleBuffer[Index],\r
- FvbProtocol,\r
- ConfigData,\r
- ImageBuffer,\r
- ImageSize\r
- );\r
- }\r
- } else if (ConfigData->UpdateType == UpdateFvFile) {\r
- Status = PerformUpdateOnFvFile (\r
- HandleBuffer[Index],\r
- FvbProtocol,\r
- ConfigData,\r
- ImageBuffer,\r
- ImageSize,\r
- FileType,\r
- FileAttributes\r
- );\r
- }\r
-\r
- if (HandleBuffer != NULL) {\r
- FreePool (HandleBuffer);\r
- HandleBuffer = NULL;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Update the file directly into flash area.\r
-\r
- @param ConfigData Pointer to the config data on updating file.\r
- @param ImageBuffer Image buffer to be updated.\r
- @param ImageSize Image size.\r
-\r
- @retval EFI_SUCCESS The file is updated into flash area.\r
- @retval EFI_NOT_FOUND The FVB protocol for the updated flash area is not found.\r
-\r
-**/\r
-EFI_STATUS\r
-PerformUpdateOnFlashArea (\r
- IN UPDATE_CONFIG_DATA *ConfigData,\r
- IN UINT8 *ImageBuffer,\r
- IN UINTN ImageSize\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINTN SizeLeft;\r
- EFI_PHYSICAL_ADDRESS FlashAddress;\r
- UINT8 *PtrImage;\r
- BOOLEAN Found;\r
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;\r
- UINTN Index;\r
- UINTN NumOfHandles;\r
- EFI_HANDLE *HandleBuffer;\r
- EFI_PHYSICAL_ADDRESS BaseAddress;\r
- EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
- EFI_HANDLE FvbHandle;\r
- UINTN SizeUpdated;\r
- CHAR16 *TmpStr;\r
- EFI_FVB_ATTRIBUTES_2 Attributes;\r
-\r
- SizeLeft = ImageSize;\r
- PtrImage = ImageBuffer;\r
- FlashAddress = ConfigData->BaseAddress;\r
- Status = EFI_SUCCESS;\r
- HandleBuffer = NULL;\r
-\r
- //\r
- // Print on screen\r
- //\r
- TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_FLASH_RANGE), NULL);\r
- if (TmpStr != NULL) {\r
- Print (TmpStr, FlashAddress, ((UINT64)SizeLeft + FlashAddress));\r
- FreePool (TmpStr);\r
- }\r
-\r
- //\r
- // Locate all Fvb protocol\r
- //\r
- Status = gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiFirmwareVolumeBlockProtocolGuid,\r
- NULL,\r
- &NumOfHandles,\r
- &HandleBuffer\r
- );\r
- if ((EFI_ERROR (Status)) || (NumOfHandles == 0) || (HandleBuffer == NULL)) {\r
- if (HandleBuffer != NULL) {\r
- FreePool (HandleBuffer);\r
- }\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- while (SizeLeft > 0) {\r
- //\r
- // First get the FVB protocols. If the flash area is a FV, or sub FV,\r
- // we can directly locate all the FVB protocol. Otherwise we should use\r
- // implementation specific method to get the alternate FVB protocol\r
- //\r
- Found = FALSE;\r
- FvbProtocol = NULL;\r
-\r
- //\r
- // Check the FVB protocol one by one\r
- //\r
- for (Index = 0; Index < NumOfHandles; Index++) {\r
- Status = gBS->HandleProtocol (\r
- HandleBuffer[Index],\r
- &gEfiFirmwareVolumeBlockProtocolGuid,\r
- (VOID **) &FvbProtocol\r
- );\r
- if (EFI_ERROR (Status)) {\r
- break;\r
- }\r
-\r
- //\r
- // Ensure this FVB protocol supported Write operation.\r
- //\r
- Status = FvbProtocol->GetAttributes (FvbProtocol, &Attributes);\r
- if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {\r
- continue;\r
- }\r
-\r
- Status = FvbProtocol->GetPhysicalAddress (\r
- FvbProtocol,\r
- &BaseAddress\r
- );\r
- if (EFI_ERROR (Status)) {\r
- break;\r
- }\r
- FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress;\r
-\r
- //\r
- // This sub area entry falls in the range of the FV\r
- //\r
- if ((FlashAddress >= BaseAddress) && (FlashAddress < (BaseAddress + FwVolHeader->FvLength))) {\r
- Found = TRUE;\r
- break;\r
- }\r
- }\r
-\r
- if (!Found) {\r
- if (HandleBuffer != NULL) {\r
- FreePool (HandleBuffer);\r
- HandleBuffer = NULL;\r
- }\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- FvbHandle = HandleBuffer[Index];\r
- SizeUpdated = 0;\r
-\r
- //\r
- // If the flash area is boot required, the update must be fault tolerant\r
- //\r
- if (ConfigData->FaultTolerant) {\r
- //\r
- // Finally we are here. We have got the corresponding FVB protocol. Now\r
- // we need to convert the physical address to LBA and offset and call\r
- // FTW write. Also check if the flash range is larger than the FV.\r
- //\r
- Status = FaultTolerantUpdateOnPartFv (\r
- PtrImage,\r
- SizeLeft,\r
- &SizeUpdated,\r
- ConfigData,\r
- FlashAddress,\r
- FvbProtocol,\r
- FvbHandle\r
- );\r
- } else {\r
- //\r
- // Finally we are here. We have got the corresponding FVB protocol. Now\r
- // we need to convert the physical address to LBA and offset and call\r
- // FVB write. Also check if the flash range is larger than the FV.\r
- //\r
- Status = NonFaultTolerantUpdateOnPartFv (\r
- PtrImage,\r
- SizeLeft,\r
- &SizeUpdated,\r
- FlashAddress,\r
- FvbProtocol,\r
- FvbHandle\r
- );\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // As part of the FV has been replaced, the FV driver shall re-parse\r
- // the firmware volume. So re-install FVB protocol here\r
- //\r
- Status = gBS->ReinstallProtocolInterface (\r
- FvbHandle,\r
- &gEfiFirmwareVolumeBlockProtocolGuid,\r
- FvbProtocol,\r
- FvbProtocol\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Check if we are done with the update\r
- //\r
- SizeLeft = SizeLeft - SizeUpdated;\r
- FlashAddress = FlashAddress + SizeUpdated;\r
- PtrImage = PtrImage + SizeUpdated;\r
- }\r
-\r
- if (HandleBuffer != NULL) {\r
- FreePool (HandleBuffer);\r
- HandleBuffer = NULL;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Find the updated file, and program it into the flash area based on the config data.\r
-\r
- @param FwVolProtocol Pointer to FV protocol that contains the updated file.\r
- @param ConfigData Pointer to the Config Data on updating file.\r
-\r
- @retval EFI_INVALID_PARAMETER The update operation is not valid.\r
- @retval EFI_NOT_FOUND The updated file is not found.\r
- @retval EFI_SUCCESS The file is updated into the flash area.\r
-\r
-**/\r
-EFI_STATUS\r
-PerformUpdate (\r
- IN EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVolProtocol,\r
- IN UPDATE_CONFIG_DATA *ConfigData\r
- )\r
-{\r
- EFI_STATUS Status;\r
- UINT8 *FileBuffer;\r
- UINTN FileBufferSize;\r
- EFI_FV_FILETYPE FileType;\r
- EFI_FV_FILE_ATTRIBUTES Attrib;\r
- EFI_SECTION_TYPE SectionType;\r
- UINT32 AuthenticationStatus;\r
- CHAR16 *TmpStr;\r
- BOOLEAN StartToUpdate;\r
-\r
- Status = EFI_SUCCESS;\r
- FileBuffer = NULL;\r
- FileBufferSize = 0;\r
- Status = FwVolProtocol->ReadFile (\r
- FwVolProtocol,\r
- &(ConfigData->FileGuid),\r
- (VOID **) &FileBuffer,\r
- &FileBufferSize,\r
- &FileType,\r
- &Attrib,\r
- &AuthenticationStatus\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- StartToUpdate = FALSE;\r
-\r
- //\r
- // Check if the update image is the one we require\r
- // and then perform the update\r
- //\r
- switch (ConfigData->UpdateType) {\r
-\r
- case UpdateWholeFV:\r
-\r
- //\r
- // For UpdateWholeFv, the update file shall be a firmware volume\r
- // image file.\r
- //\r
- if (FileType != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {\r
- DEBUG ((EFI_D_UPDATE, "UpdateDriver: Data file should be of TYPE EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n"));\r
- Status = EFI_INVALID_PARAMETER;\r
- } else {\r
- if (FileBuffer != NULL) {\r
- FreePool (FileBuffer);\r
- }\r
- SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;\r
- FileBuffer = NULL;\r
- FileBufferSize = 0;\r
- Status = FwVolProtocol->ReadSection (\r
- FwVolProtocol,\r
- &(ConfigData->FileGuid),\r
- SectionType,\r
- 0,\r
- (VOID **) &FileBuffer,\r
- &FileBufferSize,\r
- &AuthenticationStatus\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Execute the update. For UpdateWholeFv, the update\r
- // will always execute on a whole FV\r
- //\r
- StartToUpdate = TRUE;\r
- Status = PerformUpdateOnFirmwareVolume (\r
- ConfigData,\r
- FileBuffer,\r
- FileBufferSize,\r
- FileType,\r
- Attrib\r
- );\r
-\r
- } else {\r
- DEBUG ((EFI_D_UPDATE, "UpdateDriver: Data file should be sectioned with TYPE EFI_SECTION_FIRMWARE_VOLUME_IMAGE\n"));\r
- }\r
- }\r
- break;\r
-\r
- case UpdateFvRange:\r
-\r
- //\r
- // For UpdateFvRange, the update file shall be a raw file\r
- // which does not contain any sections. The contents of the file\r
- // will be directly programmed.\r
- //\r
- if (FileType != EFI_FV_FILETYPE_RAW) {\r
- DEBUG ((EFI_D_UPDATE, "UpdateDriver: Data file should of TYPE EFI_FV_FILETYPE_RAW\n"));\r
- Status = EFI_INVALID_PARAMETER;\r
- } else {\r
- //\r
- // For UpdateFvRange, the update may be performed on a sub area\r
- // of a certain FV, or a flash area that is not FV, or part of FV.\r
- // The update may also go across more than one FVs.\r
- //\r
- StartToUpdate = TRUE;\r
- Status = PerformUpdateOnFlashArea (\r
- ConfigData,\r
- FileBuffer,\r
- FileBufferSize\r
- );\r
- }\r
- break;\r
-\r
- case UpdateFvFile:\r
-\r
- //\r
- // No check will be done the the file got. The contents of the file\r
- // will be directly programmed.\r
- // Though UpdateFvFile will only update a single file, but the update\r
- // will always execute on a FV\r
- //\r
- StartToUpdate = TRUE;\r
- Status = PerformUpdateOnFirmwareVolume (\r
- ConfigData,\r
- FileBuffer,\r
- FileBufferSize,\r
- FileType,\r
- Attrib\r
- );\r
- break;\r
-\r
- default:\r
- Status = EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (StartToUpdate) {\r
- if (EFI_ERROR (Status)) {\r
- TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_DRIVER_ABORTED), NULL);\r
- } else {\r
- TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_DRIVER_DONE), NULL);\r
- }\r
- if (TmpStr != NULL) {\r
- Print (TmpStr);\r
- FreePool (TmpStr);\r
- }\r
- }\r
-\r
- if (FileBuffer != NULL) {\r
- FreePool(FileBuffer);\r
- FileBuffer = NULL;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Process the input firmware volume by using DXE service ProcessFirmwareVolume.\r
-\r
- @param DataBuffer Point to the FV image to be processed.\r
- @param BufferSize Size of the FV image buffer.\r
- @param FwVolProtocol Point to the installed FV protocol for the input FV image.\r
-\r
- @retval EFI_OUT_OF_RESOURCES No enough memory is allocated.\r
- @retval EFI_VOLUME_CORRUPTED FV image is corrupted.\r
- @retval EFI_SUCCESS FV image is processed and FV protocol is installed.\r
-\r
-**/\r
-EFI_STATUS\r
-ProcessUpdateImage (\r
- UINT8 *DataBuffer,\r
- UINTN BufferSize,\r
- EFI_FIRMWARE_VOLUME2_PROTOCOL **FwVolProtocol\r
- )\r
-{\r
- EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
- EFI_HANDLE FwVolHandle;\r
- EFI_STATUS Status;\r
- UINT8 *ProcessedDataBuffer;\r
- UINT32 FvAlignment;\r
-\r
- ProcessedDataBuffer = NULL;\r
- FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DataBuffer;\r
- if (FwVolHeader->FvLength != BufferSize) {\r
- return EFI_VOLUME_CORRUPTED;\r
- }\r
-\r
- FvAlignment = 1 << ((FwVolHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16);\r
- //\r
- // FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value.\r
- //\r
- if (FvAlignment < 8) {\r
- FvAlignment = 8;\r
- }\r
- //\r
- // Check FvImage Align is required.\r
- //\r
- if (((UINTN) FwVolHeader % FvAlignment) == 0) {\r
- ProcessedDataBuffer = DataBuffer;\r
- } else {\r
- //\r
- // Allocate new aligned buffer to store DataBuffer.\r
- //\r
- ProcessedDataBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), (UINTN) FvAlignment);\r
- if (ProcessedDataBuffer == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- CopyMem (ProcessedDataBuffer, DataBuffer, BufferSize);\r
- }\r
- //\r
- // Process the firmware volume\r
- //\r
- gDS->ProcessFirmwareVolume (\r
- ProcessedDataBuffer,\r
- BufferSize,\r
- &FwVolHandle\r
- );\r
-\r
- //\r
- // Get the FwVol protocol\r
- //\r
- Status = gBS->HandleProtocol (\r
- FwVolHandle,\r
- &gEfiFirmwareVolume2ProtocolGuid,\r
- (VOID **) FwVolProtocol\r
- );\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Find the image in the same FV and program it in a target Firmware Volume device.\r
- After update image, it will reset system and no return.\r
-\r
- @param ImageHandle A handle for the image that is initializing this driver\r
- @param SystemTable A pointer to the EFI system table\r
-\r
- @retval EFI_ABORTED System reset failed.\r
- @retval EFI_NOT_FOUND The updated image is not found in the same FV.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-InitializeUpdateDriver (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_LOADED_IMAGE_PROTOCOL *LoadedImageProtocol;\r
- EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVolProtocol;\r
- EFI_FIRMWARE_VOLUME2_PROTOCOL *DataFwVolProtocol;\r
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FwVolFilePathNode;\r
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *AlignedDevPathNode;\r
- EFI_DEVICE_PATH_PROTOCOL *FilePathNode;\r
- EFI_SECTION_TYPE SectionType;\r
- UINT8 *FileBuffer;\r
- UINTN FileBufferSize;\r
- EFI_FV_FILETYPE FileType;\r
- EFI_FV_FILE_ATTRIBUTES Attrib;\r
- UINT32 AuthenticationStatus;\r
- UPDATE_CONFIG_DATA *ConfigData;\r
- UPDATE_CONFIG_DATA *UpdateConfigData;\r
- UINTN NumOfUpdates;\r
- UINTN Index;\r
- CHAR16 *TmpStr;\r
-\r
- //\r
- // Clear screen\r
- //\r
- if (gST->ConOut != NULL) {\r
- gST->ConOut->ClearScreen (gST->ConOut);\r
- gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);\r
- gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
- }\r
-\r
- gHiiHandle = HiiAddPackages (\r
- &gEfiCallerIdGuid,\r
- NULL,\r
- UpdateDriverDxeStrings,\r
- NULL\r
- );\r
- ASSERT (gHiiHandle != NULL);\r
-\r
- //\r
- // In order to look for the update data file and programmed image file\r
- // from the same volume which this driver is dispatched from, we need\r
- // to get the device path of this driver image. It is done by first\r
- // locate the LoadedImageProtocol and then get its device path\r
- //\r
- Status = gBS->OpenProtocol (\r
- ImageHandle,\r
- &gEfiLoadedImageProtocolGuid,\r
- (VOID **)&LoadedImageProtocol,\r
- ImageHandle,\r
- NULL,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- //\r
- // Get the firmware volume protocol where this file resides\r
- //\r
- Status = gBS->HandleProtocol (\r
- LoadedImageProtocol->DeviceHandle,\r
- &gEfiFirmwareVolume2ProtocolGuid,\r
- (VOID **) &FwVolProtocol\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- //\r
- // Shall do some extra check to see if it is really contained in the FV?\r
- // Should be able to find the section of this driver in the the FV.\r
- //\r
- FilePathNode = LoadedImageProtocol->FilePath;\r
- FwVolFilePathNode = NULL;\r
- while (!IsDevicePathEnd (FilePathNode)) {\r
- if (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)FilePathNode)!= NULL) {\r
- FwVolFilePathNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) FilePathNode;\r
- break;\r
- }\r
- FilePathNode = NextDevicePathNode (FilePathNode);\r
- }\r
-\r
- if (FwVolFilePathNode != NULL) {\r
- AlignedDevPathNode = AllocateCopyPool (DevicePathNodeLength (FwVolFilePathNode), FwVolFilePathNode);\r
-\r
- SectionType = EFI_SECTION_PE32;\r
- FileBuffer = NULL;\r
- FileBufferSize = 0;\r
- Status = FwVolProtocol->ReadSection (\r
- FwVolProtocol,\r
- &(AlignedDevPathNode->FvFileName),\r
- SectionType,\r
- 0,\r
- (VOID **) &FileBuffer,\r
- &FileBufferSize,\r
- &AuthenticationStatus\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreePool (AlignedDevPathNode);\r
- return Status;\r
- }\r
-\r
- if (FileBuffer != NULL) {\r
- FreePool(FileBuffer);\r
- FileBuffer = NULL;\r
- }\r
-\r
- //\r
- // Check the NameGuid of the udpate driver so that it can be\r
- // used as the CallerId in fault tolerant write protocol\r
- //\r
- if (!CompareGuid (&gEfiCallerIdGuid, &(AlignedDevPathNode->FvFileName))) {\r
- FreePool (AlignedDevPathNode);\r
- return EFI_NOT_FOUND;\r
- }\r
- FreePool (AlignedDevPathNode);\r
- } else {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- //\r
- // Now try to find the script file. The script file is usually\r
- // a raw data file which does not contain any sections.\r
- //\r
- FileBuffer = NULL;\r
- FileBufferSize = 0;\r
- Status = FwVolProtocol->ReadFile (\r
- FwVolProtocol,\r
- &gEfiConfigFileNameGuid,\r
- (VOID **) &FileBuffer,\r
- &FileBufferSize,\r
- &FileType,\r
- &Attrib,\r
- &AuthenticationStatus\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- if (FileType != EFI_FV_FILETYPE_RAW) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- //\r
- // Parse the configuration file.\r
- //\r
- ConfigData = NULL;\r
- NumOfUpdates = 0;\r
- Status = ParseUpdateDataFile (\r
- FileBuffer,\r
- FileBufferSize,\r
- &NumOfUpdates,\r
- &ConfigData\r
- );\r
- if (FileBuffer != NULL) {\r
- FreePool (FileBuffer);\r
- FileBuffer = NULL;\r
- }\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- ASSERT (ConfigData != NULL);\r
-\r
- //\r
- // Now find the update image. The update image should be put in a FV, and then\r
- // encapsulated as a raw FFS file. This is to prevent the update image from\r
- // being dispatched. So the raw data we get here should be an FV. We need to\r
- // process this FV and read the files that is going to be updated.\r
- //\r
- FileBuffer = NULL;\r
- FileBufferSize = 0;\r
- Status = FwVolProtocol->ReadFile (\r
- FwVolProtocol,\r
- &gEfiUpdateDataFileGuid,\r
- (VOID **) &FileBuffer,\r
- &FileBufferSize,\r
- &FileType,\r
- &Attrib,\r
- &AuthenticationStatus\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- if (FileType != EFI_FV_FILETYPE_RAW) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- //\r
- // FileBuffer should be an FV. Process the FV\r
- //\r
- DataFwVolProtocol = NULL;\r
- Status = ProcessUpdateImage (\r
- FileBuffer,\r
- FileBufferSize,\r
- &DataFwVolProtocol\r
- );\r
- if (EFI_ERROR (Status)) {\r
- FreePool (FileBuffer);\r
- return Status;\r
- }\r
-\r
- //\r
- // Print on screen\r
- //\r
- TmpStr = HiiGetString (gHiiHandle, STRING_TOKEN(UPDATE_PROCESS_DATA), NULL);\r
- if (TmpStr != NULL) {\r
- Print (TmpStr);\r
- FreePool(TmpStr);\r
- }\r
-\r
- //\r
- // Execute the update\r
- //\r
- Index = 0;\r
- UpdateConfigData = ConfigData;\r
- while (Index < NumOfUpdates) {\r
- Status = PerformUpdate (\r
- DataFwVolProtocol,\r
- UpdateConfigData\r
- );\r
- //\r
- // Shall updates be serialized so that if an update is not successfully completed,\r
- // the remaining updates won't be performed.\r
- //\r
- if (EFI_ERROR (Status)) {\r
- break;\r
- }\r
-\r
- Index++;\r
- UpdateConfigData++;\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- if (ConfigData != NULL) {\r
- FreePool(ConfigData);\r
- ConfigData = NULL;\r
- }\r
- return Status;\r
- }\r
-\r
- //\r
- // Call system reset\r
- //\r
- gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);\r
-\r
- //\r
- // Hopefully it won't be reached\r
- //\r
- return EFI_ABORTED;\r
-}\r