252 lines
7.2 KiB
C
252 lines
7.2 KiB
C
//*****************************************************************************
|
|
// //
|
|
// Copyright (c) 2012 - 2017, Hefei LCFC Information Technology Co.Ltd.
|
|
// And/or its affiliates. All rights reserved.
|
|
// Hefei LCFC Information Technology Co.Ltd. PROPRIETARY/CONFIDENTIAL.
|
|
// Use is subject to license terms.
|
|
//
|
|
//******************************************************************************
|
|
/*++
|
|
Abstract:
|
|
This driver is used BIOS Hang Check feature. It will beep twice and blink power LED, when novo button
|
|
is pressed for longer than 4s, while the unit is software hang.
|
|
|
|
History:
|
|
Date Name Version Description
|
|
2017.06.06 Mandy Xiao/Annie Wei v1.00 Initial release
|
|
2018.09.14 Storm Yin/Rita Zhang v1.01 Add dump pci configuration registers function sample code
|
|
2018.09.18 Storm Yin v1.02 optimize for dumping pci configuration registers function sample code
|
|
|
|
Module Name:
|
|
HangCheck.c
|
|
--*/
|
|
|
|
#include <Uefi.h>
|
|
#include <Library/LfcLib.h>
|
|
#include <Library/LfcEcLib.h>
|
|
#include <Library/GpioLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Protocol/SmmGpiDispatch2.h>
|
|
#include <Library/SmmServicesTableLib.h>
|
|
#include <Library/FdSupportLib.h>
|
|
#include <Library/TimerLib.h>
|
|
#include <Guid/LfcVariableGuid.h>
|
|
#include <Library/IoLib.h>
|
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
|
#include <Library/OemSvcLfcGetEcSmiGpioPad.h>
|
|
|
|
UINT32 mGpioSmiPad = 0;
|
|
|
|
// for easy to handle NB BDF, assuem max PCI bus # is 8: PCI_MAX_BUS_NUM
|
|
#define PCI_STORE_MAX_DEV 50
|
|
#define PCI_MAX_BUS_NUM 8
|
|
#define PCI_MAX_DEV 31
|
|
#define PCI_MAX_FUN 7
|
|
#define PcieBsaeAddress 0xE0000000
|
|
#define PciExpressConfigAddress(Bus,Device,Function,Offset) \
|
|
(((Offset) & 0xfff) | (((Function) & 0x07) << 12) | (((Device) & 0x1f) << 15) | (((Bus) & 0xff) << 20) + PcieBsaeAddress)
|
|
|
|
// LCFCTODO need change according your Resize Region map
|
|
#define DUMP_LOG_SPI_OFFSET 0xff630000
|
|
|
|
|
|
EFI_STATUS
|
|
DumpLogToVariable (
|
|
)
|
|
{
|
|
UINT8 Bus;
|
|
UINT8 Dev;
|
|
UINT8 Fun;
|
|
UINT8 WriteLog[PCI_STORE_MAX_DEV][256]={0};
|
|
UINT32 SrcAddress32;
|
|
EFI_STATUS Status;
|
|
UINTN Num1;
|
|
UINTN Num2;
|
|
|
|
Num1 = 0;
|
|
//
|
|
// Dump all PCI configuration registers to structure.
|
|
//
|
|
|
|
for ( Bus=0; Bus < PCI_MAX_BUS_NUM; Bus++) {
|
|
for ( Dev=0; Dev < PCI_MAX_DEV; Dev++ ) {
|
|
for ( Fun=0; Fun < PCI_MAX_FUN; Fun++) {
|
|
SrcAddress32 = PciExpressConfigAddress(Bus,Dev,Fun,0);
|
|
if (0xFFFF != *(UINT16 *)((UINTN) SrcAddress32)) {
|
|
if (Num1++ > PCI_STORE_MAX_DEV) {
|
|
break;
|
|
}
|
|
for (Num2 = 0; Num2 < 256; Num2++) {
|
|
WriteLog[Num1][Num2] = MmioRead8 (SrcAddress32 + Num2);
|
|
}
|
|
}
|
|
else {
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Save structure to UEFI variable.
|
|
//
|
|
Status = gRT->SetVariable (
|
|
L"HangCheckPciLog",
|
|
&gLfcVariableGuid,
|
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
|
sizeof(WriteLog),
|
|
&WriteLog
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
return Status;
|
|
}
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
EFI_STATUS
|
|
DumpLogToBiosSpi (
|
|
)
|
|
{
|
|
|
|
UINT8 Bus;
|
|
UINT8 Dev;
|
|
UINT8 Fun;
|
|
EFI_STATUS Status;
|
|
UINT32 WriteAddress;
|
|
UINT32 WriteSize;
|
|
UINT32 SrcAddress32;
|
|
|
|
//
|
|
// Warning!!! BIOS SPI rom address need re-porting when used.
|
|
//
|
|
|
|
WriteAddress = DUMP_LOG_SPI_OFFSET;
|
|
|
|
for ( Bus=0; Bus < PCI_MAX_BUS_NUM; Bus++) {
|
|
for ( Dev=0; Dev < PCI_MAX_DEV; Dev++ ) {
|
|
for ( Fun=0; Fun < PCI_MAX_FUN; Fun++) {
|
|
SrcAddress32 = PciExpressConfigAddress(Bus,Dev,Fun,0);
|
|
if (0xFFFF != *(UINT16 *)((UINTN) SrcAddress32)) {
|
|
WriteSize = 0x100;
|
|
Status = FlashProgram (
|
|
(VOID *)((UINTN) WriteAddress),
|
|
(VOID *)((UINTN) SrcAddress32),
|
|
(UINTN *)&WriteSize,
|
|
(WriteAddress & ~(0xFFFF))
|
|
);
|
|
MicroSecondDelay (50);
|
|
WriteAddress += WriteSize;
|
|
}
|
|
else {
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
HangCheckHandler (
|
|
IN EFI_HANDLE DispatchHandle,
|
|
IN CONST EFI_SMM_GPI_REGISTER_CONTEXT *GpiRegisterContext
|
|
)
|
|
{
|
|
UINTN Num;
|
|
UINT8 Data;
|
|
|
|
//
|
|
// Clear ALT_GPI_SMI_STS register for GPIO (EC SMI#)
|
|
//
|
|
GpioClearGpiSmiSts (mGpioSmiPad);
|
|
|
|
//Send command to EC for starting to light shine
|
|
LfcEcLibStartLight();
|
|
|
|
//Beep
|
|
for (Num = 0; Num < 2; Num++) {
|
|
Data = IoRead8 ( 0x61 );
|
|
Data |= 0x03;
|
|
IoWrite8 ( 0x61, Data );
|
|
LfcProjectLibStall (200000);
|
|
Data = IoRead8 ( 0x61 );
|
|
Data = Data & 0xFC;
|
|
IoWrite8 ( 0x61, Data );
|
|
LfcProjectLibStall (200000);
|
|
}
|
|
|
|
//
|
|
// Note!!!
|
|
// Following is store dump log sample code, please enable it by needed.
|
|
//
|
|
|
|
// Store log in UEFI variable.
|
|
//DumpLogToVariable ();
|
|
|
|
// Backup store log way, store log in BIOS SPI. If use this way dump log, please re-porting SPI address.
|
|
DumpLogToBiosSpi ();
|
|
|
|
//Beep again to note store log.
|
|
for (Num = 0; Num < 2; Num++) {
|
|
Data = IoRead8 ( 0x61 );
|
|
Data |= 0x03;
|
|
IoWrite8 ( 0x61, Data );
|
|
LfcProjectLibStall (200000);
|
|
Data = IoRead8 ( 0x61 );
|
|
Data = Data & 0xFC;
|
|
IoWrite8 ( 0x61, Data );
|
|
LfcProjectLibStall (200000);
|
|
}
|
|
|
|
//Send command to EC for stopping to light shine
|
|
LfcEcLibStopLight();
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
HangCheckEntry(
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_SMM_GPI_DISPATCH2_PROTOCOL *mSmmGpiDispatch;
|
|
EFI_SMM_GPI_REGISTER_CONTEXT GpiRegisterContext;
|
|
EFI_HANDLE GpiHandle;
|
|
UINT32 LfcEcSmiGpioPad;
|
|
|
|
// Get GpioPad value for EC SMI#
|
|
OemSvcLfcGetEcSmiGpioPad(&LfcEcSmiGpioPad);
|
|
mGpioSmiPad = LfcEcSmiGpioPad;
|
|
|
|
//
|
|
// Get GpiNum according to GPIO Group+Pad
|
|
//
|
|
GpioGetGpiSmiNum (mGpioSmiPad, &GpiRegisterContext.GpiNum);
|
|
|
|
//
|
|
// Register SMI handler EC SMI usage during Connected Standby
|
|
//
|
|
Status = gSmst->SmmLocateProtocol (&gEfiSmmGpiDispatch2ProtocolGuid, NULL, &mSmmGpiDispatch);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
return Status;
|
|
}
|
|
|
|
DEBUG ((DEBUG_ERROR, "Installing HangCheckHandler Handler \n"));
|
|
Status = mSmmGpiDispatch->Register (
|
|
mSmmGpiDispatch,
|
|
(EFI_SMM_HANDLER_ENTRY_POINT2)HangCheckHandler,
|
|
&GpiRegisterContext,
|
|
&GpiHandle
|
|
);
|
|
DEBUG ((DEBUG_ERROR, "HangCheckHandler Install Status: %x\n", Status));
|
|
|
|
return Status;
|
|
}
|