Add SMM Variable implementation.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11151 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
@ -157,4 +157,90 @@ struct _VARIABLE_INFO_ENTRY {
|
|||||||
BOOLEAN Volatile; ///< TRUE if volatile, FALSE if non-volatile.
|
BOOLEAN Volatile; ///< TRUE if volatile, FALSE if non-volatile.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// This structure is used for SMM variable. the collected statistics data is saved in SMRAM. It can be got from
|
||||||
|
// SMI handler. The communication buffer should be:
|
||||||
|
// EFI_SMM_COMMUNICATE_HEADER + SMM_VARIABLE_COMMUNICATE_HEADER + payload.
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
UINTN Function;
|
||||||
|
EFI_STATUS ReturnStatus;
|
||||||
|
UINT8 Data[1];
|
||||||
|
} SMM_VARIABLE_COMMUNICATE_HEADER;
|
||||||
|
|
||||||
|
//
|
||||||
|
// The payload for this function is SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE.
|
||||||
|
//
|
||||||
|
#define SMM_VARIABLE_FUNCTION_GET_VARIABLE 1
|
||||||
|
//
|
||||||
|
// The payload for this function is SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME.
|
||||||
|
//
|
||||||
|
#define SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME 2
|
||||||
|
//
|
||||||
|
// The payload for this function is SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE.
|
||||||
|
//
|
||||||
|
#define SMM_VARIABLE_FUNCTION_SET_VARIABLE 3
|
||||||
|
//
|
||||||
|
// The payload for this function is SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO.
|
||||||
|
//
|
||||||
|
#define SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO 4
|
||||||
|
//
|
||||||
|
// It is a notify event, no extra payload for this function.
|
||||||
|
//
|
||||||
|
#define SMM_VARIABLE_FUNCTION_READY_TO_BOOT 5
|
||||||
|
//
|
||||||
|
// It is a notify event, no extra payload for this function.
|
||||||
|
//
|
||||||
|
#define SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE 6
|
||||||
|
//
|
||||||
|
// The payload for this function is VARIABLE_INFO_ENTRY. The GUID in EFI_SMM_COMMUNICATE_HEADER
|
||||||
|
// is gEfiSmmVariableProtocolGuid.
|
||||||
|
//
|
||||||
|
#define SMM_VARIABLE_FUNCTION_GET_STATISTICS 7
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Size of SMM communicate header, without including the payload.
|
||||||
|
///
|
||||||
|
#define SMM_COMMUNICATE_HEADER_SIZE (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data))
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Size of SMM variable communicate header, without including the payload.
|
||||||
|
///
|
||||||
|
#define SMM_VARIABLE_COMMUNICATE_HEADER_SIZE (OFFSET_OF (SMM_VARIABLE_COMMUNICATE_HEADER, Data))
|
||||||
|
|
||||||
|
///
|
||||||
|
/// This structure is used to communicate with SMI handler by SetVariable and GetVariable.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
EFI_GUID Guid;
|
||||||
|
UINTN DataSize;
|
||||||
|
UINTN NameSize;
|
||||||
|
UINT32 Attributes;
|
||||||
|
CHAR16 Name[1];
|
||||||
|
} SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// This structure is used to communicate with SMI handler by GetNextVariableName.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
EFI_GUID Guid;
|
||||||
|
UINTN NameSize;
|
||||||
|
CHAR16 Name[1];
|
||||||
|
} SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// This structure is used to communicate with SMI handler by QueryVariableInfo.
|
||||||
|
///
|
||||||
|
typedef struct {
|
||||||
|
UINT64 MaximumVariableStorageSize;
|
||||||
|
UINT64 RemainingVariableStorageSize;
|
||||||
|
UINT64 MaximumVariableSize;
|
||||||
|
UINT32 Attributes;
|
||||||
|
} SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// This structure is used to communicate with SMI handler to get variable statistics information.
|
||||||
|
///
|
||||||
|
typedef VARIABLE_INFO_ENTRY SMM_VARIABLE_COMMUNICATE_VARIABLE_INFO_ENTRY;
|
||||||
|
|
||||||
#endif // _EFI_VARIABLE_H_
|
#endif // _EFI_VARIABLE_H_
|
||||||
|
38
MdeModulePkg/Include/Protocol/SmmFaultTolerantWrite.h
Normal file
38
MdeModulePkg/Include/Protocol/SmmFaultTolerantWrite.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/** @file
|
||||||
|
SMM Fault Tolerant Write protocol is related to EDK II-specific implementation of FTW,
|
||||||
|
provides boot-time service for fault tolerant write capability for block devices in
|
||||||
|
EFI SMM environment. The protocol provides for non-volatile storage of the intermediate
|
||||||
|
data and private information a caller would need to recover from a critical fault,
|
||||||
|
such as a power failure.
|
||||||
|
|
||||||
|
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials are licensed and made available under
|
||||||
|
the terms and conditions of the BSD License that accompanies this distribution.
|
||||||
|
The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php.
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef __SMM_FAULT_TOLERANT_WRITE_H__
|
||||||
|
#define __SMM_FAULT_TOLERANT_WRITE_H__
|
||||||
|
|
||||||
|
#include <Protocol/FaultTolerantWrite.h>
|
||||||
|
|
||||||
|
#define EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL_GUID \
|
||||||
|
{ \
|
||||||
|
0x3868fc3b, 0x7e45, 0x43a7, { 0x90, 0x6c, 0x4b, 0xa4, 0x7d, 0xe1, 0x75, 0x4d } \
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// SMM Fault Tolerant Write protocol structure is the same as Fault Tolerant Write protocol.
|
||||||
|
// The SMM one is intend to run in SMM environment, which means it can be used by
|
||||||
|
// SMM drivers after ExitPmAuth.
|
||||||
|
//
|
||||||
|
typedef EFI_FAULT_TOLERANT_WRITE_PROTOCOL EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL;
|
||||||
|
|
||||||
|
extern EFI_GUID gEfiSmmFaultTolerantWriteProtocolGuid;
|
||||||
|
|
||||||
|
#endif
|
36
MdeModulePkg/Include/Protocol/SmmFirmwareVolumeBlock.h
Normal file
36
MdeModulePkg/Include/Protocol/SmmFirmwareVolumeBlock.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/** @file
|
||||||
|
SMM Firmware Volume Block protocol is related to EDK II-specific implementation of
|
||||||
|
FVB driver, provides control over block-oriented firmware devices and is intended
|
||||||
|
to use in the EFI SMM environment.
|
||||||
|
|
||||||
|
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials are licensed and made available under
|
||||||
|
the terms and conditions of the BSD License that accompanies this distribution.
|
||||||
|
The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php.
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef __SMM_FIRMWARE_VOLUME_BLOCK_H__
|
||||||
|
#define __SMM_FIRMWARE_VOLUME_BLOCK_H__
|
||||||
|
|
||||||
|
#include <Protocol/FirmwareVolumeBlock.h>
|
||||||
|
|
||||||
|
#define EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID \
|
||||||
|
{ \
|
||||||
|
0xf52fc9ff, 0x8025, 0x4432, { 0xa5, 0x3b, 0xb4, 0x7b, 0x5e, 0x9, 0xdb, 0xf9 } \
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// SMM Firmware Volume Block protocol structure is the same as Firmware Volume Block
|
||||||
|
// protocol. The SMM one is intend to run in SMM environment, which means it can be
|
||||||
|
// used by SMM drivers after ExitPmAuth.
|
||||||
|
//
|
||||||
|
typedef EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL;
|
||||||
|
|
||||||
|
extern EFI_GUID gEfiSmmFirmwareVolumeBlockProtocolGuid;
|
||||||
|
|
||||||
|
#endif
|
40
MdeModulePkg/Include/Protocol/SmmSwapAddressRange.h
Normal file
40
MdeModulePkg/Include/Protocol/SmmSwapAddressRange.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/** @file
|
||||||
|
The EFI_SMM_SWAP_ADDRESS_RANGE_PROTOCOL is related to EDK II-specific implementation
|
||||||
|
and used to abstract the swap operation of boot block and backup block of FV in EFI
|
||||||
|
SMM environment. This swap is especially needed when updating the boot block of FV.
|
||||||
|
If a power failure happens during the boot block update, the swapped backup block
|
||||||
|
(now the boot block) can boot the machine with the old boot block backed up in it.
|
||||||
|
The swap operation is platform dependent, so other protocols such as SMM FTW (Fault
|
||||||
|
Tolerant Write) should use this protocol instead of handling hardware directly.
|
||||||
|
|
||||||
|
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials are licensed and made available under
|
||||||
|
the terms and conditions of the BSD License that accompanies this distribution.
|
||||||
|
The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php.
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef __SMM_SWAP_ADDRESS_RANGE_H__
|
||||||
|
#define __SMM_SWAP_ADDRESS_RANGE_H__
|
||||||
|
|
||||||
|
#include <Protocol/SwapAddressRange.h>
|
||||||
|
|
||||||
|
#define EFI_SMM_SWAP_ADDRESS_RANGE_PROTOCOL_GUID \
|
||||||
|
{ \
|
||||||
|
0x67c4f112, 0x3385, 0x4e55, { 0x9c, 0x5b, 0xc0, 0x5b, 0x71, 0x7c, 0x42, 0x28 } \
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// SMM Swap Address Range protocol structure is the same as Swap Address Range protocol.
|
||||||
|
// The SMM one is intend to run in SMM environment, which means it can be used by
|
||||||
|
// SMM drivers after ExitPmAuth.
|
||||||
|
//
|
||||||
|
typedef EFI_SWAP_ADDRESS_RANGE_PROTOCOL EFI_SMM_SWAP_ADDRESS_RANGE_PROTOCOL;
|
||||||
|
|
||||||
|
extern EFI_GUID gEfiSmmSwapAddressRangeProtocolGuid;
|
||||||
|
|
||||||
|
#endif
|
39
MdeModulePkg/Include/Protocol/SmmVariable.h
Normal file
39
MdeModulePkg/Include/Protocol/SmmVariable.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/** @file
|
||||||
|
EFI SMM Variable Protocol is related to EDK II-specific implementation of variables
|
||||||
|
and intended for use as a means to store data in the EFI SMM environment.
|
||||||
|
|
||||||
|
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef __SMM_VARIABLE_H__
|
||||||
|
#define __SMM_VARIABLE_H__
|
||||||
|
|
||||||
|
#define EFI_SMM_VARIABLE_PROTOCOL_GUID \
|
||||||
|
{ \
|
||||||
|
0xed32d533, 0x99e6, 0x4209, { 0x9c, 0xc0, 0x2d, 0x72, 0xcd, 0xd9, 0x98, 0xa7 } \
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct _EFI_SMM_VARIABLE_PROTOCOL EFI_SMM_VARIABLE_PROTOCOL;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// EFI SMM Variable Protocol is intended for use as a means
|
||||||
|
/// to store data in the EFI SMM environment.
|
||||||
|
///
|
||||||
|
struct _EFI_SMM_VARIABLE_PROTOCOL {
|
||||||
|
EFI_GET_VARIABLE SmmGetVariable;
|
||||||
|
EFI_GET_NEXT_VARIABLE_NAME SmmGetNextVariableName;
|
||||||
|
EFI_SET_VARIABLE SmmSetVariable;
|
||||||
|
EFI_QUERY_VARIABLE_INFO SmmQueryVariableInfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern EFI_GUID gEfiSmmVariableProtocolGuid;
|
||||||
|
|
||||||
|
#endif
|
@ -171,9 +171,25 @@
|
|||||||
# Include/Protocol/FaultTolerantWrite.h
|
# Include/Protocol/FaultTolerantWrite.h
|
||||||
gEfiFaultTolerantWriteProtocolGuid = { 0x3EBD9E82, 0x2C78, 0x4DE6, { 0x97, 0x86, 0x8D, 0x4B, 0xFC, 0xB7, 0xC8, 0x81 }}
|
gEfiFaultTolerantWriteProtocolGuid = { 0x3EBD9E82, 0x2C78, 0x4DE6, { 0x97, 0x86, 0x8D, 0x4B, 0xFC, 0xB7, 0xC8, 0x81 }}
|
||||||
|
|
||||||
|
## This protocol provides boot-time service to do fault tolerant write capability for block devices in SMM environment.
|
||||||
|
# Include/Protocol/SmmFaultTolerantWrite.h
|
||||||
|
gEfiSmmFaultTolerantWriteProtocolGuid = { 0x3868fc3b, 0x7e45, 0x43a7, { 0x90, 0x6c, 0x4b, 0xa4, 0x7d, 0xe1, 0x75, 0x4d }}
|
||||||
|
|
||||||
## This protocol is used to abstract the swap operation of boot block and backup block of boot FV.
|
## This protocol is used to abstract the swap operation of boot block and backup block of boot FV.
|
||||||
# Include/Protocol/SwapAddressRange.h
|
# Include/Protocol/SwapAddressRange.h
|
||||||
gEfiSwapAddressRangeProtocolGuid = { 0x1259F60D, 0xB754, 0x468E, { 0xA7, 0x89, 0x4D, 0xB8, 0x5D, 0x55, 0xE8, 0x7E }}
|
gEfiSwapAddressRangeProtocolGuid = { 0x1259F60D, 0xB754, 0x468E, { 0xA7, 0x89, 0x4D, 0xB8, 0x5D, 0x55, 0xE8, 0x7E }}
|
||||||
|
|
||||||
|
## This protocol is used to abstract the swap operation of boot block and backup block of boot FV in SMM environment.
|
||||||
|
# Include/Protocol/SmmSwapAddressRange.h
|
||||||
|
gEfiSmmSwapAddressRangeProtocolGuid = { 0x67c4f112, 0x3385, 0x4e55, { 0x9c, 0x5b, 0xc0, 0x5b, 0x71, 0x7c, 0x42, 0x28 }}
|
||||||
|
|
||||||
|
## This protocol is intended for use as a means to store data in the EFI SMM environment.
|
||||||
|
# Include/Protocol/SmmVariableProtocol.h
|
||||||
|
gEfiSmmVariableProtocolGuid = { 0xed32d533, 0x99e6, 0x4209, { 0x9c, 0xc0, 0x2d, 0x72, 0xcd, 0xd9, 0x98, 0xa7 }}
|
||||||
|
|
||||||
|
## This protocol is similar with DXE FVB protocol and used in the UEFI SMM evvironment.
|
||||||
|
# Include/Protocol/SmmFirmwareVolumeBlock.h
|
||||||
|
gEfiSmmFirmwareVolumeBlockProtocolGuid = { 0xd326d041, 0xbd31, 0x4c01, { 0xb5, 0xa8, 0x62, 0x8b, 0xe8, 0x7f, 0x6, 0x53 }}
|
||||||
|
|
||||||
[PcdsFeatureFlag]
|
[PcdsFeatureFlag]
|
||||||
## Indicate whether platform can support update capsule across a system reset
|
## Indicate whether platform can support update capsule across a system reset
|
||||||
@ -224,6 +240,10 @@
|
|||||||
# interrupt to access usb device in the case of absence of usb stack.
|
# interrupt to access usb device in the case of absence of usb stack.
|
||||||
# DUET platform requires the token to be TRUE.
|
# DUET platform requires the token to be TRUE.
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdTurnOffUsbLegacySupport|FALSE|BOOLEAN|0x00010047
|
gEfiMdeModulePkgTokenSpaceGuid.PcdTurnOffUsbLegacySupport|FALSE|BOOLEAN|0x00010047
|
||||||
|
|
||||||
|
## If TRUE, the variable services are provided in DXE_SMM. The SMM driver can use SMM variable protocol
|
||||||
|
# to access variable. Otherwise the variable services are provided in DXE_RUNTIME.
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdSmmVariableEnable|TRUE|BOOLEAN|0x00010048
|
||||||
|
|
||||||
## If TRUE, HiiImageProtocol will be installed.
|
## If TRUE, HiiImageProtocol will be installed.
|
||||||
# FALSE is for size reduction.
|
# FALSE is for size reduction.
|
||||||
|
@ -257,6 +257,7 @@
|
|||||||
MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
|
MdeModulePkg/Universal/Variable/Pei/VariablePei.inf
|
||||||
MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
|
MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
|
||||||
MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
|
MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
|
||||||
|
MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
|
||||||
|
|
||||||
MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf
|
MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf
|
||||||
MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
|
MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
|
||||||
@ -278,6 +279,8 @@
|
|||||||
[Components.IA32, Components.X64]
|
[Components.IA32, Components.X64]
|
||||||
MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
|
MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
|
||||||
MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
|
MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
|
||||||
|
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
|
||||||
|
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
|
||||||
MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf
|
MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf
|
||||||
MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.inf
|
MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.inf
|
||||||
MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.inf
|
MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.inf
|
||||||
|
@ -1,44 +1,7 @@
|
|||||||
/** @file
|
/** @file
|
||||||
|
|
||||||
This is a simple fault tolerant write driver.
|
These are the common Fault Tolerant Write (FTW) functions that are shared
|
||||||
|
by DXE FTW driver and SMM FTW driver.
|
||||||
This boot service protocol only provides fault tolerant write capability for
|
|
||||||
block devices. The protocol has internal non-volatile intermediate storage
|
|
||||||
of the data and private information. It should be able to recover
|
|
||||||
automatically from a critical fault, such as power failure.
|
|
||||||
|
|
||||||
The implementation uses an FTW (Fault Tolerant Write) Work Space.
|
|
||||||
This work space is a memory copy of the work space on the Working Block,
|
|
||||||
the size of the work space is the FTW_WORK_SPACE_SIZE bytes.
|
|
||||||
|
|
||||||
The work space stores each write record as EFI_FTW_RECORD structure.
|
|
||||||
The spare block stores the write buffer before write to the target block.
|
|
||||||
|
|
||||||
The write record has three states to specify the different phase of write operation.
|
|
||||||
1) WRITE_ALLOCATED is that the record is allocated in write space.
|
|
||||||
The information of write operation is stored in write record structure.
|
|
||||||
2) SPARE_COMPLETED is that the data from write buffer is writed into the spare block as the backup.
|
|
||||||
3) WRITE_COMPLETED is that the data is copied from the spare block to the target block.
|
|
||||||
|
|
||||||
This driver operates the data as the whole size of spare block.
|
|
||||||
It first read the SpareAreaLength data from the target block into the spare memory buffer.
|
|
||||||
Then copy the write buffer data into the spare memory buffer.
|
|
||||||
Then write the spare memory buffer into the spare block.
|
|
||||||
Final copy the data from the spare block to the target block.
|
|
||||||
|
|
||||||
To make this drive work well, the following conditions must be satisfied:
|
|
||||||
1. The write NumBytes data must be fit within Spare area.
|
|
||||||
Offset + NumBytes <= SpareAreaLength
|
|
||||||
2. The whole flash range has the same block size.
|
|
||||||
3. Working block is an area which contains working space in its last block and has the same size as spare block.
|
|
||||||
4. Working Block area must be in the single one Firmware Volume Block range which FVB protocol is produced on.
|
|
||||||
5. Spare area must be in the single one Firmware Volume Block range which FVB protocol is produced on.
|
|
||||||
6. Any write data area (SpareAreaLength Area) which the data will be written into must be
|
|
||||||
in the single one Firmware Volume Block range which FVB protocol is produced on.
|
|
||||||
7. If write data area (such as Variable range) is enlarged, the spare area range must be enlarged.
|
|
||||||
The spare area must be enough large to store the write data before write them into the target range.
|
|
||||||
If one of them is not satisfied, FtwWrite may fail.
|
|
||||||
Usually, Spare area only takes one block. That's SpareAreaLength = BlockSize, NumberOfSpareBlock = 1.
|
|
||||||
|
|
||||||
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
@ -53,8 +16,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
|
|
||||||
#include "FaultTolerantWrite.h"
|
#include "FaultTolerantWrite.h"
|
||||||
|
|
||||||
EFI_EVENT mFvbRegistration = NULL;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Fault Tolerant Write Protocol API
|
// Fault Tolerant Write Protocol API
|
||||||
//
|
//
|
||||||
@ -237,7 +198,7 @@ FtwWriteRecord (
|
|||||||
|
|
||||||
//
|
//
|
||||||
// Spare Complete but Destination not complete,
|
// Spare Complete but Destination not complete,
|
||||||
// Recover the targt block with the spare block.
|
// Recover the target block with the spare block.
|
||||||
//
|
//
|
||||||
Header = FtwDevice->FtwLastWriteHeader;
|
Header = FtwDevice->FtwLastWriteHeader;
|
||||||
Record = FtwDevice->FtwLastWriteRecord;
|
Record = FtwDevice->FtwLastWriteRecord;
|
||||||
@ -864,390 +825,3 @@ FtwGetLastWrite (
|
|||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Firmware Volume Block Protocol notification event handler.
|
|
||||||
|
|
||||||
Initialization for Fault Tolerant Write is done in this handler.
|
|
||||||
|
|
||||||
@param[in] Event Event whose notification function is being invoked.
|
|
||||||
@param[in] Context Pointer to the notification function's context.
|
|
||||||
**/
|
|
||||||
VOID
|
|
||||||
EFIAPI
|
|
||||||
FvbNotificationEvent (
|
|
||||||
IN EFI_EVENT Event,
|
|
||||||
IN VOID *Context
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_STATUS Status;
|
|
||||||
EFI_HANDLE *HandleBuffer;
|
|
||||||
UINTN HandleCount;
|
|
||||||
UINTN Index;
|
|
||||||
EFI_PHYSICAL_ADDRESS FvbBaseAddress;
|
|
||||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
|
|
||||||
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
|
|
||||||
EFI_FVB_ATTRIBUTES_2 Attributes;
|
|
||||||
EFI_FTW_DEVICE *FtwDevice;
|
|
||||||
EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry;
|
|
||||||
UINT32 LbaIndex;
|
|
||||||
UINTN Length;
|
|
||||||
EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader;
|
|
||||||
UINTN Offset;
|
|
||||||
EFI_HANDLE FvbHandle;
|
|
||||||
|
|
||||||
FtwDevice = (EFI_FTW_DEVICE *)Context;
|
|
||||||
FvbHandle = NULL;
|
|
||||||
Fvb = NULL;
|
|
||||||
|
|
||||||
FtwDevice->WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageFtwWorkingBase64);
|
|
||||||
if (FtwDevice->WorkSpaceAddress == 0) {
|
|
||||||
FtwDevice->WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwWorkingBase);
|
|
||||||
}
|
|
||||||
|
|
||||||
FtwDevice->SpareAreaAddress = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageFtwSpareBase64);
|
|
||||||
if (FtwDevice->SpareAreaAddress == 0) {
|
|
||||||
FtwDevice->SpareAreaAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwSpareBase);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Locate all handles of Fvb protocol
|
|
||||||
//
|
|
||||||
Status = gBS->LocateHandleBuffer (
|
|
||||||
ByProtocol,
|
|
||||||
&gEfiFirmwareVolumeBlockProtocolGuid,
|
|
||||||
NULL,
|
|
||||||
&HandleCount,
|
|
||||||
&HandleBuffer
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get the FVB to access variable store
|
|
||||||
//
|
|
||||||
for (Index = 0; Index < HandleCount; Index += 1) {
|
|
||||||
Status = gBS->HandleProtocol (
|
|
||||||
HandleBuffer[Index],
|
|
||||||
&gEfiFirmwareVolumeBlockProtocolGuid,
|
|
||||||
(VOID **) &Fvb
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
Status = EFI_NOT_FOUND;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Ensure this FVB protocol supported Write operation.
|
|
||||||
//
|
|
||||||
Status = Fvb->GetAttributes (Fvb, &Attributes);
|
|
||||||
if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// Compare the address and select the right one
|
|
||||||
//
|
|
||||||
Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);
|
|
||||||
if ((FtwDevice->FtwFvBlock == NULL) && (FtwDevice->WorkSpaceAddress >= FvbBaseAddress) &&
|
|
||||||
((FtwDevice->WorkSpaceAddress + FtwDevice->WorkSpaceLength) <= (FvbBaseAddress + FwVolHeader->FvLength))
|
|
||||||
) {
|
|
||||||
FtwDevice->FtwFvBlock = Fvb;
|
|
||||||
//
|
|
||||||
// To get the LBA of work space
|
|
||||||
//
|
|
||||||
if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {
|
|
||||||
//
|
|
||||||
// Now, one FV has one type of BlockLength
|
|
||||||
//
|
|
||||||
FvbMapEntry = &FwVolHeader->BlockMap[0];
|
|
||||||
for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {
|
|
||||||
if ((FtwDevice->WorkSpaceAddress >= (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)))
|
|
||||||
&& (FtwDevice->WorkSpaceAddress < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex))) {
|
|
||||||
FtwDevice->FtwWorkSpaceLba = LbaIndex - 1;
|
|
||||||
//
|
|
||||||
// Get the Work space size and Base(Offset)
|
|
||||||
//
|
|
||||||
FtwDevice->FtwWorkSpaceSize = FtwDevice->WorkSpaceLength;
|
|
||||||
FtwDevice->FtwWorkSpaceBase = (UINTN) (FtwDevice->WorkSpaceAddress - (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((FtwDevice->FtwBackupFvb == NULL) && (FtwDevice->SpareAreaAddress >= FvbBaseAddress) &&
|
|
||||||
((FtwDevice->SpareAreaAddress + FtwDevice->SpareAreaLength) <= (FvbBaseAddress + FwVolHeader->FvLength))
|
|
||||||
) {
|
|
||||||
FtwDevice->FtwBackupFvb = Fvb;
|
|
||||||
//
|
|
||||||
// To get the LBA of spare
|
|
||||||
//
|
|
||||||
if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {
|
|
||||||
//
|
|
||||||
// Now, one FV has one type of BlockLength
|
|
||||||
//
|
|
||||||
FvbMapEntry = &FwVolHeader->BlockMap[0];
|
|
||||||
for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {
|
|
||||||
if ((FtwDevice->SpareAreaAddress >= (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)))
|
|
||||||
&& (FtwDevice->SpareAreaAddress < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex))) {
|
|
||||||
//
|
|
||||||
// Get the NumberOfSpareBlock and BlockSize
|
|
||||||
//
|
|
||||||
FtwDevice->FtwSpareLba = LbaIndex - 1;
|
|
||||||
FtwDevice->BlockSize = FvbMapEntry->Length;
|
|
||||||
FtwDevice->NumberOfSpareBlock = FtwDevice->SpareAreaLength / FtwDevice->BlockSize;
|
|
||||||
//
|
|
||||||
// Check the range of spare area to make sure that it's in FV range
|
|
||||||
//
|
|
||||||
if ((FtwDevice->FtwSpareLba + FtwDevice->NumberOfSpareBlock) > FvbMapEntry->NumBlocks) {
|
|
||||||
DEBUG ((EFI_D_ERROR, "Ftw: Spare area is out of FV range\n"));
|
|
||||||
ASSERT (FALSE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((FtwDevice->FtwBackupFvb == NULL) || (FtwDevice->FtwFvBlock == NULL) ||
|
|
||||||
(FtwDevice->FtwWorkSpaceLba == (EFI_LBA) (-1)) || (FtwDevice->FtwSpareLba == (EFI_LBA) (-1))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG ((EFI_D_INFO, "Ftw: Working and spare FVB is ready\n"));
|
|
||||||
//
|
|
||||||
// Calculate the start LBA of working block. Working block is an area which
|
|
||||||
// contains working space in its last block and has the same size as spare
|
|
||||||
// block, unless there are not enough blocks before the block that contains
|
|
||||||
// working space.
|
|
||||||
//
|
|
||||||
FtwDevice->FtwWorkBlockLba = FtwDevice->FtwWorkSpaceLba - FtwDevice->NumberOfSpareBlock + 1;
|
|
||||||
ASSERT ((INT64) (FtwDevice->FtwWorkBlockLba) >= 0);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE.
|
|
||||||
//
|
|
||||||
FtwDevice->FtwWorkSpace = (UINT8 *) (FtwDevice + 1);
|
|
||||||
FtwDevice->FtwWorkSpaceHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FtwDevice->FtwWorkSpace;
|
|
||||||
|
|
||||||
FtwDevice->FtwLastWriteHeader = NULL;
|
|
||||||
FtwDevice->FtwLastWriteRecord = NULL;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Refresh the working space data from working block
|
|
||||||
//
|
|
||||||
Status = WorkSpaceRefresh (FtwDevice);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
//
|
|
||||||
// If the working block workspace is not valid, try the spare block
|
|
||||||
//
|
|
||||||
if (!IsValidWorkSpace (FtwDevice->FtwWorkSpaceHeader)) {
|
|
||||||
//
|
|
||||||
// Read from spare block
|
|
||||||
//
|
|
||||||
Length = FtwDevice->FtwWorkSpaceSize;
|
|
||||||
Status = FtwDevice->FtwBackupFvb->Read (
|
|
||||||
FtwDevice->FtwBackupFvb,
|
|
||||||
FtwDevice->FtwSpareLba,
|
|
||||||
FtwDevice->FtwWorkSpaceBase,
|
|
||||||
&Length,
|
|
||||||
FtwDevice->FtwWorkSpace
|
|
||||||
);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
|
|
||||||
//
|
|
||||||
// If spare block is valid, then replace working block content.
|
|
||||||
//
|
|
||||||
if (IsValidWorkSpace (FtwDevice->FtwWorkSpaceHeader)) {
|
|
||||||
Status = FlushSpareBlockToWorkingBlock (FtwDevice);
|
|
||||||
DEBUG ((EFI_D_ERROR, "Ftw: Restart working block update in Init() - %r\n", Status));
|
|
||||||
FtwAbort (&FtwDevice->FtwInstance);
|
|
||||||
//
|
|
||||||
// Refresh work space.
|
|
||||||
//
|
|
||||||
Status = WorkSpaceRefresh (FtwDevice);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
} else {
|
|
||||||
DEBUG ((EFI_D_ERROR, "Ftw: Both are invalid, init workspace\n"));
|
|
||||||
//
|
|
||||||
// If both are invalid, then initialize work space.
|
|
||||||
//
|
|
||||||
SetMem (
|
|
||||||
FtwDevice->FtwWorkSpace,
|
|
||||||
FtwDevice->FtwWorkSpaceSize,
|
|
||||||
FTW_ERASED_BYTE
|
|
||||||
);
|
|
||||||
InitWorkSpaceHeader (FtwDevice->FtwWorkSpaceHeader);
|
|
||||||
//
|
|
||||||
// Initialize the work space
|
|
||||||
//
|
|
||||||
Status = FtwReclaimWorkSpace (FtwDevice, FALSE);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// If the FtwDevice->FtwLastWriteRecord is 1st record of write header &&
|
|
||||||
// (! SpareComplete) THEN call Abort().
|
|
||||||
//
|
|
||||||
if ((FtwDevice->FtwLastWriteHeader->HeaderAllocated == FTW_VALID_STATE) &&
|
|
||||||
(FtwDevice->FtwLastWriteRecord->SpareComplete != FTW_VALID_STATE) &&
|
|
||||||
IsFirstRecordOfWrites (FtwDevice->FtwLastWriteHeader, FtwDevice->FtwLastWriteRecord)
|
|
||||||
) {
|
|
||||||
DEBUG ((EFI_D_ERROR, "Ftw: Init.. find first record not SpareCompleted, abort()\n"));
|
|
||||||
FtwAbort (&FtwDevice->FtwInstance);
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// If Header is incompleted and the last record has completed, then
|
|
||||||
// call Abort() to set the Header->Complete FLAG.
|
|
||||||
//
|
|
||||||
if ((FtwDevice->FtwLastWriteHeader->Complete != FTW_VALID_STATE) &&
|
|
||||||
(FtwDevice->FtwLastWriteRecord->DestinationComplete == FTW_VALID_STATE) &&
|
|
||||||
IsLastRecordOfWrites (FtwDevice->FtwLastWriteHeader, FtwDevice->FtwLastWriteRecord)
|
|
||||||
) {
|
|
||||||
DEBUG ((EFI_D_ERROR, "Ftw: Init.. find last record completed but header not, abort()\n"));
|
|
||||||
FtwAbort (&FtwDevice->FtwInstance);
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// To check the workspace buffer following last Write header/records is EMPTY or not.
|
|
||||||
// If it's not EMPTY, FTW also need to call reclaim().
|
|
||||||
//
|
|
||||||
FtwHeader = FtwDevice->FtwLastWriteHeader;
|
|
||||||
Offset = (UINT8 *) FtwHeader - FtwDevice->FtwWorkSpace;
|
|
||||||
if (FtwDevice->FtwWorkSpace[Offset] != FTW_ERASED_BYTE) {
|
|
||||||
Offset += WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsErasedFlashBuffer (FtwDevice->FtwWorkSpace + Offset, FtwDevice->FtwWorkSpaceSize - Offset)) {
|
|
||||||
Status = FtwReclaimWorkSpace (FtwDevice, TRUE);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Restart if it's boot block
|
|
||||||
//
|
|
||||||
if ((FtwDevice->FtwLastWriteHeader->Complete != FTW_VALID_STATE) &&
|
|
||||||
(FtwDevice->FtwLastWriteRecord->SpareComplete == FTW_VALID_STATE)
|
|
||||||
) {
|
|
||||||
if (FtwDevice->FtwLastWriteRecord->BootBlockUpdate == FTW_VALID_STATE) {
|
|
||||||
Status = FlushSpareBlockToBootBlock (FtwDevice);
|
|
||||||
DEBUG ((EFI_D_ERROR, "Ftw: Restart boot block update - %r\n", Status));
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
FtwAbort (&FtwDevice->FtwInstance);
|
|
||||||
} else {
|
|
||||||
//
|
|
||||||
// if (SpareCompleted) THEN Restart to fault tolerant write.
|
|
||||||
//
|
|
||||||
FvbHandle = GetFvbByAddress (FtwDevice->FtwLastWriteRecord->FvBaseAddress, &Fvb);
|
|
||||||
if (FvbHandle != NULL) {
|
|
||||||
Status = FtwRestart (&FtwDevice->FtwInstance, FvbHandle);
|
|
||||||
DEBUG ((EFI_D_ERROR, "FtwLite: Restart last write - %r\n", Status));
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
}
|
|
||||||
FtwAbort (&FtwDevice->FtwInstance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// Hook the protocol API
|
|
||||||
//
|
|
||||||
FtwDevice->FtwInstance.GetMaxBlockSize = FtwGetMaxBlockSize;
|
|
||||||
FtwDevice->FtwInstance.Allocate = FtwAllocate;
|
|
||||||
FtwDevice->FtwInstance.Write = FtwWrite;
|
|
||||||
FtwDevice->FtwInstance.Restart = FtwRestart;
|
|
||||||
FtwDevice->FtwInstance.Abort = FtwAbort;
|
|
||||||
FtwDevice->FtwInstance.GetLastWrite = FtwGetLastWrite;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Install protocol interface
|
|
||||||
//
|
|
||||||
Status = gBS->InstallProtocolInterface (
|
|
||||||
&FtwDevice->Handle,
|
|
||||||
&gEfiFaultTolerantWriteProtocolGuid,
|
|
||||||
EFI_NATIVE_INTERFACE,
|
|
||||||
&FtwDevice->FtwInstance
|
|
||||||
);
|
|
||||||
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Close the notify event to avoid install FaultTolerantWriteProtocol again.
|
|
||||||
//
|
|
||||||
Status = gBS->CloseEvent (Event);
|
|
||||||
ASSERT_EFI_ERROR (Status);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function is the entry point of the Fault Tolerant Write driver.
|
|
||||||
|
|
||||||
@param ImageHandle A handle for the image that is initializing this driver
|
|
||||||
@param SystemTable A pointer to the EFI system table
|
|
||||||
|
|
||||||
@return EFI_SUCCESS FTW has finished the initialization
|
|
||||||
@retval EFI_NOT_FOUND Locate FVB protocol error
|
|
||||||
@retval EFI_OUT_OF_RESOURCES Allocate memory error
|
|
||||||
@retval EFI_VOLUME_CORRUPTED Firmware volume is error
|
|
||||||
@retval EFI_ABORTED FTW initialization error
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
EFIAPI
|
|
||||||
InitializeFaultTolerantWrite (
|
|
||||||
IN EFI_HANDLE ImageHandle,
|
|
||||||
IN EFI_SYSTEM_TABLE *SystemTable
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_FTW_DEVICE *FtwDevice;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Allocate Private data of this driver,
|
|
||||||
// INCLUDING THE FtwWorkSpace[FTW_WORK_SPACE_SIZE].
|
|
||||||
//
|
|
||||||
FtwDevice = NULL;
|
|
||||||
FtwDevice = AllocateZeroPool (sizeof (EFI_FTW_DEVICE) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize));
|
|
||||||
if (FtwDevice == NULL) {
|
|
||||||
return EFI_OUT_OF_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
ZeroMem (FtwDevice, sizeof (EFI_FTW_DEVICE));
|
|
||||||
FtwDevice->Signature = FTW_DEVICE_SIGNATURE;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE.
|
|
||||||
//
|
|
||||||
|
|
||||||
FtwDevice->WorkSpaceLength = (UINTN) PcdGet32 (PcdFlashNvStorageFtwWorkingSize);
|
|
||||||
|
|
||||||
FtwDevice->SpareAreaLength = (UINTN) PcdGet32 (PcdFlashNvStorageFtwSpareSize);
|
|
||||||
|
|
||||||
if ((FtwDevice->WorkSpaceLength == 0) || (FtwDevice->SpareAreaLength == 0)) {
|
|
||||||
DEBUG ((EFI_D_ERROR, "Ftw: Workspace or Spare block does not exist!\n"));
|
|
||||||
FreePool (FtwDevice);
|
|
||||||
return EFI_OUT_OF_RESOURCES;
|
|
||||||
}
|
|
||||||
FtwDevice->FtwFvBlock = NULL;
|
|
||||||
FtwDevice->FtwBackupFvb = NULL;
|
|
||||||
FtwDevice->FtwWorkSpaceLba = (EFI_LBA) (-1);
|
|
||||||
FtwDevice->FtwSpareLba = (EFI_LBA) (-1);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Register FvbNotificationEvent () notify function.
|
|
||||||
//
|
|
||||||
EfiCreateProtocolNotifyEvent (
|
|
||||||
&gEfiFirmwareVolumeBlockProtocolGuid,
|
|
||||||
TPL_CALLBACK,
|
|
||||||
FvbNotificationEvent,
|
|
||||||
(VOID *)FtwDevice,
|
|
||||||
&mFvbRegistration
|
|
||||||
);
|
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
The internal header file includes the common header files, defines
|
The internal header file includes the common header files, defines
|
||||||
internal structure and functions used by FtwLite module.
|
internal structure and functions used by FtwLite module.
|
||||||
|
|
||||||
Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -670,4 +670,71 @@ GetFvbByAddress (
|
|||||||
OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
|
OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrive the proper Swap Address Range protocol interface.
|
||||||
|
|
||||||
|
@param[out] SarProtocol The interface of SAR protocol
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The SAR protocol instance was found and returned in SarProtocol.
|
||||||
|
@retval EFI_NOT_FOUND The SAR protocol instance was not found.
|
||||||
|
@retval EFI_INVALID_PARAMETER SarProtocol is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FtwGetSarProtocol (
|
||||||
|
OUT VOID **SarProtocol
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Function returns an array of handles that support the FVB protocol
|
||||||
|
in a buffer allocated from pool.
|
||||||
|
|
||||||
|
@param[out] NumberHandles The number of handles returned in Buffer.
|
||||||
|
@param[out] Buffer A pointer to the buffer to return the requested
|
||||||
|
array of handles that support FVB protocol.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of
|
||||||
|
handles in Buffer was returned in NumberHandles.
|
||||||
|
@retval EFI_NOT_FOUND No FVB handle was found.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
|
||||||
|
@retval EFI_INVALID_PARAMETER NumberHandles is NULL or Buffer is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GetFvbCountAndBuffer (
|
||||||
|
OUT UINTN *NumberHandles,
|
||||||
|
OUT EFI_HANDLE **Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Allocate private data for FTW driver and initialize it.
|
||||||
|
|
||||||
|
@param[out] FtwData Pointer to the FTW device structure
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Initialize the FTW device successfully.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Allocate memory error
|
||||||
|
@retval EFI_INVALID_PARAMETER Workspace or Spare block does not exist
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
InitFtwDevice (
|
||||||
|
OUT EFI_FTW_DEVICE **FtwData
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialization for Fault Tolerant Write is done in this handler.
|
||||||
|
|
||||||
|
@param[in,out] FtwData Pointer to the FTW device structure
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Initialize the FTW protocol successfully.
|
||||||
|
@retval EFI_NOT_FOUND No proper FVB protocol was found.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
InitFtwProtocol (
|
||||||
|
IN OUT EFI_FTW_DEVICE *FtwDevice
|
||||||
|
);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -0,0 +1,250 @@
|
|||||||
|
/** @file
|
||||||
|
|
||||||
|
This is a simple fault tolerant write driver.
|
||||||
|
|
||||||
|
This boot service protocol only provides fault tolerant write capability for
|
||||||
|
block devices. The protocol has internal non-volatile intermediate storage
|
||||||
|
of the data and private information. It should be able to recover
|
||||||
|
automatically from a critical fault, such as power failure.
|
||||||
|
|
||||||
|
The implementation uses an FTW (Fault Tolerant Write) Work Space.
|
||||||
|
This work space is a memory copy of the work space on the Working Block,
|
||||||
|
the size of the work space is the FTW_WORK_SPACE_SIZE bytes.
|
||||||
|
|
||||||
|
The work space stores each write record as EFI_FTW_RECORD structure.
|
||||||
|
The spare block stores the write buffer before write to the target block.
|
||||||
|
|
||||||
|
The write record has three states to specify the different phase of write operation.
|
||||||
|
1) WRITE_ALLOCATED is that the record is allocated in write space.
|
||||||
|
The information of write operation is stored in write record structure.
|
||||||
|
2) SPARE_COMPLETED is that the data from write buffer is writed into the spare block as the backup.
|
||||||
|
3) WRITE_COMPLETED is that the data is copied from the spare block to the target block.
|
||||||
|
|
||||||
|
This driver operates the data as the whole size of spare block.
|
||||||
|
It first read the SpareAreaLength data from the target block into the spare memory buffer.
|
||||||
|
Then copy the write buffer data into the spare memory buffer.
|
||||||
|
Then write the spare memory buffer into the spare block.
|
||||||
|
Final copy the data from the spare block to the target block.
|
||||||
|
|
||||||
|
To make this drive work well, the following conditions must be satisfied:
|
||||||
|
1. The write NumBytes data must be fit within Spare area.
|
||||||
|
Offset + NumBytes <= SpareAreaLength
|
||||||
|
2. The whole flash range has the same block size.
|
||||||
|
3. Working block is an area which contains working space in its last block and has the same size as spare block.
|
||||||
|
4. Working Block area must be in the single one Firmware Volume Block range which FVB protocol is produced on.
|
||||||
|
5. Spare area must be in the single one Firmware Volume Block range which FVB protocol is produced on.
|
||||||
|
6. Any write data area (SpareAreaLength Area) which the data will be written into must be
|
||||||
|
in the single one Firmware Volume Block range which FVB protocol is produced on.
|
||||||
|
7. If write data area (such as Variable range) is enlarged, the spare area range must be enlarged.
|
||||||
|
The spare area must be enough large to store the write data before write them into the target range.
|
||||||
|
If one of them is not satisfied, FtwWrite may fail.
|
||||||
|
Usually, Spare area only takes one block. That's SpareAreaLength = BlockSize, NumberOfSpareBlock = 1.
|
||||||
|
|
||||||
|
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "FaultTolerantWrite.h"
|
||||||
|
EFI_EVENT mFvbRegistration = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrive the FVB protocol interface by HANDLE.
|
||||||
|
|
||||||
|
@param[in] FvBlockHandle The handle of FVB protocol that provides services for
|
||||||
|
reading, writing, and erasing the target block.
|
||||||
|
@param[out] FvBlock The interface of FVB protocol
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The interface information for the specified protocol was returned.
|
||||||
|
@retval EFI_UNSUPPORTED The device does not support the FVB protocol.
|
||||||
|
@retval EFI_INVALID_PARAMETER FvBlockHandle is not a valid EFI_HANDLE or FvBlock is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FtwGetFvbByHandle (
|
||||||
|
IN EFI_HANDLE FvBlockHandle,
|
||||||
|
OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// To get the FVB protocol interface on the handle
|
||||||
|
//
|
||||||
|
return gBS->HandleProtocol (
|
||||||
|
FvBlockHandle,
|
||||||
|
&gEfiFirmwareVolumeBlockProtocolGuid,
|
||||||
|
(VOID **) FvBlock
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrive the Swap Address Range protocol interface.
|
||||||
|
|
||||||
|
@param[out] SarProtocol The interface of SAR protocol
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The SAR protocol instance was found and returned in SarProtocol.
|
||||||
|
@retval EFI_NOT_FOUND The SAR protocol instance was not found.
|
||||||
|
@retval EFI_INVALID_PARAMETER SarProtocol is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FtwGetSarProtocol (
|
||||||
|
OUT VOID **SarProtocol
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Locate Swap Address Range protocol
|
||||||
|
//
|
||||||
|
Status = gBS->LocateProtocol (
|
||||||
|
&gEfiSwapAddressRangeProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
SarProtocol
|
||||||
|
);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Function returns an array of handles that support the FVB protocol
|
||||||
|
in a buffer allocated from pool.
|
||||||
|
|
||||||
|
@param[out] NumberHandles The number of handles returned in Buffer.
|
||||||
|
@param[out] Buffer A pointer to the buffer to return the requested
|
||||||
|
array of handles that support FVB protocol.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of
|
||||||
|
handles in Buffer was returned in NumberHandles.
|
||||||
|
@retval EFI_NOT_FOUND No FVB handle was found.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
|
||||||
|
@retval EFI_INVALID_PARAMETER NumberHandles is NULL or Buffer is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GetFvbCountAndBuffer (
|
||||||
|
OUT UINTN *NumberHandles,
|
||||||
|
OUT EFI_HANDLE **Buffer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Locate all handles of Fvb protocol
|
||||||
|
//
|
||||||
|
Status = gBS->LocateHandleBuffer (
|
||||||
|
ByProtocol,
|
||||||
|
&gEfiFirmwareVolumeBlockProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
NumberHandles,
|
||||||
|
Buffer
|
||||||
|
);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Firmware Volume Block Protocol notification event handler.
|
||||||
|
|
||||||
|
@param[in] Event Event whose notification function is being invoked.
|
||||||
|
@param[in] Context Pointer to the notification function's context.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
FvbNotificationEvent (
|
||||||
|
IN EFI_EVENT Event,
|
||||||
|
IN VOID *Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
|
||||||
|
EFI_FTW_DEVICE *FtwDevice;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Just return to avoid install SMM FaultTolerantWriteProtocol again
|
||||||
|
// if Fault Tolerant Write protocol had been installed.
|
||||||
|
//
|
||||||
|
Status = gBS->LocateProtocol (
|
||||||
|
&gEfiFaultTolerantWriteProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
(VOID **) &FtwProtocol
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Found proper FVB protocol and initialize FtwDevice for protocol installation
|
||||||
|
//
|
||||||
|
FtwDevice = (EFI_FTW_DEVICE *)Context;
|
||||||
|
Status = InitFtwProtocol (FtwDevice);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Install protocol interface
|
||||||
|
//
|
||||||
|
Status = gBS->InstallProtocolInterface (
|
||||||
|
&FtwDevice->Handle,
|
||||||
|
&gEfiFaultTolerantWriteProtocolGuid,
|
||||||
|
EFI_NATIVE_INTERFACE,
|
||||||
|
&FtwDevice->FtwInstance
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
Status = gBS->CloseEvent (Event);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function is the entry point of the Fault Tolerant Write driver.
|
||||||
|
|
||||||
|
@param[in] ImageHandle A handle for the image that is initializing this driver
|
||||||
|
@param[in] SystemTable A pointer to the EFI system table
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The initialization finished successfully.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Allocate memory error
|
||||||
|
@retval EFI_INVALID_PARAMETER Workspace or Spare block does not exist
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FaultTolerantWriteInitialize (
|
||||||
|
IN EFI_HANDLE ImageHandle,
|
||||||
|
IN EFI_SYSTEM_TABLE *SystemTable
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_FTW_DEVICE *FtwDevice;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Allocate private data structure for FTW protocol and do some initialization
|
||||||
|
//
|
||||||
|
Status = InitFtwDevice (&FtwDevice);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Register FvbNotificationEvent () notify function.
|
||||||
|
//
|
||||||
|
EfiCreateProtocolNotifyEvent (
|
||||||
|
&gEfiFirmwareVolumeBlockProtocolGuid,
|
||||||
|
TPL_CALLBACK,
|
||||||
|
FvbNotificationEvent,
|
||||||
|
(VOID *)FtwDevice,
|
||||||
|
&mFvbRegistration
|
||||||
|
);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
@ -20,7 +20,7 @@
|
|||||||
FILE_GUID = FE5CEA76-4F72-49e8-986F-2CD899DFFE5D
|
FILE_GUID = FE5CEA76-4F72-49e8-986F-2CD899DFFE5D
|
||||||
MODULE_TYPE = DXE_DRIVER
|
MODULE_TYPE = DXE_DRIVER
|
||||||
VERSION_STRING = 1.0
|
VERSION_STRING = 1.0
|
||||||
ENTRY_POINT = InitializeFaultTolerantWrite
|
ENTRY_POINT = FaultTolerantWriteInitialize
|
||||||
|
|
||||||
#
|
#
|
||||||
# The following information is for reference only and not required by the build tools.
|
# The following information is for reference only and not required by the build tools.
|
||||||
@ -32,6 +32,7 @@
|
|||||||
FtwMisc.c
|
FtwMisc.c
|
||||||
UpdateWorkingBlock.c
|
UpdateWorkingBlock.c
|
||||||
FaultTolerantWrite.c
|
FaultTolerantWrite.c
|
||||||
|
FaultTolerantWriteDxe.c
|
||||||
FaultTolerantWrite.h
|
FaultTolerantWrite.h
|
||||||
|
|
||||||
[Packages]
|
[Packages]
|
||||||
|
@ -0,0 +1,281 @@
|
|||||||
|
/** @file
|
||||||
|
|
||||||
|
This is a simple fault tolerant write driver that is intended to use in the SMM environment.
|
||||||
|
|
||||||
|
This boot service protocol only provides fault tolerant write capability for
|
||||||
|
block devices. The protocol has internal non-volatile intermediate storage
|
||||||
|
of the data and private information. It should be able to recover
|
||||||
|
automatically from a critical fault, such as power failure.
|
||||||
|
|
||||||
|
The implementation uses an FTW (Fault Tolerant Write) Work Space.
|
||||||
|
This work space is a memory copy of the work space on the Working Block,
|
||||||
|
the size of the work space is the FTW_WORK_SPACE_SIZE bytes.
|
||||||
|
|
||||||
|
The work space stores each write record as EFI_FTW_RECORD structure.
|
||||||
|
The spare block stores the write buffer before write to the target block.
|
||||||
|
|
||||||
|
The write record has three states to specify the different phase of write operation.
|
||||||
|
1) WRITE_ALLOCATED is that the record is allocated in write space.
|
||||||
|
The information of write operation is stored in write record structure.
|
||||||
|
2) SPARE_COMPLETED is that the data from write buffer is writed into the spare block as the backup.
|
||||||
|
3) WRITE_COMPLETED is that the data is copied from the spare block to the target block.
|
||||||
|
|
||||||
|
This driver operates the data as the whole size of spare block.
|
||||||
|
It first read the SpareAreaLength data from the target block into the spare memory buffer.
|
||||||
|
Then copy the write buffer data into the spare memory buffer.
|
||||||
|
Then write the spare memory buffer into the spare block.
|
||||||
|
Final copy the data from the spare block to the target block.
|
||||||
|
|
||||||
|
To make this drive work well, the following conditions must be satisfied:
|
||||||
|
1. The write NumBytes data must be fit within Spare area.
|
||||||
|
Offset + NumBytes <= SpareAreaLength
|
||||||
|
2. The whole flash range has the same block size.
|
||||||
|
3. Working block is an area which contains working space in its last block and has the same size as spare block.
|
||||||
|
4. Working Block area must be in the single one Firmware Volume Block range which FVB protocol is produced on.
|
||||||
|
5. Spare area must be in the single one Firmware Volume Block range which FVB protocol is produced on.
|
||||||
|
6. Any write data area (SpareAreaLength Area) which the data will be written into must be
|
||||||
|
in the single one Firmware Volume Block range which FVB protocol is produced on.
|
||||||
|
7. If write data area (such as Variable range) is enlarged, the spare area range must be enlarged.
|
||||||
|
The spare area must be enough large to store the write data before write them into the target range.
|
||||||
|
If one of them is not satisfied, FtwWrite may fail.
|
||||||
|
Usually, Spare area only takes one block. That's SpareAreaLength = BlockSize, NumberOfSpareBlock = 1.
|
||||||
|
|
||||||
|
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <Library/SmmServicesTableLib.h>
|
||||||
|
#include "FaultTolerantWrite.h"
|
||||||
|
#include <Protocol/SmmFirmwareVolumeBlock.h>
|
||||||
|
#include <Protocol/SmmSwapAddressRange.h>
|
||||||
|
#include <Protocol/SmmFaultTolerantWrite.h>
|
||||||
|
|
||||||
|
EFI_EVENT mFvbRegistration = NULL;
|
||||||
|
EFI_FTW_DEVICE *gFtwDevice = NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrive the SMM FVB protocol interface by HANDLE.
|
||||||
|
|
||||||
|
@param[in] FvBlockHandle The handle of SMM FVB protocol that provides services for
|
||||||
|
reading, writing, and erasing the target block.
|
||||||
|
@param[out] FvBlock The interface of SMM FVB protocol
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The interface information for the specified protocol was returned.
|
||||||
|
@retval EFI_UNSUPPORTED The device does not support the SMM FVB protocol.
|
||||||
|
@retval EFI_INVALID_PARAMETER FvBlockHandle is not a valid EFI_HANDLE or FvBlock is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FtwGetFvbByHandle (
|
||||||
|
IN EFI_HANDLE FvBlockHandle,
|
||||||
|
OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// To get the SMM FVB protocol interface on the handle
|
||||||
|
//
|
||||||
|
return gSmst->SmmHandleProtocol (
|
||||||
|
FvBlockHandle,
|
||||||
|
&gEfiSmmFirmwareVolumeBlockProtocolGuid,
|
||||||
|
(VOID **) FvBlock
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrive the SMM Swap Address Range protocol interface.
|
||||||
|
|
||||||
|
@param[out] SarProtocol The interface of SMM SAR protocol
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The SMM SAR protocol instance was found and returned in SarProtocol.
|
||||||
|
@retval EFI_NOT_FOUND The SMM SAR protocol instance was not found.
|
||||||
|
@retval EFI_INVALID_PARAMETER SarProtocol is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FtwGetSarProtocol (
|
||||||
|
OUT VOID **SarProtocol
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Locate Smm Swap Address Range protocol
|
||||||
|
//
|
||||||
|
Status = gSmst->SmmLocateProtocol (
|
||||||
|
&gEfiSmmSwapAddressRangeProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
SarProtocol
|
||||||
|
);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Function returns an array of handles that support the SMM FVB protocol
|
||||||
|
in a buffer allocated from pool.
|
||||||
|
|
||||||
|
@param[out] NumberHandles The number of handles returned in Buffer.
|
||||||
|
@param[out] Buffer A pointer to the buffer to return the requested
|
||||||
|
array of handles that support SMM FVB protocol.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of
|
||||||
|
handles in Buffer was returned in NumberHandles.
|
||||||
|
@retval EFI_NOT_FOUND No SMM FVB handle was found.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
|
||||||
|
@retval EFI_INVALID_PARAMETER NumberHandles is NULL or Buffer is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GetFvbCountAndBuffer (
|
||||||
|
OUT UINTN *NumberHandles,
|
||||||
|
OUT EFI_HANDLE **Buffer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN BufferSize;
|
||||||
|
|
||||||
|
if ((NumberHandles == NULL) || (Buffer == NULL)) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferSize = 0;
|
||||||
|
*NumberHandles = 0;
|
||||||
|
*Buffer = NULL;
|
||||||
|
Status = gSmst->SmmLocateHandle (
|
||||||
|
ByProtocol,
|
||||||
|
&gEfiSmmFirmwareVolumeBlockProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
&BufferSize,
|
||||||
|
*Buffer
|
||||||
|
);
|
||||||
|
if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
*Buffer = AllocatePool (BufferSize);
|
||||||
|
if (*Buffer == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = gSmst->SmmLocateHandle (
|
||||||
|
ByProtocol,
|
||||||
|
&gEfiSmmFirmwareVolumeBlockProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
&BufferSize,
|
||||||
|
*Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
*NumberHandles = BufferSize / sizeof(EFI_HANDLE);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
*NumberHandles = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
SMM Firmware Volume Block Protocol notification event handler.
|
||||||
|
|
||||||
|
@param[in] Protocol Points to the protocol's unique identifier
|
||||||
|
@param[in] Interface Points to the interface instance
|
||||||
|
@param[in] Handle The handle on which the interface was installed
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS SmmEventCallback runs successfully
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
FvbNotificationEvent (
|
||||||
|
IN CONST EFI_GUID *Protocol,
|
||||||
|
IN VOID *Interface,
|
||||||
|
IN EFI_HANDLE Handle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Just return to avoid install SMM FaultTolerantWriteProtocol again
|
||||||
|
// if SMM Fault Tolerant Write protocol had been installed.
|
||||||
|
//
|
||||||
|
Status = gSmst->SmmLocateProtocol (
|
||||||
|
&gEfiSmmFaultTolerantWriteProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
(VOID **) &FtwProtocol
|
||||||
|
);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Found proper FVB protocol and initialize FtwDevice for protocol installation
|
||||||
|
//
|
||||||
|
Status = InitFtwProtocol (gFtwDevice);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Install protocol interface
|
||||||
|
//
|
||||||
|
Status = gSmst->SmmInstallProtocolInterface (
|
||||||
|
&gFtwDevice->Handle,
|
||||||
|
&gEfiSmmFaultTolerantWriteProtocolGuid,
|
||||||
|
EFI_NATIVE_INTERFACE,
|
||||||
|
&gFtwDevice->FtwInstance
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function is the entry point of the Fault Tolerant Write driver.
|
||||||
|
|
||||||
|
@param[in] ImageHandle A handle for the image that is initializing this driver
|
||||||
|
@param[in] SystemTable A pointer to the EFI system table
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The initialization finished successfully.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Allocate memory error
|
||||||
|
@retval EFI_INVALID_PARAMETER Workspace or Spare block does not exist
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmFaultTolerantWriteInitialize (
|
||||||
|
IN EFI_HANDLE ImageHandle,
|
||||||
|
IN EFI_SYSTEM_TABLE *SystemTable
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Allocate private data structure for SMM FTW protocol and do some initialization
|
||||||
|
//
|
||||||
|
Status = InitFtwDevice (&gFtwDevice);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Register FvbNotificationEvent () notify function.
|
||||||
|
//
|
||||||
|
Status = gSmst->SmmRegisterProtocolNotify (
|
||||||
|
&gEfiSmmFirmwareVolumeBlockProtocolGuid,
|
||||||
|
FvbNotificationEvent,
|
||||||
|
&mFvbRegistration
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
FvbNotificationEvent (NULL, NULL, NULL);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
## @file
|
||||||
|
# This driver installs SMM Fault Tolerant Write (FTW) protocol, which provides fault
|
||||||
|
# tolerant write capability in SMM environment for block devices. Its implementation
|
||||||
|
# depends on the full functionality SMM FVB protocol that support read, write/erase
|
||||||
|
# flash access.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
#
|
||||||
|
# This program and the accompanying materials
|
||||||
|
# are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
# which accompanies this distribution. The full text of the license may be found at
|
||||||
|
# http://opensource.org/licenses/bsd-license.php
|
||||||
|
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
#
|
||||||
|
##
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
INF_VERSION = 0x00010005
|
||||||
|
BASE_NAME = SmmFaultTolerantWriteDxe
|
||||||
|
FILE_GUID = 470CB248-E8AC-473c-BB4F-81069A1FE6FD
|
||||||
|
MODULE_TYPE = DXE_SMM_DRIVER
|
||||||
|
VERSION_STRING = 1.0
|
||||||
|
PI_SPECIFICATION_VERSION = 0x0001000A
|
||||||
|
ENTRY_POINT = SmmFaultTolerantWriteInitialize
|
||||||
|
|
||||||
|
#
|
||||||
|
# The following information is for reference only and not required by the build tools.
|
||||||
|
#
|
||||||
|
# VALID_ARCHITECTURES = IA32 X64
|
||||||
|
#
|
||||||
|
|
||||||
|
[Sources]
|
||||||
|
FtwMisc.c
|
||||||
|
UpdateWorkingBlock.c
|
||||||
|
FaultTolerantWrite.c
|
||||||
|
FaultTolerantWriteSmm.c
|
||||||
|
FaultTolerantWrite.h
|
||||||
|
|
||||||
|
[Packages]
|
||||||
|
MdePkg/MdePkg.dec
|
||||||
|
MdeModulePkg/MdeModulePkg.dec
|
||||||
|
|
||||||
|
[LibraryClasses]
|
||||||
|
SmmServicesTableLib
|
||||||
|
MemoryAllocationLib
|
||||||
|
BaseMemoryLib
|
||||||
|
UefiDriverEntryPoint
|
||||||
|
DebugLib
|
||||||
|
UefiLib
|
||||||
|
|
||||||
|
[Guids]
|
||||||
|
gEfiSystemNvDataFvGuid ## CONSUMES ## FV Signature of Working Space Header
|
||||||
|
|
||||||
|
[Protocols]
|
||||||
|
gEfiSmmSwapAddressRangeProtocolGuid | PcdFullFtwServiceEnable ## CONSUMES
|
||||||
|
gEfiSmmFirmwareVolumeBlockProtocolGuid ## CONSUMES
|
||||||
|
gEfiSmmFaultTolerantWriteProtocolGuid ## PRODUCES
|
||||||
|
|
||||||
|
[FeaturePcd]
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdFullFtwServiceEnable
|
||||||
|
|
||||||
|
[Pcd]
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
|
||||||
|
|
||||||
|
[Depex]
|
||||||
|
gEfiSmmFirmwareVolumeBlockProtocolGuid
|
||||||
|
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Internal generic functions to operate flash block.
|
Internal generic functions to operate flash block.
|
||||||
|
|
||||||
Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -104,34 +104,6 @@ FtwEraseSpareBlock (
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Retrive the proper FVB protocol interface by HANDLE.
|
|
||||||
|
|
||||||
|
|
||||||
@param FvBlockHandle The handle of FVB protocol that provides services for
|
|
||||||
reading, writing, and erasing the target block.
|
|
||||||
@param FvBlock The interface of FVB protocol
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS The function completed successfully
|
|
||||||
@retval EFI_ABORTED The function could not complete successfully
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
FtwGetFvbByHandle (
|
|
||||||
IN EFI_HANDLE FvBlockHandle,
|
|
||||||
OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
|
|
||||||
)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// To get the FVB protocol interface on the handle
|
|
||||||
//
|
|
||||||
return gBS->HandleProtocol (
|
|
||||||
FvBlockHandle,
|
|
||||||
&gEfiFirmwareVolumeBlockProtocolGuid,
|
|
||||||
(VOID **) FvBlock
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
Is it in working block?
|
Is it in working block?
|
||||||
@ -195,13 +167,7 @@ GetFvbByAddress (
|
|||||||
//
|
//
|
||||||
// Locate all handles of Fvb protocol
|
// Locate all handles of Fvb protocol
|
||||||
//
|
//
|
||||||
Status = gBS->LocateHandleBuffer (
|
Status = GetFvbCountAndBuffer (&HandleCount, &HandleBuffer);
|
||||||
ByProtocol,
|
|
||||||
&gEfiFirmwareVolumeBlockProtocolGuid,
|
|
||||||
NULL,
|
|
||||||
&HandleCount,
|
|
||||||
&HandleBuffer
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -209,11 +175,7 @@ GetFvbByAddress (
|
|||||||
// Get the FVB to access variable store
|
// Get the FVB to access variable store
|
||||||
//
|
//
|
||||||
for (Index = 0; Index < HandleCount; Index += 1) {
|
for (Index = 0; Index < HandleCount; Index += 1) {
|
||||||
Status = gBS->HandleProtocol (
|
Status = FtwGetFvbByHandle (HandleBuffer[Index], &Fvb);
|
||||||
HandleBuffer[Index],
|
|
||||||
&gEfiFirmwareVolumeBlockProtocolGuid,
|
|
||||||
(VOID **) &Fvb
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -269,7 +231,7 @@ IsBootBlock (
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = gBS->LocateProtocol (&gEfiSwapAddressRangeProtocolGuid, NULL, (VOID **) &SarProtocol);
|
Status = FtwGetSarProtocol ((VOID **) &SarProtocol);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -358,7 +320,7 @@ FlushSpareBlockToBootBlock (
|
|||||||
//
|
//
|
||||||
// Locate swap address range protocol
|
// Locate swap address range protocol
|
||||||
//
|
//
|
||||||
Status = gBS->LocateProtocol (&gEfiSwapAddressRangeProtocolGuid, NULL, (VOID **) &SarProtocol);
|
Status = FtwGetSarProtocol ((VOID **) &SarProtocol);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
@ -969,3 +931,371 @@ GetPreviousRecordOfWrites (
|
|||||||
*FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) Ptr;
|
*FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) Ptr;
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Allocate private data for FTW driver and initialize it.
|
||||||
|
|
||||||
|
@param[out] FtwData Pointer to the FTW device structure
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Initialize the FTW device successfully.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Allocate memory error
|
||||||
|
@retval EFI_INVALID_PARAMETER Workspace or Spare block does not exist
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
InitFtwDevice (
|
||||||
|
OUT EFI_FTW_DEVICE **FtwData
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_FTW_DEVICE *FtwDevice;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Allocate private data of this driver,
|
||||||
|
// Including the FtwWorkSpace[FTW_WORK_SPACE_SIZE].
|
||||||
|
//
|
||||||
|
FtwDevice = AllocateZeroPool (sizeof (EFI_FTW_DEVICE) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize));
|
||||||
|
if (FtwDevice == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE.
|
||||||
|
//
|
||||||
|
FtwDevice->WorkSpaceLength = (UINTN) PcdGet32 (PcdFlashNvStorageFtwWorkingSize);
|
||||||
|
FtwDevice->SpareAreaLength = (UINTN) PcdGet32 (PcdFlashNvStorageFtwSpareSize);
|
||||||
|
if ((FtwDevice->WorkSpaceLength == 0) || (FtwDevice->SpareAreaLength == 0)) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "Ftw: Workspace or Spare block does not exist!\n"));
|
||||||
|
FreePool (FtwDevice);
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
FtwDevice->Signature = FTW_DEVICE_SIGNATURE;
|
||||||
|
FtwDevice->FtwFvBlock = NULL;
|
||||||
|
FtwDevice->FtwBackupFvb = NULL;
|
||||||
|
FtwDevice->FtwWorkSpaceLba = (EFI_LBA) (-1);
|
||||||
|
FtwDevice->FtwSpareLba = (EFI_LBA) (-1);
|
||||||
|
|
||||||
|
FtwDevice->WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageFtwWorkingBase64);
|
||||||
|
if (FtwDevice->WorkSpaceAddress == 0) {
|
||||||
|
FtwDevice->WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwWorkingBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
FtwDevice->SpareAreaAddress = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageFtwSpareBase64);
|
||||||
|
if (FtwDevice->SpareAreaAddress == 0) {
|
||||||
|
FtwDevice->SpareAreaAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwSpareBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
*FtwData = FtwDevice;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialization for Fault Tolerant Write is done in this handler.
|
||||||
|
|
||||||
|
@param[in,out] FtwData Pointer to the FTW device structure
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Initialize the FTW device successfully.
|
||||||
|
@retval EFI_NOT_FOUND No proper FVB protocol was found.
|
||||||
|
@retval EFI_ABORTED Some data can not be got or be invalid.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
FindFvbForFtw (
|
||||||
|
IN OUT EFI_FTW_DEVICE *FtwDevice
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_HANDLE *HandleBuffer;
|
||||||
|
UINTN HandleCount;
|
||||||
|
UINTN Index;
|
||||||
|
EFI_PHYSICAL_ADDRESS FvbBaseAddress;
|
||||||
|
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
|
||||||
|
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
|
||||||
|
EFI_FVB_ATTRIBUTES_2 Attributes;
|
||||||
|
EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry;
|
||||||
|
UINT32 LbaIndex;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get all FVB handle.
|
||||||
|
//
|
||||||
|
Status = GetFvbCountAndBuffer (&HandleCount, &HandleBuffer);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the FVB to access variable store
|
||||||
|
//
|
||||||
|
Fvb = NULL;
|
||||||
|
for (Index = 0; Index < HandleCount; Index += 1) {
|
||||||
|
Status = FtwGetFvbByHandle (HandleBuffer[Index], &Fvb);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
Status = EFI_NOT_FOUND;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Ensure this FVB protocol support Write operation.
|
||||||
|
//
|
||||||
|
Status = Fvb->GetAttributes (Fvb, &Attributes);
|
||||||
|
if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Compare the address and select the right one
|
||||||
|
//
|
||||||
|
Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);
|
||||||
|
if ((FtwDevice->FtwFvBlock == NULL) && (FtwDevice->WorkSpaceAddress >= FvbBaseAddress) &&
|
||||||
|
((FtwDevice->WorkSpaceAddress + FtwDevice->WorkSpaceLength) <= (FvbBaseAddress + FwVolHeader->FvLength))
|
||||||
|
) {
|
||||||
|
FtwDevice->FtwFvBlock = Fvb;
|
||||||
|
//
|
||||||
|
// To get the LBA of work space
|
||||||
|
//
|
||||||
|
if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {
|
||||||
|
//
|
||||||
|
// Now, one FV has one type of BlockLength
|
||||||
|
//
|
||||||
|
FvbMapEntry = &FwVolHeader->BlockMap[0];
|
||||||
|
for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {
|
||||||
|
if ((FtwDevice->WorkSpaceAddress >= (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)))
|
||||||
|
&& (FtwDevice->WorkSpaceAddress < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex))) {
|
||||||
|
FtwDevice->FtwWorkSpaceLba = LbaIndex - 1;
|
||||||
|
//
|
||||||
|
// Get the Work space size and Base(Offset)
|
||||||
|
//
|
||||||
|
FtwDevice->FtwWorkSpaceSize = FtwDevice->WorkSpaceLength;
|
||||||
|
FtwDevice->FtwWorkSpaceBase = (UINTN) (FtwDevice->WorkSpaceAddress - (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((FtwDevice->FtwBackupFvb == NULL) && (FtwDevice->SpareAreaAddress >= FvbBaseAddress) &&
|
||||||
|
((FtwDevice->SpareAreaAddress + FtwDevice->SpareAreaLength) <= (FvbBaseAddress + FwVolHeader->FvLength))
|
||||||
|
) {
|
||||||
|
FtwDevice->FtwBackupFvb = Fvb;
|
||||||
|
//
|
||||||
|
// To get the LBA of spare
|
||||||
|
//
|
||||||
|
if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {
|
||||||
|
//
|
||||||
|
// Now, one FV has one type of BlockLength
|
||||||
|
//
|
||||||
|
FvbMapEntry = &FwVolHeader->BlockMap[0];
|
||||||
|
for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {
|
||||||
|
if ((FtwDevice->SpareAreaAddress >= (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)))
|
||||||
|
&& (FtwDevice->SpareAreaAddress < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex))) {
|
||||||
|
//
|
||||||
|
// Get the NumberOfSpareBlock and BlockSize
|
||||||
|
//
|
||||||
|
FtwDevice->FtwSpareLba = LbaIndex - 1;
|
||||||
|
FtwDevice->BlockSize = FvbMapEntry->Length;
|
||||||
|
FtwDevice->NumberOfSpareBlock = FtwDevice->SpareAreaLength / FtwDevice->BlockSize;
|
||||||
|
//
|
||||||
|
// Check the range of spare area to make sure that it's in FV range
|
||||||
|
//
|
||||||
|
if ((FtwDevice->FtwSpareLba + FtwDevice->NumberOfSpareBlock) > FvbMapEntry->NumBlocks) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "Ftw: Spare area is out of FV range\n"));
|
||||||
|
FreePool (HandleBuffer);
|
||||||
|
ASSERT (FALSE);
|
||||||
|
return EFI_ABORTED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreePool (HandleBuffer);
|
||||||
|
|
||||||
|
if ((FtwDevice->FtwBackupFvb == NULL) || (FtwDevice->FtwFvBlock == NULL) ||
|
||||||
|
(FtwDevice->FtwWorkSpaceLba == (EFI_LBA) (-1)) || (FtwDevice->FtwSpareLba == (EFI_LBA) (-1))) {
|
||||||
|
return EFI_ABORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialization for Fault Tolerant Write protocol.
|
||||||
|
|
||||||
|
@param[in,out] FtwData Pointer to the FTW device structure
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Initialize the FTW protocol successfully.
|
||||||
|
@retval EFI_NOT_FOUND No proper FVB protocol was found.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
InitFtwProtocol (
|
||||||
|
IN OUT EFI_FTW_DEVICE *FtwDevice
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
|
||||||
|
UINTN Length;
|
||||||
|
EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader;
|
||||||
|
UINTN Offset;
|
||||||
|
EFI_HANDLE FvbHandle;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Find the right SMM Fvb protocol instance for FTW.
|
||||||
|
//
|
||||||
|
Status = FindFvbForFtw (FtwDevice);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Calculate the start LBA of working block. Working block is an area which
|
||||||
|
// contains working space in its last block and has the same size as spare
|
||||||
|
// block, unless there are not enough blocks before the block that contains
|
||||||
|
// working space.
|
||||||
|
//
|
||||||
|
FtwDevice->FtwWorkBlockLba = FtwDevice->FtwWorkSpaceLba - FtwDevice->NumberOfSpareBlock + 1;
|
||||||
|
ASSERT ((INT64) (FtwDevice->FtwWorkBlockLba) >= 0);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE.
|
||||||
|
//
|
||||||
|
FtwDevice->FtwWorkSpace = (UINT8 *) (FtwDevice + 1);
|
||||||
|
FtwDevice->FtwWorkSpaceHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FtwDevice->FtwWorkSpace;
|
||||||
|
|
||||||
|
FtwDevice->FtwLastWriteHeader = NULL;
|
||||||
|
FtwDevice->FtwLastWriteRecord = NULL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Refresh the working space data from working block
|
||||||
|
//
|
||||||
|
Status = WorkSpaceRefresh (FtwDevice);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
//
|
||||||
|
// If the working block workspace is not valid, try the spare block
|
||||||
|
//
|
||||||
|
if (!IsValidWorkSpace (FtwDevice->FtwWorkSpaceHeader)) {
|
||||||
|
//
|
||||||
|
// Read from spare block
|
||||||
|
//
|
||||||
|
Length = FtwDevice->FtwWorkSpaceSize;
|
||||||
|
Status = FtwDevice->FtwBackupFvb->Read (
|
||||||
|
FtwDevice->FtwBackupFvb,
|
||||||
|
FtwDevice->FtwSpareLba,
|
||||||
|
FtwDevice->FtwWorkSpaceBase,
|
||||||
|
&Length,
|
||||||
|
FtwDevice->FtwWorkSpace
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
//
|
||||||
|
// If spare block is valid, then replace working block content.
|
||||||
|
//
|
||||||
|
if (IsValidWorkSpace (FtwDevice->FtwWorkSpaceHeader)) {
|
||||||
|
Status = FlushSpareBlockToWorkingBlock (FtwDevice);
|
||||||
|
DEBUG ((EFI_D_ERROR, "Ftw: Restart working block update in InitFtwProtocol() - %r\n", Status));
|
||||||
|
FtwAbort (&FtwDevice->FtwInstance);
|
||||||
|
//
|
||||||
|
// Refresh work space.
|
||||||
|
//
|
||||||
|
Status = WorkSpaceRefresh (FtwDevice);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
} else {
|
||||||
|
DEBUG ((EFI_D_ERROR, "Ftw: Both are invalid, init workspace\n"));
|
||||||
|
//
|
||||||
|
// If both are invalid, then initialize work space.
|
||||||
|
//
|
||||||
|
SetMem (
|
||||||
|
FtwDevice->FtwWorkSpace,
|
||||||
|
FtwDevice->FtwWorkSpaceSize,
|
||||||
|
FTW_ERASED_BYTE
|
||||||
|
);
|
||||||
|
InitWorkSpaceHeader (FtwDevice->FtwWorkSpaceHeader);
|
||||||
|
//
|
||||||
|
// Initialize the work space
|
||||||
|
//
|
||||||
|
Status = FtwReclaimWorkSpace (FtwDevice, FALSE);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// If the FtwDevice->FtwLastWriteRecord is 1st record of write header &&
|
||||||
|
// (! SpareComplete) THEN call Abort().
|
||||||
|
//
|
||||||
|
if ((FtwDevice->FtwLastWriteHeader->HeaderAllocated == FTW_VALID_STATE) &&
|
||||||
|
(FtwDevice->FtwLastWriteRecord->SpareComplete != FTW_VALID_STATE) &&
|
||||||
|
IsFirstRecordOfWrites (FtwDevice->FtwLastWriteHeader, FtwDevice->FtwLastWriteRecord)
|
||||||
|
) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "Ftw: Init.. find first record not SpareCompleted, abort()\n"));
|
||||||
|
FtwAbort (&FtwDevice->FtwInstance);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// If Header is incompleted and the last record has completed, then
|
||||||
|
// call Abort() to set the Header->Complete FLAG.
|
||||||
|
//
|
||||||
|
if ((FtwDevice->FtwLastWriteHeader->Complete != FTW_VALID_STATE) &&
|
||||||
|
(FtwDevice->FtwLastWriteRecord->DestinationComplete == FTW_VALID_STATE) &&
|
||||||
|
IsLastRecordOfWrites (FtwDevice->FtwLastWriteHeader, FtwDevice->FtwLastWriteRecord)
|
||||||
|
) {
|
||||||
|
DEBUG ((EFI_D_ERROR, "Ftw: Init.. find last record completed but header not, abort()\n"));
|
||||||
|
FtwAbort (&FtwDevice->FtwInstance);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// To check the workspace buffer following last Write header/records is EMPTY or not.
|
||||||
|
// If it's not EMPTY, FTW also need to call reclaim().
|
||||||
|
//
|
||||||
|
FtwHeader = FtwDevice->FtwLastWriteHeader;
|
||||||
|
Offset = (UINT8 *) FtwHeader - FtwDevice->FtwWorkSpace;
|
||||||
|
if (FtwDevice->FtwWorkSpace[Offset] != FTW_ERASED_BYTE) {
|
||||||
|
Offset += WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsErasedFlashBuffer (FtwDevice->FtwWorkSpace + Offset, FtwDevice->FtwWorkSpaceSize - Offset)) {
|
||||||
|
Status = FtwReclaimWorkSpace (FtwDevice, TRUE);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Restart if it's boot block
|
||||||
|
//
|
||||||
|
if ((FtwDevice->FtwLastWriteHeader->Complete != FTW_VALID_STATE) &&
|
||||||
|
(FtwDevice->FtwLastWriteRecord->SpareComplete == FTW_VALID_STATE)
|
||||||
|
) {
|
||||||
|
if (FtwDevice->FtwLastWriteRecord->BootBlockUpdate == FTW_VALID_STATE) {
|
||||||
|
Status = FlushSpareBlockToBootBlock (FtwDevice);
|
||||||
|
DEBUG ((EFI_D_ERROR, "Ftw: Restart boot block update - %r\n", Status));
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
FtwAbort (&FtwDevice->FtwInstance);
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// if (SpareCompleted) THEN Restart to fault tolerant write.
|
||||||
|
//
|
||||||
|
FvbHandle = NULL;
|
||||||
|
FvbHandle = GetFvbByAddress (FtwDevice->FtwLastWriteRecord->FvBaseAddress, &Fvb);
|
||||||
|
if (FvbHandle != NULL) {
|
||||||
|
Status = FtwRestart (&FtwDevice->FtwInstance, FvbHandle);
|
||||||
|
DEBUG ((EFI_D_ERROR, "FtwLite: Restart last write - %r\n", Status));
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
}
|
||||||
|
FtwAbort (&FtwDevice->FtwInstance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// Hook the protocol API
|
||||||
|
//
|
||||||
|
FtwDevice->FtwInstance.GetMaxBlockSize = FtwGetMaxBlockSize;
|
||||||
|
FtwDevice->FtwInstance.Allocate = FtwAllocate;
|
||||||
|
FtwDevice->FtwInstance.Write = FtwWrite;
|
||||||
|
FtwDevice->FtwInstance.Restart = FtwRestart;
|
||||||
|
FtwDevice->FtwInstance.Abort = FtwAbort;
|
||||||
|
FtwDevice->FtwInstance.GetLastWrite = FtwGetLastWrite;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
Handles non-volatile variable store garbage collection, using FTW
|
Handles non-volatile variable store garbage collection, using FTW
|
||||||
(Fault Tolerant Write) protocol.
|
(Fault Tolerant Write) protocol.
|
||||||
|
|
||||||
Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
@ -14,105 +14,23 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
|
||||||
#include "Variable.h"
|
#include "Variable.h"
|
||||||
|
|
||||||
/**
|
|
||||||
Gets firmware volume block handle by given address.
|
|
||||||
|
|
||||||
This function gets firmware volume block handle whose
|
|
||||||
address range contains the parameter Address.
|
|
||||||
|
|
||||||
@param Address Address which should be contained
|
|
||||||
by returned FVB handle
|
|
||||||
@param FvbHandle Pointer to FVB handle for output
|
|
||||||
|
|
||||||
@retval EFI_SUCCESS FVB handle successfully returned
|
|
||||||
@retval EFI_NOT_FOUND Fail to find FVB handle by address
|
|
||||||
|
|
||||||
**/
|
|
||||||
EFI_STATUS
|
|
||||||
GetFvbHandleByAddress (
|
|
||||||
IN EFI_PHYSICAL_ADDRESS Address,
|
|
||||||
OUT EFI_HANDLE *FvbHandle
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_STATUS Status;
|
|
||||||
EFI_HANDLE *HandleBuffer;
|
|
||||||
UINTN HandleCount;
|
|
||||||
UINTN Index;
|
|
||||||
EFI_PHYSICAL_ADDRESS FvbBaseAddress;
|
|
||||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
|
|
||||||
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
|
|
||||||
EFI_FVB_ATTRIBUTES_2 Attributes;
|
|
||||||
|
|
||||||
*FvbHandle = NULL;
|
|
||||||
//
|
|
||||||
// Locate all handles of Fvb protocol
|
|
||||||
//
|
|
||||||
Status = gBS->LocateHandleBuffer (
|
|
||||||
ByProtocol,
|
|
||||||
&gEfiFirmwareVolumeBlockProtocolGuid,
|
|
||||||
NULL,
|
|
||||||
&HandleCount,
|
|
||||||
&HandleBuffer
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
return EFI_NOT_FOUND;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// Get the FVB to access variable store
|
|
||||||
//
|
|
||||||
for (Index = 0; Index < HandleCount; Index += 1) {
|
|
||||||
Status = gBS->HandleProtocol (
|
|
||||||
HandleBuffer[Index],
|
|
||||||
&gEfiFirmwareVolumeBlockProtocolGuid,
|
|
||||||
(VOID **) &Fvb
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
Status = EFI_NOT_FOUND;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = Fvb->GetAttributes (Fvb, &Attributes);
|
|
||||||
if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// Compare the address and select the right one
|
|
||||||
//
|
|
||||||
Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);
|
|
||||||
if ((Address >= FvbBaseAddress) && (Address <= (FvbBaseAddress + FwVolHeader->FvLength))) {
|
|
||||||
*FvbHandle = HandleBuffer[Index];
|
|
||||||
Status = EFI_SUCCESS;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FreePool (HandleBuffer);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Gets LBA of block and offset by given address.
|
Gets LBA of block and offset by given address.
|
||||||
|
|
||||||
This function gets the Logical Block Address (LBA) of firmware
|
This function gets the Logical Block Address (LBA) of a firmware
|
||||||
volume block containing the given address, and the offset of
|
volume block containing the given address, and the offset of the
|
||||||
address on the block.
|
address on the block.
|
||||||
|
|
||||||
@param Address Address which should be contained
|
@param Address Address which should be contained
|
||||||
by returned FVB handle
|
by returned FVB handle.
|
||||||
@param Lba Pointer to LBA for output
|
@param Lba Pointer to LBA for output.
|
||||||
@param Offset Pointer to offset for output
|
@param Offset Pointer to offset for output.
|
||||||
|
|
||||||
@retval EFI_SUCCESS LBA and offset successfully returned
|
@retval EFI_SUCCESS LBA and offset successfully returned.
|
||||||
@retval EFI_NOT_FOUND Fail to find FVB handle by address
|
@retval EFI_NOT_FOUND Fail to find FVB handle by address.
|
||||||
@retval EFI_ABORTED Fail to find valid LBA and offset
|
@retval EFI_ABORTED Fail to find valid LBA and offset.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
@ -123,7 +41,6 @@ GetLbaAndOffsetByAddress (
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
EFI_HANDLE FvbHandle;
|
|
||||||
EFI_PHYSICAL_ADDRESS FvbBaseAddress;
|
EFI_PHYSICAL_ADDRESS FvbBaseAddress;
|
||||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
|
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
|
||||||
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
|
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
|
||||||
@ -132,25 +49,17 @@ GetLbaAndOffsetByAddress (
|
|||||||
|
|
||||||
*Lba = (EFI_LBA) (-1);
|
*Lba = (EFI_LBA) (-1);
|
||||||
*Offset = 0;
|
*Offset = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the proper FVB
|
// Get the proper FVB protocol.
|
||||||
//
|
//
|
||||||
Status = GetFvbHandleByAddress (Address, &FvbHandle);
|
Status = GetFvbInfoByAddress (Address, NULL, &Fvb);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = gBS->HandleProtocol (
|
|
||||||
FvbHandle,
|
|
||||||
&gEfiFirmwareVolumeBlockProtocolGuid,
|
|
||||||
(VOID **) &Fvb
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
//
|
//
|
||||||
// Get the Base Address of FV
|
// Get the Base Address of FV.
|
||||||
//
|
//
|
||||||
Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
|
Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
@ -160,24 +69,22 @@ GetLbaAndOffsetByAddress (
|
|||||||
FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);
|
FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the (LBA, Offset) of Address
|
// Get the (LBA, Offset) of Address.
|
||||||
//
|
//
|
||||||
if ((Address >= FvbBaseAddress) && (Address <= (FvbBaseAddress + FwVolHeader->FvLength))) {
|
if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {
|
||||||
if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {
|
//
|
||||||
//
|
// BUGBUG: Assume one FV has one type of BlockLength.
|
||||||
// BUGBUG: Assume one FV has one type of BlockLength
|
//
|
||||||
//
|
FvbMapEntry = &FwVolHeader->BlockMap[0];
|
||||||
FvbMapEntry = &FwVolHeader->BlockMap[0];
|
for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {
|
||||||
for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {
|
if (Address < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex)) {
|
||||||
if (Address < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex)) {
|
//
|
||||||
//
|
// Found the (Lba, Offset).
|
||||||
// Found the (Lba, Offset)
|
//
|
||||||
//
|
*Lba = LbaIndex - 1;
|
||||||
*Lba = LbaIndex - 1;
|
*Offset = (UINTN) (Address - (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)));
|
||||||
*Offset = (UINTN) (Address - (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)));
|
return EFI_SUCCESS;
|
||||||
return EFI_SUCCESS;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,17 +94,17 @@ GetLbaAndOffsetByAddress (
|
|||||||
/**
|
/**
|
||||||
Writes a buffer to variable storage space, in the working block.
|
Writes a buffer to variable storage space, in the working block.
|
||||||
|
|
||||||
This function writes a buffer to variable storage space into firmware
|
This function writes a buffer to variable storage space into a firmware
|
||||||
volume block device. The destination is specified by parameter
|
volume block device. The destination is specified by parameter
|
||||||
VariableBase. Fault Tolerant Write protocol is used for writing.
|
VariableBase. Fault Tolerant Write protocol is used for writing.
|
||||||
|
|
||||||
@param VariableBase Base address of variable to write
|
@param VariableBase Base address of variable to write
|
||||||
@param Buffer Point to the data buffer
|
@param Buffer Point to the data buffer.
|
||||||
@param BufferSize The number of bytes of the data Buffer
|
@param BufferSize The number of bytes of the data Buffer.
|
||||||
|
|
||||||
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_SUCCESS The function completed successfully.
|
||||||
@retval EFI_NOT_FOUND Fail to locate Fault Tolerant Write protocol
|
@retval EFI_NOT_FOUND Fail to locate Fault Tolerant Write protocol.
|
||||||
@retval EFI_ABORTED The function could not complete successfully
|
@retval EFI_ABORTED The function could not complete successfully.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
@ -216,35 +123,31 @@ FtwVariableSpace (
|
|||||||
EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
|
EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Locate fault tolerant write protocol
|
// Locate fault tolerant write protocol.
|
||||||
//
|
//
|
||||||
Status = gBS->LocateProtocol (
|
Status = GetFtwProtocol((VOID **) &FtwProtocol);
|
||||||
&gEfiFaultTolerantWriteProtocolGuid,
|
|
||||||
NULL,
|
|
||||||
(VOID **) &FtwProtocol
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return EFI_NOT_FOUND;
|
return EFI_NOT_FOUND;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// Locate Fvb handle by address
|
// Locate Fvb handle by address.
|
||||||
//
|
//
|
||||||
Status = GetFvbHandleByAddress (VariableBase, &FvbHandle);
|
Status = GetFvbInfoByAddress (VariableBase, &FvbHandle, NULL);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// Get LBA and Offset by address
|
// Get LBA and Offset by address.
|
||||||
//
|
//
|
||||||
Status = GetLbaAndOffsetByAddress (VariableBase, &VarLba, &VarOffset);
|
Status = GetLbaAndOffsetByAddress (VariableBase, &VarLba, &VarOffset);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
return EFI_ABORTED;
|
return EFI_ABORTED;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// Prepare for the variable data
|
// Prepare for the variable data.
|
||||||
//
|
//
|
||||||
FtwBufferSize = ((VARIABLE_STORE_HEADER *) ((UINTN) VariableBase))->Size;
|
FtwBufferSize = ((VARIABLE_STORE_HEADER *) ((UINTN) VariableBase))->Size;
|
||||||
FtwBuffer = AllocateRuntimePool (FtwBufferSize);
|
FtwBuffer = AllocatePool (FtwBufferSize);
|
||||||
if (FtwBuffer == NULL) {
|
if (FtwBuffer == NULL) {
|
||||||
return EFI_OUT_OF_RESOURCES;
|
return EFI_OUT_OF_RESOURCES;
|
||||||
}
|
}
|
||||||
@ -253,17 +156,17 @@ FtwVariableSpace (
|
|||||||
CopyMem (FtwBuffer, Buffer, BufferSize);
|
CopyMem (FtwBuffer, Buffer, BufferSize);
|
||||||
|
|
||||||
//
|
//
|
||||||
// FTW write record
|
// FTW write record.
|
||||||
//
|
//
|
||||||
Status = FtwProtocol->Write (
|
Status = FtwProtocol->Write (
|
||||||
FtwProtocol,
|
FtwProtocol,
|
||||||
VarLba, // LBA
|
VarLba, // LBA
|
||||||
VarOffset, // Offset
|
VarOffset, // Offset
|
||||||
FtwBufferSize, // NumBytes
|
FtwBufferSize, // NumBytes
|
||||||
NULL, // PrivateData NULL
|
NULL, // PrivateData NULL
|
||||||
FvbHandle, // Fvb Handle
|
FvbHandle, // Fvb Handle
|
||||||
FtwBuffer // write buffer
|
FtwBuffer // write buffer
|
||||||
);
|
);
|
||||||
|
|
||||||
FreePool (FtwBuffer);
|
FreePool (FtwBuffer);
|
||||||
return Status;
|
return Status;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
|||||||
/** @file
|
/** @file
|
||||||
|
|
||||||
The internal header file includes the common header files, defines
|
The internal header file includes the common header files, defines
|
||||||
internal structure and functions used by RuntimeVariable module.
|
internal structure and functions used by Variable modules.
|
||||||
|
|
||||||
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
@ -82,17 +82,17 @@ typedef struct {
|
|||||||
/**
|
/**
|
||||||
Writes a buffer to variable storage space, in the working block.
|
Writes a buffer to variable storage space, in the working block.
|
||||||
|
|
||||||
This function writes a buffer to variable storage space into firmware
|
This function writes a buffer to variable storage space into a firmware
|
||||||
volume block device. The destination is specified by parameter
|
volume block device. The destination is specified by the parameter
|
||||||
VariableBase. Fault Tolerant Write protocol is used for writing.
|
VariableBase. Fault Tolerant Write protocol is used for writing.
|
||||||
|
|
||||||
@param VariableBase Base address of variable to write
|
@param VariableBase Base address of the variable to write.
|
||||||
@param Buffer Point to the data buffer
|
@param Buffer Point to the data buffer.
|
||||||
@param BufferSize The number of bytes of the data Buffer
|
@param BufferSize The number of bytes of the data Buffer.
|
||||||
|
|
||||||
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_SUCCESS The function completed successfully.
|
||||||
@retval EFI_NOT_FOUND Fail to locate Fault Tolerant Write protocol
|
@retval EFI_NOT_FOUND Fail to locate Fault Tolerant Write protocol.
|
||||||
@retval EFI_ABORTED The function could not complete successfully
|
@retval EFI_ABORTED The function could not complete successfully.
|
||||||
|
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
@ -103,4 +103,329 @@ FtwVariableSpace (
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Update the variable region with Variable information. These are the same
|
||||||
|
arguments as the EFI Variable services.
|
||||||
|
|
||||||
|
@param[in] VariableName Name of variable.
|
||||||
|
|
||||||
|
@param[in] VendorGuid Guid of variable.
|
||||||
|
|
||||||
|
@param[in] Data Variable data.
|
||||||
|
|
||||||
|
@param[in] DataSize Size of data. 0 means delete.
|
||||||
|
|
||||||
|
@param[in] Attributes Attribues of the variable.
|
||||||
|
|
||||||
|
@param[in] Variable The variable information that is used to keep track of variable usage.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The update operation is success.
|
||||||
|
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Variable region is full, cannot write other data into this region.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
UpdateVariable (
|
||||||
|
IN CHAR16 *VariableName,
|
||||||
|
IN EFI_GUID *VendorGuid,
|
||||||
|
IN VOID *Data,
|
||||||
|
IN UINTN DataSize,
|
||||||
|
IN UINT32 Attributes OPTIONAL,
|
||||||
|
IN VARIABLE_POINTER_TRACK *Variable
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return TRUE if ExitBootServices () has been called.
|
||||||
|
|
||||||
|
@retval TRUE If ExitBootServices () has been called.
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
AtRuntime (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initializes a basic mutual exclusion lock.
|
||||||
|
|
||||||
|
This function initializes a basic mutual exclusion lock to the released state
|
||||||
|
and returns the lock. Each lock provides mutual exclusion access at its task
|
||||||
|
priority level. Since there is no preemption or multiprocessor support in EFI,
|
||||||
|
acquiring the lock only consists of raising to the locks TPL.
|
||||||
|
If Lock is NULL, then ASSERT().
|
||||||
|
If Priority is not a valid TPL value, then ASSERT().
|
||||||
|
|
||||||
|
@param Lock A pointer to the lock data structure to initialize.
|
||||||
|
@param Priority EFI TPL is associated with the lock.
|
||||||
|
|
||||||
|
@return The lock.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_LOCK *
|
||||||
|
InitializeLock (
|
||||||
|
IN OUT EFI_LOCK *Lock,
|
||||||
|
IN EFI_TPL Priority
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Acquires lock only at boot time. Simply returns at runtime.
|
||||||
|
|
||||||
|
This is a temperary function that will be removed when
|
||||||
|
EfiAcquireLock() in UefiLib can handle the call in UEFI
|
||||||
|
Runtimer driver in RT phase.
|
||||||
|
It calls EfiAcquireLock() at boot time, and simply returns
|
||||||
|
at runtime.
|
||||||
|
|
||||||
|
@param Lock A pointer to the lock to acquire.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
AcquireLockOnlyAtBootTime (
|
||||||
|
IN EFI_LOCK *Lock
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Releases lock only at boot time. Simply returns at runtime.
|
||||||
|
|
||||||
|
This is a temperary function which will be removed when
|
||||||
|
EfiReleaseLock() in UefiLib can handle the call in UEFI
|
||||||
|
Runtimer driver in RT phase.
|
||||||
|
It calls EfiReleaseLock() at boot time and simply returns
|
||||||
|
at runtime.
|
||||||
|
|
||||||
|
@param Lock A pointer to the lock to release.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
ReleaseLockOnlyAtBootTime (
|
||||||
|
IN EFI_LOCK *Lock
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrive the FVB protocol interface by HANDLE.
|
||||||
|
|
||||||
|
@param[in] FvBlockHandle The handle of FVB protocol that provides services for
|
||||||
|
reading, writing, and erasing the target block.
|
||||||
|
@param[out] FvBlock The interface of FVB protocol
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The interface information for the specified protocol was returned.
|
||||||
|
@retval EFI_UNSUPPORTED The device does not support the FVB protocol.
|
||||||
|
@retval EFI_INVALID_PARAMETER FvBlockHandle is not a valid EFI_HANDLE or FvBlock is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GetFvbByHandle (
|
||||||
|
IN EFI_HANDLE FvBlockHandle,
|
||||||
|
OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrive the Swap Address Range protocol interface.
|
||||||
|
|
||||||
|
@param[out] SarProtocol The interface of SAR protocol
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The SAR protocol instance was found and returned in SarProtocol.
|
||||||
|
@retval EFI_NOT_FOUND The SAR protocol instance was not found.
|
||||||
|
@retval EFI_INVALID_PARAMETER SarProtocol is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GetSarProtocol (
|
||||||
|
OUT VOID **SarProtocol
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Function returns an array of handles that support the FVB protocol
|
||||||
|
in a buffer allocated from pool.
|
||||||
|
|
||||||
|
@param[out] NumberHandles The number of handles returned in Buffer.
|
||||||
|
@param[out] Buffer A pointer to the buffer to return the requested
|
||||||
|
array of handles that support FVB protocol.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of
|
||||||
|
handles in Buffer was returned in NumberHandles.
|
||||||
|
@retval EFI_NOT_FOUND No FVB handle was found.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
|
||||||
|
@retval EFI_INVALID_PARAMETER NumberHandles is NULL or Buffer is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GetFvbCountAndBuffer (
|
||||||
|
OUT UINTN *NumberHandles,
|
||||||
|
OUT EFI_HANDLE **Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initializes variable store area for non-volatile and volatile variable.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Function successfully executed.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate enough memory resource.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
VariableCommonInitialize (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function reclaims variable storage if free size is below the threshold.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
ReclaimForOS(
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initializes variable write service after FVB was ready.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Function successfully executed.
|
||||||
|
@retval Others Fail to initialize the variable service.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
VariableWriteServiceInitialize (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrive the SMM Fault Tolerent Write protocol interface.
|
||||||
|
|
||||||
|
@param[out] FtwProtocol The interface of SMM Ftw protocol
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The SMM SAR protocol instance was found and returned in SarProtocol.
|
||||||
|
@retval EFI_NOT_FOUND The SMM SAR protocol instance was not found.
|
||||||
|
@retval EFI_INVALID_PARAMETER SarProtocol is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GetFtwProtocol (
|
||||||
|
OUT VOID **FtwProtocol
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the proper fvb handle and/or fvb protocol by the given Flash address.
|
||||||
|
|
||||||
|
@param[in] Address The Flash address.
|
||||||
|
@param[out] FvbHandle In output, if it is not NULL, it points to the proper FVB handle.
|
||||||
|
@param[out] FvbProtocol In output, if it is not NULL, it points to the proper FVB protocol.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GetFvbInfoByAddress (
|
||||||
|
IN EFI_PHYSICAL_ADDRESS Address,
|
||||||
|
OUT EFI_HANDLE *FvbHandle OPTIONAL,
|
||||||
|
OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvbProtocol OPTIONAL
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
This code finds variable in storage blocks (Volatile or Non-Volatile).
|
||||||
|
|
||||||
|
@param VariableName Name of Variable to be found.
|
||||||
|
@param VendorGuid Variable vendor GUID.
|
||||||
|
@param Attributes Attribute value of the variable found.
|
||||||
|
@param DataSize Size of Data found. If size is less than the
|
||||||
|
data, this value contains the required size.
|
||||||
|
@param Data Data pointer.
|
||||||
|
|
||||||
|
@return EFI_INVALID_PARAMETER Invalid parameter.
|
||||||
|
@return EFI_SUCCESS Find the specified variable.
|
||||||
|
@return EFI_NOT_FOUND Not found.
|
||||||
|
@return EFI_BUFFER_TO_SMALL DataSize is too small for the result.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
VariableServiceGetVariable (
|
||||||
|
IN CHAR16 *VariableName,
|
||||||
|
IN EFI_GUID *VendorGuid,
|
||||||
|
OUT UINT32 *Attributes OPTIONAL,
|
||||||
|
IN OUT UINTN *DataSize,
|
||||||
|
OUT VOID *Data
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
This code Finds the Next available variable.
|
||||||
|
|
||||||
|
@param VariableNameSize Size of the variable name.
|
||||||
|
@param VariableName Pointer to variable name.
|
||||||
|
@param VendorGuid Variable Vendor Guid.
|
||||||
|
|
||||||
|
@return EFI_INVALID_PARAMETER Invalid parameter.
|
||||||
|
@return EFI_SUCCESS Find the specified variable.
|
||||||
|
@return EFI_NOT_FOUND Not found.
|
||||||
|
@return EFI_BUFFER_TO_SMALL DataSize is too small for the result.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
VariableServiceGetNextVariableName (
|
||||||
|
IN OUT UINTN *VariableNameSize,
|
||||||
|
IN OUT CHAR16 *VariableName,
|
||||||
|
IN OUT EFI_GUID *VendorGuid
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
This code sets variable in storage blocks (Volatile or Non-Volatile).
|
||||||
|
|
||||||
|
@param VariableName Name of Variable to be found.
|
||||||
|
@param VendorGuid Variable vendor GUID.
|
||||||
|
@param Attributes Attribute value of the variable found
|
||||||
|
@param DataSize Size of Data found. If size is less than the
|
||||||
|
data, this value contains the required size.
|
||||||
|
@param Data Data pointer.
|
||||||
|
|
||||||
|
@return EFI_INVALID_PARAMETER Invalid parameter.
|
||||||
|
@return EFI_SUCCESS Set successfully.
|
||||||
|
@return EFI_OUT_OF_RESOURCES Resource not enough to set variable.
|
||||||
|
@return EFI_NOT_FOUND Not found.
|
||||||
|
@return EFI_WRITE_PROTECTED Variable is read-only.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
VariableServiceSetVariable (
|
||||||
|
IN CHAR16 *VariableName,
|
||||||
|
IN EFI_GUID *VendorGuid,
|
||||||
|
IN UINT32 Attributes,
|
||||||
|
IN UINTN DataSize,
|
||||||
|
IN VOID *Data
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
This code returns information about the EFI variables.
|
||||||
|
|
||||||
|
@param Attributes Attributes bitmask to specify the type of variables
|
||||||
|
on which to return information.
|
||||||
|
@param MaximumVariableStorageSize Pointer to the maximum size of the storage space available
|
||||||
|
for the EFI variables associated with the attributes specified.
|
||||||
|
@param RemainingVariableStorageSize Pointer to the remaining size of the storage space available
|
||||||
|
for EFI variables associated with the attributes specified.
|
||||||
|
@param MaximumVariableSize Pointer to the maximum size of an individual EFI variables
|
||||||
|
associated with the attributes specified.
|
||||||
|
|
||||||
|
@return EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.
|
||||||
|
@return EFI_SUCCESS Query successfully.
|
||||||
|
@return EFI_UNSUPPORTED The attribute is not supported on this platform.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
VariableServiceQueryVariableInfo (
|
||||||
|
IN UINT32 Attributes,
|
||||||
|
OUT UINT64 *MaximumVariableStorageSize,
|
||||||
|
OUT UINT64 *RemainingVariableStorageSize,
|
||||||
|
OUT UINT64 *MaximumVariableSize
|
||||||
|
);
|
||||||
|
|
||||||
|
extern VARIABLE_MODULE_GLOBAL *mVariableModuleGlobal;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
402
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
Normal file
402
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
Normal file
@ -0,0 +1,402 @@
|
|||||||
|
/** @file
|
||||||
|
|
||||||
|
Implement all four UEFI Runtime Variable services for the nonvolatile
|
||||||
|
and volatile storage space and install variable architecture protocol.
|
||||||
|
|
||||||
|
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "Variable.h"
|
||||||
|
|
||||||
|
extern VARIABLE_STORE_HEADER *mNvVariableCache;
|
||||||
|
VARIABLE_INFO_ENTRY *gVariableInfo;
|
||||||
|
EFI_HANDLE mHandle = NULL;
|
||||||
|
EFI_EVENT mVirtualAddressChangeEvent = NULL;
|
||||||
|
EFI_EVENT mFtwRegistration = NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return TRUE if ExitBootServices () has been called
|
||||||
|
|
||||||
|
@retval TRUE If ExitBootServices () has been called
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
AtRuntime (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return EfiAtRuntime ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initializes a basic mutual exclusion lock.
|
||||||
|
|
||||||
|
This function initializes a basic mutual exclusion lock to the released state
|
||||||
|
and returns the lock. Each lock provides mutual exclusion access at its task
|
||||||
|
priority level. Since there is no preemption or multiprocessor support in EFI,
|
||||||
|
acquiring the lock only consists of raising to the locks TPL.
|
||||||
|
If Lock is NULL, then ASSERT().
|
||||||
|
If Priority is not a valid TPL value, then ASSERT().
|
||||||
|
|
||||||
|
@param Lock A pointer to the lock data structure to initialize.
|
||||||
|
@param Priority EFI TPL is associated with the lock.
|
||||||
|
|
||||||
|
@return The lock.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_LOCK *
|
||||||
|
InitializeLock (
|
||||||
|
IN OUT EFI_LOCK *Lock,
|
||||||
|
IN EFI_TPL Priority
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return EfiInitializeLock (Lock, Priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Acquires lock only at boot time. Simply returns at runtime.
|
||||||
|
|
||||||
|
This is a temperary function that will be removed when
|
||||||
|
EfiAcquireLock() in UefiLib can handle the call in UEFI
|
||||||
|
Runtimer driver in RT phase.
|
||||||
|
It calls EfiAcquireLock() at boot time, and simply returns
|
||||||
|
at runtime.
|
||||||
|
|
||||||
|
@param Lock A pointer to the lock to acquire.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
AcquireLockOnlyAtBootTime (
|
||||||
|
IN EFI_LOCK *Lock
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!AtRuntime ()) {
|
||||||
|
EfiAcquireLock (Lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Releases lock only at boot time. Simply returns at runtime.
|
||||||
|
|
||||||
|
This is a temperary function which will be removed when
|
||||||
|
EfiReleaseLock() in UefiLib can handle the call in UEFI
|
||||||
|
Runtimer driver in RT phase.
|
||||||
|
It calls EfiReleaseLock() at boot time and simply returns
|
||||||
|
at runtime.
|
||||||
|
|
||||||
|
@param Lock A pointer to the lock to release.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
ReleaseLockOnlyAtBootTime (
|
||||||
|
IN EFI_LOCK *Lock
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!AtRuntime ()) {
|
||||||
|
EfiReleaseLock (Lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrive the Fault Tolerent Write protocol interface.
|
||||||
|
|
||||||
|
@param[out] FtwProtocol The interface of Ftw protocol
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The FTW protocol instance was found and returned in FtwProtocol.
|
||||||
|
@retval EFI_NOT_FOUND The FTW protocol instance was not found.
|
||||||
|
@retval EFI_INVALID_PARAMETER SarProtocol is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GetFtwProtocol (
|
||||||
|
OUT VOID **FtwProtocol
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Locate Fault Tolerent Write protocol
|
||||||
|
//
|
||||||
|
Status = gBS->LocateProtocol (
|
||||||
|
&gEfiFaultTolerantWriteProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
FtwProtocol
|
||||||
|
);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrive the FVB protocol interface by HANDLE.
|
||||||
|
|
||||||
|
@param[in] FvBlockHandle The handle of FVB protocol that provides services for
|
||||||
|
reading, writing, and erasing the target block.
|
||||||
|
@param[out] FvBlock The interface of FVB protocol
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The interface information for the specified protocol was returned.
|
||||||
|
@retval EFI_UNSUPPORTED The device does not support the FVB protocol.
|
||||||
|
@retval EFI_INVALID_PARAMETER FvBlockHandle is not a valid EFI_HANDLE or FvBlock is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GetFvbByHandle (
|
||||||
|
IN EFI_HANDLE FvBlockHandle,
|
||||||
|
OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// To get the FVB protocol interface on the handle
|
||||||
|
//
|
||||||
|
return gBS->HandleProtocol (
|
||||||
|
FvBlockHandle,
|
||||||
|
&gEfiFirmwareVolumeBlockProtocolGuid,
|
||||||
|
(VOID **) FvBlock
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Function returns an array of handles that support the FVB protocol
|
||||||
|
in a buffer allocated from pool.
|
||||||
|
|
||||||
|
@param[out] NumberHandles The number of handles returned in Buffer.
|
||||||
|
@param[out] Buffer A pointer to the buffer to return the requested
|
||||||
|
array of handles that support FVB protocol.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of
|
||||||
|
handles in Buffer was returned in NumberHandles.
|
||||||
|
@retval EFI_NOT_FOUND No FVB handle was found.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
|
||||||
|
@retval EFI_INVALID_PARAMETER NumberHandles is NULL or Buffer is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GetFvbCountAndBuffer (
|
||||||
|
OUT UINTN *NumberHandles,
|
||||||
|
OUT EFI_HANDLE **Buffer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Locate all handles of Fvb protocol
|
||||||
|
//
|
||||||
|
Status = gBS->LocateHandleBuffer (
|
||||||
|
ByProtocol,
|
||||||
|
&gEfiFirmwareVolumeBlockProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
NumberHandles,
|
||||||
|
Buffer
|
||||||
|
);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
|
||||||
|
|
||||||
|
This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
|
||||||
|
It convers pointer to new virtual address.
|
||||||
|
|
||||||
|
@param Event Event whose notification function is being invoked.
|
||||||
|
@param Context Pointer to the notification function's context.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
VariableClassAddressChangeEvent (
|
||||||
|
IN EFI_EVENT Event,
|
||||||
|
IN VOID *Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetBlockSize);
|
||||||
|
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetPhysicalAddress);
|
||||||
|
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetAttributes);
|
||||||
|
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->SetAttributes);
|
||||||
|
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->Read);
|
||||||
|
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->Write);
|
||||||
|
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->EraseBlocks);
|
||||||
|
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance);
|
||||||
|
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLangCodes);
|
||||||
|
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->LangCodes);
|
||||||
|
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLang);
|
||||||
|
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);
|
||||||
|
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);
|
||||||
|
EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal);
|
||||||
|
EfiConvertPointer (0x0, (VOID **) &mNvVariableCache);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Notification function of EVT_GROUP_READY_TO_BOOT event group.
|
||||||
|
|
||||||
|
This is a notification function registered on EVT_GROUP_READY_TO_BOOT event group.
|
||||||
|
When the Boot Manager is about to load and execute a boot option, it reclaims variable
|
||||||
|
storage if free size is below the threshold.
|
||||||
|
|
||||||
|
@param Event Event whose notification function is being invoked.
|
||||||
|
@param Context Pointer to the notification function's context.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
OnReadyToBoot (
|
||||||
|
EFI_EVENT Event,
|
||||||
|
VOID *Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ReclaimForOS ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Fault Tolerant Write protocol notification event handler.
|
||||||
|
|
||||||
|
Non-Volatile variable write may needs FTW protocol to reclaim when
|
||||||
|
writting variable.
|
||||||
|
|
||||||
|
@param[in] Event Event whose notification function is being invoked.
|
||||||
|
@param[in] Context Pointer to the notification function's context.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
FtwNotificationEvent (
|
||||||
|
IN EFI_EVENT Event,
|
||||||
|
IN VOID *Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;
|
||||||
|
EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
|
||||||
|
EFI_PHYSICAL_ADDRESS NvStorageVariableBase;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Ensure FTW protocol is installed.
|
||||||
|
//
|
||||||
|
Status = GetFtwProtocol (&FtwProtocol);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Find the proper FVB protocol for variable.
|
||||||
|
//
|
||||||
|
NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);
|
||||||
|
if (NvStorageVariableBase == 0) {
|
||||||
|
NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);
|
||||||
|
}
|
||||||
|
Status = GetFvbInfoByAddress (NvStorageVariableBase, NULL, &FvbProtocol);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
mVariableModuleGlobal->FvbInstance = FvbProtocol;
|
||||||
|
|
||||||
|
Status = VariableWriteServiceInitialize ();
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Install the Variable Write Architectural protocol.
|
||||||
|
//
|
||||||
|
Status = gBS->InstallProtocolInterface (
|
||||||
|
&mHandle,
|
||||||
|
&gEfiVariableWriteArchProtocolGuid,
|
||||||
|
EFI_NATIVE_INTERFACE,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Close the notify event to avoid install gEfiVariableWriteArchProtocolGuid again.
|
||||||
|
//
|
||||||
|
gBS->CloseEvent (Event);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Variable Driver main entry point. The Variable driver places the 4 EFI
|
||||||
|
runtime services in the EFI System Table and installs arch protocols
|
||||||
|
for variable read and write services being availible. It also registers
|
||||||
|
a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
|
||||||
|
|
||||||
|
@param[in] ImageHandle The firmware allocated handle for the EFI image.
|
||||||
|
@param[in] SystemTable A pointer to the EFI System Table.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Variable service successfully initialized.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
VariableServiceInitialize (
|
||||||
|
IN EFI_HANDLE ImageHandle,
|
||||||
|
IN EFI_SYSTEM_TABLE *SystemTable
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_EVENT ReadyToBootEvent;
|
||||||
|
|
||||||
|
Status = VariableCommonInitialize ();
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
SystemTable->RuntimeServices->GetVariable = VariableServiceGetVariable;
|
||||||
|
SystemTable->RuntimeServices->GetNextVariableName = VariableServiceGetNextVariableName;
|
||||||
|
SystemTable->RuntimeServices->SetVariable = VariableServiceSetVariable;
|
||||||
|
SystemTable->RuntimeServices->QueryVariableInfo = VariableServiceQueryVariableInfo;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Now install the Variable Runtime Architectural protocol on a new handle.
|
||||||
|
//
|
||||||
|
Status = gBS->InstallProtocolInterface (
|
||||||
|
&mHandle,
|
||||||
|
&gEfiVariableArchProtocolGuid,
|
||||||
|
EFI_NATIVE_INTERFACE,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Register FtwNotificationEvent () notify function.
|
||||||
|
//
|
||||||
|
EfiCreateProtocolNotifyEvent (
|
||||||
|
&gEfiFaultTolerantWriteProtocolGuid,
|
||||||
|
TPL_CALLBACK,
|
||||||
|
FtwNotificationEvent,
|
||||||
|
(VOID *)SystemTable,
|
||||||
|
&mFtwRegistration
|
||||||
|
);
|
||||||
|
|
||||||
|
Status = gBS->CreateEventEx (
|
||||||
|
EVT_NOTIFY_SIGNAL,
|
||||||
|
TPL_NOTIFY,
|
||||||
|
VariableClassAddressChangeEvent,
|
||||||
|
NULL,
|
||||||
|
&gEfiEventVirtualAddressChangeGuid,
|
||||||
|
&mVirtualAddressChangeEvent
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Register the event handling function to reclaim variable for OS usage.
|
||||||
|
//
|
||||||
|
Status = EfiCreateEventReadyToBootEx (
|
||||||
|
TPL_NOTIFY,
|
||||||
|
OnReadyToBoot,
|
||||||
|
NULL,
|
||||||
|
&ReadyToBootEvent
|
||||||
|
);
|
||||||
|
|
||||||
|
if (FeaturePcdGet (PcdVariableCollectStatistics)) {
|
||||||
|
gBS->InstallConfigurationTable (&gEfiVariableGuid, gVariableInfo);
|
||||||
|
}
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
@ -33,6 +33,7 @@
|
|||||||
[Sources]
|
[Sources]
|
||||||
Reclaim.c
|
Reclaim.c
|
||||||
Variable.c
|
Variable.c
|
||||||
|
VariableDxe.c
|
||||||
Variable.h
|
Variable.h
|
||||||
|
|
||||||
[Packages]
|
[Packages]
|
||||||
@ -76,7 +77,7 @@
|
|||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## SOMETIME_CONSUMES (statistic the information of variable.)
|
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## SOMETIME_CONSUMES (statistic the information of variable.)
|
||||||
|
|
||||||
[Depex]
|
[Depex]
|
||||||
gEfiFirmwareVolumeBlockProtocolGuid AND gEfiFaultTolerantWriteProtocolGuid
|
TRUE
|
||||||
|
|
||||||
# [Event]
|
# [Event]
|
||||||
# ##
|
# ##
|
||||||
@ -84,4 +85,5 @@
|
|||||||
# #
|
# #
|
||||||
# EVENT_TYPE_NOTIFY_SIGNAL ## PRODUCES
|
# EVENT_TYPE_NOTIFY_SIGNAL ## PRODUCES
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
|
585
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
Normal file
585
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
Normal file
@ -0,0 +1,585 @@
|
|||||||
|
/** @file
|
||||||
|
|
||||||
|
The sample implementation for SMM variable protocol. And this driver
|
||||||
|
implements an SMI handler to communicate with the DXE runtime driver
|
||||||
|
to provide variable services.
|
||||||
|
|
||||||
|
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
#include <Protocol/SmmFaultTolerantWrite.h>
|
||||||
|
#include <Library/SmmServicesTableLib.h>
|
||||||
|
|
||||||
|
#include "Variable.h"
|
||||||
|
#include "VariableSmmCommon.h"
|
||||||
|
|
||||||
|
extern SMM_VARIABLE_COMMUNICATE_VARIABLE_INFO_ENTRY *gVariableInfo;
|
||||||
|
EFI_HANDLE mSmmVariableHandle = NULL;
|
||||||
|
EFI_HANDLE mVariableHandle = NULL;
|
||||||
|
BOOLEAN mAtRuntime = FALSE;
|
||||||
|
EFI_GUID mZeroGuid = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
|
||||||
|
EFI_GUID mSmmVariableWriteGuid = EFI_SMM_VARIABLE_WRITE_GUID;
|
||||||
|
|
||||||
|
EFI_SMM_VARIABLE_PROTOCOL gSmmVariable = {
|
||||||
|
VariableServiceGetVariable,
|
||||||
|
VariableServiceGetNextVariableName,
|
||||||
|
VariableServiceSetVariable,
|
||||||
|
VariableServiceQueryVariableInfo
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return TRUE if ExitBootServices () has been called.
|
||||||
|
|
||||||
|
@retval TRUE If ExitBootServices () has been called.
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
AtRuntime (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return mAtRuntime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initializes a basic mutual exclusion lock.
|
||||||
|
|
||||||
|
This function initializes a basic mutual exclusion lock to the released state
|
||||||
|
and returns the lock. Each lock provides mutual exclusion access at its task
|
||||||
|
priority level. Since there is no preemption or multiprocessor support in EFI,
|
||||||
|
acquiring the lock only consists of raising to the locks TPL.
|
||||||
|
If Lock is NULL, then ASSERT().
|
||||||
|
If Priority is not a valid TPL value, then ASSERT().
|
||||||
|
|
||||||
|
@param Lock A pointer to the lock data structure to initialize.
|
||||||
|
@param Priority EFI TPL is associated with the lock.
|
||||||
|
|
||||||
|
@return The lock.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_LOCK *
|
||||||
|
InitializeLock (
|
||||||
|
IN OUT EFI_LOCK *Lock,
|
||||||
|
IN EFI_TPL Priority
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return Lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Acquires lock only at boot time. Simply returns at runtime.
|
||||||
|
|
||||||
|
This is a temperary function that will be removed when
|
||||||
|
EfiAcquireLock() in UefiLib can handle the call in UEFI
|
||||||
|
Runtimer driver in RT phase.
|
||||||
|
It calls EfiAcquireLock() at boot time, and simply returns
|
||||||
|
at runtime.
|
||||||
|
|
||||||
|
@param Lock A pointer to the lock to acquire.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
AcquireLockOnlyAtBootTime (
|
||||||
|
IN EFI_LOCK *Lock
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Releases lock only at boot time. Simply returns at runtime.
|
||||||
|
|
||||||
|
This is a temperary function which will be removed when
|
||||||
|
EfiReleaseLock() in UefiLib can handle the call in UEFI
|
||||||
|
Runtimer driver in RT phase.
|
||||||
|
It calls EfiReleaseLock() at boot time and simply returns
|
||||||
|
at runtime.
|
||||||
|
|
||||||
|
@param Lock A pointer to the lock to release.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
ReleaseLockOnlyAtBootTime (
|
||||||
|
IN EFI_LOCK *Lock
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrive the SMM Fault Tolerent Write protocol interface.
|
||||||
|
|
||||||
|
@param[out] FtwProtocol The interface of SMM Ftw protocol
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The SMM FTW protocol instance was found and returned in FtwProtocol.
|
||||||
|
@retval EFI_NOT_FOUND The SMM FTW protocol instance was not found.
|
||||||
|
@retval EFI_INVALID_PARAMETER SarProtocol is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GetFtwProtocol (
|
||||||
|
OUT VOID **FtwProtocol
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Locate Smm Fault Tolerent Write protocol
|
||||||
|
//
|
||||||
|
Status = gSmst->SmmLocateProtocol (
|
||||||
|
&gEfiSmmFaultTolerantWriteProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
FtwProtocol
|
||||||
|
);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrive the SMM FVB protocol interface by HANDLE.
|
||||||
|
|
||||||
|
@param[in] FvBlockHandle The handle of SMM FVB protocol that provides services for
|
||||||
|
reading, writing, and erasing the target block.
|
||||||
|
@param[out] FvBlock The interface of SMM FVB protocol
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The interface information for the specified protocol was returned.
|
||||||
|
@retval EFI_UNSUPPORTED The device does not support the SMM FVB protocol.
|
||||||
|
@retval EFI_INVALID_PARAMETER FvBlockHandle is not a valid EFI_HANDLE or FvBlock is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GetFvbByHandle (
|
||||||
|
IN EFI_HANDLE FvBlockHandle,
|
||||||
|
OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// To get the SMM FVB protocol interface on the handle
|
||||||
|
//
|
||||||
|
return gSmst->SmmHandleProtocol (
|
||||||
|
FvBlockHandle,
|
||||||
|
&gEfiSmmFirmwareVolumeBlockProtocolGuid,
|
||||||
|
(VOID **) FvBlock
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Function returns an array of handles that support the SMM FVB protocol
|
||||||
|
in a buffer allocated from pool.
|
||||||
|
|
||||||
|
@param[out] NumberHandles The number of handles returned in Buffer.
|
||||||
|
@param[out] Buffer A pointer to the buffer to return the requested
|
||||||
|
array of handles that support SMM FVB protocol.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of
|
||||||
|
handles in Buffer was returned in NumberHandles.
|
||||||
|
@retval EFI_NOT_FOUND No SMM FVB handle was found.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
|
||||||
|
@retval EFI_INVALID_PARAMETER NumberHandles is NULL or Buffer is NULL.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
GetFvbCountAndBuffer (
|
||||||
|
OUT UINTN *NumberHandles,
|
||||||
|
OUT EFI_HANDLE **Buffer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN BufferSize;
|
||||||
|
|
||||||
|
if ((NumberHandles == NULL) || (Buffer == NULL)) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferSize = 0;
|
||||||
|
*NumberHandles = 0;
|
||||||
|
*Buffer = NULL;
|
||||||
|
Status = gSmst->SmmLocateHandle (
|
||||||
|
ByProtocol,
|
||||||
|
&gEfiSmmFirmwareVolumeBlockProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
&BufferSize,
|
||||||
|
*Buffer
|
||||||
|
);
|
||||||
|
if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
*Buffer = AllocatePool (BufferSize);
|
||||||
|
if (*Buffer == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = gSmst->SmmLocateHandle (
|
||||||
|
ByProtocol,
|
||||||
|
&gEfiSmmFirmwareVolumeBlockProtocolGuid,
|
||||||
|
NULL,
|
||||||
|
&BufferSize,
|
||||||
|
*Buffer
|
||||||
|
);
|
||||||
|
|
||||||
|
*NumberHandles = BufferSize / sizeof(EFI_HANDLE);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
*NumberHandles = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the variable statistics information from the information buffer pointed by gVariableInfo.
|
||||||
|
|
||||||
|
@param[in, out] InfoEntry A pointer to the buffer of variable information entry.
|
||||||
|
On input, point to the variable information returned last time. if
|
||||||
|
InfoEntry->VendorGuid is zero, return the first information.
|
||||||
|
On output, point to the next variable information.
|
||||||
|
@param[in, out] InfoSize On input, the size of the variable information buffer.
|
||||||
|
On output, the returned variable information size.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The variable information is found and returned successfully.
|
||||||
|
@retval EFI_UNSUPPORTED No variable inoformation exists in variable driver. The
|
||||||
|
PcdVariableCollectStatistics should be set TRUE to support it.
|
||||||
|
@retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the next variable information.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
SmmVariableGetStatistics (
|
||||||
|
IN OUT SMM_VARIABLE_COMMUNICATE_VARIABLE_INFO_ENTRY *InfoEntry,
|
||||||
|
IN OUT UINTN *InfoSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SMM_VARIABLE_COMMUNICATE_VARIABLE_INFO_ENTRY *VariableInfo;
|
||||||
|
UINTN NameLength;
|
||||||
|
UINTN StatisticsInfoSize;
|
||||||
|
CHAR16 *InfoName;
|
||||||
|
|
||||||
|
ASSERT (InfoEntry != NULL);
|
||||||
|
VariableInfo = gVariableInfo;
|
||||||
|
if (VariableInfo == NULL) {
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
StatisticsInfoSize = sizeof (SMM_VARIABLE_COMMUNICATE_VARIABLE_INFO_ENTRY) + StrSize (VariableInfo->Name);
|
||||||
|
if (*InfoSize < sizeof (SMM_VARIABLE_COMMUNICATE_VARIABLE_INFO_ENTRY)) {
|
||||||
|
*InfoSize = StatisticsInfoSize;
|
||||||
|
return EFI_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
InfoName = (CHAR16 *)(InfoEntry + 1);
|
||||||
|
|
||||||
|
if (CompareGuid (&InfoEntry->VendorGuid, &mZeroGuid)) {
|
||||||
|
//
|
||||||
|
// Return the first variable info
|
||||||
|
//
|
||||||
|
CopyMem (InfoEntry, VariableInfo, sizeof (SMM_VARIABLE_COMMUNICATE_VARIABLE_INFO_ENTRY));
|
||||||
|
CopyMem (InfoName, VariableInfo->Name, StrSize (VariableInfo->Name));
|
||||||
|
*InfoSize = StatisticsInfoSize;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the next variable info
|
||||||
|
//
|
||||||
|
while (VariableInfo != NULL) {
|
||||||
|
if (CompareGuid (&VariableInfo->VendorGuid, &InfoEntry->VendorGuid)) {
|
||||||
|
NameLength = StrSize (VariableInfo->Name);
|
||||||
|
if (NameLength == StrSize (InfoName)) {
|
||||||
|
if (CompareMem (VariableInfo->Name, InfoName, NameLength) == 0) {
|
||||||
|
//
|
||||||
|
// Find the match one
|
||||||
|
//
|
||||||
|
VariableInfo = VariableInfo->Next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VariableInfo = VariableInfo->Next;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (VariableInfo == NULL) {
|
||||||
|
*InfoSize = 0;
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Output the new variable info
|
||||||
|
//
|
||||||
|
StatisticsInfoSize = sizeof (SMM_VARIABLE_COMMUNICATE_VARIABLE_INFO_ENTRY) + StrSize (VariableInfo->Name);
|
||||||
|
if (*InfoSize < StatisticsInfoSize) {
|
||||||
|
*InfoSize = StatisticsInfoSize;
|
||||||
|
return EFI_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CopyMem (InfoEntry, VariableInfo, sizeof (SMM_VARIABLE_COMMUNICATE_VARIABLE_INFO_ENTRY));
|
||||||
|
CopyMem (InfoName, VariableInfo->Name, StrSize (VariableInfo->Name));
|
||||||
|
*InfoSize = StatisticsInfoSize;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Communication service SMI Handler entry.
|
||||||
|
|
||||||
|
This SMI handler provides services for the variable wrapper driver.
|
||||||
|
|
||||||
|
@param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
|
||||||
|
@param[in] RegisterContext Points to an optional handler context which was specified when the
|
||||||
|
handler was registered.
|
||||||
|
@param[in, out] CommBuffer A pointer to a collection of data in memory that will
|
||||||
|
be conveyed from a non-SMM environment into an SMM environment.
|
||||||
|
@param[in, out] CommBufferSize The size of the CommBuffer.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
|
||||||
|
should still be called.
|
||||||
|
@retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
|
||||||
|
still be called.
|
||||||
|
@retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
|
||||||
|
be called.
|
||||||
|
@retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmVariableHandler (
|
||||||
|
IN EFI_HANDLE DispatchHandle,
|
||||||
|
IN CONST VOID *RegisterContext,
|
||||||
|
IN OUT VOID *CommBuffer,
|
||||||
|
IN OUT UINTN *CommBufferSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
|
||||||
|
SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;
|
||||||
|
SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *GetNextVariableName;
|
||||||
|
SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *QueryVariableInfo;
|
||||||
|
SMM_VARIABLE_COMMUNICATE_VARIABLE_INFO_ENTRY *VariableInfo;
|
||||||
|
UINTN InfoSize;
|
||||||
|
|
||||||
|
ASSERT (CommBuffer != NULL);
|
||||||
|
|
||||||
|
SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)CommBuffer;
|
||||||
|
switch (SmmVariableFunctionHeader->Function) {
|
||||||
|
case SMM_VARIABLE_FUNCTION_GET_VARIABLE:
|
||||||
|
SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) SmmVariableFunctionHeader->Data;
|
||||||
|
Status = VariableServiceGetVariable (
|
||||||
|
SmmVariableHeader->Name,
|
||||||
|
&SmmVariableHeader->Guid,
|
||||||
|
&SmmVariableHeader->Attributes,
|
||||||
|
&SmmVariableHeader->DataSize,
|
||||||
|
(UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME:
|
||||||
|
GetNextVariableName = (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *) SmmVariableFunctionHeader->Data;
|
||||||
|
Status = VariableServiceGetNextVariableName (
|
||||||
|
&GetNextVariableName->NameSize,
|
||||||
|
GetNextVariableName->Name,
|
||||||
|
&GetNextVariableName->Guid
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SMM_VARIABLE_FUNCTION_SET_VARIABLE:
|
||||||
|
SmmVariableHeader = (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *) SmmVariableFunctionHeader->Data;
|
||||||
|
Status = VariableServiceSetVariable (
|
||||||
|
SmmVariableHeader->Name,
|
||||||
|
&SmmVariableHeader->Guid,
|
||||||
|
SmmVariableHeader->Attributes,
|
||||||
|
SmmVariableHeader->DataSize,
|
||||||
|
(UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO:
|
||||||
|
QueryVariableInfo = (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *) SmmVariableFunctionHeader->Data;
|
||||||
|
Status = VariableServiceQueryVariableInfo (
|
||||||
|
QueryVariableInfo->Attributes,
|
||||||
|
&QueryVariableInfo->MaximumVariableStorageSize,
|
||||||
|
&QueryVariableInfo->RemainingVariableStorageSize,
|
||||||
|
&QueryVariableInfo->MaximumVariableSize
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SMM_VARIABLE_FUNCTION_READY_TO_BOOT:
|
||||||
|
ReclaimForOS ();
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE:
|
||||||
|
mAtRuntime = TRUE;
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SMM_VARIABLE_FUNCTION_GET_STATISTICS:
|
||||||
|
VariableInfo = (SMM_VARIABLE_COMMUNICATE_VARIABLE_INFO_ENTRY *) SmmVariableFunctionHeader->Data;
|
||||||
|
InfoSize = *CommBufferSize - OFFSET_OF (SMM_VARIABLE_COMMUNICATE_HEADER, Data);
|
||||||
|
Status = SmmVariableGetStatistics (VariableInfo, &InfoSize);
|
||||||
|
*CommBufferSize = InfoSize + OFFSET_OF (SMM_VARIABLE_COMMUNICATE_HEADER, Data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ASSERT (FALSE);
|
||||||
|
Status = EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmmVariableFunctionHeader->ReturnStatus = Status;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
SMM Fault Tolerant Write protocol notification event handler.
|
||||||
|
|
||||||
|
Non-Volatile variable write may needs FTW protocol to reclaim when
|
||||||
|
writting variable.
|
||||||
|
|
||||||
|
@param Protocol Points to the protocol's unique identifier
|
||||||
|
@param Interface Points to the interface instance
|
||||||
|
@param Handle The handle on which the interface was installed
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS SmmEventCallback runs successfully
|
||||||
|
@retval EFI_NOT_FOUND The Fvb protocol for variable is not found.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
SmmFtwNotificationEvent (
|
||||||
|
IN CONST EFI_GUID *Protocol,
|
||||||
|
IN VOID *Interface,
|
||||||
|
IN EFI_HANDLE Handle
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_SMM_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;
|
||||||
|
EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
|
||||||
|
EFI_PHYSICAL_ADDRESS NvStorageVariableBase;
|
||||||
|
|
||||||
|
if (mVariableModuleGlobal->FvbInstance != NULL) {
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Ensure SMM FTW protocol is installed.
|
||||||
|
//
|
||||||
|
Status = GetFtwProtocol (&FtwProtocol);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Find the proper FVB protocol for variable.
|
||||||
|
//
|
||||||
|
NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);
|
||||||
|
if (NvStorageVariableBase == 0) {
|
||||||
|
NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);
|
||||||
|
}
|
||||||
|
Status = GetFvbInfoByAddress (NvStorageVariableBase, NULL, &FvbProtocol);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return EFI_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
mVariableModuleGlobal->FvbInstance = FvbProtocol;
|
||||||
|
|
||||||
|
Status = VariableWriteServiceInitialize ();
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Notify the variable wrapper driver the variable write service is ready
|
||||||
|
//
|
||||||
|
Status = gBS->InstallProtocolInterface (
|
||||||
|
&mSmmVariableHandle,
|
||||||
|
&mSmmVariableWriteGuid,
|
||||||
|
EFI_NATIVE_INTERFACE,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Variable Driver main entry point. The Variable driver places the 4 EFI
|
||||||
|
runtime services in the EFI System Table and installs arch protocols
|
||||||
|
for variable read and write services being availible. It also registers
|
||||||
|
a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
|
||||||
|
|
||||||
|
@param[in] ImageHandle The firmware allocated handle for the EFI image.
|
||||||
|
@param[in] SystemTable A pointer to the EFI System Table.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Variable service successfully initialized.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
VariableServiceInitialize (
|
||||||
|
IN EFI_HANDLE ImageHandle,
|
||||||
|
IN EFI_SYSTEM_TABLE *SystemTable
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_HANDLE VariableHandle;
|
||||||
|
VOID *SmmFtwRegistration;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Variable initialize.
|
||||||
|
//
|
||||||
|
Status = VariableCommonInitialize ();
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Install the Smm Variable Protocol on a new handle.
|
||||||
|
//
|
||||||
|
VariableHandle = NULL;
|
||||||
|
Status = gSmst->SmmInstallProtocolInterface (
|
||||||
|
&VariableHandle,
|
||||||
|
&gEfiSmmVariableProtocolGuid,
|
||||||
|
EFI_NATIVE_INTERFACE,
|
||||||
|
&gSmmVariable
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Register SMM variable SMI handler
|
||||||
|
///
|
||||||
|
VariableHandle = NULL;
|
||||||
|
Status = gSmst->SmiHandlerRegister (SmmVariableHandler, &gEfiSmmVariableProtocolGuid, &VariableHandle);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Notify the variable wrapper driver the variable service is ready
|
||||||
|
//
|
||||||
|
Status = SystemTable->BootServices->InstallProtocolInterface (
|
||||||
|
&mVariableHandle,
|
||||||
|
&gEfiSmmVariableProtocolGuid,
|
||||||
|
EFI_NATIVE_INTERFACE,
|
||||||
|
&gSmmVariable
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Register FtwNotificationEvent () notify function.
|
||||||
|
//
|
||||||
|
Status = gSmst->SmmRegisterProtocolNotify (
|
||||||
|
&gEfiSmmFaultTolerantWriteProtocolGuid,
|
||||||
|
SmmFtwNotificationEvent,
|
||||||
|
&SmmFtwRegistration
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
SmmFtwNotificationEvent (NULL, NULL, NULL);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
86
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
Normal file
86
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
## @file
|
||||||
|
# Component description file for SMM Variable module.
|
||||||
|
#
|
||||||
|
# This module installs SMM variable protocol into SMM protocol database,
|
||||||
|
# which can be used by SMM driver, and installs SMM variable protocol
|
||||||
|
# into BS protocol database, which can be used to notify the SMM Runtime
|
||||||
|
# Dxe driver that the SMM variable service is ready.
|
||||||
|
# This module should be used with SMM Runtime DXE module together. The
|
||||||
|
# SMM Runtime DXE module would install variable arch protocol and variable
|
||||||
|
# write arch protocol based on SMM variable module.
|
||||||
|
# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
#
|
||||||
|
# This program and the accompanying materials
|
||||||
|
# are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
# which accompanies this distribution. The full text of the license may be found at
|
||||||
|
# http://opensource.org/licenses/bsd-license.php
|
||||||
|
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
##
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
INF_VERSION = 0x00010005
|
||||||
|
BASE_NAME = VariableSmm
|
||||||
|
FILE_GUID = 23A089B3-EED5-4ac5-B2AB-43E3298C2343
|
||||||
|
MODULE_TYPE = DXE_SMM_DRIVER
|
||||||
|
VERSION_STRING = 1.0
|
||||||
|
PI_SPECIFICATION_VERSION = 0x0001000A
|
||||||
|
ENTRY_POINT = VariableServiceInitialize
|
||||||
|
|
||||||
|
#
|
||||||
|
# The following information is for reference only and not required by the build tools.
|
||||||
|
#
|
||||||
|
# VALID_ARCHITECTURES = IA32 X64
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
[Sources]
|
||||||
|
Reclaim.c
|
||||||
|
Variable.c
|
||||||
|
VariableSmm.c
|
||||||
|
Variable.h
|
||||||
|
VariableSmmCommon.h
|
||||||
|
|
||||||
|
[Packages]
|
||||||
|
MdePkg/MdePkg.dec
|
||||||
|
MdeModulePkg/MdeModulePkg.dec
|
||||||
|
|
||||||
|
[LibraryClasses]
|
||||||
|
UefiDriverEntryPoint
|
||||||
|
MemoryAllocationLib
|
||||||
|
BaseLib
|
||||||
|
SynchronizationLib
|
||||||
|
UefiLib
|
||||||
|
SmmLib
|
||||||
|
SmmServicesTableLib
|
||||||
|
BaseMemoryLib
|
||||||
|
DebugLib
|
||||||
|
DxeServicesTableLib
|
||||||
|
|
||||||
|
[Protocols]
|
||||||
|
gEfiSmmFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES
|
||||||
|
gEfiSmmVariableProtocolGuid ## ALWAYS_PRODUCES
|
||||||
|
gEfiSmmFaultTolerantWriteProtocolGuid ## SOMETIMES_CONSUMES
|
||||||
|
|
||||||
|
[Guids]
|
||||||
|
gEfiVariableGuid ## PRODUCES ## Configuration Table Guid
|
||||||
|
gEfiGlobalVariableGuid ## PRODUCES ## Variable Guid
|
||||||
|
|
||||||
|
[Pcd]
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize
|
||||||
|
|
||||||
|
[FeaturePcd]
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## SOMETIME_CONSUMES (statistic the information of variable.)
|
||||||
|
|
||||||
|
[Depex]
|
||||||
|
TRUE
|
||||||
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
|||||||
|
/** @file
|
||||||
|
|
||||||
|
The internal header file includes the common header files shared
|
||||||
|
by VariableSmm module and VariableSmmRuntimeDxe module.
|
||||||
|
|
||||||
|
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef _VARIABLE_SMM_COMMON_H_
|
||||||
|
#define _VARIABLE_SMM_COMMON_H_
|
||||||
|
|
||||||
|
#include <PiDxe.h>
|
||||||
|
|
||||||
|
#include <Protocol/SmmVariable.h>
|
||||||
|
#include <Protocol/SmmFirmwareVolumeBlock.h>
|
||||||
|
#include <Guid/VariableFormat.h>
|
||||||
|
|
||||||
|
#define EFI_SMM_VARIABLE_WRITE_GUID \
|
||||||
|
{ 0x93ba1826, 0xdffb, 0x45dd, { 0x82, 0xa7, 0xe7, 0xdc, 0xaa, 0x3b, 0xbd, 0xf3 } }
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Size of SMM communicate header, without including the payload.
|
||||||
|
///
|
||||||
|
#define SMM_COMMUNICATE_HEADER_SIZE (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data))
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Size of SMM variable communicate header, without including the payload.
|
||||||
|
///
|
||||||
|
#define SMM_VARIABLE_COMMUNICATE_HEADER_SIZE (OFFSET_OF (SMM_VARIABLE_COMMUNICATE_HEADER, Data))
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,650 @@
|
|||||||
|
/** @file
|
||||||
|
|
||||||
|
Implement all four UEFI Runtime Variable services for the nonvolatile
|
||||||
|
and volatile storage space and install variable architecture protocol
|
||||||
|
based on SMM variable module.
|
||||||
|
|
||||||
|
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <Protocol/VariableWrite.h>
|
||||||
|
#include <Protocol/Variable.h>
|
||||||
|
#include <Protocol/SmmCommunication.h>
|
||||||
|
|
||||||
|
#include <Library/UefiBootServicesTableLib.h>
|
||||||
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||||
|
#include <Library/MemoryAllocationLib.h>
|
||||||
|
#include <Library/UefiDriverEntryPoint.h>
|
||||||
|
#include <Library/UefiRuntimeLib.h>
|
||||||
|
#include <Library/BaseMemoryLib.h>
|
||||||
|
#include <Library/DebugLib.h>
|
||||||
|
#include <Library/PcdLib.h>
|
||||||
|
#include <Library/UefiLib.h>
|
||||||
|
#include <Library/BaseLib.h>
|
||||||
|
|
||||||
|
#include <Guid/EventGroup.h>
|
||||||
|
#include "VariableSmmCommon.h"
|
||||||
|
|
||||||
|
EFI_HANDLE mHandle = NULL;
|
||||||
|
EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable = NULL;
|
||||||
|
EFI_EVENT mVirtualAddressChangeEvent = NULL;
|
||||||
|
EFI_SMM_COMMUNICATION_PROTOCOL *mSmmCommunication = NULL;
|
||||||
|
UINT8 *mVariableBuffer = NULL;
|
||||||
|
UINT8 *mVariableBufferPhysical = NULL;
|
||||||
|
EFI_GUID mSmmVariableWriteGuid = EFI_SMM_VARIABLE_WRITE_GUID;
|
||||||
|
UINTN mVariableBufferSize;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialize the communicate buffer using DataSize and Function.
|
||||||
|
|
||||||
|
The communicate size is: SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE +
|
||||||
|
DataSize.
|
||||||
|
|
||||||
|
@param[out] DataPtr Points to the data in the communicate buffer.
|
||||||
|
@param[in] DataSize The data size to send to SMM.
|
||||||
|
@param[in] Function The function number to initialize the communicate header.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER The data size is too big.
|
||||||
|
@retval EFI_SUCCESS Find the specified variable.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
InitCommunicateBuffer (
|
||||||
|
OUT VOID **DataPtr OPTIONAL,
|
||||||
|
IN UINTN DataSize,
|
||||||
|
IN UINTN Function
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;
|
||||||
|
SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
|
||||||
|
|
||||||
|
|
||||||
|
if (DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE > mVariableBufferSize) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) mVariableBuffer;
|
||||||
|
CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);
|
||||||
|
SmmCommunicateHeader->MessageLength = DataSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
|
||||||
|
|
||||||
|
SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) SmmCommunicateHeader->Data;
|
||||||
|
SmmVariableFunctionHeader->Function = Function;
|
||||||
|
if (DataPtr != NULL) {
|
||||||
|
*DataPtr = SmmVariableFunctionHeader->Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Send the data in communicate buffer to SMM.
|
||||||
|
|
||||||
|
@param[in] DataSize This size of the function header and the data.
|
||||||
|
|
||||||
|
@RetVal EFI_SUCCESS Success is returned from the functin in SMM.
|
||||||
|
@RetVal Others Failure is returned from the function in SMM.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
SendCommunicateBuffer (
|
||||||
|
IN UINTN DataSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN CommSize;
|
||||||
|
EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;
|
||||||
|
SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
|
||||||
|
|
||||||
|
CommSize = DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
|
||||||
|
Status = mSmmCommunication->Communicate (mSmmCommunication, mVariableBufferPhysical, &CommSize);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) mVariableBuffer;
|
||||||
|
SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;
|
||||||
|
return SmmVariableFunctionHeader->ReturnStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This code finds variable in storage blocks (Volatile or Non-Volatile).
|
||||||
|
|
||||||
|
@param[in] VariableName Name of Variable to be found.
|
||||||
|
@param[in] VendorGuid Variable vendor GUID.
|
||||||
|
@param[out] Attributes Attribute value of the variable found.
|
||||||
|
@param[in, out] DataSize Size of Data found. If size is less than the
|
||||||
|
data, this value contains the required size.
|
||||||
|
@param[out] Data Data pointer.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||||
|
@retval EFI_SUCCESS Find the specified variable.
|
||||||
|
@retval EFI_NOT_FOUND Not found.
|
||||||
|
@retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
RuntimeServiceGetVariable (
|
||||||
|
IN CHAR16 *VariableName,
|
||||||
|
IN EFI_GUID *VendorGuid,
|
||||||
|
OUT UINT32 *Attributes OPTIONAL,
|
||||||
|
IN OUT UINTN *DataSize,
|
||||||
|
OUT VOID *Data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN PayloadSize;
|
||||||
|
SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;
|
||||||
|
|
||||||
|
if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*DataSize != 0) && (Data == NULL)) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Init the communicate buffer. The buffer data size is:
|
||||||
|
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
|
||||||
|
//
|
||||||
|
PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + StrSize (VariableName);
|
||||||
|
Status = InitCommunicateBuffer (&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_GET_VARIABLE);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
ASSERT (SmmVariableHeader != NULL);
|
||||||
|
|
||||||
|
CopyGuid (&SmmVariableHeader->Guid, VendorGuid);
|
||||||
|
SmmVariableHeader->DataSize = *DataSize;
|
||||||
|
SmmVariableHeader->NameSize = StrSize (VariableName);
|
||||||
|
if (Attributes == NULL) {
|
||||||
|
SmmVariableHeader->Attributes = 0;
|
||||||
|
} else {
|
||||||
|
SmmVariableHeader->Attributes = *Attributes;
|
||||||
|
}
|
||||||
|
CopyMem (SmmVariableHeader->Name, VariableName, SmmVariableHeader->NameSize);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Send data to SMM.
|
||||||
|
//
|
||||||
|
Status = SendCommunicateBuffer (PayloadSize);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get data from SMM.
|
||||||
|
//
|
||||||
|
*DataSize = SmmVariableHeader->DataSize;
|
||||||
|
if (Attributes != NULL) {
|
||||||
|
*Attributes = SmmVariableHeader->Attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
CopyMem (Data, (UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize, SmmVariableHeader->DataSize);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This code Finds the Next available variable.
|
||||||
|
|
||||||
|
@param[in, out] VariableNameSize Size of the variable name.
|
||||||
|
@param[in, out] VariableName Pointer to variable name.
|
||||||
|
@param[in, out] VendorGuid Variable Vendor Guid.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||||
|
@retval EFI_SUCCESS Find the specified variable.
|
||||||
|
@retval EFI_NOT_FOUND Not found.
|
||||||
|
@retval EFI_BUFFER_TO_SMALL DataSize is too small for the result.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
RuntimeServiceGetNextVariableName (
|
||||||
|
IN OUT UINTN *VariableNameSize,
|
||||||
|
IN OUT CHAR16 *VariableName,
|
||||||
|
IN OUT EFI_GUID *VendorGuid
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN PayloadSize;
|
||||||
|
SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME *SmmGetNextVariableName;
|
||||||
|
|
||||||
|
if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Init the communicate buffer. The buffer data size is:
|
||||||
|
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
|
||||||
|
//
|
||||||
|
PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + *VariableNameSize;
|
||||||
|
Status = InitCommunicateBuffer (&SmmGetNextVariableName, PayloadSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
ASSERT (SmmGetNextVariableName != NULL);
|
||||||
|
|
||||||
|
SmmGetNextVariableName->NameSize = *VariableNameSize;
|
||||||
|
CopyGuid (&SmmGetNextVariableName->Guid, VendorGuid);
|
||||||
|
CopyMem (SmmGetNextVariableName->Name, VariableName, *VariableNameSize);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Send data to SMM
|
||||||
|
//
|
||||||
|
Status = SendCommunicateBuffer (PayloadSize);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get data from SMM.
|
||||||
|
//
|
||||||
|
*VariableNameSize = SmmGetNextVariableName->NameSize;
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
CopyGuid (VendorGuid, &SmmGetNextVariableName->Guid);
|
||||||
|
CopyMem (VariableName, SmmGetNextVariableName->Name, SmmGetNextVariableName->NameSize);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
This code sets variable in storage blocks (Volatile or Non-Volatile).
|
||||||
|
|
||||||
|
@param[in] VariableName Name of Variable to be found.
|
||||||
|
@param[in] VendorGuid Variable vendor GUID.
|
||||||
|
@param[in] Attributes Attribute value of the variable found
|
||||||
|
@param[in] DataSize Size of Data found. If size is less than the
|
||||||
|
data, this value contains the required size.
|
||||||
|
@param[in] Data Data pointer.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
||||||
|
@retval EFI_SUCCESS Set successfully.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES Resource not enough to set variable.
|
||||||
|
@retval EFI_NOT_FOUND Not found.
|
||||||
|
@retval EFI_WRITE_PROTECTED Variable is read-only.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
RuntimeServiceSetVariable (
|
||||||
|
IN CHAR16 *VariableName,
|
||||||
|
IN EFI_GUID *VendorGuid,
|
||||||
|
IN UINT32 Attributes,
|
||||||
|
IN UINTN DataSize,
|
||||||
|
IN VOID *Data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN PayloadSize;
|
||||||
|
SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *SmmVariableHeader;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check input parameters.
|
||||||
|
//
|
||||||
|
if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DataSize != 0 && Data == NULL) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Init the communicate buffer. The buffer data size is:
|
||||||
|
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.
|
||||||
|
//
|
||||||
|
PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) + StrSize (VariableName) + DataSize;
|
||||||
|
Status = InitCommunicateBuffer (&SmmVariableHeader, PayloadSize, SMM_VARIABLE_FUNCTION_SET_VARIABLE);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
ASSERT (SmmVariableHeader != NULL);
|
||||||
|
|
||||||
|
CopyGuid ((EFI_GUID *) &SmmVariableHeader->Guid, VendorGuid);
|
||||||
|
SmmVariableHeader->DataSize = DataSize;
|
||||||
|
SmmVariableHeader->NameSize = StrSize (VariableName);
|
||||||
|
SmmVariableHeader->Attributes = Attributes;
|
||||||
|
CopyMem (SmmVariableHeader->Name, VariableName, SmmVariableHeader->NameSize);
|
||||||
|
CopyMem ((UINT8 *) SmmVariableHeader->Name + SmmVariableHeader->NameSize, Data, DataSize);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Send data to SMM.
|
||||||
|
//
|
||||||
|
Status = SendCommunicateBuffer (PayloadSize);
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This code returns information about the EFI variables.
|
||||||
|
|
||||||
|
@param[in] Attributes Attributes bitmask to specify the type of variables
|
||||||
|
on which to return information.
|
||||||
|
@param[out] MaximumVariableStorageSize Pointer to the maximum size of the storage space available
|
||||||
|
for the EFI variables associated with the attributes specified.
|
||||||
|
@param[out] RemainingVariableStorageSize Pointer to the remaining size of the storage space available
|
||||||
|
for EFI variables associated with the attributes specified.
|
||||||
|
@param[out] MaximumVariableSize Pointer to the maximum size of an individual EFI variables
|
||||||
|
associated with the attributes specified.
|
||||||
|
|
||||||
|
@retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied.
|
||||||
|
@retval EFI_SUCCESS Query successfully.
|
||||||
|
@retval EFI_UNSUPPORTED The attribute is not supported on this platform.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
RuntimeServiceQueryVariableInfo (
|
||||||
|
IN UINT32 Attributes,
|
||||||
|
OUT UINT64 *MaximumVariableStorageSize,
|
||||||
|
OUT UINT64 *RemainingVariableStorageSize,
|
||||||
|
OUT UINT64 *MaximumVariableSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN PayloadSize;
|
||||||
|
SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *SmmQueryVariableInfo;
|
||||||
|
|
||||||
|
if(MaximumVariableStorageSize == NULL || RemainingVariableStorageSize == NULL || MaximumVariableSize == NULL || Attributes == 0) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Init the communicate buffer. The buffer data size is:
|
||||||
|
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize;
|
||||||
|
//
|
||||||
|
PayloadSize = sizeof (SMM_VARIABLE_COMMUNICATE_VARIABLE_INFO_ENTRY);
|
||||||
|
Status = InitCommunicateBuffer (&SmmQueryVariableInfo, PayloadSize, SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
ASSERT (SmmQueryVariableInfo != NULL);
|
||||||
|
|
||||||
|
SmmQueryVariableInfo->Attributes = Attributes;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Send data to SMM.
|
||||||
|
//
|
||||||
|
Status = SendCommunicateBuffer (PayloadSize);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get data from SMM.
|
||||||
|
//
|
||||||
|
*MaximumVariableSize = SmmQueryVariableInfo->MaximumVariableSize;
|
||||||
|
*MaximumVariableStorageSize = SmmQueryVariableInfo->MaximumVariableStorageSize;
|
||||||
|
*RemainingVariableStorageSize = SmmQueryVariableInfo->RemainingVariableStorageSize;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Exit Boot Services Event notification handler.
|
||||||
|
|
||||||
|
Notify SMM variable driver about the event.
|
||||||
|
|
||||||
|
@param[in] Event Event whose notification function is being invoked.
|
||||||
|
@param[in] Context Pointer to the notification function's context.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
OnExitBootServices (
|
||||||
|
IN EFI_EVENT Event,
|
||||||
|
IN VOID *Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Init the communicate buffer. The buffer data size is:
|
||||||
|
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.
|
||||||
|
//
|
||||||
|
InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Send data to SMM.
|
||||||
|
//
|
||||||
|
SendCommunicateBuffer (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
On Ready To Boot Services Event notification handler.
|
||||||
|
|
||||||
|
Notify SMM variable driver about the event.
|
||||||
|
|
||||||
|
@param[in] Event Event whose notification function is being invoked
|
||||||
|
@param[in] Context Pointer to the notification function's context
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
OnReadyToBoot (
|
||||||
|
IN EFI_EVENT Event,
|
||||||
|
IN VOID *Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Init the communicate buffer. The buffer data size is:
|
||||||
|
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.
|
||||||
|
//
|
||||||
|
InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_READY_TO_BOOT);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Send data to SMM.
|
||||||
|
//
|
||||||
|
SendCommunicateBuffer (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
|
||||||
|
|
||||||
|
This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
|
||||||
|
It convers pointer to new virtual address.
|
||||||
|
|
||||||
|
@param[in] Event Event whose notification function is being invoked.
|
||||||
|
@param[in] Context Pointer to the notification function's context.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
VariableAddressChangeEvent (
|
||||||
|
IN EFI_EVENT Event,
|
||||||
|
IN VOID *Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EfiConvertPointer (0x0, (VOID **) &mVariableBuffer);
|
||||||
|
EfiConvertPointer (0x0, (VOID **) &mSmmCommunication);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialize variable service and install Variable Architectural protocol.
|
||||||
|
|
||||||
|
@param[in] Event Event whose notification function is being invoked.
|
||||||
|
@param[in] Context Pointer to the notification function's context.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
SmmVariableReady (
|
||||||
|
IN EFI_EVENT Event,
|
||||||
|
IN VOID *Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
Status = gBS->LocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **)&mSmmVariable);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &mSmmCommunication);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Allocate memory for variable store.
|
||||||
|
//
|
||||||
|
mVariableBufferSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
|
||||||
|
mVariableBufferSize += MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize));
|
||||||
|
mVariableBuffer = AllocateRuntimePool (mVariableBufferSize);
|
||||||
|
ASSERT (mVariableBuffer != NULL);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Save the buffer physical address used for SMM conmunication.
|
||||||
|
//
|
||||||
|
mVariableBufferPhysical = mVariableBuffer;
|
||||||
|
|
||||||
|
gRT->GetVariable = RuntimeServiceGetVariable;
|
||||||
|
gRT->GetNextVariableName = RuntimeServiceGetNextVariableName;
|
||||||
|
gRT->SetVariable = RuntimeServiceSetVariable;
|
||||||
|
gRT->QueryVariableInfo = RuntimeServiceQueryVariableInfo;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Install the Variable Architectural Protocol on a new handle.
|
||||||
|
//
|
||||||
|
Status = gBS->InstallProtocolInterface (
|
||||||
|
&mHandle,
|
||||||
|
&gEfiVariableArchProtocolGuid,
|
||||||
|
EFI_NATIVE_INTERFACE,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
SMM Non-Volatile variable write service is ready notify event handler.
|
||||||
|
|
||||||
|
@param[in] Event Event whose notification function is being invoked.
|
||||||
|
@param[in] Context Pointer to the notification function's context.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
SmmVariableWriteReady (
|
||||||
|
IN EFI_EVENT Event,
|
||||||
|
IN VOID *Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
VOID *ProtocolOps;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check whether the protocol is installed or not.
|
||||||
|
//
|
||||||
|
Status = gBS->LocateProtocol (&mSmmVariableWriteGuid, NULL, (VOID **) &ProtocolOps);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = gBS->InstallProtocolInterface (
|
||||||
|
&mHandle,
|
||||||
|
&gEfiVariableWriteArchProtocolGuid,
|
||||||
|
EFI_NATIVE_INTERFACE,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Variable Driver main entry point. The Variable driver places the 4 EFI
|
||||||
|
runtime services in the EFI System Table and installs arch protocols
|
||||||
|
for variable read and write services being availible. It also registers
|
||||||
|
a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
|
||||||
|
|
||||||
|
@param[in] ImageHandle The firmware allocated handle for the EFI image.
|
||||||
|
@param[in] SystemTable A pointer to the EFI System Table.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Variable service successfully initialized.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
VariableSmmRuntimeInitialize (
|
||||||
|
IN EFI_HANDLE ImageHandle,
|
||||||
|
IN EFI_SYSTEM_TABLE *SystemTable
|
||||||
|
)
|
||||||
|
{
|
||||||
|
VOID *SmmVariableRegistration;
|
||||||
|
VOID *SmmVariableWriteRegistration;
|
||||||
|
EFI_EVENT OnReadyToBootEvent;
|
||||||
|
EFI_EVENT ExitBootServiceEvent;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Smm variable service is ready
|
||||||
|
//
|
||||||
|
EfiCreateProtocolNotifyEvent (
|
||||||
|
&gEfiSmmVariableProtocolGuid,
|
||||||
|
TPL_CALLBACK,
|
||||||
|
SmmVariableReady,
|
||||||
|
NULL,
|
||||||
|
&SmmVariableRegistration
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Smm Non-Volatile variable write service is ready
|
||||||
|
//
|
||||||
|
EfiCreateProtocolNotifyEvent (
|
||||||
|
&mSmmVariableWriteGuid,
|
||||||
|
TPL_CALLBACK,
|
||||||
|
SmmVariableWriteReady,
|
||||||
|
NULL,
|
||||||
|
&SmmVariableWriteRegistration
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Register the event to reclaim variable for OS usage.
|
||||||
|
//
|
||||||
|
EfiCreateEventReadyToBootEx (
|
||||||
|
TPL_NOTIFY,
|
||||||
|
OnReadyToBoot,
|
||||||
|
NULL,
|
||||||
|
&OnReadyToBootEvent
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Register the event to inform SMM variable that it is at runtime.
|
||||||
|
//
|
||||||
|
gBS->CreateEventEx (
|
||||||
|
EVT_NOTIFY_SIGNAL,
|
||||||
|
TPL_NOTIFY,
|
||||||
|
OnExitBootServices,
|
||||||
|
NULL,
|
||||||
|
&gEfiEventExitBootServicesGuid,
|
||||||
|
&ExitBootServiceEvent
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Register the event to convert the pointer for runtime.
|
||||||
|
//
|
||||||
|
gBS->CreateEventEx (
|
||||||
|
EVT_NOTIFY_SIGNAL,
|
||||||
|
TPL_NOTIFY,
|
||||||
|
VariableAddressChangeEvent,
|
||||||
|
NULL,
|
||||||
|
&gEfiEventVirtualAddressChangeGuid,
|
||||||
|
&mVirtualAddressChangeEvent
|
||||||
|
);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,69 @@
|
|||||||
|
## @file
|
||||||
|
# Component description file for Variable SmmRuntimeDxe module.
|
||||||
|
#
|
||||||
|
# This module is the Runtime DXE part correspond to SMM variable module. It
|
||||||
|
# installs variable arch protocol and variable write arch protocol and works
|
||||||
|
# with SMM variable module together.
|
||||||
|
# Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||||
|
#
|
||||||
|
# This program and the accompanying materials
|
||||||
|
# are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
# which accompanies this distribution. The full text of the license may be found at
|
||||||
|
# http://opensource.org/licenses/bsd-license.php
|
||||||
|
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
##
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
INF_VERSION = 0x00010005
|
||||||
|
BASE_NAME = VariableSmmRuntimeDxe
|
||||||
|
FILE_GUID = 9F7DCADE-11EA-448a-A46F-76E003657DD1
|
||||||
|
MODULE_TYPE = DXE_RUNTIME_DRIVER
|
||||||
|
VERSION_STRING = 1.0
|
||||||
|
ENTRY_POINT = VariableSmmRuntimeInitialize
|
||||||
|
|
||||||
|
#
|
||||||
|
# The following information is for reference only and not required by the build tools.
|
||||||
|
#
|
||||||
|
# VALID_ARCHITECTURES = IA32 X64
|
||||||
|
#
|
||||||
|
# VIRTUAL_ADDRESS_MAP_CALLBACK = VariableAddressChangeEvent
|
||||||
|
#
|
||||||
|
|
||||||
|
[Sources]
|
||||||
|
VariableSmmRuntimeDxe.c
|
||||||
|
VariableSmmCommon.h
|
||||||
|
|
||||||
|
[Packages]
|
||||||
|
MdePkg/MdePkg.dec
|
||||||
|
MdeModulePkg/MdeModulePkg.dec
|
||||||
|
SecurityPkg/SecurityPkg.dec
|
||||||
|
|
||||||
|
[LibraryClasses]
|
||||||
|
MemoryAllocationLib
|
||||||
|
BaseLib
|
||||||
|
UefiBootServicesTableLib
|
||||||
|
DebugLib
|
||||||
|
UefiRuntimeLib
|
||||||
|
DxeServicesTableLib
|
||||||
|
UefiDriverEntryPoint
|
||||||
|
PcdLib
|
||||||
|
|
||||||
|
[Protocols]
|
||||||
|
gEfiVariableWriteArchProtocolGuid ## ALWAYS_PRODUCES
|
||||||
|
gEfiVariableArchProtocolGuid ## ALWAYS_PRODUCES
|
||||||
|
gEfiSmmCommunicationProtocolGuid
|
||||||
|
gEfiSmmVariableProtocolGuid
|
||||||
|
|
||||||
|
[Guids]
|
||||||
|
gEfiEventVirtualAddressChangeGuid ## PRODUCES ## Event
|
||||||
|
|
||||||
|
[Pcd]
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
|
||||||
|
|
||||||
|
[Depex]
|
||||||
|
gEfiSmmCommunicationProtocolGuid
|
Reference in New Issue
Block a user