672 lines
22 KiB
C
672 lines
22 KiB
C
/** @file
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2012 - 2016, 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 "SpecificVariableServiceDxe.h"
|
|
|
|
EFI_SMM_FW_BLOCK_SERVICE_PROTOCOL *mSmmFwb = NULL;
|
|
|
|
EFI_STATUS
|
|
LenovoVariableSyncDataAndBufferWithRom (
|
|
IN OUT LENOVO_VARIABLE_PRIVATE_DATA *PrivateData
|
|
)
|
|
{
|
|
LENOVO_VARIABLE_RIGION_HEADER *FlashRegion1Address;
|
|
LENOVO_VARIABLE_RIGION_HEADER *FlashRegion2Address;
|
|
UINT32 L05VariableRegion1Size;
|
|
UINT32 L05VariableRegion2Size;
|
|
|
|
L05VariableRegion1Size = (UINT32) FdmGetNAtSize (&gL05H2OFlashMapRegionVaribale1Guid, 1);
|
|
L05VariableRegion2Size = (UINT32) FdmGetNAtSize (&gL05H2OFlashMapRegionVaribale2Guid, 1);
|
|
|
|
FlashRegion1Address = (LENOVO_VARIABLE_RIGION_HEADER *) (UINTN) FdmGetNAtAddr (&gL05H2OFlashMapRegionVaribale1Guid, 1);
|
|
FlashRegion2Address = (LENOVO_VARIABLE_RIGION_HEADER *) (UINTN) FdmGetNAtAddr (&gL05H2OFlashMapRegionVaribale2Guid, 1);
|
|
|
|
if (FlashRegion1Address->PriorityFlag == 0 && FlashRegion2Address->PriorityFlag == 0) {
|
|
//Nothing in region
|
|
PrivateData->Region = LENOVO_VARIABLE_NO_DATA;
|
|
SetMem (PrivateData->VariableBuffer, L05VariableRegion1Size, 0);
|
|
CopyMem (PrivateData->VariableBuffer, FlashRegion1Address, sizeof (LENOVO_VARIABLE_RIGION_HEADER));
|
|
|
|
//Generate RandomNumber
|
|
{
|
|
UINT64 TimeStamp;
|
|
|
|
TimeStamp = AsmReadTsc ();
|
|
|
|
while ((UINT8) TimeStamp == 0) {
|
|
TimeStamp = AsmReadTsc ();
|
|
}
|
|
|
|
((LENOVO_VARIABLE_RIGION_HEADER *) PrivateData->VariableBuffer)->RandomNumber = (UINT8) TimeStamp;
|
|
}
|
|
|
|
} else if (FlashRegion1Address->PriorityFlag > FlashRegion2Address->PriorityFlag) {
|
|
//Use sub region 1
|
|
if (CompareMem (PrivateData->VariableBuffer, FlashRegion1Address, sizeof (LENOVO_VARIABLE_RIGION_HEADER)) == 0 && PrivateData->Region == LENOVO_VARIABLE_USING_REGION_1) {
|
|
return EFI_SUCCESS;
|
|
|
|
} else {
|
|
//if not the same, read from ROM to sync
|
|
PrivateData->Region = LENOVO_VARIABLE_USING_REGION_1;
|
|
CopyMem (PrivateData->VariableBuffer, FlashRegion1Address, L05VariableRegion1Size);
|
|
|
|
//Verify sub region 1 checksum
|
|
{
|
|
UINTN Index;
|
|
UINT8 *BufferPointer;
|
|
UINT16 Checksum;
|
|
|
|
Checksum = 0;
|
|
|
|
BufferPointer = PrivateData->VariableBuffer + sizeof (LENOVO_VARIABLE_RIGION_HEADER);
|
|
|
|
for (Index = 0; Index < L05VariableRegion1Size - sizeof (LENOVO_VARIABLE_RIGION_HEADER); Index++) {
|
|
Checksum += *(BufferPointer + Index);
|
|
}
|
|
|
|
if (Checksum != FlashRegion1Address->Checksum) {
|
|
PrivateData->Region = LENOVO_VARIABLE_USING_REGION_2;
|
|
CopyMem (PrivateData->VariableBuffer, FlashRegion2Address, L05VariableRegion2Size);
|
|
}
|
|
}
|
|
}
|
|
|
|
} else {
|
|
//Use sub region 2
|
|
if (CompareMem (PrivateData->VariableBuffer, FlashRegion2Address, sizeof (LENOVO_VARIABLE_RIGION_HEADER)) == 0 && PrivateData->Region == LENOVO_VARIABLE_USING_REGION_2) {
|
|
return EFI_SUCCESS;
|
|
|
|
} else {
|
|
PrivateData->Region = LENOVO_VARIABLE_USING_REGION_2;
|
|
CopyMem (PrivateData->VariableBuffer, FlashRegion2Address, L05VariableRegion2Size);
|
|
|
|
//Verify sub region 2 checksum
|
|
{
|
|
UINTN Index;
|
|
UINT8 *BufferPointer;
|
|
UINT16 Checksum;
|
|
|
|
Checksum = 0;
|
|
|
|
BufferPointer = PrivateData->VariableBuffer + sizeof (LENOVO_VARIABLE_RIGION_HEADER);
|
|
|
|
for (Index = 0; Index < L05VariableRegion2Size - sizeof (LENOVO_VARIABLE_RIGION_HEADER); Index++) {
|
|
Checksum += *(BufferPointer + Index);
|
|
}
|
|
|
|
if (Checksum != FlashRegion2Address->Checksum) {
|
|
PrivateData->Region = LENOVO_VARIABLE_USING_REGION_1;
|
|
CopyMem (PrivateData->VariableBuffer, FlashRegion1Address, L05VariableRegion1Size);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//Decode
|
|
if (PrivateData->Region != LENOVO_VARIABLE_NO_DATA) {
|
|
UINT8 *BufferPointer;
|
|
UINTN Index;
|
|
|
|
BufferPointer = PrivateData->VariableBuffer + sizeof (LENOVO_VARIABLE_RIGION_HEADER);
|
|
|
|
for (Index = 0; Index < L05VariableRegion1Size - sizeof (LENOVO_VARIABLE_RIGION_HEADER); Index++) {
|
|
*(BufferPointer + Index) = *(BufferPointer + Index) ^ ((LENOVO_VARIABLE_RIGION_HEADER *) PrivateData->VariableBuffer)->RandomNumber;
|
|
}
|
|
}
|
|
|
|
//Update LastByte field
|
|
{
|
|
UINT8 *BufferPointer;
|
|
UINTN Index;
|
|
|
|
BufferPointer = PrivateData->VariableBuffer + sizeof (LENOVO_VARIABLE_RIGION_HEADER);
|
|
|
|
for (Index = 0; Index < ((LENOVO_VARIABLE_RIGION_HEADER *) PrivateData->VariableBuffer)->VariableCount; Index++) {
|
|
BufferPointer = BufferPointer + ((LENOVO_VARIABLE_VARIABLE *) BufferPointer)->VariableDataSize;
|
|
BufferPointer = BufferPointer + sizeof (LENOVO_VARIABLE_VARIABLE) - 1;
|
|
}
|
|
|
|
BufferPointer--;
|
|
PrivateData->LastByte = BufferPointer;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
LenovoVariableInitRegion (
|
|
VOID
|
|
)
|
|
{
|
|
UINT32 WriteFlashAddress;
|
|
UINTN WriteFlashSize;
|
|
UINT8 *BufferAddress;
|
|
EFI_STATUS Status;
|
|
UINT32 L05VariableRegion1Size;
|
|
UINT32 L05VariableRegion2Size;
|
|
|
|
L05VariableRegion1Size = (UINT32) FdmGetNAtSize (&gL05H2OFlashMapRegionVaribale1Guid, 1);
|
|
L05VariableRegion2Size = (UINT32) FdmGetNAtSize (&gL05H2OFlashMapRegionVaribale2Guid, 1);
|
|
|
|
WriteFlashAddress = (UINT32) FdmGetNAtAddr (&gL05H2OFlashMapRegionVaribale1Guid, 1);
|
|
WriteFlashSize = L05VariableRegion1Size + L05VariableRegion2Size;
|
|
|
|
BufferAddress = AllocateZeroPool (WriteFlashSize);
|
|
|
|
SetMem (BufferAddress, WriteFlashSize, 0);
|
|
|
|
*(CHAR8 *) (BufferAddress) = 'L';
|
|
*(CHAR8 *) (BufferAddress + 1) = 'E';
|
|
*(CHAR8 *) (BufferAddress + 2) = 'N';
|
|
*(CHAR8 *) (BufferAddress + 3) = 'V';
|
|
*(CHAR8 *) (BufferAddress + L05VariableRegion1Size) = 'L';
|
|
*(CHAR8 *) (BufferAddress + L05VariableRegion1Size + 1) = 'E';
|
|
*(CHAR8 *) (BufferAddress + L05VariableRegion1Size + 2) = 'N';
|
|
*(CHAR8 *) (BufferAddress + L05VariableRegion1Size + 3) = 'V';
|
|
|
|
Status = mSmmFwb->EraseBlocks (mSmmFwb, WriteFlashAddress, &WriteFlashSize);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
Status = mSmmFwb->Write (
|
|
mSmmFwb,
|
|
WriteFlashAddress,
|
|
&WriteFlashSize,
|
|
(UINT8 *) BufferAddress
|
|
);
|
|
}
|
|
|
|
FreePool (BufferAddress);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
Search VariableGuidName from PrivateData->VariableBuffer
|
|
If found, VariableSizeAddress point to the variable address
|
|
If not found, VariableSizeAddress = NULL
|
|
*/
|
|
VOID
|
|
LenovoVariableSearchVar (
|
|
IN LENOVO_VARIABLE_PRIVATE_DATA *PrivateData,
|
|
IN EFI_GUID *VariableGuidName,
|
|
OUT UINT8 **VariableAddress
|
|
)
|
|
{
|
|
UINT8 *BufferPointer;
|
|
UINTN Index;
|
|
|
|
BufferPointer = PrivateData->VariableBuffer + sizeof (LENOVO_VARIABLE_RIGION_HEADER);
|
|
|
|
for (Index = 0; Index < ((LENOVO_VARIABLE_RIGION_HEADER *) PrivateData->VariableBuffer)->VariableCount; Index++) {
|
|
if (CompareGuid (VariableGuidName, &(((LENOVO_VARIABLE_VARIABLE *) BufferPointer)->VariableGuidName))) {
|
|
*VariableAddress = BufferPointer;
|
|
return;
|
|
|
|
} else {
|
|
BufferPointer = BufferPointer + ((LENOVO_VARIABLE_VARIABLE *) BufferPointer)->VariableDataSize;
|
|
BufferPointer = BufferPointer + sizeof (LENOVO_VARIABLE_VARIABLE) - 1;
|
|
}
|
|
}
|
|
|
|
*VariableAddress = NULL;
|
|
return;
|
|
}
|
|
|
|
EFI_STATUS
|
|
LenovoVariableWriteBufferToFlash (
|
|
IN LENOVO_VARIABLE_PRIVATE_DATA *PrivateData
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN WriteFlashAddress;
|
|
UINTN WriteFlashSize;
|
|
|
|
WriteFlashAddress = 0;
|
|
WriteFlashSize = (UINTN) FdmGetNAtSize (&gL05H2OFlashMapRegionVaribale1Guid, 1);
|
|
|
|
switch (PrivateData->Region) {
|
|
|
|
case LENOVO_VARIABLE_NO_DATA:
|
|
WriteFlashAddress = (UINTN) FdmGetNAtAddr (&gL05H2OFlashMapRegionVaribale1Guid, 1);
|
|
break;
|
|
|
|
case LENOVO_VARIABLE_USING_REGION_1:
|
|
WriteFlashAddress = (UINTN) FdmGetNAtAddr (&gL05H2OFlashMapRegionVaribale2Guid, 1);
|
|
break;
|
|
|
|
case LENOVO_VARIABLE_USING_REGION_2:
|
|
WriteFlashAddress = (UINTN) FdmGetNAtAddr (&gL05H2OFlashMapRegionVaribale1Guid, 1);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
((LENOVO_VARIABLE_RIGION_HEADER *) (PrivateData->VariableBuffer))->PriorityFlag++;
|
|
|
|
//Encode
|
|
{
|
|
UINT8 *BufferPointer;
|
|
UINTN Index;
|
|
|
|
BufferPointer = PrivateData->VariableBuffer + sizeof (LENOVO_VARIABLE_RIGION_HEADER);
|
|
|
|
for (Index = 0; Index < WriteFlashSize - sizeof (LENOVO_VARIABLE_RIGION_HEADER); Index++) {
|
|
*(BufferPointer + Index) = *(BufferPointer + Index) ^ ((LENOVO_VARIABLE_RIGION_HEADER *) PrivateData->VariableBuffer)->RandomNumber;
|
|
}
|
|
}
|
|
|
|
//Update checksum
|
|
{
|
|
UINT8 *BufferPointer;
|
|
UINTN Index;
|
|
UINT16 Checksum;
|
|
|
|
Checksum = 0;
|
|
|
|
BufferPointer = PrivateData->VariableBuffer + sizeof (LENOVO_VARIABLE_RIGION_HEADER);
|
|
|
|
for (Index = 0; Index < (UINTN) FdmGetNAtSize (&gL05H2OFlashMapRegionVaribale1Guid, 1) - sizeof (LENOVO_VARIABLE_RIGION_HEADER); Index++) {
|
|
Checksum += *(BufferPointer + Index);
|
|
}
|
|
|
|
((LENOVO_VARIABLE_RIGION_HEADER *) PrivateData->VariableBuffer)->Checksum = Checksum;
|
|
}
|
|
|
|
//Write buffer to flash
|
|
Status = mSmmFwb->EraseBlocks (mSmmFwb, WriteFlashAddress, &WriteFlashSize);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
Status = mSmmFwb->Write (
|
|
mSmmFwb,
|
|
WriteFlashAddress,
|
|
&WriteFlashSize,
|
|
PrivateData->VariableBuffer
|
|
);
|
|
}
|
|
|
|
//Update region
|
|
if (!EFI_ERROR (Status)) {
|
|
PrivateData->Region = (PrivateData->Region == LENOVO_VARIABLE_USING_REGION_1) ? LENOVO_VARIABLE_USING_REGION_2 : LENOVO_VARIABLE_USING_REGION_1;
|
|
}
|
|
|
|
//Decode
|
|
{
|
|
UINT8 *BufferPointer;
|
|
UINTN Index;
|
|
|
|
BufferPointer = PrivateData->VariableBuffer + sizeof (LENOVO_VARIABLE_RIGION_HEADER);
|
|
|
|
for (Index = 0; Index < WriteFlashSize - sizeof (LENOVO_VARIABLE_RIGION_HEADER); Index++) {
|
|
*(BufferPointer + Index) = *(BufferPointer + Index) ^ ((LENOVO_VARIABLE_RIGION_HEADER *) PrivateData->VariableBuffer)->RandomNumber;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
EFI_STATUS
|
|
LenovoDeleteVariable (
|
|
IN EFI_L05_VARIABLE_PROTOCOL *This,
|
|
IN EFI_GUID *VariableGuidName
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
LENOVO_VARIABLE_PRIVATE_DATA *PrivateData;
|
|
UINT8 *VariableAddress;
|
|
UINT8 *ShiftBegin;
|
|
UINTN ShiftCount;
|
|
UINTN Index;
|
|
|
|
PrivateData = INSTANCE_FROM_LENV_THIS (This);
|
|
|
|
if (VariableGuidName == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
LenovoVariableSyncDataAndBufferWithRom (PrivateData);
|
|
|
|
if (((LENOVO_VARIABLE_RIGION_HEADER *) PrivateData->VariableBuffer)->LockFlag == LENOVO_VARIABLE_REGION_LOCKED) {
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
LenovoVariableSearchVar (PrivateData, VariableGuidName, &VariableAddress);
|
|
|
|
if (VariableAddress == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
if ((((LENOVO_VARIABLE_VARIABLE *) VariableAddress)->VariableAttribute & LENOVO_VARIABLE_ATTRIBUTE_LOCKED) == LENOVO_VARIABLE_ATTRIBUTE_LOCKED) {
|
|
return EFI_WRITE_PROTECTED;
|
|
}
|
|
|
|
ShiftBegin = VariableAddress + ((LENOVO_VARIABLE_VARIABLE *) VariableAddress)->VariableDataSize;
|
|
ShiftBegin = ShiftBegin + sizeof (LENOVO_VARIABLE_VARIABLE) - 1;
|
|
|
|
ShiftCount = 0 + ((LENOVO_VARIABLE_VARIABLE *) VariableAddress)->VariableDataSize;
|
|
ShiftCount = ShiftCount + sizeof (LENOVO_VARIABLE_VARIABLE) - 1;
|
|
|
|
//Begin shift
|
|
while (ShiftBegin <= PrivateData->LastByte) {
|
|
*(ShiftBegin - ShiftCount) = *ShiftBegin;
|
|
ShiftBegin++;
|
|
}
|
|
|
|
for (Index = 0; Index < ShiftCount; Index++) {
|
|
*(ShiftBegin - ShiftCount + Index) = 0;
|
|
}
|
|
|
|
((LENOVO_VARIABLE_RIGION_HEADER *) PrivateData->VariableBuffer)->VariableCount--;
|
|
PrivateData->LastByte -= ShiftCount;
|
|
|
|
Status = LenovoVariableWriteBufferToFlash (PrivateData);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Using runtime service GetVariable(DXE) or SMM variable protocol(SMM) to get variable.
|
|
Variable name always be the same, we only use GUID to distingue variable.
|
|
Simply return get variable function.
|
|
|
|
--*/
|
|
EFI_STATUS
|
|
L05GetVariable (
|
|
IN EFI_L05_VARIABLE_PROTOCOL *This,
|
|
IN EFI_GUID *VariableGuidName,
|
|
IN OUT UINT32 *DataSize,
|
|
OUT VOID *Data
|
|
)
|
|
{
|
|
LENOVO_VARIABLE_PRIVATE_DATA *PrivateData;
|
|
UINT32 VariableSize;
|
|
UINT8 *VariableAddress;
|
|
|
|
PrivateData = INSTANCE_FROM_LENV_THIS (This);
|
|
|
|
if (VariableGuidName == NULL || DataSize == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
LenovoVariableSyncDataAndBufferWithRom (PrivateData);
|
|
|
|
if (PrivateData->Region == LENOVO_VARIABLE_NO_DATA || ((LENOVO_VARIABLE_RIGION_HEADER *) PrivateData->VariableBuffer)->VariableCount == 0) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
LenovoVariableSearchVar (PrivateData, VariableGuidName, &VariableAddress);
|
|
|
|
if (VariableAddress != NULL) {
|
|
VariableSize = ((LENOVO_VARIABLE_VARIABLE *) VariableAddress)->VariableDataSize;
|
|
|
|
if (*DataSize < VariableSize) {
|
|
*DataSize = VariableSize;
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
if (Data == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
*DataSize = VariableSize;
|
|
CopyMem (Data, ((LENOVO_VARIABLE_VARIABLE *) VariableAddress)->VariableData, VariableSize);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Using runtime service SetVariable(DXE) or SMM variable protocol(SMM) to set variable.
|
|
Variable name always be the same, we only use GUID to distingue variable.
|
|
Simply return set variable function.
|
|
|
|
--*/
|
|
EFI_STATUS
|
|
L05SetVariable (
|
|
IN EFI_L05_VARIABLE_PROTOCOL *This,
|
|
IN EFI_GUID *VariableGuidName,
|
|
IN UINT32 DataSize,
|
|
IN VOID *Data
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
LENOVO_VARIABLE_PRIVATE_DATA *PrivateData;
|
|
LENOVO_VARIABLE_RIGION_HEADER *FlashRegion1Address;
|
|
LENOVO_VARIABLE_RIGION_HEADER *FlashRegion2Address;
|
|
UINTN L05VariableRegion1Size;
|
|
UINTN L05VariableRegion2Size;
|
|
|
|
L05VariableRegion1Size = (UINTN) FdmGetNAtSize (&gL05H2OFlashMapRegionVaribale1Guid, 1);
|
|
L05VariableRegion2Size = (UINTN) FdmGetNAtSize (&gL05H2OFlashMapRegionVaribale2Guid, 1);
|
|
|
|
FlashRegion1Address = (LENOVO_VARIABLE_RIGION_HEADER *) (UINTN) FdmGetNAtAddr (&gL05H2OFlashMapRegionVaribale1Guid, 1);
|
|
FlashRegion2Address = (LENOVO_VARIABLE_RIGION_HEADER *) (UINTN) FdmGetNAtAddr (&gL05H2OFlashMapRegionVaribale2Guid, 1);
|
|
|
|
PrivateData = INSTANCE_FROM_LENV_THIS (This);
|
|
|
|
if (VariableGuidName == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
LenovoVariableSyncDataAndBufferWithRom (PrivateData);
|
|
|
|
if (((LENOVO_VARIABLE_RIGION_HEADER *) PrivateData->VariableBuffer)->LockFlag == LENOVO_VARIABLE_REGION_LOCKED) {
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
//If DataSize = 0, then delete variable, sync with EFI variable
|
|
if (DataSize == 0) {
|
|
return LenovoDeleteVariable (This, VariableGuidName);
|
|
}
|
|
|
|
if (Data == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
//If variable exist, need delete it first
|
|
Status = LenovoDeleteVariable (This, VariableGuidName);
|
|
|
|
if (Status != EFI_NOT_FOUND && Status != EFI_SUCCESS) {
|
|
return Status;
|
|
}
|
|
|
|
//Make sure we have enough space
|
|
if (PrivateData->Region == LENOVO_VARIABLE_USING_REGION_2) {
|
|
//Is using region2
|
|
if ((UINTN) (PrivateData->LastByte) + sizeof (LENOVO_VARIABLE_VARIABLE) - 1 + DataSize > \
|
|
(UINTN) FlashRegion2Address + L05VariableRegion2Size - 1) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
} else {
|
|
if ((UINTN) (PrivateData->LastByte) + sizeof (LENOVO_VARIABLE_VARIABLE) - 1 + DataSize > \
|
|
(UINTN) FlashRegion1Address + L05VariableRegion1Size - 1) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
}
|
|
|
|
//Add a variable
|
|
{
|
|
LENOVO_VARIABLE_VARIABLE Variable;
|
|
CopyMem (&(Variable.VariableGuidName), VariableGuidName, sizeof (*VariableGuidName));
|
|
Variable.VariableDataSize = DataSize;
|
|
Variable.VariableAttribute = 0;
|
|
|
|
CopyMem ((PrivateData->LastByte) + 1, &Variable, sizeof (Variable) - 1);
|
|
CopyMem ((PrivateData->LastByte) + 1 + sizeof (Variable) - 1, Data, DataSize);
|
|
PrivateData->LastByte = PrivateData->LastByte + sizeof (Variable) - 1 + DataSize;
|
|
}
|
|
((LENOVO_VARIABLE_RIGION_HEADER *) PrivateData->VariableBuffer)->VariableCount++;
|
|
|
|
Status = LenovoVariableWriteBufferToFlash (PrivateData);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Not implemented.
|
|
|
|
--*/
|
|
EFI_STATUS
|
|
L05LockVariable (
|
|
IN EFI_L05_VARIABLE_PROTOCOL *This,
|
|
IN EFI_GUID *VariableGuidName
|
|
)
|
|
{
|
|
LENOVO_VARIABLE_PRIVATE_DATA *PrivateData;
|
|
UINT8 *VariableAddress;
|
|
|
|
PrivateData = INSTANCE_FROM_LENV_THIS (This);
|
|
|
|
LenovoVariableSyncDataAndBufferWithRom (PrivateData);
|
|
|
|
if (((LENOVO_VARIABLE_RIGION_HEADER *) PrivateData->VariableBuffer)->LockFlag == LENOVO_VARIABLE_REGION_LOCKED) {
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
if (PrivateData->Region == LENOVO_VARIABLE_NO_DATA || ((LENOVO_VARIABLE_RIGION_HEADER *) PrivateData->VariableBuffer)->VariableCount == 0) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
LenovoVariableSearchVar (PrivateData, VariableGuidName, &VariableAddress);
|
|
|
|
if (VariableAddress != NULL) {
|
|
((LENOVO_VARIABLE_VARIABLE *) VariableAddress)->VariableAttribute |= LENOVO_VARIABLE_ATTRIBUTE_LOCKED;
|
|
return LenovoVariableWriteBufferToFlash (PrivateData);
|
|
|
|
} else {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Not implemented.
|
|
|
|
--*/
|
|
EFI_STATUS
|
|
L05UnlockVariable (
|
|
IN EFI_L05_VARIABLE_PROTOCOL *This,
|
|
IN EFI_GUID *VariableGuidName,
|
|
IN CHAR16 *Password
|
|
)
|
|
{
|
|
LENOVO_VARIABLE_PRIVATE_DATA *PrivateData;
|
|
UINT8 *VariableAddress;
|
|
CHAR16 *LenovoVariablePassword = LENOVO_VARIABLE_UNLOCK_PASSWORD;
|
|
|
|
PrivateData = INSTANCE_FROM_LENV_THIS (This);
|
|
|
|
LenovoVariableSyncDataAndBufferWithRom (PrivateData);
|
|
|
|
if (((LENOVO_VARIABLE_RIGION_HEADER *) PrivateData->VariableBuffer)->LockFlag == LENOVO_VARIABLE_REGION_LOCKED) {
|
|
return EFI_ACCESS_DENIED;
|
|
}
|
|
|
|
if (PrivateData->Region == LENOVO_VARIABLE_NO_DATA || ((LENOVO_VARIABLE_RIGION_HEADER *) PrivateData->VariableBuffer)->VariableCount == 0) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
LenovoVariableSearchVar (PrivateData, VariableGuidName, &VariableAddress);
|
|
|
|
if (VariableAddress != NULL) {
|
|
//Verify Password
|
|
if (StrCmp (Password, LenovoVariablePassword) != 0) {
|
|
return EFI_SECURITY_VIOLATION;
|
|
}
|
|
|
|
((LENOVO_VARIABLE_VARIABLE *) VariableAddress)->VariableAttribute &= ~LENOVO_VARIABLE_ATTRIBUTE_LOCKED;
|
|
return LenovoVariableWriteBufferToFlash (PrivateData);
|
|
|
|
} else {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
EFI_STATUS
|
|
L05VariableServiceDxeEntry (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
LENOVO_VARIABLE_PRIVATE_DATA *PrivateData;
|
|
EFI_STATUS Status;
|
|
UINT8 *BufferAddress;
|
|
LENOVO_VARIABLE_RIGION_HEADER *FlashRegion1Address;
|
|
LENOVO_VARIABLE_RIGION_HEADER *FlashRegion2Address;
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
Status = gBS->LocateProtocol (&gEfiSmmFwBlockServiceProtocolGuid, NULL, (VOID **) &mSmmFwb);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
FlashRegion1Address = (LENOVO_VARIABLE_RIGION_HEADER *) (UINTN) FdmGetNAtAddr (&gL05H2OFlashMapRegionVaribale1Guid, 1);
|
|
FlashRegion2Address = (LENOVO_VARIABLE_RIGION_HEADER *) (UINTN) FdmGetNAtAddr (&gL05H2OFlashMapRegionVaribale2Guid, 1);
|
|
|
|
PrivateData = AllocateZeroPool (sizeof (LENOVO_VARIABLE_PRIVATE_DATA));
|
|
|
|
if (PrivateData == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
BufferAddress = AllocateZeroPool ((UINTN) FdmGetNAtSize (&gL05H2OFlashMapRegionVaribale1Guid, 1));
|
|
|
|
PrivateData->Signature = LENV_SIGNATURE;
|
|
PrivateData->VariableBuffer = BufferAddress;
|
|
|
|
|
|
if (AsciiStrnCmp (FlashRegion1Address->Signature, "LENV", 4) || AsciiStrnCmp (FlashRegion2Address->Signature, "LENV", 4)) {
|
|
//In case lvar region is unknow data, init it to 'lenv' + all 00
|
|
if (EFI_ERROR (LenovoVariableInitRegion ())) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
}
|
|
|
|
LenovoVariableSyncDataAndBufferWithRom (PrivateData);
|
|
|
|
|
|
PrivateData->LenovoVariableInstance.GetVariable = L05GetVariable;
|
|
PrivateData->LenovoVariableInstance.SetVariable = L05SetVariable;
|
|
PrivateData->LenovoVariableInstance.LockVariable = L05LockVariable;
|
|
PrivateData->LenovoVariableInstance.UnlockVariable = L05UnlockVariable;
|
|
|
|
Status = gBS->InstallProtocolInterface (
|
|
&ImageHandle,
|
|
&gEfiL05VariableProtocolGuid,
|
|
EFI_NATIVE_INTERFACE,
|
|
&(PrivateData->LenovoVariableInstance)
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
return Status;
|
|
}
|