222 lines
6.8 KiB
C
222 lines
6.8 KiB
C
/** @file
|
|
This OemService provides OEM to decide the method of recovery request.
|
|
When DXE loader found that the DXE-core of firmware volume is corrupt, it will force system to restart.
|
|
This service will be called to set the recovery requests before system restart.
|
|
To design the recovery requests according to OEM specification.
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2012 - 2021, Insyde Software Corporation. 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 <Library/PeiOemSvcKernelLib.h>
|
|
#include <Library/CmosLib.h>
|
|
#include <Library/HobLib.h>
|
|
#include <ChipsetCmos.h>
|
|
#ifdef L05_CRISIS_ENABLE
|
|
#include <L05Config.h>
|
|
#include <Library/PeiServicesLib.h>
|
|
#include <Library/CmosLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/FeatureLib/OemSvcBIOSCrisis.h>
|
|
#include <OemCmos.h>
|
|
#endif
|
|
#ifdef L05_BIOS_SELF_HEALING_SUPPORT
|
|
#include <Library/FeatureLib/OemSvcNotifyEcToStopWdt.h>
|
|
#endif
|
|
|
|
#ifdef L05_CRISIS_ENABLE
|
|
/**
|
|
Update L05 Crisis BIOS Name.
|
|
|
|
[Lenovo China Minimum BIOS Spec V1.40]
|
|
3.5.1 Crisis Recovery
|
|
4. the Crisis BIOS must be name as: xxCN.bin, xx is BIOS build ID.
|
|
|
|
@param None
|
|
|
|
@retval EFI_SUCCESS The operation completed successfully.
|
|
@retval Others An unexpected error occurred.
|
|
**/
|
|
EFI_STATUS
|
|
UpdateL05CrisisBiosName (
|
|
VOID
|
|
)
|
|
{
|
|
CHAR16 CrisisBiosName[10];
|
|
UINTN BufferSize;
|
|
CHAR16 *FirmwareVersionString;
|
|
|
|
FirmwareVersionString = NULL;
|
|
BufferSize = sizeof (CrisisBiosName);
|
|
|
|
ZeroMem (CrisisBiosName, BufferSize);
|
|
StrCpyS (CrisisBiosName, BufferSize / sizeof (CHAR16), L05_CRISIS_BIOS_NAME);
|
|
|
|
FirmwareVersionString = (CHAR16 *) PcdGetPtr (PcdFirmwareVersionString);
|
|
CrisisBiosName[0] = FirmwareVersionString[0];
|
|
CrisisBiosName[1] = FirmwareVersionString[1];
|
|
|
|
PcdSetPtrS (PcdPeiRecoveryFile, &BufferSize, CrisisBiosName);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Check BIOS recovery hotkey status.
|
|
|
|
@param None
|
|
|
|
@retval EFI_UNSUPPORTED To do default.
|
|
@retval EFI_MEDIA_CHANGED Hotkey detected. Change current boot mode to recovery mode.
|
|
**/
|
|
EFI_STATUS
|
|
CheckL05RecoveryHotkey (
|
|
VOID
|
|
)
|
|
{
|
|
//
|
|
// Todo:
|
|
// Add project specific code in here.
|
|
//
|
|
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
This OemService provides OEM to detect the recovery mode.
|
|
OEM designs the rule to detect that boot mode is recovery mode or not,
|
|
The rule bases on the recovery request which defined in OemService "OemSetRecoveryRequest".
|
|
|
|
@param[in, out] *IsRecovery If service detects that the current system is recovery mode.
|
|
This parameter will return TRUE, else return FALSE.
|
|
|
|
@retval EFI_UNSUPPORTED Returns unsupported by default.
|
|
@retval EFI_SUCCESS The service is customized in the project.
|
|
@retval EFI_MEDIA_CHANGED The value of IN OUT parameter is changed.
|
|
@retval Others Depends on customization.
|
|
**/
|
|
EFI_STATUS
|
|
OemSvcDetectRecoveryRequest (
|
|
IN OUT BOOLEAN *IsRecovery
|
|
)
|
|
{
|
|
#ifdef L05_CRISIS_ENABLE
|
|
EFI_STATUS Status;
|
|
EFI_BOOT_MODE BootMode;
|
|
#endif
|
|
|
|
#ifdef L05_CRISIS_ENABLE
|
|
//
|
|
// [Lenovo China Minimum BIOS Spec V1.40]
|
|
// 3.5.1 Crisis Recovery
|
|
// 4. the Crisis BIOS must be name as: xxCN.bin, xx is BIOS build ID.
|
|
//
|
|
Status = UpdateL05CrisisBiosName ();
|
|
|
|
Status = PeiServicesGetBootMode (&BootMode);
|
|
|
|
if (!EFI_ERROR (Status) && (BootMode == BOOT_ON_S3_RESUME)) {
|
|
*IsRecovery = FALSE;
|
|
return EFI_SUCCESS;
|
|
}
|
|
#endif
|
|
|
|
if (RECOVERY_VALUE == ReadExtCmos8 ( R_XCMOS_INDEX, R_XCMOS_DATA, ChipsetRecoveryFlag)) {
|
|
*IsRecovery = TRUE;
|
|
#ifndef L05_CRISIS_ENABLE
|
|
if (PcdGet8(PcdChasmFallsSupport) == 1) {
|
|
BuildGuidDataHob (&gChasmfallsCrisisRecoveryGuid, IsRecovery, sizeof(BOOLEAN));
|
|
}
|
|
#endif
|
|
} else {
|
|
*IsRecovery = FALSE;
|
|
}
|
|
|
|
#ifdef L05_CRISIS_ENABLE
|
|
//
|
|
// BUG!! BUG!! BUG!!
|
|
// This is for Lenovo INTERNAL NovoButton and CrisisRecovery test.
|
|
// Project need to remove this code.
|
|
// 0x01 = Crisis Recovery.
|
|
// 0x02 = Novo button pressed.
|
|
//
|
|
if (ReadCmos8 (EFI_L05_NOVO_BUTTON_CRISIS_TEST) == (UINT8)0x01) {
|
|
*IsRecovery = TRUE;
|
|
PcdSetBoolS (PcdL05BiosRecoveryHotkeyFlag, TRUE);
|
|
if (PcdGet8 (PcdChasmFallsSupport) == 2) {
|
|
WriteCmos8 (EFI_L05_NOVO_BUTTON_CRISIS_TEST, (UINT8)0x00);
|
|
}
|
|
}
|
|
|
|
//
|
|
// [Lenovo China Minimum BIOS Spec V1.39]
|
|
// 3.5.1 Crisis Recovery
|
|
// Lenovo require the BIOS support user can press "Fn + R" hot key and power on system
|
|
// to crisis recovery corrupted BIOS.
|
|
//
|
|
Status = CheckL05RecoveryHotkey ();
|
|
|
|
if (Status == EFI_MEDIA_CHANGED) {
|
|
*IsRecovery = TRUE;
|
|
PcdSetBoolS (PcdL05BiosRecoveryHotkeyFlag, TRUE);
|
|
}
|
|
|
|
#ifdef L05_BIOS_SELF_HEALING_SUPPORT
|
|
if (ReadCmos8 (EfiL05BiosSelfHealingModeSwitch) == V_EFI_L05_BIOS_SELF_HEALING_MODE_CRISIS_RECOVERY) {
|
|
PcdSetBoolS (PcdL05BiosRecoveryHotkeyFlag, TRUE);
|
|
WriteCmos8 (EfiL05BiosSelfHealingModeSwitch, V_EFI_L05_BIOS_SELF_HEALING_MODE_NORMAL);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// [Lenovo China Minimum BIOS Spec V1.39]
|
|
// 3.5.1 Crisis Recovery
|
|
// Systems must be enabled the Battery LED in the whole recovery process.
|
|
//
|
|
#ifdef L05_BIOS_SELF_HEALING_SUPPORT
|
|
if (*IsRecovery && PcdGetBool (PcdL05BiosRecoveryHotkeyFlag)) {
|
|
#else
|
|
if (*IsRecovery) {
|
|
#endif
|
|
OemSvcSetCrisisLedState ();
|
|
}
|
|
|
|
if (*IsRecovery) {
|
|
if (PcdGet8(PcdChasmFallsSupport) == 1) {
|
|
BuildGuidDataHob (&gChasmfallsCrisisRecoveryGuid, IsRecovery, sizeof(BOOLEAN));
|
|
}
|
|
}
|
|
|
|
#ifdef L05_BIOS_SELF_HEALING_SUPPORT
|
|
//
|
|
// [Lenovo BIOS Self-Healing Design Guidance Specification V1.9]
|
|
// 2.1 Overview
|
|
// The EC boot flow and BIOS top swap self-healing flow :
|
|
// BIOS should check Top Swap pin status.
|
|
// If Top Swap bit is enabled then enter recovery mode and notify EC to stop WDT.
|
|
//
|
|
if (PcdGetBool (PcdL05TopSwapEnable)) {
|
|
OemSvcNotifyEcToStopWdt ();
|
|
}
|
|
|
|
//
|
|
// Set flag to indicate that crisis recovery will continue on the next boot
|
|
//
|
|
if (PcdGetBool (PcdL05BiosRecoveryHotkeyFlag) &&
|
|
(ReadCmos8 (EfiL05BiosSelfHealingModeSwitch) != V_EFI_L05_BIOS_SELF_HEALING_MODE_CRISIS_RECOVERY)) {
|
|
WriteCmos8 (EfiL05BiosSelfHealingModeSwitch, V_EFI_L05_BIOS_SELF_HEALING_MODE_CRISIS_RECOVERY);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
return EFI_MEDIA_CHANGED;
|
|
}
|