Newer
Older
AMI-Aptio-BIOS-Reversed / MdePkg / Library / UefiBootServicesTableLib / AmiDeviceGuardApi / AmiDeviceGuardApi.md
@Ajax Dong Ajax Dong 2 days ago 15 KB Restructure the repo

AmiDeviceGuardApi

Function Table

Address Name Description
GetImageSecurityDatabase
AsciiStrLen
ZeroMem
HobLibInit
CompareGuid
ReadUnaligned64
WriteUnaligned64
GetTimeStampSize
SetVariableWithTimestamp
FindCertificateInSignatureList
CpuId
GetDebugLevelFromCmos
DebugPrint
DebugAssert
FreePool
IsMatchingHobGuid
LocateHandleBufferByProtocol
GetFvbProtocol
GetFvbAndReadData
FreeFvbBuffer
FindCertificateBySubject
ParseDbSignatureData
AppendSignatureEntry
ReadSignatureDatabase
UpdateSignatureDatabase
ReadVariableFromFvb
FreeFvbReadBuffer
DeviceGuardEntryPoint
ReadSignatureDatabaseImpl
FindCertificateBySubjectImpl
AppendSignatureEntryImpl
UpdateSignatureDatabaseImpl
Global protocol GUID
EFI_GUID gAmiDeviceGuardApiProtocolGuid = AMI_DEVICE_GUARD_API_PROTOCOL_GUID;
Globals (from .data segment, addresses relative to image base)
0x1F10 - gEfiFirmwareVolumeBlockProtocolGuid or similar protocol GUID
Used to locate the debug mask protocol.
STATIC EFI_GUID mDebugProtocolGuid;
0x1F20 - EFI_GLOBAL_VARIABLE GUID
Used for access to "db" UEFI variable.
STATIC EFI_GUID mGlobalVariableGuid;
0x1F30 - First component GUID for timestamp magic
0x1F38 - Second component GUID for timestamp magic
Used by sub_14A0 when building the timestamp header.
STATIC EFI_GUID mTimeStampGuid1;
0x1F40 - gEfiImageSecurityDatabaseGuid
Protocol used for certificate parsing services.
STATIC EFI_GUID mImageSecurityDatabaseGuid;
0x1F50 - Protocol GUID for locating FVB (Firmware Volume Block)
instances via BootServices->LocateProtocol.
STATIC EFI_GUID mFirmwareVolumeBlockProtocolGuid;
0x1F60 - EFI_CERT_SHA256_GUID value (16-byte buffer).
Compared against signature list type to identify SHA-256
certificate entries.
STATIC UINT8 mCertSha256Guid[16];
0x1F70 - GUID for the Variable Write service inside the
EFI_IMAGE_SECURITY_DATABASE protocol.
STATIC EFI_GUID mVariableWriteGuid;
0x1F80 - First GUID for HOB list owner GUID comparison
0x1F88 - Second GUID for HOB list owner GUID comparison
Used by sub_14E4 to match against HOB owner GUIDs.
STATIC EFI_GUID mHobOwnerGuid1;
0x1F90 - The Device Guard API Protocol GUID structure (installed).
0x1FA0 - Pointer to "Microsoft Corporation UEFI CA 2011" string.
The well-known subject name for the Microsoft UEFI CA 2011
certificate trusted by Windows Secure Boot.
STATIC CONST CHAR8 *mMsftUefiCa2011Subject = "Microsoft Corporation UEFI CA 2011";
0x1FD0 - Protocol instance flag (dword, initialised to 1).
Indicates that the protocol has been installed.
STATIC UINT32 mProtocolInstalled = 0;
0x20A0 - Debug mask protocol pointer (cached)
0x20A8 - HOB list pointer (cached)
STATIC VOID *mDebugMaskProtocol;
Global UEFI table pointers assigned in entry point
EFI_HANDLE gImageHandle = NULL;
Forward declarations for internal helper functions
Functions that are library-level wrappers
Function Implementations
Read CMOS index 0x4B from bank 0x70.
Preserve the NMI disable bit (bit 7).
Index = IoRead8 (0x70);
If DebugLevel > 3 and DebugLevel == 0, read from MEMORY[0xFDAF0490].
if (DebugLevel > 3) {
Map debug level to EFI debug mask.
Level 1 -> INFO (0x00000004)
Level 2 -> WARN (0x00000008)
if (DebugLevel == 1) {
Level 0 or > 2 -> disabled.
return 0;
Debug mask protocol structure
Used for debug print and assertion support.
typedef struct {
Locate the debug mask protocol. The GUID is stored at
address 0x1F10 in the data section.
Status = gBootServices->LocateProtocol (
if (Length >= 8) {
Handle misaligned head
Index = ((UINTN)DestBytes & 7);
Compare aligned 8-byte chunks
while ((UINTN)DestBytes <= (UINTN)(Destination + Length - 8) &&
Compare remaining bytes one at a time
while ((UINTN)DestBytes < (UINTN)(Destination + Length)) {
EDK2 unaligned read: copy byte-by-byte from the buffer.
CopyMem (Value, Buffer, sizeof (UINT64));
Read GUIDs as two 64-bit values for fast comparison.
UINT64 Guid1Part1;
HOB List Support
The HOB list pointer is stored in SystemTable at offset +104
if (gSystemTable->HobList == NULL) {
Iterate through HOBs. Each HOB entry is 24 bytes:
Offset 0: EFI_GUID (16 bytes) - Owner GUID
Offset 16: (8 bytes) - HOB data pointer
while (HobCount < (UINTN)gSystemTable->HobList) {
If we reach here, no matching HOB was found.
Log an assertion failure.
DebugPrint (
Timestamp and Variable Support
Structure consists of:
EFI_TIME (16 bytes) + 0x10 pad/magic + 8 bytes GUID + 8 bytes GUID
return sizeof (EFI_TIME) + 24;
Magic values for timestamp structure initialisation
UINT32 MagicValue = 0x07060402; // 117704678 decimal
927510 decimal
Initialise the MagicValue trackers for debug print
ZeroMem (TimeStamp, sizeof (EFI_TIME) + 24);
Try to get the current time from the runtime services.
If time services are not available, use the magic defaults above.
if (gRuntimeServices != NULL) {
Debug print the time information
Day (MagicValue >> 16) & 0xFF, // Hour
Minute MagicValue2 // Second
Copy time data into timestamp buffer
CopyMem (TimeStamp, &Now, sizeof (EFI_TIME));
Fill in the remaining fields of the timestamp structure:
Offset 16: MonotonicCount
Offset 20: FormatMagic
MonotonicCount (or structure version)
250675712 - format magic
Write the two GUID components for timestamp verification
WriteUnaligned64 ((UINT64 )TimeStamp + 3, (UINT64 *)&mTimeStampGuid1);
Timestamp **attributes: EFI_VARIABLE_NON_VOLATILE **
EFI_VARIABLE_BOOTSERVICE_ACCESS ** **
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS **// (0x21 = NV BS AT)**
UINT32 TimeAttributes;
Attempt to query the current variable size.
If the variable does not exist, gRT->GetVariable returns
EFI_BUFFER_TOO_SMALL with the required size in OldDataSize.
OldDataSize = 0;
The variable exists. Re-write with timestamp attributes.
BuildTimestamp (&TimeStamp);
Attributes **= NV BS AT (0x21) + time-based auth.**
TimeAttributes **= Attributes EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;**
Variable does not exist yet. Use the raw attributes.
TimeAttributes = Attributes;
Now write the variable with the requested data.
Attributes **= NV BS (AT if existing) -> 0x21 or 0x07.**
AttemptAttributes **= TimeAttributes 0x21;**
EFI_UNSUPPORTED (0x800000000000000E) means we succeeded
if (Status == EFI_UNSUPPORTED) {
If the write succeeded, query the old variable size for debug
logging so the caller can see the size change.
if (!EFI_ERROR (Status)) {
Certificate Lookup
Already cached, return existing pointer.
Get the list of all FVB protocol instances
Status = LocateHandleBufferByProtocol (
Iterate through handles to find one where Read can succeed
for (Index = 0; Index < HandleCount; Index++) {
Try to read from the FVB volume
Allocate a buffer and read from FVB
Buffer = AllocatePool (BufferSize);
No suitable FVB handle found
Status = EFI_NOT_FOUND;
Query the "db" variable size first
Allocate a buffer and read the variable data
Data = AllocatePool (DataSize);
Search for the certificate in the signature list
if (DataSize > 0) {
The "db" variable does not exist at all
return EFI_NOT_FOUND;
Get the Image Security Database protocol for certificate parsing
SecurityDatabase = NULL;
Calculate the subject name length
SubjectNameLen = AsciiStrLen (SubjectName);
Allocate a buffer for certificate parsing
CertBufferSize = DataSize + 1;
Count the number of signature lists
Debug print the signature list info
Iterate through each signature list
CertCount = SigListCount;
Calculate the offset to the signature data within this list
UINTN SigDataOffset;
Get the owner GUID from the signature list
Actually owner GUID for this list context
This is simplified
Check if this signature type is EFI_CERT_SHA256_GUID
if (CompareMem (&SigList->SignatureType, mCertSha256Guid, sizeof (EFI_GUID)) == 0) {
Iterate through each signature data entry in this list
SigData = (EFI_SIGNATURE_DATA )((UINT8 )SigList + SigDataOffset);
The signature data contains:
EFI_GUID SignatureOwner (16 bytes)
UINT8 SignatureData[...]
For X.509 certs, the SignatureData starts with the X.509 certificate.
We can search for the subject name within the DER-encoded cert.
UINTN CertDataOffset;
Zero the cert buffer and call the security database to parse
ZeroMem (CertBuffer, CertBufferSize);
If SecurityDatabase is available, call its parse function
if (SecurityDatabase != NULL) {
The security database protocol entry point for parsing
certificates and extracting subject names.
This calls into the Authenticated Variable parser.
UINTN ParsedDataSize;
Call the parse function. This typically invokes
an internal function that extracts the subject from
an X.509 certificate.
if (mDebugMaskProtocol != NULL) {
Use the image security database protocol's parse function
to extract the subject name from the certificate.
Compare the parsed subject name with the target
if (CompareMem (CertBuffer, SubjectName, SubjectNameLen) == 0) {
Move to the next signature data entry
SigData = (EFI_SIGNATURE_DATA )((UINT8 )SigData + SigSize);
Move to the next signature list
SigList = (EFI_SIGNATURE_LIST )((UINT8 )SigList + SigList->SignatureListSize);
Signature Database Update
This function validates the EFI_SIGNATURE_LIST structure(s)
in the buffer and returns the total size of valid entries.
Currently a stub that returns the input size after validation.
if **(Data == NULL ParsedSize == NULL) {**
Step 1: Read the current "db" variable size
Step 2: Allocate and read the current data
DbData = AllocatePool (DbDataSize);
Step 3: Parse the existing data to validate it
Status = ParseDbSignatureData (DbData, &ParsedSize);
Step 4: Allocate a new buffer with room for timestamp + existing + new data
NewDataSize = GetTimeStampSize () + DbDataSize;
Step 5: Build the timestamp at the start of the new buffer
BuildTimestamp ((EFI_TIME *)NewData);
Step 6: Copy existing signature data after the timestamp
Step 7: Write the updated variable
Status = SetVariableWithTimestamp (
Query the "db" variable size
Status = gRuntimeServices->GetVariable (
Step 2: Allocate and read the current variable data
Step 3: Allocate new buffer with room for timestamp
Step 4: Build timestamp at the start
Step 5: Copy existing data after timestamp
Step 6: Write the updated variable
Get the FVB protocol on the given handle
Status = gBootServices->HandleProtocol (
Query FVB size
Allocate buffer and read
Buffer = AllocatePool (Size);
Driver Entry Point
Cache global table pointers.
This mirrors the standard UEFI BootServicesTableLib initialisation.
gImageHandle = ImageHandle;
Initialise the HOB list (required for variable services)
HobLibInit ();
Cache runtime/BS pointers if not already set in the global init above
if (SystemTable->RuntimeServices == NULL) {
Create a new handle and install the Device Guard API protocol.
The protocol is a singleton interface for managing the "db" variable.
Expand 16-bit value to 32-bit pattern
WordValue **= Value ((UINT32)Value << 16);**
Handle misalignment
AlignAdjust = (4 - ((UINTN)ByteBuffer & 3)) & 3;
Fill 4 bytes at a time
WordBuffer = (UINT32 *)ByteBuffer;
Fill remaining bytes
for (Index = 0; Index < Size; Index++) {
Save interrupt state and disable interrupts
InterruptState = SaveAndDisableInterrupts ();
Handle overlapping regions where source < dest
by copying from the end.
if ((UINTN)Source < (UINTN)Destination &&
SrcBytes = (CONST UINT8 *)Source + Length;
Align destination
AlignDelta = (UINTN)DestBytes & 7;
Copy 8 bytes at a time
Count64 = Length >> 3;
Copy remaining bytes backwards
while (Length-- != 0) {
if (Length >= 8 && (UINTN)((INTN)DestBytes - (INTN)SrcBytes) >= 8) {
Align source and destination
Restore interrupt state
RestoreInterrupts (InterruptState);
Protocol Method Implementation (for the installed protocol structure)
The AMI_DEVICE_GUARD_API_PROTOCOL instance
AMI_DEVICE_GUARD_API_PROTOCOL gAmiDeviceGuardApiProtocol = {

Generated by HR650X BIOS Decompilation Project