# 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*