699 lines
21 KiB
C
699 lines
21 KiB
C
/** @file
|
|
This file include all BDS platform recovery flash functions.
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2012 - 2021, Insyde Software Corp. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
*/
|
|
|
|
#include "RecoveryFlash.h"
|
|
#include <Library/VariableSupportLib.h>
|
|
#include "SecureFlash.h"
|
|
#include <Library/LockBoxLib.h>
|
|
#include <Library/H2OIhisiLib.h>
|
|
#include <H2OIhisi.h>
|
|
|
|
STATIC UINT8 *mAuthVarBackupDataBuffer = NULL;
|
|
STATIC EFI_RESET_SYSTEM mOriginalResetSystemPtr;
|
|
|
|
|
|
|
|
BOOLEAN
|
|
RecoveryCapsuleIsExecutable (
|
|
IN EFI_PEI_HOB_POINTERS *RecoveryHob
|
|
);
|
|
|
|
EFI_STATUS
|
|
ExecuteRecoveryCapsule (
|
|
IN EFI_PEI_HOB_POINTERS *RecoveryHob
|
|
);
|
|
|
|
VOID
|
|
EFIAPI
|
|
ResetSystemDoNothing (
|
|
IN EFI_RESET_TYPE ResetType,
|
|
IN EFI_STATUS ResetStatus,
|
|
IN UINTN DataSize,
|
|
IN VOID *ResetData OPTIONAL
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
HookResetSystem (
|
|
IN BOOLEAN ToHook
|
|
)
|
|
{
|
|
|
|
if (ToHook) {
|
|
mOriginalResetSystemPtr = gRT->ResetSystem;
|
|
gRT->ResetSystem = ResetSystemDoNothing;
|
|
} else {
|
|
gRT->ResetSystem = mOriginalResetSystemPtr;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Restore authenticated variables from the buffer mAuthVarBackupDataBuffer.
|
|
|
|
**/
|
|
VOID
|
|
RestoreAuthVariable (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_FIRMWARE_VOLUME_HEADER *OnboardNvStoreageFvHeader;
|
|
VARIABLE_HEADER *VariableHeader;
|
|
UINTN SkipHeaderSize;
|
|
UINT32 FlashSize;
|
|
UINT32 FlashAddress;
|
|
UINT8 GetCmdStatus;
|
|
VOID *CmdBuffer;
|
|
UINT32 CmdBufferSize;
|
|
UINTN Index;
|
|
UINTN Count;
|
|
|
|
|
|
|
|
if (mAuthVarBackupDataBuffer == NULL) {
|
|
return ;
|
|
}
|
|
|
|
OnboardNvStoreageFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN) FdmGetNAtAddr (&gH2OFlashMapRegionVarGuid , 1);
|
|
if (OnboardNvStoreageFvHeader == NULL) {
|
|
return;
|
|
}
|
|
|
|
SkipHeaderSize = (UINTN)OnboardNvStoreageFvHeader->HeaderLength + GetVariableStoreHeaderSize ();
|
|
|
|
//
|
|
// The current variable region should be empty after done Crisis Recovery Flash.
|
|
// If the variable region with any data, not to restore AuthVariable data to prevent variable region from breaking.
|
|
// But it shall not happen.
|
|
//
|
|
VariableHeader = NULL;
|
|
VariableHeader = (VARIABLE_HEADER *)((UINTN) FdmGetNAtAddr (&gH2OFlashMapRegionVarGuid , 1) + SkipHeaderSize);
|
|
if (IsValidVariableHeader (VariableHeader)) {
|
|
FreePool (mAuthVarBackupDataBuffer);
|
|
return ;
|
|
}
|
|
|
|
//
|
|
// Copy new BIOS firmware volume and variable store header information to mAuthVarBackupDataBuffer.
|
|
//
|
|
CopyMem (mAuthVarBackupDataBuffer, OnboardNvStoreageFvHeader, SkipHeaderSize);
|
|
FlashSize = (UINT32) FdmGetNAtSize (&gH2OFlashMapRegionVarGuid, 1);
|
|
FlashAddress = (UINT32)(UINTN)OnboardNvStoreageFvHeader;
|
|
H2OIhisiAuthLock ();
|
|
GetCmdStatus = H2OIhisiGetCmdBuffer (&CmdBuffer, &CmdBufferSize, NULL, NULL);
|
|
if (GetCmdStatus != 0) {
|
|
H2OIhisiFbtsWrite (FlashSize, FlashAddress, mAuthVarBackupDataBuffer);
|
|
} else {
|
|
Count = FlashSize / SIZE_4KB;
|
|
for (Index = 0; Index < Count; Index++) {
|
|
CopyMem ((VOID *) (UINTN) CmdBuffer, mAuthVarBackupDataBuffer + (Index * SIZE_4KB), SIZE_4KB);
|
|
H2OIhisiFbtsWrite (SIZE_4KB, (UINT32)(FlashAddress + (Index * SIZE_4KB)), (UINT8 *) (UINTN) CmdBuffer);
|
|
}
|
|
}
|
|
H2OIhisiAuthUnlock ();
|
|
}
|
|
|
|
/**
|
|
Backup authenticated variables to the buffer mAuthVarBackupDataBuffer.
|
|
|
|
**/
|
|
VOID
|
|
BackupAuthVariable (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_FIRMWARE_VOLUME_HEADER *OnboardNvStoreageFvHeader;
|
|
VARIABLE_HEADER *VariableHeader;
|
|
VARIABLE_HEADER *NextVariable;
|
|
UINTN VariableSize;
|
|
UINTN LastVariableOffset;
|
|
UINTN SkipHeaderSize;
|
|
|
|
|
|
OnboardNvStoreageFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN) FdmGetNAtAddr (&gH2OFlashMapRegionVarGuid , 1);
|
|
if (OnboardNvStoreageFvHeader == NULL) {
|
|
return;
|
|
}
|
|
|
|
SkipHeaderSize = (UINTN)OnboardNvStoreageFvHeader->HeaderLength + GetVariableStoreHeaderSize ();
|
|
|
|
mAuthVarBackupDataBuffer = AllocatePool ((UINTN)FdmGetNAtSize (&gH2OFlashMapRegionVarGuid, 1));
|
|
if (mAuthVarBackupDataBuffer == NULL) {
|
|
return;
|
|
}
|
|
gBS->SetMem (mAuthVarBackupDataBuffer, (UINTN) FdmGetNAtSize (&gH2OFlashMapRegionVarGuid, 1), 0xFF);
|
|
|
|
LastVariableOffset = 0;
|
|
VariableSize = 0;
|
|
NextVariable = NULL;
|
|
VariableHeader = (VARIABLE_HEADER *)((UINTN) FdmGetNAtAddr (&gH2OFlashMapRegionVarGuid , 1) + SkipHeaderSize);
|
|
while (IsValidVariableHeader (VariableHeader)) {
|
|
NextVariable = GetNextVariablePtr (VariableHeader);
|
|
if (VariableHeader->State == VAR_ADDED || VariableHeader->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION)) {
|
|
if (((VariableHeader->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) ||
|
|
((VariableHeader->Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)){
|
|
VariableSize = (UINTN)NextVariable - (UINTN)VariableHeader;
|
|
if (LastVariableOffset + VariableSize < (UINTN) FdmGetNAtSize (&gH2OFlashMapRegionVarGuid, 1)) {
|
|
CopyMem (
|
|
&mAuthVarBackupDataBuffer[LastVariableOffset] + SkipHeaderSize,
|
|
VariableHeader,
|
|
VariableSize
|
|
);
|
|
}
|
|
LastVariableOffset += VariableSize;
|
|
}
|
|
}
|
|
VariableHeader = NextVariable;
|
|
}
|
|
|
|
}
|
|
|
|
VOID
|
|
CreateSetupModeVariable (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT8 SetupMode;
|
|
UINTN Size;
|
|
|
|
|
|
Size = sizeof (UINT8);
|
|
Status = gRT->GetVariable (
|
|
EFI_SETUP_MODE_NAME,
|
|
&gEfiGlobalVariableGuid,
|
|
NULL,
|
|
&Size,
|
|
&SetupMode
|
|
);
|
|
if (Status == EFI_NOT_FOUND) {
|
|
SetupMode = 0;
|
|
Status = gRT->SetVariable (
|
|
EFI_SETUP_MODE_NAME,
|
|
&gEfiGlobalVariableGuid,
|
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
|
|
sizeof (UINT8),
|
|
&SetupMode
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Prints a formatted unicode string to the default console, at
|
|
the supplied cursor position
|
|
|
|
@param Column The column of cursor position to print the string at
|
|
@param Row The row of cursor position to print the string at
|
|
@param Fmt Format string
|
|
|
|
@return Length of string printed to the console
|
|
|
|
**/
|
|
UINTN
|
|
PrintAt (
|
|
IN UINTN Column,
|
|
IN UINTN Row,
|
|
IN CHAR16 *Fmt,
|
|
...
|
|
)
|
|
{
|
|
CHAR16 *Buffer;
|
|
UINTN StrLen;
|
|
VA_LIST Marker;
|
|
|
|
|
|
Buffer = AllocateZeroPool (0x10000);
|
|
ASSERT (Buffer);
|
|
if (Column != (UINTN) - 1) {
|
|
gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row);
|
|
}
|
|
|
|
VA_START (Marker, Fmt);
|
|
StrLen = UnicodeVSPrint (Buffer, 0x10000, Fmt, Marker);
|
|
VA_END (Marker);
|
|
|
|
if (gST->ConOut != NULL) {
|
|
//
|
|
// To be extra safe make sure ConOut has been initialized
|
|
//
|
|
gST->ConOut->OutputString (gST->ConOut, Buffer);
|
|
}
|
|
FreePool (Buffer);
|
|
|
|
return StrLen;
|
|
}
|
|
|
|
/**
|
|
Display the Recovery flash user interface to user to select
|
|
|
|
@param FlashMode Input flash mode (DEFAULT_FLASH_DEVICE_TYPE, SPI_FLASH_DEVICE_TYPE, OTHER_FLASH_DEVICE_TYPE)
|
|
|
|
@retval EFI_SUCCESS Success
|
|
@retval Other Error
|
|
|
|
**/
|
|
EFI_STATUS
|
|
RecoveryPopUp (
|
|
IN UINTN FlashMode
|
|
)
|
|
{
|
|
CHAR16 *TitleString;
|
|
CHAR16 *FlashInfoStringArray[3];
|
|
UINT32 Index;
|
|
EFI_INPUT_KEY Key;
|
|
H2O_DIALOG_PROTOCOL *H2ODialog;
|
|
EFI_STATUS Status;
|
|
H2O_BDS_SERVICES_PROTOCOL *H2OBdsServices;
|
|
BOOLEAN EnableHotKey;
|
|
|
|
Status = gBS->LocateProtocol (&gH2OBdsServicesProtocolGuid, NULL, (VOID **)&H2OBdsServices);
|
|
if (!EFI_ERROR (Status)) {
|
|
EnableHotKey = FALSE;
|
|
H2OBdsServices->EnableHotKeys (H2OBdsServices, &EnableHotKey);
|
|
}
|
|
|
|
if (IsFirmwareFailureRecovery ()) {
|
|
//
|
|
// If it is recovery from firmware failure, update firmware directly without user interface
|
|
//
|
|
RecoveryFlash (FlashMode);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
Status = gBS->LocateProtocol (
|
|
&gH2ODialogProtocolGuid,
|
|
NULL,
|
|
(VOID **) &H2ODialog
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
//
|
|
// Intialize local variable and string for use
|
|
//
|
|
Index = 0;
|
|
TitleString = BdsLibGetStringById (STRING_TOKEN (STR_RECOVERY_FLASH_TITLE));
|
|
FlashInfoStringArray[0] = BdsLibGetStringById (STRING_TOKEN (STR_RECOVERY_FLASH_YES));
|
|
FlashInfoStringArray[1] = BdsLibGetStringById (STRING_TOKEN (STR_RECOVERY_FLASH_RESETSYSTEM));
|
|
FlashInfoStringArray[2] = 0x00;
|
|
|
|
gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_WHITE, EFI_BLACK));
|
|
while (TRUE) {
|
|
//
|
|
// Print recovery flash message
|
|
//
|
|
H2ODialog->OneOfOptionDialog (
|
|
2,
|
|
FALSE,
|
|
NULL,
|
|
&Key,
|
|
60,
|
|
TitleString,
|
|
&Index,
|
|
(CHAR16 **) (FlashInfoStringArray),
|
|
0
|
|
);
|
|
|
|
if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
|
|
//
|
|
// Adjust the item number, there are 3 choices.
|
|
//
|
|
if (Index == 0) {
|
|
RecoveryFlash (FlashMode);
|
|
} else {
|
|
ResetCommand ();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
gST->ConOut->ClearScreen (gST->ConOut);
|
|
//
|
|
// Free allocated strings
|
|
//
|
|
FreePool (TitleString);
|
|
FreePool (FlashInfoStringArray[0]);
|
|
FreePool (FlashInfoStringArray[1]);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
Send reset request to reset system
|
|
|
|
@retval EFI_SUCCESS
|
|
|
|
**/
|
|
EFI_STATUS
|
|
ResetCommand (
|
|
VOID
|
|
)
|
|
{
|
|
UINT8 RecoveryFlag;
|
|
|
|
RecoveryFlag = RESET_IN_RECOVERY;
|
|
SaveLockBox (&gSecureFlashInfoGuid, &RecoveryFlag, sizeof (RecoveryFlag));
|
|
H2OIhisiAuthLock ();
|
|
H2OIhisiAuth (IHISI_AUTH_POST_ONLY, NULL);
|
|
H2OIhisiFbtsFlashComplete (IHISI_REBOOT, NormalFlash);
|
|
H2OIhisiAuthUnlock ();
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
Update the precentage of recovery flash progress in dialog
|
|
|
|
@param PercentageValue The finished percentage of flash process
|
|
|
|
**/
|
|
VOID
|
|
Drawpercentage (
|
|
IN UINTN PercentageValue
|
|
)
|
|
{
|
|
UINTN Columns;
|
|
UINTN ColumnPosition;
|
|
UINTN Rows;
|
|
UINTN RowPosition;
|
|
|
|
|
|
gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Columns, &Rows);
|
|
RowPosition = Columns / 2;
|
|
ColumnPosition = Rows / 2;
|
|
PrintAt (RowPosition, ColumnPosition, L"%d%%", PercentageValue);
|
|
}
|
|
|
|
/**
|
|
Drawing dialog for showing recovery flash progress
|
|
|
|
**/
|
|
VOID
|
|
DrawDialogBlock (
|
|
VOID
|
|
)
|
|
{
|
|
CHAR16 CleanLine[80];
|
|
CHAR16 *StatusString;
|
|
CHAR16 SelectIndexLin[80];
|
|
UINTN Color;
|
|
UINTN Columns;
|
|
UINTN Index;
|
|
UINTN Item;
|
|
UINTN Rows;
|
|
UINTN StrLenth;
|
|
|
|
Color = 0;
|
|
Item = 1;
|
|
StrLenth = 20;
|
|
|
|
//
|
|
// Set the background
|
|
//
|
|
gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Columns, &Rows);
|
|
Color = EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLUE);
|
|
gST->ConOut->SetAttribute (gST->ConOut, Color);
|
|
StrLenth = StrLenth / 2;
|
|
for (Index = 0; Index < (StrLenth + 2) * 2 + 1; Index++) {
|
|
CleanLine[Index] = 0x20;
|
|
SelectIndexLin[Index] = 0x20;
|
|
}
|
|
CleanLine[(StrLenth + 2) * 2 + 1] = 0x0000;
|
|
SelectIndexLin[1 + 1] = 0x0000;
|
|
Item = Item / 2;
|
|
for (Index = Rows / 2 - (Item + 3); Index <= Rows / 2 + (Item + 1); Index++) {
|
|
PrintAt (Columns / 2 - (StrLenth + 2), Index, L"%s", CleanLine);
|
|
}
|
|
|
|
//
|
|
// Next three step will draw a dialog
|
|
// 1.draw three row line
|
|
// 2.draw two side
|
|
// 3.draw four corner
|
|
//
|
|
|
|
//
|
|
// This is draw three row line
|
|
//
|
|
for (Index = Columns / 2 - (StrLenth + 1); Index < Columns / 2 + (StrLenth + 2) ; Index++) {
|
|
PrintAt (Index, Rows / 2 - (Item + 3), L"%c", BOXDRAW_HORIZONTAL);
|
|
PrintAt (Index, Rows / 2 - (Item + 1), L"%c", BOXDRAW_HORIZONTAL);
|
|
PrintAt (Index, Rows / 2 + (Item + 1), L"%c", BOXDRAW_HORIZONTAL);
|
|
}
|
|
|
|
//
|
|
// Draw two side
|
|
//
|
|
for (Index = Rows / 2 - (Item + 2); Index < Rows / 2 + (Item + 1); Index++) {
|
|
PrintAt (Columns / 2 - (StrLenth + 2), Index, L"%c", BOXDRAW_VERTICAL);
|
|
PrintAt (Columns / 2 + (StrLenth + 2), Index, L"%c", BOXDRAW_VERTICAL);
|
|
}
|
|
|
|
//
|
|
// This is draw the dialog four corner
|
|
//
|
|
PrintAt (Columns / 2 + (StrLenth + 2) ,Rows / 2 + (Item + 1), L"%c", BOXDRAW_UP_LEFT);
|
|
PrintAt (Columns / 2 + (StrLenth + 2) ,Rows / 2 - (Item + 3), L"%c", BOXDRAW_DOWN_LEFT);
|
|
PrintAt (Columns / 2 - (StrLenth + 2), Rows / 2 + (Item + 1), L"%c", BOXDRAW_UP_RIGHT);
|
|
PrintAt (Columns / 2 - (StrLenth + 2), Rows / 2 - (Item + 3), L"%c", BOXDRAW_DOWN_RIGHT);
|
|
|
|
//
|
|
// Print the title and flash status percentage
|
|
//
|
|
StatusString = BdsLibGetStringById (STRING_TOKEN (STR_RECOVERY_FLASH_STATUS));
|
|
if (StatusString == NULL) {
|
|
return;
|
|
}
|
|
PrintAt (Columns / 2 - (StrLen (StatusString) / 2), Rows / 2 - (Item + 2), L"%s", StatusString);
|
|
FreePool (StatusString);
|
|
}
|
|
|
|
/**
|
|
Transfer flash complete request to the reset action of recovery complete checkpoint.
|
|
|
|
@param[in] FlashCompleteRequest Flash complete request
|
|
|
|
@return The reset action of recovery complete checkpoint
|
|
**/
|
|
STATIC
|
|
UINT8
|
|
GetCpRecoveryCompleteResetAction (
|
|
IN UINT8 FlashCompleteRequest
|
|
)
|
|
{
|
|
switch (FlashCompleteRequest) {
|
|
|
|
case FlashCompleteDoNothing:
|
|
return H2O_BDS_CP_RECOVERY_COMPLETE_DO_NOTHING;
|
|
|
|
case FlashCompleteShutdown:
|
|
return H2O_BDS_CP_RECOVERY_COMPLETE_SHUTDOWN;
|
|
|
|
case FlashCompleteReboot:
|
|
default:
|
|
return H2O_BDS_CP_RECOVERY_COMPLETE_REBOOT;
|
|
}
|
|
}
|
|
|
|
/**
|
|
The entry point to doing recovery flash
|
|
|
|
@param[in] FlashMode Input flash mode (DEFAULT_FLASH_DEVICE_TYPE, SPI_FLASH_DEVICE_TYPE, OTHER_FLASH_DEVICE_TYPE)
|
|
|
|
**/
|
|
VOID
|
|
RecoveryFlash (
|
|
IN UINTN FlashMode
|
|
)
|
|
{
|
|
UINT8 *BufferTmp;
|
|
UINT8 FlashDevice;
|
|
UINT8 *FlashTmp;
|
|
UINT8 CommTmp;
|
|
UINT8 *MapTmp;
|
|
UINT8 Index;
|
|
CHAR16 *RebootString;
|
|
UINT32 FlashAddress;
|
|
UINT32 FlashSize;
|
|
UINTN Columns;
|
|
UINTN CompareTemp;
|
|
UINTN FlashPrecentage;
|
|
UINTN IndexCounter;
|
|
UINTN Item;
|
|
UINTN PEIBaseTemp[20];
|
|
UINTN Rows;
|
|
UINTN WriteSize;
|
|
VOID *HobList;
|
|
EFI_PEI_HOB_POINTERS RecoveryHob;
|
|
EFI_STATUS Status;
|
|
UINTN TotalFlashSectors;
|
|
UINTN FirmwareSize;
|
|
UINT8 RecoveryFlag;
|
|
VOID *CmdBuffer;
|
|
UINT32 CmdBufferSize;
|
|
UINT8 GetCmdStatus;
|
|
|
|
POST_CODE (BDS_RECOVERY_START_FLASH);
|
|
|
|
//
|
|
// Initial local variable
|
|
//
|
|
Item = 0;
|
|
WriteSize = 0;
|
|
CommTmp = 0xFF;
|
|
Index = 0;
|
|
CompareTemp = 0;
|
|
FlashTmp = NULL;
|
|
MapTmp = NULL;
|
|
FlashDevice = (UINT8) FlashMode;
|
|
|
|
BackupAuthVariable ();
|
|
|
|
ZeroMem (PEIBaseTemp, 20);
|
|
gST->ConOut->ClearScreen (gST->ConOut);
|
|
|
|
//
|
|
// Get the PEI phase .FD file memory base addess Hob ()
|
|
//
|
|
HobList = GetHobList ();
|
|
RecoveryHob.Raw = HobList;
|
|
RecoveryHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, RecoveryHob.Raw);
|
|
while (RecoveryHob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION &&
|
|
!CompareGuid (&RecoveryHob.MemoryAllocationModule->MemoryAllocationHeader.Name,
|
|
&gEfiRecoveryFileAddressGuid)) {
|
|
RecoveryHob.Raw = GET_NEXT_HOB (RecoveryHob);
|
|
RecoveryHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, RecoveryHob.Raw);
|
|
}
|
|
|
|
HookResetSystem (TRUE);
|
|
if (RecoveryCapsuleIsExecutable (&RecoveryHob)) {
|
|
//
|
|
// Set this flag to hook IHISI 16h(FbtsComplete), force it to return here,
|
|
// so, we can restore the authenticated variables.
|
|
//
|
|
RecoveryFlag = FLASH_COMPLETE_IN_RECOVERY;
|
|
Status = SaveLockBox (&gSecureFlashInfoGuid, &RecoveryFlag, sizeof (RecoveryFlag));
|
|
ExecuteRecoveryCapsule (&RecoveryHob);
|
|
RestoreAuthVariable ();
|
|
HookResetSystem (FALSE);
|
|
//
|
|
// Clear firmware update flag by erase the signature in flash part for seamless recovery
|
|
//
|
|
SetFirmwareUpdatingFlag (FALSE);
|
|
|
|
//
|
|
// Use checkpoint to provide project customization interface and use PCD to control this interface is
|
|
// enabled or disabled.
|
|
//
|
|
if (FeaturePcdGet (PcdH2OBdsCpRecoveryCompleteSupported)) {
|
|
H2O_BDS_CP_RECOVERY_COMPLETE_DATA BdsRecoveryCompleteData;
|
|
UINT8 RequestAction;
|
|
UINTN Size;
|
|
EFI_RESET_TYPE ResetType;
|
|
|
|
RequestAction = 0;
|
|
Size = sizeof (RequestAction);
|
|
Status = RestoreLockBox (&gSecureFlashInfoGuid, &RequestAction, &Size);
|
|
BdsRecoveryCompleteData.Size = sizeof (H2O_BDS_CP_RECOVERY_COMPLETE_DATA);
|
|
BdsRecoveryCompleteData.Status = H2O_CP_TASK_NORMAL;
|
|
BdsRecoveryCompleteData.RequestAction = GetCpRecoveryCompleteResetAction (RequestAction);
|
|
BdsRecoveryCompleteData.ResetData = NULL;
|
|
BdsRecoveryCompleteData.ResetDataSize = 0;
|
|
DEBUG_CP ((DEBUG_INFO, "Checkpoint Trigger: %g\n", &gH2OBdsCpRecoveryCompleteGuid));
|
|
Status = H2OCpTrigger (&gH2OBdsCpRecoveryCompleteGuid, &BdsRecoveryCompleteData);
|
|
DEBUG_CP ((DEBUG_INFO, "Checkpoint Result: %x\n", BdsRecoveryCompleteData.Status));
|
|
if (BdsRecoveryCompleteData.Status == H2O_CP_TASK_SKIP) {
|
|
return;
|
|
}
|
|
if (BdsRecoveryCompleteData.Status == H2O_CP_TASK_UPDATE) {
|
|
if (BdsRecoveryCompleteData.RequestAction == H2O_BDS_CP_RECOVERY_COMPLETE_DO_NOTHING) {
|
|
return;
|
|
} else if (BdsRecoveryCompleteData.RequestAction == H2O_BDS_CP_RECOVERY_COMPLETE_SHUTDOWN) {
|
|
ResetType = EfiResetShutdown;
|
|
} else if (BdsRecoveryCompleteData.RequestAction == H2O_BDS_CP_RECOVERY_COMPLETE_REBOOT) {
|
|
ResetType = EfiResetCold;
|
|
} else if (BdsRecoveryCompleteData.RequestAction == H2O_BDS_CP_RECOVERY_COMPLETE_WARM_RESET) {
|
|
ResetType = EfiResetWarm;
|
|
} else if (BdsRecoveryCompleteData.RequestAction == H2O_BDS_CP_RECOVERY_COMPLETE_PLATFORM_SPECIFIC_RESET) {
|
|
ResetType = EfiResetPlatformSpecific;
|
|
} else {
|
|
return;
|
|
}
|
|
gRT->ResetSystem (ResetType, EFI_SUCCESS, BdsRecoveryCompleteData.ResetDataSize, BdsRecoveryCompleteData.ResetData);
|
|
}
|
|
}
|
|
gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
|
|
}
|
|
BufferTmp =(UINT8 *) (UINTN)RecoveryHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress;
|
|
FirmwareSize = (UINTN) RecoveryHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength;
|
|
|
|
H2OIhisiAuthLock ();
|
|
GetCmdStatus = H2OIhisiGetCmdBuffer (&CmdBuffer, &CmdBufferSize, NULL, NULL);
|
|
if (GetCmdStatus != 0) {
|
|
FlashTmp = AllocatePool (0x100);
|
|
MapTmp = AllocatePool (0x100);
|
|
if (FlashTmp == NULL || MapTmp == NULL) {
|
|
return;
|
|
}
|
|
} else {
|
|
FlashTmp = (UINT8 *)(UINTN) CmdBuffer;
|
|
MapTmp = (UINT8 *)((UINTN) CmdBuffer + 0x100);
|
|
}
|
|
gBS->SetMem (FlashTmp, 0x100, 0);
|
|
gBS->SetMem (MapTmp, 0x100, 0);
|
|
CommTmp = H2OIhisiFbtsGetFlashPartInfo ((FBTS_FLASH_DEVICE **) &FlashTmp, (FD_BLOCK_MAP **)&MapTmp);
|
|
FlashAddress = 0xFFFFFFFF - (UINT32)FirmwareSize + 1;
|
|
WriteSize = *(UINT16 *)(&(MapTmp[0]));
|
|
|
|
if (FLASH_BLOCK_SIZE == WriteSize * SMI_FLASH_UNIT_BYTES) {
|
|
FlashSize = FLASH_BLOCK_SIZE;
|
|
} else {
|
|
FlashSize = FLASH_SECTOR_SIZE;
|
|
}
|
|
|
|
//
|
|
// Each block size is 0x1000 or 0x10000 and Call IHISI to flash ROM part
|
|
//
|
|
DrawDialogBlock ();
|
|
TotalFlashSectors = FirmwareSize / FlashSize;
|
|
H2OIhisiAuth (IHISI_AUTH_POST_ONLY, NULL);
|
|
for (IndexCounter = 0; IndexCounter < TotalFlashSectors; IndexCounter++) {
|
|
if (GetCmdStatus != 0) {
|
|
CommTmp = H2OIhisiFbtsWrite (FlashSize, FlashAddress, BufferTmp);
|
|
} else {
|
|
CopyMem ((VOID *) (UINTN) CmdBuffer, BufferTmp, FlashSize);
|
|
CommTmp = H2OIhisiFbtsWrite (FlashSize, FlashAddress, (VOID *)(UINTN)CmdBuffer );
|
|
}
|
|
FlashAddress += FlashSize;
|
|
BufferTmp += FlashSize;
|
|
FlashPrecentage = (IndexCounter + 1) * 100 / TotalFlashSectors;
|
|
Drawpercentage (FlashPrecentage);
|
|
}
|
|
H2OIhisiAuthUnlock ();
|
|
RestoreAuthVariable ();
|
|
HookResetSystem (FALSE);
|
|
|
|
gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Columns, &Rows);
|
|
RebootString = BdsLibGetStringById (STRING_TOKEN (STR_RECOVERY_FLASH_REBOOT));
|
|
PrintAt (Columns / 2 - 4, Rows / 2 - Item + 0, L"%s", RebootString);
|
|
FreePool (RebootString);
|
|
for (IndexCounter = 0; IndexCounter < 10000; IndexCounter++) {
|
|
gBS->Stall (300);
|
|
}
|
|
ResetCommand ();
|
|
}
|
|
|