923 lines
24 KiB
C
923 lines
24 KiB
C
/** @file
|
|
SPEC : Computrace implement requirement v1.2.doc
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2013 - 2016, 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 "L05Computrace.h"
|
|
|
|
EFI_EVENT AfterDiskInfoEvent;
|
|
VOID *DiskInfoEventRegistration;
|
|
EFI_EVENT L05ComputraceStartUpEvent;
|
|
VOID *L05ComputraceStartUpRegistration;
|
|
EFI_HANDLE mImageHandle = NULL_HANDLE;
|
|
UINT8 BatterySerialBuffer[L05_COMPUTRACE_SERIAL_LENGTH];
|
|
UINT8 HardDiskSerialBuffer[L05_COMPUTRACE_SERIAL_LENGTH];
|
|
UINT8 SystemSerialBuffer[L05_COMPUTRACE_SERIAL_LENGTH];
|
|
UINT32 ComputraceState;
|
|
|
|
VOID
|
|
EFIAPI
|
|
DiksInfoProtocolNotify (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN BufferSize;
|
|
EFI_HANDLE Handle;
|
|
EFI_DISK_INFO_PROTOCOL *DiskInfo;
|
|
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
|
UINT32 IdDataSize;
|
|
EFI_IDENTIFY_DATA IdData;
|
|
|
|
Status = EFI_SUCCESS;
|
|
BufferSize = 0;
|
|
DiskInfo = NULL;
|
|
BlockIo = NULL;
|
|
IdDataSize = 0;
|
|
|
|
BufferSize = sizeof (EFI_HANDLE);
|
|
Status = gBS->LocateHandle (
|
|
ByRegisterNotify,
|
|
NULL,
|
|
DiskInfoEventRegistration,
|
|
&BufferSize,
|
|
&Handle
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return;
|
|
}
|
|
|
|
Status = gBS->HandleProtocol (
|
|
Handle,
|
|
&gEfiDiskInfoProtocolGuid,
|
|
&DiskInfo
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return;
|
|
}
|
|
|
|
Status = gBS->HandleProtocol (
|
|
Handle,
|
|
&gEfiBlockIoProtocolGuid,
|
|
&BlockIo
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Skip CD-ROM or other Removable Media
|
|
//
|
|
if (BlockIo->Media->RemovableMedia) {
|
|
return;
|
|
}
|
|
|
|
IdDataSize = sizeof (EFI_IDENTIFY_DATA);
|
|
ZeroMem (&IdData, sizeof (EFI_IDENTIFY_DATA));
|
|
|
|
Status = DiskInfo->Identify (DiskInfo, &IdData, &IdDataSize);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return;
|
|
}
|
|
|
|
CopyMem (HardDiskSerialBuffer, IdData.AtaData.SerialNo, sizeof (IdData.AtaData.SerialNo));
|
|
|
|
gBS->CloseEvent (AfterDiskInfoEvent);
|
|
|
|
return;
|
|
}
|
|
|
|
EFI_STATUS
|
|
GetSystemSerial (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT8 Length;
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
Length = L05_COMPUTRACE_SERIAL_LENGTH;
|
|
Status = OemSvcGetSystemSerial (&Length, SystemSerialBuffer);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
GetBatterySerial (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT8 Length;
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
Length = L05_COMPUTRACE_SERIAL_LENGTH;
|
|
Status = OemSvcGetBatterySerial (&Length, BatterySerialBuffer);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
SyncComputraceStateWithSetup (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN VarSize;
|
|
SYSTEM_CONFIGURATION SetupVariable;
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
//
|
|
// Sync Computrace state with Setup varibale.
|
|
//
|
|
VarSize = sizeof (SYSTEM_CONFIGURATION);
|
|
Status = gRT->GetVariable (
|
|
L"Setup",
|
|
&gSystemConfigurationGuid,
|
|
NULL,
|
|
&VarSize,
|
|
&SetupVariable
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
//
|
|
// Setup menu is default setting.
|
|
//
|
|
return Status;
|
|
}
|
|
|
|
if ((UINT8) ComputraceState != SetupVariable.ComputraceState) {
|
|
SetupVariable.ComputraceState = (UINT8) ComputraceState;
|
|
Status = gRT->SetVariable (
|
|
L"Setup",
|
|
&gSystemConfigurationGuid,
|
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
|
VarSize,
|
|
&SetupVariable
|
|
);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LoadAndStartImage
|
|
(
|
|
IN EFI_HANDLE *ImageHandle,
|
|
IN EFI_GUID *ImageGuid
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN FvHandleCount;
|
|
EFI_HANDLE *FvHandleBuffer;
|
|
UINTN Index;
|
|
EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
|
|
UINTN ImageSize;
|
|
EFI_FV_FILETYPE Type;
|
|
EFI_FV_FILE_ATTRIBUTES FvFileAttributes;
|
|
UINT32 AuthenticationStatus;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
MEDIA_FW_VOL_FILEPATH_DEVICE_PATH ImageNode;
|
|
EFI_HANDLE NewImageHandle;
|
|
UINTN ExitDataSize;
|
|
CHAR16 *ExitData;
|
|
|
|
//
|
|
//Get ComputraceComponents.efi
|
|
//
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiFirmwareVolume2ProtocolGuid,
|
|
NULL,
|
|
&FvHandleCount,
|
|
&FvHandleBuffer
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
for (Index = 0; Index < FvHandleCount; Index++) {
|
|
gBS->HandleProtocol (
|
|
FvHandleBuffer[Index],
|
|
&gEfiFirmwareVolume2ProtocolGuid,
|
|
(VOID **) &Fv
|
|
);
|
|
|
|
Status = Fv->ReadFile (
|
|
Fv,
|
|
ImageGuid,
|
|
NULL,
|
|
&ImageSize,
|
|
&Type,
|
|
&FvFileAttributes,
|
|
&AuthenticationStatus
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Get FV device path.
|
|
//
|
|
DevicePath = DevicePathFromHandle (FvHandleBuffer[Index]);
|
|
|
|
//
|
|
// Get ComputraceComponents.efi device path.
|
|
//
|
|
EfiInitializeFwVolDevicepathNode (&ImageNode, ImageGuid);
|
|
|
|
//
|
|
// Append ComputraceComponents.efi device path to FV device path.
|
|
//
|
|
DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &ImageNode);
|
|
|
|
//
|
|
// Load ComputraceComponents.efi.
|
|
//
|
|
Status = gBS->LoadImage (
|
|
FALSE,
|
|
mImageHandle,
|
|
DevicePath,
|
|
NULL,
|
|
0,
|
|
&NewImageHandle
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Start ComputraceComponent.efi.
|
|
//
|
|
Status = gBS->StartImage (NewImageHandle, &ExitDataSize, &ExitData);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
SaveL05ComputraceInfo (
|
|
IN EFI_L05_COMPUTRACE_AREA *L05ComputraceArea
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN DataLength;
|
|
UINTN L05ComputraceRegionBase;
|
|
UINTN L05ComputraceRegionSize;
|
|
EFI_SMM_FW_BLOCK_SERVICE_PROTOCOL *SmmFwb;
|
|
|
|
Status = EFI_SUCCESS;
|
|
DataLength = 0;
|
|
SmmFwb = NULL;
|
|
|
|
L05ComputraceRegionBase = (UINTN) FdmGetNAtAddr (&gL05H2OFlashMapRegionComputraceGuid, 1);
|
|
L05ComputraceRegionSize = (UINTN) FdmGetNAtSize (&gL05H2OFlashMapRegionComputraceGuid, 1);
|
|
|
|
if ((L05ComputraceRegionBase == (UINTN) L05_INVALID_VALUE) ||
|
|
(L05ComputraceRegionSize == (UINTN) L05_INVALID_VALUE)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
Status = gBS->LocateProtocol (&gEfiSmmFwBlockServiceProtocolGuid, NULL, (VOID **) &SmmFwb);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = SmmFwb->EraseBlocks (SmmFwb, L05ComputraceRegionBase, &L05ComputraceRegionSize);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
DataLength = MIN (L05ComputraceRegionSize, sizeof (EFI_L05_COMPUTRACE_AREA));
|
|
Status = SmmFwb->Write (
|
|
SmmFwb,
|
|
L05ComputraceRegionBase,
|
|
&DataLength,
|
|
(UINT8 *) L05ComputraceArea
|
|
);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
GetL05ComputraceInfo (
|
|
IN OUT EFI_L05_COMPUTRACE_AREA *L05ComputraceArea
|
|
)
|
|
{
|
|
|
|
if (((UINTN) FdmGetNAtAddr (&gL05H2OFlashMapRegionComputraceGuid, 1) == (UINTN) L05_INVALID_VALUE) ||
|
|
((UINTN) FdmGetNAtSize (&gL05H2OFlashMapRegionComputraceGuid, 1) == (UINTN) L05_INVALID_VALUE)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
CopyMem (L05ComputraceArea, (VOID *) (UINTN) FdmGetNAtAddr (&gL05H2OFlashMapRegionComputraceGuid, 1), sizeof (EFI_L05_COMPUTRACE_AREA));
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
GetComputraceState (
|
|
IN OUT UINT32 *EfiL05ComputraceState
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_L05_COMPUTRACE_AREA L05ComputraceArea;
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
Status = GetL05ComputraceInfo (&L05ComputraceArea);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
*EfiL05ComputraceState = L05ComputraceArea.ComputraceState;
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
SetComputraceState (
|
|
IN UINT32 *EfiL05ComputraceState
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_L05_COMPUTRACE_AREA L05ComputraceArea;
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
switch (*EfiL05ComputraceState) {
|
|
|
|
case EFI_L05_COMPUTRACE_ENABLED:
|
|
Status = GetL05ComputraceInfo (&L05ComputraceArea);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
break;
|
|
|
|
case EFI_L05_COMPUTRACE_DISABLED:
|
|
//
|
|
// Clear All Computrace Area when disable it.
|
|
//
|
|
SetMem (&L05ComputraceArea, sizeof (EFI_L05_COMPUTRACE_AREA), 0xFF);
|
|
break;
|
|
|
|
default:
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
L05ComputraceArea.ComputraceState = *EfiL05ComputraceState;
|
|
|
|
return SaveL05ComputraceInfo (&L05ComputraceArea);
|
|
}
|
|
|
|
/**
|
|
Check Erase Flag is exist or not.
|
|
|
|
@param None
|
|
|
|
@retval TRUE Erase Flag is exist.
|
|
@retval FALSE Erase Flag is not exist.
|
|
**/
|
|
BOOLEAN
|
|
IsExistingEraseFlag (
|
|
VOID
|
|
)
|
|
{
|
|
#ifdef L05_SPECIFIC_VARIABLE_SERVICE_ENABLE
|
|
EFI_STATUS Status;
|
|
EFI_L05_VARIABLE_PROTOCOL *L05VariablePtr;
|
|
UINT32 DataLength;
|
|
UINT8 ComputraceEraseFlag;
|
|
#else
|
|
UINTN EepromBase;
|
|
#endif
|
|
|
|
#ifdef L05_SPECIFIC_VARIABLE_SERVICE_ENABLE
|
|
Status = EFI_SUCCESS;
|
|
L05VariablePtr = NULL;
|
|
|
|
Status = gBS->LocateProtocol (&gEfiL05VariableProtocolGuid, NULL, &L05VariablePtr);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
ComputraceEraseFlag = 0;
|
|
DataLength = sizeof (ComputraceEraseFlag);
|
|
|
|
Status = L05VariablePtr->GetVariable (
|
|
L05VariablePtr,
|
|
&gL05ComputraceEraseFlagGuid,
|
|
&DataLength,
|
|
&ComputraceEraseFlag
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return FALSE;
|
|
}
|
|
|
|
return (ComputraceEraseFlag == L05_ERASE_FLAG_ENABLE) ? TRUE : FALSE;
|
|
|
|
#else
|
|
EepromBase = (UINTN) FdmGetNAtAddr (&gL05H2OFlashMapRegionEepromGuid, 1);
|
|
|
|
if (EepromBase == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
return (((EFI_L05_EEPROM_MAP_120 *) EepromBase)->ComputraceEraseFlag[0] == L05_ERASE_FLAG_ENABLE) ? TRUE : FALSE;
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
Clear Erase Flag.
|
|
|
|
@param None
|
|
|
|
@retval EFI_SUCCESS The operation completed successfully.
|
|
@retval Others An unexpected error occurred.
|
|
**/
|
|
EFI_STATUS
|
|
ClearEraseFlag (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
#ifdef L05_SPECIFIC_VARIABLE_SERVICE_ENABLE
|
|
EFI_L05_VARIABLE_PROTOCOL *L05VariablePtr;
|
|
UINT8 ComputraceEraseFlag;
|
|
UINT32 DataLength;
|
|
#else
|
|
EFI_SMM_FW_BLOCK_SERVICE_PROTOCOL *SmmFwb;
|
|
UINTN EepromBase;
|
|
UINTN EepromSize;
|
|
UINT8 *EepromBuffer;
|
|
#endif
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
#ifdef L05_SPECIFIC_VARIABLE_SERVICE_ENABLE
|
|
L05VariablePtr = NULL;
|
|
|
|
Status = gBS->LocateProtocol (&gEfiL05VariableProtocolGuid, NULL, &L05VariablePtr);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
ComputraceEraseFlag = L05_ERASE_FLAG_DISABLE;
|
|
DataLength = sizeof (ComputraceEraseFlag);
|
|
|
|
Status = L05VariablePtr->SetVariable (
|
|
L05VariablePtr,
|
|
&gL05ComputraceEraseFlagGuid,
|
|
DataLength,
|
|
&ComputraceEraseFlag
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
#else
|
|
SmmFwb = NULL;
|
|
EepromBuffer = NULL;
|
|
|
|
Status = gBS->LocateProtocol (&gEfiSmmFwBlockServiceProtocolGuid, NULL, (VOID **) &SmmFwb);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
EepromBase = (UINTN) FdmGetNAtAddr (&gL05H2OFlashMapRegionEepromGuid, 1);
|
|
EepromSize = (UINTN) FdmGetNAtSize (&gL05H2OFlashMapRegionEepromGuid, 1);
|
|
|
|
if ((EepromBase == 0) || (EepromSize == 0)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
EepromBuffer = AllocatePages (EFI_SIZE_TO_PAGES (EepromSize));
|
|
|
|
if (EepromBuffer == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
ZeroMem (EepromBuffer, (EFI_SIZE_TO_PAGES (EepromSize) * EFI_PAGE_SIZE));
|
|
CopyMem (EepromBuffer, (VOID *) EepromBase, EepromSize);
|
|
((EFI_L05_EEPROM_MAP_120 *) EepromBuffer)->ComputraceEraseFlag[0] = L05_ERASE_FLAG_DISABLE;
|
|
|
|
Status = SmmFwb->EraseBlocks (SmmFwb, EepromBase, &EepromSize);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = SmmFwb->Write (SmmFwb, EepromBase, &EepromSize, EepromBuffer);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
FreePages (EepromBuffer, EFI_SIZE_TO_PAGES (EepromSize));
|
|
#endif
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Erase Computrace FV.
|
|
|
|
@param ComputraceFvBase Point to Computrace FV.
|
|
@param ComputraceFvSize Size of Computrace FV.
|
|
|
|
@retval EFI_SUCCESS The operation completed successfully.
|
|
@retval Others An unexpected error occurred.
|
|
**/
|
|
EFI_STATUS
|
|
EraseComputraceFv (
|
|
IN UINTN ComputraceFvBase,
|
|
IN UINTN ComputraceFvSize
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_SMM_FW_BLOCK_SERVICE_PROTOCOL *SmmFwb;
|
|
UINTN EraseSize;
|
|
|
|
Status = EFI_SUCCESS;
|
|
SmmFwb = NULL;
|
|
EraseSize = ComputraceFvSize;
|
|
|
|
Status = gBS->LocateProtocol (&gEfiSmmFwBlockServiceProtocolGuid, NULL, (VOID **) &SmmFwb);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = SmmFwb->EraseBlocks (SmmFwb, ComputraceFvBase, &EraseSize);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Check Computrace Erase Request.
|
|
|
|
@param None
|
|
|
|
@retval EFI_SUCCESS The operation completed successfully.
|
|
@retval EFI_ABORTED No need to do this operation.
|
|
@retval Others An unexpected error occurred.
|
|
**/
|
|
EFI_STATUS
|
|
CheckComputraceEraseRequest (
|
|
VOID
|
|
)
|
|
{
|
|
UINTN ComputraceFvBase;
|
|
UINTN ComputraceFvSize;
|
|
EFI_FIRMWARE_VOLUME_HEADER *Fvh;
|
|
|
|
ComputraceFvBase = 0;
|
|
ComputraceFvSize = 0;
|
|
Fvh = NULL;
|
|
|
|
//
|
|
// According to Lenovo Notebook Remove Computrace Requirement for PRC Version 1.32 draft
|
|
// 3. Compatible Design
|
|
//
|
|
|
|
//
|
|
// Step1: Check Erase Flag
|
|
//
|
|
if (!IsExistingEraseFlag ()) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
//
|
|
// Step2: Check Computrace FV already earsed or not
|
|
//
|
|
ComputraceFvBase = (UINTN) FdmGetAddressById (&gH2OFlashMapRegionFvGuid, &gL05H2OFlashMapRegionComputraceFvGuid, 1);
|
|
ComputraceFvSize = (UINTN) FdmGetSizeById (&gH2OFlashMapRegionFvGuid, &gL05H2OFlashMapRegionComputraceFvGuid, 1);
|
|
|
|
if ((ComputraceFvBase == 0) || (ComputraceFvSize == 0)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
Fvh = (EFI_FIRMWARE_VOLUME_HEADER *) ComputraceFvBase;
|
|
|
|
if (Fvh->Signature != EFI_FVH_SIGNATURE) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Step3: Check Computrace state is enabled & activated or not
|
|
//
|
|
if (ComputraceState == EFI_L05_COMPUTRACE_ENABLED) {
|
|
//
|
|
// Computrace state is enabled, so keep Computrace module in ROM
|
|
//
|
|
ClearEraseFlag ();
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
EraseComputraceFv (ComputraceFvBase, ComputraceFvSize);
|
|
|
|
gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
|
|
|
|
//
|
|
// Waiting for system reset
|
|
//
|
|
CpuDeadLoop ();
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
L05ComputraceEntry (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT16 SmiPort;
|
|
BOOLEAN ComputraceSupported;
|
|
|
|
SmiPort = 0;
|
|
mImageHandle = ImageHandle;
|
|
ComputraceSupported = TRUE;
|
|
|
|
Status = GetComputraceState (&ComputraceState);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// According to Lenovo Notebook Remove Computrace Requirement for PRC Version 1.32 draft
|
|
// 2. Lenovo Requirements of Removing Computrace for PRC
|
|
// 2.2 SMB
|
|
// For SMB products, if Computrace function supported, then for the systems ship to PRC:
|
|
// - Computrace module such as efiinstnats.efi / efiinstnats64.efi MUST be completely removed from SPI rom.
|
|
// - Computrace SMM service code MUST be completely removed from SPI rom.
|
|
//
|
|
CheckComputraceEraseRequest ();
|
|
|
|
//
|
|
// Skip Computrace init if the OemSvc return platform doesn't support Computrace.
|
|
//
|
|
Status = OemSvcCheckComputraceSupportStatus (&ComputraceSupported);
|
|
|
|
if (Status == EFI_MEDIA_CHANGED && !ComputraceSupported) {
|
|
//
|
|
// If Computrace is Enabled, and then ComputraceSupportStatus changes to unsupported.
|
|
// The Computace string in SCU need to be hidden.
|
|
//
|
|
ComputraceState = EFI_L05_COMPUTRACE_DISABLED;
|
|
Status = SyncComputraceStateWithSetup ();
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Check SMI port address in CMOS.
|
|
//
|
|
SmiPort = SW_SMI_PORT;
|
|
|
|
if (SmiPort != ReadCmos16 (EFI_L05_COMPUTRACE_CMOS_ADDRESS_LOW)) {
|
|
WriteCmos16 (EFI_L05_COMPUTRACE_CMOS_ADDRESS_LOW, SmiPort);
|
|
}
|
|
|
|
//
|
|
// Disable Computrace when first boot.
|
|
//
|
|
if (ComputraceState == EFI_L05_COMPUTRACE_NOT_SUPPORTED) {
|
|
ComputraceState = EFI_L05_COMPUTRACE_DISABLED;
|
|
SetComputraceState (&ComputraceState);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
}
|
|
|
|
Status = SyncComputraceStateWithSetup ();
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
switch (ComputraceState) {
|
|
|
|
case EFI_L05_COMPUTRACE_ENABLING:
|
|
case EFI_L05_COMPUTRACE_ENABLED:
|
|
break;
|
|
|
|
default :
|
|
//
|
|
// Only need to continue when Computrace enabled.
|
|
//
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Clear each serial buffer.
|
|
//
|
|
ZeroMem (BatterySerialBuffer, L05_COMPUTRACE_SERIAL_LENGTH);
|
|
ZeroMem (HardDiskSerialBuffer, L05_COMPUTRACE_SERIAL_LENGTH);
|
|
ZeroMem (SystemSerialBuffer, L05_COMPUTRACE_SERIAL_LENGTH);
|
|
|
|
Status = gBS->CreateEvent (
|
|
EVT_NOTIFY_SIGNAL,
|
|
TPL_CALLBACK,
|
|
DiksInfoProtocolNotify,
|
|
NULL,
|
|
&AfterDiskInfoEvent
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
Status = gBS->RegisterProtocolNotify (
|
|
&gEfiDiskInfoProtocolGuid,
|
|
AfterDiskInfoEvent,
|
|
&DiskInfoEventRegistration
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
//
|
|
// Register notify function to install WPBT on ReadyToBoot Event.
|
|
//
|
|
Status = EfiCreateEventReadyToBootEx (
|
|
TPL_CALLBACK,
|
|
L05ComputraceFunction,
|
|
NULL,
|
|
&L05ComputraceStartUpEvent
|
|
);
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
GetComputraceSerialCrc (
|
|
IN OUT VOID *EfiL05ComputraceSerialCrc
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_L05_COMPUTRACE_AREA L05ComputraceArea;
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
Status = GetL05ComputraceInfo (&L05ComputraceArea);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
CopyMem (EfiL05ComputraceSerialCrc, &L05ComputraceArea.ComputraceSerialCrc, sizeof (EFI_L05_COMPUTRACE_SERIAL_CRC));
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
SetComputraceSerialCrc (
|
|
IN VOID *EfiL05ComputraceSerialCrc
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_L05_COMPUTRACE_AREA L05ComputraceArea;
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
Status = GetL05ComputraceInfo (&L05ComputraceArea);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
CopyMem (&L05ComputraceArea.ComputraceSerialCrc, EfiL05ComputraceSerialCrc, sizeof (EFI_L05_COMPUTRACE_SERIAL_CRC));
|
|
|
|
return SaveL05ComputraceInfo (&L05ComputraceArea);
|
|
}
|
|
|
|
VOID
|
|
EFIAPI
|
|
L05ComputraceFunction (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_GUID DriverGuid = L05_COMPUTRACE_EFI_DRIVER_FILE_GUID;
|
|
//WOD EFI_GUID WpbtGuid = L05_COMPUTRACE_EFI_WPBT_FILE_GUID;
|
|
EFI_L05_COMPUTRACE_SERIAL_CRC SerialCrc;
|
|
UINT32 BatteryCrc;
|
|
UINT32 HardDiskCrc;
|
|
UINT32 SystemCrc;
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
gBS->CloseEvent (Event);
|
|
|
|
GetBatterySerial ();
|
|
GetSystemSerial ();
|
|
|
|
gBS->CalculateCrc32 ((VOID *) BatterySerialBuffer, L05_COMPUTRACE_SERIAL_LENGTH, &BatteryCrc);
|
|
gBS->CalculateCrc32 ((VOID *) HardDiskSerialBuffer, L05_COMPUTRACE_SERIAL_LENGTH, &HardDiskCrc);
|
|
gBS->CalculateCrc32 ((VOID *) SystemSerialBuffer, L05_COMPUTRACE_SERIAL_LENGTH, &SystemCrc);
|
|
|
|
if (ComputraceState == EFI_L05_COMPUTRACE_ENABLING) {
|
|
//
|
|
// If Computrace was just enabled, we should store CRC of each serial.
|
|
//
|
|
SerialCrc.BatterySerialCrc = BatteryCrc;
|
|
SerialCrc.HardDiskSerialCrc = HardDiskCrc;
|
|
SerialCrc.SystemSerialCrc = SystemCrc;
|
|
|
|
SetComputraceSerialCrc (&SerialCrc);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// After CRCs are stored, change the Computrace state.
|
|
//
|
|
ComputraceState = EFI_L05_COMPUTRACE_ENABLED;
|
|
SetComputraceState (&ComputraceState);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return;
|
|
}
|
|
|
|
} else {
|
|
|
|
GetComputraceSerialCrc (&SerialCrc);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// If all serials changes at the same time, we should auto-disable Computrace.
|
|
//
|
|
if ((BatteryCrc != SerialCrc.BatterySerialCrc) &&
|
|
(HardDiskCrc != SerialCrc.HardDiskSerialCrc) &&
|
|
(SystemCrc != SerialCrc.SystemSerialCrc)
|
|
) {
|
|
ComputraceState = EFI_L05_COMPUTRACE_DISABLED;
|
|
|
|
SetComputraceState (&ComputraceState);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return;
|
|
}
|
|
|
|
Status = SyncComputraceStateWithSetup ();
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Prepare to load Computrace EFI Driver.
|
|
//
|
|
//WOD Status = LoadAndStartImage((EFI_HANDLE*)Context, &WpbtGuid);
|
|
Status = GetComputraceState (&ComputraceState);
|
|
|
|
if (!EFI_ERROR (Status) && (ComputraceState == EFI_L05_COMPUTRACE_ENABLED)) {
|
|
LoadAndStartImage ((EFI_HANDLE *) Context, &DriverGuid);
|
|
}
|
|
|
|
return;
|
|
}
|