summaryrefslogtreecommitdiff
path: root/Core/EM/Recovery/ReFlash/ReFlash.c
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/Recovery/ReFlash/ReFlash.c')
-rw-r--r--Core/EM/Recovery/ReFlash/ReFlash.c601
1 files changed, 601 insertions, 0 deletions
diff --git a/Core/EM/Recovery/ReFlash/ReFlash.c b/Core/EM/Recovery/ReFlash/ReFlash.c
new file mode 100644
index 0000000..773d7f9
--- /dev/null
+++ b/Core/EM/Recovery/ReFlash/ReFlash.c
@@ -0,0 +1,601 @@
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (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/ReFlash.c 3 10/01/13 2:03a Thomaschen $
+//
+// $Revision: 3 $
+//
+// $Date: 10/01/13 2:03a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/Recovery/ReFlash/ReFlash.c $
+//
+// 3 10/01/13 2:03a Thomaschen
+// Update for EIP137328.
+//
+// 2 4/16/13 5:48a Thomaschen
+// Fixed for EIP106722.
+//
+//
+// 40 2/11/13 3:41p Artems
+// [TAG] EIP112180
+// [Category] Bug Fix
+// [Severity] Critical
+// [Symptom] In non-interactive mode system updated flash even when
+// there is no valid image
+// [RootCause] In non-interactive mode system didn't check flash image
+// validity
+// [Solution] Added check of flash image validity. Inform user if image
+// is invalid or not found
+// [Files] Reflash.c ReflashWorker.c Reflash.uni Reflash.vfr
+//
+// 39 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
+//
+// 38 7/20/12 10:17a Artems
+// [TAG] EIP93520
+// [Category] New Feature
+// [Description] Support of Microsoft ESRT spec
+// [Files] Reflash.c Esrt.c Reflash.h Capsule.h ReflashWorker.c
+// Protocol.cif AmiReflashProtocol.h Setup.h
+//
+// 37 5/22/12 4:54p Artems
+// [TAG] EIP88314
+// [Category] Improvement
+// [Description] Recovery takes a long time for large flash size
+// Rewrite reflash code to not give control back to TSE until finished
+// reporting progress via DisplayProgress API of AMI Post manager
+// [Files] Reflash.c Reflash.h ReflashWorker.c Reflash.mak Reflash.vfr
+// Reflash.uni
+//
+// 36 4/09/12 6:03p Artems
+// Undo previous change
+//
+// 35 2/08/12 4:27a Nerofan
+// Update it for capsule function if memory size is over 2G.
+//
+// 34 12/05/11 1:49p Artems
+// EIP 74623: Add capabilities similar to ones in SMIFlash module
+//
+// 33 11/14/11 4:07p Artems
+// Fixed bug with hob size comparison
+// Set default attributes for Reflash Setup variable
+//
+// 32 11/14/11 3:18p Artems
+// Defined Extended errors for security recovery capsule check
+//
+// 31 11/12/11 6:48p Artems
+// Added fault tolerant recovery support
+//
+// 30 11/02/11 4:54p Artems
+// EIP 74446: Fixed bug - reflash is enabled when recovery image is not
+// found
+//
+// 29 5/13/11 4:51p Artems
+// Added secure flash recovery/update support. Extended error reporting
+// Added handling of unsupported FormBrowser actions
+//
+// 28 5/05/11 2:00p Artems
+// Bugfix: callback supports only "CHANGING" browser action
+//
+// 27 5/04/11 5:54p Artems
+// Bugfix: function FlashProgress output parameter ActionRequest was
+// undefined
+//
+// 26 11/17/10 2:52p Felixp
+// Enhencement (EIP 36355):
+// The Reflash component is updated to be extensible with external
+// eModules.
+// The eModules can contribute content for the Recovery setup page,
+// and provide callback function that will be periodically called
+// once BIOS update is completed.The external eModules can be used
+// to implement update of non-standard firmware components.
+// For example, update of the non-shared EC firmware.
+//
+// 25 10/07/10 11:02a Felixp
+// FlashDeviceWriteEnable/FlashDeviceWriteDisable calls added.
+//
+// 24 10/01/10 2:14p Felixp
+// Previous changes related to descrete EC firmware update are rolled back
+// for the Core labeling.
+//
+// 22 12/24/09 12:42p Oleksiyy
+// EIP 30173: Support for the EC Firmware Area Update control added. Main
+// token to enable this support is EC_FIRMWARE_UPDATE_INTERFACE_SUPPORT
+// should be located in specific EC-related .sdl file.
+//
+// 21 11/25/09 11:38a Felixp
+//
+// 20 11/25/09 11:27a Felixp
+// Action parameter of the Callback function is updated based on UEFI
+// errata
+//
+// 19 10/09/09 6:30p Felixp
+// ReFlash component is updated to support Framework and UEFI 2.1 HII
+//
+// 18 8/25/09 5:29p Felixp
+// Recovery module is updated to pass recovery image location via special
+// GUIDed HOB.
+// Old implementation that was relying on Firmware Volume (FV) handle,
+// required porting for a projects with non standard FV management policy.
+//
+// 17 7/09/09 5:59p Oleksiyy
+// Files clean-up, some headers added
+//
+// 16 5/21/09 4:44p Felixp
+// ReFlash driver is updated to use FlashProtocol instead of Flash library
+// functions.
+//
+// 15 1/02/09 1:14p Felixp
+// Bug fix: initialize size before call to GetVariable
+//
+// 14 10/10/08 5:30p Felixp
+//
+// 13 3/12/08 2:55p Felixp
+// Error code reporting when flash update failed added
+//
+// 12 10/19/07 6:23p Felixp
+// Recovery Flash Update module extended to support Boot Block update.
+// Boot block update can be enabled or disabled using SDL token.
+// In addition to that there is an SDL token that enables/disables
+// checkbox on the
+// recovery setup page that user can use to enable or disable boot block
+// update.
+//
+// 11 4/13/07 6:07p Ambikas
+// Coding standard changes: updated the year in the AMI copyright
+// header/footer.
+//
+// 10 1/26/07 10:31a Anandakrishnanl
+// Added Flash Device Write Enabling and Disabling code to make the device
+// Write wnable before Flash Block writes.
+//
+// 9 12/29/06 2:58p Felixp
+// Updated to use new Flash Interface
+//
+// 8 12/22/06 9:38a Felixp
+// Support for optional NVRAM reset based on user input added
+//
+// 7 12/20/06 1:36p Felixp
+//
+// 6 10/30/06 5:44p Felixp
+// Updated to be complient with HII Spec. 0.92 (used to be 0.91)
+//
+// 5 10/27/06 11:48a Felixp
+// Flash related external variables from Tokens.c are used (instead of
+// global variables declared in Reflash.c)
+//
+// 4 8/24/06 9:19a Felixp
+// x64 Support
+//
+// 3 4/12/06 5:49p Felixp
+//
+// 2 3/13/06 1:47a Felixp
+//
+// 1 12/01/05 9:35a Felixp
+//
+// 1 11/08/05 4:04a Felixp
+//
+//**********************************************************************
+//<AMI_FHDR_START>
+//
+// Name: ReFlash.c
+//
+// Description:
+//
+//<AMI_FHDR_END>
+//**********************************************************************
+#include <HOB.h>
+#include <Flash.h>
+#include <AmiCspLib.h>
+#include <AmiHobs.h>
+#include "ReFlash.h"
+
+
+static EFI_GUID guidRecovery = RECOVERY_FORM_SET_GUID;
+EFI_HANDLE ThisImageHandle;
+FLASH_PROTOCOL *Flash;
+EFI_HII_HANDLE ReflashHiiHandle = NULL;
+UINT8 *RecoveryBuffer = NULL;
+EFI_STATUS RecoveryStatus = EFI_SUCCESS;
+
+
+EFI_HII_CONFIG_ACCESS_PROTOCOL CallBack = { NULL,NULL,FlashProgressEx };
+
+CALLBACK_INFO SetupCallBack[] =
+{
+ // Last field in every structure will be filled by the Setup
+ { &guidRecovery, &CallBack, RECOVERY_FORM_SET_CLASS, 0, 0},
+};
+
+
+//-------------------------------
+//Before flash and After flash eLinks
+
+typedef VOID (OEM_FLASH_UPDATE_CALLBACK) (VOID);
+extern OEM_FLASH_UPDATE_CALLBACK OEM_BEFORE_FLASH_UPDATE_CALLBACK_LIST EndOfList;
+extern OEM_FLASH_UPDATE_CALLBACK OEM_AFTER_FLASH_UPDATE_CALLBACK_LIST EndOfList;
+OEM_FLASH_UPDATE_CALLBACK* OemBeforeFlashCallbackList[] = { OEM_BEFORE_FLASH_UPDATE_CALLBACK_LIST NULL };
+OEM_FLASH_UPDATE_CALLBACK* OemAfterFlashCallbackList[] = { OEM_AFTER_FLASH_UPDATE_CALLBACK_LIST NULL };
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: OemBeforeFlashCallback
+//
+// Description: This function executes OEM porting hooks before starting flash update
+//
+// Input:
+// None
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID OemBeforeFlashCallback(
+ VOID
+)
+{
+ UINT32 i;
+ for(i = 0; OemBeforeFlashCallbackList[i] != NULL; i++)
+ OemBeforeFlashCallbackList[i]();
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+//
+// Procedure: OemAfterFlashCallback
+//
+// Description: This function executes OEM porting hooks after finishing flash update
+//
+// Input:
+// None
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID OemAfterFlashCallback(
+ VOID
+)
+{
+ UINT32 i;
+ for(i = 0; OemAfterFlashCallbackList[i] != NULL; i++)
+ OemAfterFlashCallbackList[i]();
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetHiiString
+//
+// Description: This function reads a string from HII
+//
+// Input: IN EFI_HII_HANDLE HiiHandle - Efi Hii Handle
+// IN STRING_REF Token - String Token
+// IN OUT UINTN *pDataSize - Length of the StringBuffer
+// OUT EFI_STRING *ppData - The buffer to receive the characters in the string.
+//
+// Output: EFI_STATUS - Depending on result
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS GetHiiString(
+ IN EFI_HII_HANDLE HiiHandle,
+ IN STRING_REF Token,
+ IN OUT UINTN *pDataSize,
+ OUT EFI_STRING *ppData
+)
+{
+ EFI_STATUS Status;
+
+ if (!*ppData) *pDataSize=0;
+
+ Status = HiiLibGetString(HiiHandle, Token, pDataSize, *ppData);
+ if (!EFI_ERROR(Status)) return Status;
+ //--- If size was too small free pool and try with right size, which was passed
+ if (Status==EFI_BUFFER_TOO_SMALL)
+ {
+ if (*ppData) pBS->FreePool(*ppData);
+
+ if (!(*ppData=Malloc(*pDataSize))) return EFI_OUT_OF_RESOURCES;
+
+ Status = HiiLibGetString(HiiHandle, Token, pDataSize, *ppData);
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ApplyUserSelection
+//
+// Description: This function updates flash parameteres based on user selection
+// or Setup values
+//
+// Input:
+// IN BOOLEAN Interactive - if TRUE get selection from user input, otherwise
+// use Setup values
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID ApplyUserSelection(
+ IN BOOLEAN Interactive
+)
+{
+ EFI_STATUS Status;
+ AUTOFLASH FlashUpdateControl;
+ UINTN Size = sizeof(FlashUpdateControl);
+ UINT32 i;
+
+ if(Interactive) {
+ /* get values from Setup Browser */
+ Status = HiiLibGetBrowserData(&Size, &FlashUpdateControl, &guidRecovery, L"Setup");
+ } else {
+ /* get values from NVRAM */
+ Status = pRS->GetVariable(L"Setup", &guidRecovery, NULL, &Size, &FlashUpdateControl);
+ }
+ if(EFI_ERROR(Status)) {
+ /* no user selection, use defaults */
+ FlashUpdateControl.UpdateMain = REFLASH_UPDATE_MAIN_BLOCK;
+ FlashUpdateControl.UpdateBb = REFLASH_UPDATE_BOOT_BLOCK;
+ FlashUpdateControl.UpdateNv = REFLASH_UPDATE_NVRAM;
+#if EC_FIRMWARE_UPDATE_INTERFACE_SUPPORT
+ FlashUpdateControl.UpdateEC = REFLASH_UPDATE_EC_FIRMWARE;
+#endif
+ }
+
+ for(i = 0; BlocksToUpdate[i].Type != FvTypeMax; i++) {
+ switch(BlocksToUpdate[i].Type) {
+ case FvTypeMain:
+ BlocksToUpdate[i].Update = FlashUpdateControl.UpdateMain;
+#if FtRecovery_SUPPORT
+ if(FlashUpdateControl.UpdateBb == 1)
+ BlocksToUpdate[i].Update = TRUE; //with fault tolerant recovery FV_MAIN is used for backup - force update
+#endif
+ break;
+ case FvTypeBootBlock:
+ BlocksToUpdate[i].Update = FlashUpdateControl.UpdateBb;
+#if FtRecovery_SUPPORT
+ if(IsTopSwapOn()) //if we're here BB update failed we use backup copy - force BB update again
+ BlocksToUpdate[i].Update = TRUE;
+#endif
+ break;
+ case FvTypeNvRam:
+ BlocksToUpdate[i].Update = FlashUpdateControl.UpdateNv;
+ break;
+#if EC_FIRMWARE_UPDATE_INTERFACE_SUPPORT
+ case FvTypeCustom:
+ BlocksToUpdate[i].Update = FlashUpdateControl.UpdateEC;
+ break;
+#endif
+ default:
+ break;
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+// IsRecovery prototypes
+//----------------------------------------------------------------------------
+// Bit Mask of checks to perform on Aptio FW Image
+// 1- Capsule integrity
+// 2- Verify Signature
+// 3- Verify FW Key
+// 4- Verify FW Version compatibility.
+// To prevent possible re-play attack:
+// update current FW with older version with lower security.
+// 5- Compare MonotonicCounters/date. Replay attack
+//----------------------------------------------------------------------------
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UpdateSetupStrings
+//
+// Description: This function updates status strings in setup window, based
+// on execution results
+//
+// Input:
+// IN EFI_HII_HANDLE Handle - handle of Reflash setup formset (page)
+// IN EFI_STATUS Error - execution error if any
+// IN UINT32 FailedStage - in case of authentication error failed stage description
+//
+// Output:
+// None
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID UpdateSetupStrings(
+ IN EFI_HII_HANDLE Handle,
+ IN EFI_STATUS Error,
+ IN UINT32 FailedStage
+)
+{
+ UINTN Size;
+ EFI_STRING Template = NULL;
+ EFI_STRING Template2 = NULL;
+ CHAR16 ReportString[100];
+
+ if(!EFI_ERROR(Error)) {
+ GetHiiString(Handle, STRING_TOKEN(STR_SUBTITLE1_SUCCESS), &Size, &Template);
+ if(FailedStage == 0)
+ GetHiiString(Handle, STRING_TOKEN(STR_SUBTITLE2_SUCCESS), &Size, &Template2);
+ else //if we're here we're on manual BIOS rollback to older version
+ GetHiiString(Handle, STRING_TOKEN(STR_SUBTITLE2_ROLLBACK_WARNING), &Size, &Template2);
+
+ if(Template != NULL) {
+ HiiLibSetString(Handle, STRING_TOKEN(STR_SUBTITLE1), Template);
+ pBS->FreePool(Template);
+ }
+
+ if(Template2 != NULL) {
+ HiiLibSetString(Handle, STRING_TOKEN(STR_SUBTITLE2), Template2);
+ pBS->FreePool(Template2);
+ }
+
+ return;
+ }
+
+//Get Error string template
+ GetHiiString(Handle, STRING_TOKEN(STR_SUBTITLE1_ERROR), &Size, &Template);
+ if(Template != NULL) {
+ HiiLibSetString(Handle, STRING_TOKEN(STR_SUBTITLE1), Template);
+ pBS->FreePool(Template);
+ Template = NULL;
+ }
+
+ GetHiiString(Handle, STRING_TOKEN(STR_SUBTITLE2_ERROR_TEMPLATE), &Size, &Template);
+ switch(FailedStage) {
+ case InvalidHeader:
+ GetHiiString(Handle, STRING_TOKEN(STR_ERR), &Size, &Template2);
+ break;
+ case InvalidSignature:
+ GetHiiString(Handle, STRING_TOKEN(STR_ERR1), &Size, &Template2);
+ break;
+ case IvalidPlatformKey:
+ GetHiiString(Handle, STRING_TOKEN(STR_ERR2), &Size, &Template2);
+ break;
+ case InvalidFwVersion:
+ GetHiiString(Handle, STRING_TOKEN(STR_ERR3), &Size, &Template2);
+ break;
+ default:
+ GetHiiString(Handle, STRING_TOKEN(STR_ERR4), &Size, &Template2);
+ break;
+ }
+
+ if((Template != NULL) && (Template2 != NULL)) {
+ Swprintf(ReportString, Template, Error, Template2);
+ HiiLibSetString(Handle, STRING_TOKEN(STR_SUBTITLE2), ReportString);
+ pBS->FreePool(Template);
+ pBS->FreePool(Template2);
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ReFlashEntry
+//
+// Description: This is the standard EFI driver entry point called for
+// Recovery flash module initlaization
+// Input: IN EFI_HANDLE ImageHandle - ImageHandle of the loaded driver
+// IN EFI_SYSTEM_TABLE SystemTable - Pointer to the System Table
+//
+// Output: EFI_SUCCESS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS EFIAPI ReFlashEntry (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
+{
+ static EFI_GUID guidHob = HOB_LIST_GUID;
+ static EFI_GUID guidBootFlow = BOOT_FLOW_VARIABLE_GUID;
+ static EFI_GUID RecoveryHobGuid = AMI_RECOVERY_IMAGE_HOB_GUID;
+ UINT32 BootFlow = BOOT_FLOW_CONDITION_RECOVERY;
+ EFI_HOB_HANDOFF_INFO_TABLE *pHit;
+ UINTN Size;
+ UINT32 Attributes;
+ UINT32 FailedStage;
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ AUTOFLASH AutoFlash = {
+ (UINT8)(EFI_SUCCESS),
+ REFLASH_UPDATE_NVRAM,
+ REFLASH_UPDATE_BOOT_BLOCK,
+ REFLASH_UPDATE_MAIN_BLOCK
+#if EC_FIRMWARE_UPDATE_INTERFACE_SUPPORT
+ ,REFLASH_UPDATE_EC_FIRMWARE
+#endif
+ };
+
+ ThisImageHandle = ImageHandle;
+ InitAmiLib(ImageHandle,SystemTable);
+
+ //Get Boot Mode
+ pHit = GetEfiConfigurationTable(pST, &guidHob);
+
+ //unload the module if we are not in recovery mode
+ // TODO:need to distinguish between recovery and Flash Update
+ if (!pHit || (pHit->BootMode != BOOT_IN_RECOVERY_MODE && pHit->BootMode != BOOT_ON_FLASH_UPDATE)) {
+#if SUPPORT_WIN8_STYLE_FW_UPDATE
+ InstallEsrtTable();
+#endif
+ return EFI_UNLOAD_IMAGE;
+ }
+
+ VERIFY_EFI_ERROR(pBS->LocateProtocol(&gFlashProtocolGuid, NULL, &Flash));
+//Get Recovery Image verification status
+ if(!EFI_ERROR(FindNextHobByGuid(&RecoveryHobGuid, &pHit))) {
+ if(((EFI_HOB_GENERIC_HEADER *)pHit)->HobLength < sizeof(RECOVERY_IMAGE_HOB)) {
+ //we got update from older Core here
+ FailedStage = 0;
+ RecoveryStatus = EFI_SUCCESS;
+ } else {
+ FailedStage = ((RECOVERY_IMAGE_HOB*)pHit)->FailedStage;
+ RecoveryStatus = ((RECOVERY_IMAGE_HOB*)pHit)->Status;
+
+ //Since RECOVERY_IMAGE_HOB Status field is byte long, we should set error bit by ourselves
+ if(RecoveryStatus != NULL)
+ RecoveryStatus |= EFI_ERROR_BIT;
+ }
+ RecoveryBuffer = (UINT8 *)(UINTN)((RECOVERY_IMAGE_HOB*)pHit)->Address;
+ } else { //Recovery Hob not found - should not happen, we always create this hob to report errors
+ FailedStage = 0;
+ RecoveryStatus = EFI_ABORTED;
+ }
+
+ AutoFlash.FailedRecovery = (UINT8)RecoveryStatus;
+
+//Update Reflash parameters
+ Size = sizeof(AUTOFLASH);
+ Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
+ pRS->SetVariable(L"Setup", &guidRecovery, Attributes, Size, &AutoFlash);
+
+#if SUPPORT_WIN8_STYLE_FW_UPDATE
+//Verify if we're on OS firmware update path
+ Status = IsWin8Update((EFI_ERROR(RecoveryStatus)) ? TRUE : FALSE);
+ if(Status == EFI_SUCCESS || Status == EFI_UNLOAD_IMAGE)
+ return Status;
+#endif
+
+//Load setup page and create error message if necessary
+ LoadResources(ImageHandle, sizeof(SetupCallBack) / sizeof(CALLBACK_INFO), SetupCallBack, NULL);
+ ReflashHiiHandle = SetupCallBack[0].HiiHandle;
+ pRS->SetVariable(L"BootFlow", &guidBootFlow, EFI_VARIABLE_BOOTSERVICE_ACCESS, sizeof(BootFlow), &BootFlow);
+
+ UpdateSetupStrings(ReflashHiiHandle, RecoveryStatus, FailedStage);
+
+ return EFI_SUCCESS;
+}
+//**********************************************************************
+//**********************************************************************
+//** **
+//** (C)Copyright 1985-2012, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//**********************************************************************
+//********************************************************************** \ No newline at end of file