/** Update System Firmware image component. @param[in] SystemFirmwareImage Points to the System Firmware image. @param[in] SystemFirmwareImageSize The length of the System Firmware image in bytes. @param[in] ConfigData Points to the component configuration structure. @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. @retval EFI_SUCCESS The System Firmware image is updated. @retval EFI_WRITE_PROTECTED The flash device is read only. **/ EFI_STATUS PerformUpdate ( IN VOID *SystemFirmwareImage, IN UINTN SystemFirmwareImageSize, IN UPDATE_CONFIG_DATA *ConfigData, OUT UINT32 *LastAttemptVersion, OUT UINT32 *LastAttemptStatus ) { EFI_STATUS Status; DEBUG((DEBUG_INFO, "PlatformUpdate:")); DEBUG((DEBUG_INFO, " BaseAddress - 0x%lx,", ConfigData->BaseAddress)); DEBUG((DEBUG_INFO, " ImageOffset - 0x%x,", ConfigData->ImageOffset)); DEBUG((DEBUG_INFO, " Legnth - 0x%x\n", ConfigData->Length)); Status = PerformFlashWrite ( ConfigData->FirmwareType, ConfigData->BaseAddress, ConfigData->AddressType, (VOID *)((UINTN)SystemFirmwareImage + (UINTN)ConfigData->ImageOffset), ConfigData->Length ); if (!EFI_ERROR(Status)) { *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS; if (ConfigData->FirmwareType == PlatformFirmwareTypeNvRam) { mNvRamUpdated = TRUE; } } else { *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; } return Status; }
/** Perform microcode write operation. @param[in] FlashAddress The address of flash device to be accessed. @param[in] Buffer The pointer to the data buffer. @param[in] Length The length of data buffer in bytes. @retval EFI_SUCCESS The operation returns successfully. @retval EFI_WRITE_PROTECTED The flash device is read only. @retval EFI_UNSUPPORTED The flash device access is unsupported. @retval EFI_INVALID_PARAMETER The input parameter is not valid. **/ EFI_STATUS EFIAPI MicrocodeFlashWrite ( IN EFI_PHYSICAL_ADDRESS FlashAddress, IN VOID *Buffer, IN UINTN Length ) { EFI_PHYSICAL_ADDRESS AlignedFlashAddress; VOID *AlignedBuffer; UINTN AlignedLength; UINTN OffsetHead; UINTN OffsetTail; EFI_STATUS Status; DEBUG((DEBUG_INFO, "MicrocodeFlashWrite - 0x%x - 0x%x\n", (UINTN)FlashAddress, Length)); // // Need make buffer 64K aligned to support ERASE // // [Aligned] FlashAddress [Aligned] // | | | // V V V // +--------------+========+------------+ // | OffsetHeader | Length | OffsetTail | // +--------------+========+------------+ // ^ // |<-----------AlignedLength-----------> // | // AlignedFlashAddress // OffsetHead = FlashAddress & (ALINGED_SIZE - 1); OffsetTail = (FlashAddress + Length) & (ALINGED_SIZE - 1); if (OffsetTail != 0) { OffsetTail = ALINGED_SIZE - OffsetTail; } if ((OffsetHead != 0) || (OffsetTail != 0)) { AlignedFlashAddress = FlashAddress - OffsetHead; AlignedLength = Length + OffsetHead + OffsetTail; AlignedBuffer = AllocatePool(AlignedLength); if (AlignedBuffer == NULL) { return EFI_OUT_OF_RESOURCES; } // // Save original buffer // if (OffsetHead != 0) { CopyMem((UINT8 *)AlignedBuffer, (VOID *)(UINTN)AlignedFlashAddress, OffsetHead); } if (OffsetTail != 0) { CopyMem((UINT8 *)AlignedBuffer + OffsetHead + Length, (VOID *)(UINTN)(AlignedFlashAddress + OffsetHead + Length), OffsetTail); } // // Override new buffer // CopyMem((UINT8 *)AlignedBuffer + OffsetHead, Buffer, Length); } else { AlignedFlashAddress = FlashAddress; AlignedBuffer = Buffer; AlignedLength = Length; } Status = PerformFlashWrite( PlatformFirmwareTypeSystemFirmware, AlignedFlashAddress, FlashAddressTypeAbsoluteAddress, AlignedBuffer, AlignedLength ); if ((OffsetHead != 0) || (OffsetTail != 0)) { FreePool (AlignedBuffer); } return Status; }
/** Update System Firmware image. @param[in] SystemFirmwareImage Points to the System Firmware image. @param[in] SystemFirmwareImageSize The length of the System Firmware image in bytes. @param[in] ConfigImage Points to the config file image. @param[in] ConfigImageSize The length of the config file image in bytes. @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. @param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR. @retval EFI_SUCCESS The System Firmware image is updated. @retval EFI_WRITE_PROTECTED The flash device is read only. **/ EFI_STATUS UpdateImage ( IN VOID *SystemFirmwareImage, IN UINTN SystemFirmwareImageSize, IN VOID *ConfigImage, IN UINTN ConfigImageSize, OUT UINT32 *LastAttemptVersion, OUT UINT32 *LastAttemptStatus ) { EFI_STATUS Status; UPDATE_CONFIG_DATA *ConfigData; UPDATE_CONFIG_DATA *UpdateConfigData; CONFIG_HEADER ConfigHeader; UINTN Index; if (ConfigImage == NULL) { DEBUG((DEBUG_INFO, "PlatformUpdate (NoConfig):")); DEBUG((DEBUG_INFO, " BaseAddress - 0x%x,", 0)); DEBUG((DEBUG_INFO, " Length - 0x%x\n", SystemFirmwareImageSize)); // ASSUME the whole System Firmware include NVRAM region. Status = PerformFlashWrite ( PlatformFirmwareTypeNvRam, 0, FlashAddressTypeRelativeAddress, SystemFirmwareImage, SystemFirmwareImageSize ); if (!EFI_ERROR(Status)) { *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS; mNvRamUpdated = TRUE; } else { *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; } return Status; } DEBUG((DEBUG_INFO, "PlatformUpdate (With Config):\n")); ConfigData = NULL; ZeroMem (&ConfigHeader, sizeof(ConfigHeader)); Status = ParseUpdateDataFile ( ConfigImage, ConfigImageSize, &ConfigHeader, &ConfigData ); DEBUG((DEBUG_INFO, "ParseUpdateDataFile - %r\n", Status)); if (EFI_ERROR(Status)) { *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL; return EFI_INVALID_PARAMETER; } DEBUG((DEBUG_INFO, "ConfigHeader.NumOfUpdates - 0x%x\n", ConfigHeader.NumOfUpdates)); DEBUG((DEBUG_INFO, "PcdEdkiiSystemFirmwareFileGuid - %g\n", PcdGetPtr(PcdEdkiiSystemFirmwareFileGuid))); Index = 0; UpdateConfigData = ConfigData; while (Index < ConfigHeader.NumOfUpdates) { if (CompareGuid(&UpdateConfigData->FileGuid, PcdGetPtr(PcdEdkiiSystemFirmwareFileGuid))) { DEBUG((DEBUG_INFO, "FileGuid - %g (processing)\n", &UpdateConfigData->FileGuid)); Status = PerformUpdate ( SystemFirmwareImage, SystemFirmwareImageSize, UpdateConfigData, LastAttemptVersion, LastAttemptStatus ); // // Shall updates be serialized so that if an update is not successfully completed, // the remaining updates won't be performed. // if (EFI_ERROR (Status)) { break; } } else { DEBUG((DEBUG_INFO, "FileGuid - %g (ignored)\n", &UpdateConfigData->FileGuid)); } Index++; UpdateConfigData++; } return Status; }