summaryrefslogtreecommitdiff
path: root/Core/EM/Recovery/ReFlash/Esrt.c
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/Recovery/ReFlash/Esrt.c')
-rw-r--r--Core/EM/Recovery/ReFlash/Esrt.c415
1 files changed, 415 insertions, 0 deletions
diff --git a/Core/EM/Recovery/ReFlash/Esrt.c b/Core/EM/Recovery/ReFlash/Esrt.c
new file mode 100644
index 0000000..1823328
--- /dev/null
+++ b/Core/EM/Recovery/ReFlash/Esrt.c
@@ -0,0 +1,415 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/Recovery/ReFlash/Esrt.c 1 3/21/13 7:25a Thomaschen $
+//
+// $Revision: 1 $
+//
+// $Date: 3/21/13 7:25a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/Recovery/ReFlash/Esrt.c $
+//
+// 1 3/21/13 7:25a Thomaschen
+//
+// 6 2/27/13 3:54p Artems
+// [TAG] EIP106722
+// [Category] Improvement
+// [Description] Used different GUID to differentiate between AMI and
+// Win8 firmware update
+// [Files] Esrt.c
+//
+// 5 2/07/13 5:26p Artems
+// [TAG] EIP106722
+// [Category] Improvement
+// [Description] Add creation of firmware update version from FID table
+// [Files] Esrt.c
+//
+// 4 2/05/13 1:41p Artems
+// [TAG] EIP111562
+// [Category] Improvement
+// [Description] Add Enable/Disable support for Windows8-style firmware
+// update
+// [Files] Esrt.c Reflash.c Reflash.sdl
+//
+// 3 1/02/13 12:18p Artems
+// [TAG] EIP N/A
+// [Category] Improvement
+// [Description] Flash update progress report changes:
+// - report progress in non-interactive flash update
+// - do not report progress in Win8-style flash update
+// [Files] ReflashWorker.c Reflash.h Esrt.c
+//
+// 2 8/02/12 11:59a Artems
+// [TAG] EIP93520
+// [Category] New Feature
+// [Description] Support of Microsoft ESRT spec
+// [Files] Recovery.h Recovery.sdl Recovery.c Reflash.c ReflashWorker.c
+// Esrt.c
+//
+// 1 7/20/12 10:20a Artems
+// [TAG] EIP93520
+// [Category] New Feature
+// [Description] Support for Microsoft ESRT spec
+// [Files] Reflash.c Esrt.c Reflash.h Capsule.h ReflashWorker.c
+// Protocol.cif AmiReflashProtocol.h Setup.h
+//
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: Esrt.c
+//
+// Description:
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+
+#include <Token.h>
+
+#if SUPPORT_WIN8_STYLE_FW_UPDATE
+
+#include <AmiHobs.h>
+#include <AmiDxeLib.h>
+#include <Capsule.h>
+#include <Setup.h>
+#include <PPI/FwVersion.h>
+#include <Protocol/AmiReflashProtocol.h>
+#include <Protocol/FirmwareVolume2.h>
+#include "Reflash.h"
+
+#define MAX_ESRT_ENTRIES 1
+
+#define FW_TYPE_UNKNOWN 0
+#define FW_TYPE_SYSTEM_FIRMWARE 1
+#define FW_TYPE_DEVICE_FIRMWARE 2
+#define FW_TYPE_FIRMWARE_DRIVER 3
+
+#define FW_UPDATE_STATUS_SUCCESS 0
+#define FW_UPDATE_STATUS_UNKNOWN_ERROR 1
+#define FW_UPDATE_STATUS_OUT_OF_RESOURCES 2
+#define FW_UPDATE_STATUS_INCORRECT_VERSION 3
+#define FW_UPDATE_STATUS_INVALID_FORMAT 4
+#define FW_UPDATE_STATUS_AUTHENTICATION_ERROR 5
+
+#define EFI_SYSTEM_RESOURCE_TABLE_GUID \
+ { 0xb122a263, 0x3661, 0x4f68, 0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80 }
+
+#define FID_FFS_FILE_NAME_GUID \
+ { 0x3fd1d3a2, 0x99f7, 0x420b, 0xbc, 0x69, 0x8b, 0xb1, 0xd4, 0x92, 0xa3, 0x32 }
+
+#define FID_FFS_FILE_SECTION_GUID \
+ { 0x2EBE0275, 0x6458, 0x4AF9, 0x91, 0xED, 0xD3, 0xF4, 0xED, 0xB1, 0x00, 0xAA }
+
+#pragma pack(push, 1)
+typedef struct _FIRMWARE_RESOURCE_ENTRY {
+ EFI_GUID FwClass;
+ UINT32 FwType;
+ UINT32 FwVersion;
+ UINT32 LowestSupportedFwVersion;
+ UINT32 CapsuleFlags;
+ UINT32 LastAttemptVersion;
+ UINT32 LastAttemptStatus;
+} FIRMWARE_RESOURCE_ENTRY;
+
+typedef struct _EFI_ESRT_TABLE {
+ UINT32 FwResourceCount;
+ UINT32 FwMaxResources;
+ UINT64 FwResourceVersion;
+ FIRMWARE_RESOURCE_ENTRY Entries[MAX_ESRT_ENTRIES];
+} EFI_ESRT_TABLE;
+
+#pragma pack(pop)
+
+static EFI_GUID SystemFirmwareUpdateClass = W8_FW_UPDATE_IMAGE_CAPSULE_GUID;
+static EFI_GUID SystemResourceTableGuid = EFI_SYSTEM_RESOURCE_TABLE_GUID;
+static EFI_GUID guidHob = HOB_LIST_GUID;
+static W8_IMAGE_CAPSULE *Image;
+
+static const UINT32 FidSignature = 0x44494624; //$FID
+
+EFI_STATUS GetDisplayImage(
+ IN EFI_REFLASH_PROTOCOL *This,
+ OUT UINTN *CoordinateX,
+ OUT UINTN *CoordinateY,
+ OUT VOID **ImageAddress
+);
+
+EFI_STATUS FwUpdate(
+ IN EFI_REFLASH_PROTOCOL *This
+);
+
+EFI_REFLASH_PROTOCOL AmiReflashProtocol = {
+ FwUpdate,
+ GetDisplayImage
+};
+
+EFI_STATUS GetFidFromFv(
+ OUT VOID *Fid
+)
+{
+ static EFI_GUID FidFileName = FID_FFS_FILE_NAME_GUID;
+ EFI_STATUS Status;
+ EFI_HANDLE *FvHandle;
+ UINTN FvCount;
+ UINTN i;
+ UINTN BufferSize;
+ VOID *Buffer;
+
+ Status = pBS->LocateHandleBuffer(ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &FvCount, &FvHandle);
+ if (EFI_ERROR(Status))
+ return Status;
+
+ for(i = 0; i < FvCount; i++)
+ {
+ EFI_FIRMWARE_VOLUME_PROTOCOL *Fv;
+ UINT32 AuthStatus;
+ Status = pBS->HandleProtocol(FvHandle[i], &gEfiFirmwareVolume2ProtocolGuid, &Fv);
+ if (EFI_ERROR(Status))
+ continue;
+ Buffer = 0;
+ BufferSize = 0;
+ Status = Fv->ReadSection(Fv, &FidFileName, EFI_SECTION_FREEFORM_SUBTYPE_GUID, 0, &Buffer, &BufferSize, &AuthStatus);
+ TRACE((-1, "extracted section with guid %g\n", (EFI_GUID *)Buffer));
+ if (!EFI_ERROR(Status)) {
+ (UINT8 *)Buffer += sizeof(EFI_GUID);
+ MemCpy(Fid, Buffer, sizeof(FW_VERSION));
+ (UINT8 *)Buffer -= sizeof(EFI_GUID);
+ pBS->FreePool(Buffer);
+ return EFI_SUCCESS;
+ }
+ }
+ pBS->FreePool(FvHandle);
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS GetFidFromBuffer(
+ IN VOID *Buffer,
+ OUT VOID *Fid
+)
+{
+ static EFI_GUID FidSectionGuid = FID_FFS_FILE_SECTION_GUID;
+ UINT32 Signature;
+ UINT32 *SearchPointer;
+ UINT32 *FidPointer;
+
+ SearchPointer = (UINT32 *)((UINT8 *)Buffer - sizeof(EFI_GUID) + FLASH_SIZE);
+ Signature = FidSectionGuid.Data1;
+
+ do {
+ if(*SearchPointer == Signature) {
+ if(!guidcmp(&FidSectionGuid, (EFI_GUID *)SearchPointer)) {
+ FidPointer = (UINT32 *)((EFI_GUID *)SearchPointer + 1);
+ if(*FidPointer == FidSignature) {
+ MemCpy(Fid, FidPointer, sizeof(FW_VERSION));
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ } while(SearchPointer-- >= (UINT32 *)Buffer);
+
+ return EFI_NOT_FOUND;
+}
+
+UINT32 GetVersionFromFid(
+ VOID *Image OPTIONAL
+)
+{
+ FW_VERSION Fid;
+ UINT32 Version;
+ EFI_STATUS Status;
+
+ if(Image == NULL)
+ Status = GetFidFromFv(&Fid);
+ else
+ Status = GetFidFromBuffer(Image, &Fid);
+
+ if(EFI_ERROR(Status))
+ return 0;
+
+ Version = Atoi(Fid.ProjectMajorVersion);
+ Version <<= 16;
+ Version += Atoi(Fid.ProjectMinorVersion);
+ return Version;
+}
+
+EFI_STATUS InstallEsrtTable(
+ VOID
+)
+{
+ static EFI_GUID RecoveryHobGuid = AMI_RECOVERY_IMAGE_HOB_GUID;
+ EFI_HOB_HANDOFF_INFO_TABLE *pHit;
+ EFI_STATUS Status;
+ UINTN Size = sizeof(UINT32);
+ UINT32 Version;
+ EFI_ESRT_TABLE *EsrtTable;
+
+ Status = pBS->AllocatePool(EfiRuntimeServicesData, sizeof(EFI_ESRT_TABLE), &EsrtTable);
+ if(EFI_ERROR(Status))
+ return Status;
+
+ EsrtTable->FwResourceCount = 1;
+ EsrtTable->FwMaxResources = MAX_ESRT_ENTRIES;
+ EsrtTable->FwResourceVersion = 1;
+
+ EsrtTable->Entries[0].FwClass = SystemFirmwareUpdateClass;
+ EsrtTable->Entries[0].FwType = FW_TYPE_SYSTEM_FIRMWARE;
+ EsrtTable->Entries[0].FwVersion = GetVersionFromFid(NULL);
+ EsrtTable->Entries[0].LowestSupportedFwVersion = EsrtTable->Entries[0].FwVersion; //no rollback allowed
+ EsrtTable->Entries[0].CapsuleFlags = 0;
+
+ Status = pRS->GetVariable(FW_VERSION_VARIABLE, &gAmiGlobalVariableGuid, NULL, &Size, &Version);
+ if(!EFI_ERROR(Status)) {
+ EsrtTable->Entries[0].LastAttemptVersion = Version;
+ EsrtTable->Entries[0].LastAttemptStatus = FW_UPDATE_STATUS_UNKNOWN_ERROR;
+ } else {
+ pHit = GetEfiConfigurationTable(pST, &guidHob);
+ if(pHit != NULL && !EFI_ERROR(FindNextHobByGuid(&RecoveryHobGuid, &pHit))) {
+ EsrtTable->Entries[0].LastAttemptVersion = GetVersionFromFid((VOID *)(UINTN)((RECOVERY_IMAGE_HOB*)pHit)->Address);
+ switch(((RECOVERY_IMAGE_HOB*)pHit)->FailedStage) {
+ case 0: //no authentication/verification error
+ EsrtTable->Entries[0].LastAttemptStatus = FW_UPDATE_STATUS_UNKNOWN_ERROR;
+ break;
+ case 1:
+ EsrtTable->Entries[0].LastAttemptStatus = FW_UPDATE_STATUS_INVALID_FORMAT;
+ break;
+ case 2:
+ EsrtTable->Entries[0].LastAttemptStatus = FW_UPDATE_STATUS_AUTHENTICATION_ERROR;
+ break;
+ case 3:
+ EsrtTable->Entries[0].LastAttemptStatus = FW_UPDATE_STATUS_AUTHENTICATION_ERROR;
+ break;
+ case 4:
+ EsrtTable->Entries[0].LastAttemptStatus = FW_UPDATE_STATUS_INCORRECT_VERSION;
+ break;
+ default:
+ EsrtTable->Entries[0].LastAttemptStatus = FW_UPDATE_STATUS_UNKNOWN_ERROR;
+ break;
+ }
+ } else { //recovery hob not found - regular boot
+ EsrtTable->Entries[0].LastAttemptVersion = EsrtTable->Entries[0].FwVersion;
+ EsrtTable->Entries[0].LastAttemptStatus = FW_UPDATE_STATUS_SUCCESS;
+ }
+ }
+
+ Status = pBS->InstallConfigurationTable(&SystemResourceTableGuid, EsrtTable);
+ return Status;
+}
+
+EFI_STATUS IsWin8Update(
+ BOOLEAN RecoveryFailed
+)
+{
+ AMI_CAPSULE_HOB *Hob;
+ static EFI_GUID AmiCapsuleHobGuid = AMI_CAPSULE_HOB_GUID;
+ static EFI_GUID ImageCapsuleGuid = W8_SCREEN_IMAGE_CAPSULE_GUID;
+ static EFI_GUID guidBootFlow = BOOT_FLOW_VARIABLE_GUID;
+ EFI_HANDLE Handle = NULL;
+ EFI_STATUS Status;
+ UINT32 BootFlow = BOOT_FLOW_CONDITION_OS_UPD_CAP;
+
+ Hob = GetEfiConfigurationTable(pST, &guidHob);
+ if(Hob == NULL)
+ return EFI_NOT_FOUND;
+
+ do {
+ Status = FindNextHobByGuid(&AmiCapsuleHobGuid, &Hob);
+ if(!EFI_ERROR(Status) && !guidcmp(&(Hob->CapsuleGuid), &ImageCapsuleGuid))
+ break;
+ } while(!EFI_ERROR(Status));
+
+ if(EFI_ERROR(Status)) //no image hob - we're not on OS FW update path
+ return Status;
+
+ if(RecoveryFailed) { //we're on OS FW update path, but recovery can't be performed
+ InstallEsrtTable();
+ return EFI_UNLOAD_IMAGE;
+ }
+
+//save image capsule pointer
+ Image = (W8_IMAGE_CAPSULE *)(VOID *)(UINTN)(Hob->CapsuleData);
+//install reflash protocol
+ Status = pBS->InstallMultipleProtocolInterfaces(
+ &Handle,
+ &gAmiReflashProtocolGuid,
+ &AmiReflashProtocol,
+ NULL);
+ if(EFI_ERROR(Status))
+ return Status;
+
+//set boot flow
+ pRS->SetVariable(L"BootFlow", &guidBootFlow, EFI_VARIABLE_BOOTSERVICE_ACCESS, sizeof(BootFlow), &BootFlow);
+ return Status;
+}
+
+EFI_STATUS GetDisplayImage(
+ IN EFI_REFLASH_PROTOCOL *This,
+ OUT UINTN *CoordinateX,
+ OUT UINTN *CoordinateY,
+ OUT VOID **ImageAddress
+)
+{
+ if(CoordinateX == NULL ||
+ CoordinateY == NULL ||
+ ImageAddress == NULL)
+ return EFI_INVALID_PARAMETER;
+
+ *CoordinateX = Image->ImageOffsetX;
+ *CoordinateY = Image->ImageOffsetY;
+ *ImageAddress = Image->Image;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS FwUpdate(
+ IN EFI_REFLASH_PROTOCOL *This
+)
+{
+ EFI_STATUS Status;
+ UINT32 Version;
+
+/* set version we're upgrading to */
+ Version = GetVersionFromFid(RecoveryBuffer);
+ Status = pRS->SetVariable(FW_VERSION_VARIABLE, &gAmiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof(UINT32), &Version);
+
+ Status = Prologue(FALSE, TRUE);
+ if(EFI_ERROR(Status))
+ pRS->ResetSystem(EfiResetCold, Status, 0, NULL);
+
+ Status = FlashWalker(FALSE);
+ if(EFI_ERROR(Status))
+ pRS->ResetSystem(EfiResetCold, Status, 0, NULL);
+
+ Status = Epilogue();
+ return Status;
+}
+
+#endif // #if SUPPORT_WIN8_STYLE_FW_UPDATE
+
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//**********************************************************************