Newer
Older
AMI-Aptio-BIOS-Reversed / TcgPei / TcgPei.c
@Ajax Dong Ajax Dong 2 days ago 43 KB Init
/*
 * TcgPei.c
 *
 * Combined decompiler listing for the TcgPei PEIM.  Addresses in comments
 * refer to offsets in the recovered IA32 image.  Names and types are recovered
 * artifacts and should be validated before reuse as source-level API.
 */

#include "TcgPei.h"

/* -------------------------------------------------------------------------
 * Memory primitives
 * ------------------------------------------------------------------------- */

// memset_v2 @ 0xffe0a9b8 void *memset_v2(void *buf, unsigned int count, char value)
{
 memset(buf, value, count); /*0xffe0a9c5*/
 return buf; /*0xffe0a9cb*/
}

// memcmp_v2 @ 0xffe0a9d8 int memcmp_v2(_BYTE *a1, _BYTE *a2, int n16)
{
 bool v6; // zf do /*0xffe0a9e6*/
 {
 if ( !n16 ) /*0xffe0a9e6*/
 break; /*0xffe0a9e6*/
 v6 = *a1++ == *a2++; /*0xffe0a9e6*/
 --n16; /*0xffe0a9e6*/
 }
 while ( v6 ); /*0xffe0a9e6*/
 return (unsigned __int8)*(a1 - 1) - (unsigned __int8)*(a2 - 1); /*0xffe0a9f2*/
}

// memmove_v2 @ 0xffe0a9f8 char *memmove_v2(char *dst, char *src, unsigned int count)
{
 unsigned int count_1; // edx char *dst_1; // edi char *src_1; // esi count_1 = count; /*0xffe0aa02*/
 if ( src < dst && &src[count - 1] >= dst ) /*0xffe0aa10*/
 {
 src_1 = &src[count - 1]; /*0xffe0aa24*/
 dst_1 = &dst[count - 1]; /*0xffe0aa26*/
 }
 else
 {
 count_1 = count & 3; /*0xffe0aa14*/
 qmemcpy(dst, src, 4 * (count >> 2)); /*0xffe0aa1d*/
 src_1 = &src[4 * (count >> 2)]; /*0xffe0aa1d*/
 dst_1 = &dst[4 * (count >> 2)]; /*0xffe0aa1d*/
 }
 qmemcpy(dst_1, src_1, count_1); /*0xffe0aa2d*/
 return dst; /*0xffe0aa34*/
}

// SetMem32 @ 0xffe0aa38 int SetMem32(int a1, int a2, int a3, int a4)
{
 do /*0xffe0aa51*/
 {
 *(_DWORD *)(a1 + 8 *a2 - 8) = a3; /*0xffe0aa49*/
 *(_DWORD *)(a1 + 8 *a2-- - 4) = a4; /*0xffe0aa4d*/
 }
 while ( a2 ); /*0xffe0aa51*/
 return a1; /*0xffe0aa55*/
}

// memset32_v2 @ 0xffe0aa58 void *memset32_v2(void *buf, unsigned int count, int value)
{
 memset32(buf, value, count); /*0xffe0aa65*/
 return buf; /*0xffe0aa6b*/
}

/* -------------------------------------------------------------------------
 * PEIM entry and protocol handoff
 * ------------------------------------------------------------------------- */

// _ModuleEntryPoint @ 0xffe0ab18 EFI_STATUS ModuleEntryPoint(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
 int v2; // eax int Signature; // eax EFI_STATUS result; // eax signed __int32 Result; // esi int Signature_1; // eax _DWORD *v7; // edi int Signature_2; // eax char v9; // al int (**v10)(void); // edi int v11; // ecx char v12; // [esp+1h] [ebp-65h] BYREF int Table; // [esp+2h] [ebp-64h] BYREF int Result; // [esp+6h] [ebp-60h] BYREF int ( **v15)(_DWORD, _BYTE *, _DWORD *, _DWORD, int *, _BYTE *); // [esp+Ah] [ebp-5Ch] BYREF int n4; // [esp+Eh] [ebp-58h] BYREF _BYTE v17[4]; // [esp+12h] [ebp-54h] BYREF _DWORD v18[4]; // [esp+16h] [ebp-50h] BYREF _BYTE Table[28]; // [esp+26h] [ebp-40h] BYREF _BYTE MonotonicCounter[34]; // [esp+42h] [ebp-24h] BYREF if ( *(char *)(sub_FFE0CFC8() + 1024068) >= 0 ) /*0xffe0ab29*/
 {
 sub_FFE0CFD4(); /*0xffe0ab2b*/
 v2 = sub_FFE0CFC8(); /*0xffe0ab30*/
 *(_BYTE *)(v2 + 1024068) |= 0x80u; /*0xffe0ab3c*/
 }
 Result = 0; /*0xffe0ab5c*/
 v12 = 0; /*0xffe0ab65*/
 qmemcpy(MonotonicCounter, L"MonotonicCounter", sizeof(MonotonicCounter)); /*0xffe0ab6a*/
 Signature = SystemTable->Hdr.Signature; /*0xffe0ab73*/
 n4 = 4; /*0xffe0ab7e*/
 v18[0] = unk_FFE0D3D4; /*0xffe0ab88*/
 v18[1] = unk_FFE0D3D8; /*0xffe0ab89*/
 v18[2] = unk_FFE0D3DC; /*0xffe0ab8a*/
 v18[3] = unk_FFE0D3E0; /*0xffe0ab8b*/
 if ( (*(int ( **)(EFI_SYSTEM_TABLE *, void *))(Signature + 24))(SystemTable, &SystemTable_) < 0 ) /*0xffe0ab93*/
 return -1610612735; /*0xffe0ab9a*/
 result = (*(int ( **)(EFI_SYSTEM_TABLE *, void *, _DWORD, _DWORD, int *))(LODWORD(SystemTable->Hdr.Signature) /*0xffe0abb0*/
 + 32))(
 SystemTable,
 &SystemTable__0,
 0,
 0,
 &Result);
 if ( (result & 0x80000000) == 0 && Result ) /*0xffe0abc4*/
 {
 (*(void ( **)(EFI_SYSTEM_TABLE *, _BYTE *))(Result + 4))(SystemTable, Table); /*0xffe0abd0*/
 if ( Table[6] != 1 ) /*0xffe0abda*/
 {
 result = (*(int ( **)(EFI_SYSTEM_TABLE *, void *, _DWORD, _DWORD, int ( ***)(_DWORD, _BYTE *, _DWORD *, _DWORD, int *, _BYTE *)))(LODWORD(SystemTable->Hdr.Signature) + 32))( /*0xffe0abf1*/
 SystemTable,
 &unk_FFE0DB58,
 0,
 0,
 &v15);
 if ( (result & 0x80000000) != 0 || !v15 ) /*0xffe0ac05*/
 return result; /*0xffe0ac05*/
 Result = (*v15)(v15, MonotonicCounter, v18, 0, &n4, v17); /*0xffe0ac24*/
 if ( Result < 0 ) /*0xffe0ac2b*/
 {
 Signature_1 = SystemTable->Hdr.Signature; /*0xffe0ac2d*/
 v12 = 1; /*0xffe0ac38*/
 Result = (*(int ( **)(EFI_SYSTEM_TABLE *, int, int, int *))(Signature_1 + 52))(SystemTable, 4, 25, &Table); /*0xffe0ac40*/
 if ( Result >= 0 ) /*0xffe0ac47*/
 {
 v7 = (_DWORD *)(Table + 8); /*0xffe0ac52*/
 *(_DWORD *)(Table + 8) = unk_FFE0DBA8; /*0xffe0ac55*/
 *++v7 = unk_FFE0DBAC; /*0xffe0ac56*/
 *++v7 = unk_FFE0DBB0; /*0xffe0ac57*/
 v7[1] = unk_FFE0DBB4; /*0xffe0ac58*/
 Result = 0; /*0xffe0ac59*/
 Signature_2 = SystemTable->Hdr.Signature; /*0xffe0ac67*/
 Table += 24; /*0xffe0ac70*/
 (*(void ( **)(int, char *, int))(Signature_2 + 80))(Table, &v12, 1); /*0xffe0ac74*/
 }
 }
 v9 = 0; /*0xffe0ac7f*/
 if ( sub_FFE0B919 ) /*0xffe0ac83*/
 {
 v10 = &off_FFE0D474; /*0xffe0ac85*/
 while ( !v9 ) /*0xffe0ac8c*/
 {
 v9 = (*v10++)(); /*0xffe0ac92*/
 if ( !*v10 ) /*0xffe0ac96*/
 {
 if ( v9 ) /*0xffe0ac9d*/
 return 0; /*0xffe0ac9d*/
 goto LABEL_18; /*0xffe0ac9d*/
 }
 }
 return 0; /*0xffe0ac8c*/
 }
LABEL_18:
 if ( !sub_FFE0B3B4() ) /*0xffe0aca3*/
 {
 Result = sub_FFE0B18A(v11, (int *)SystemTable); /*0xffe0acb3*/
 sub_FFE0B2E8(64, "TpmPeiEntry results = %r \n", Result); /*0xffe0acbd*/
 if ( Result < 0 ) /*0xffe0acc7*/
 return Result; /*0xffe0accb*/
 }
 if ( Table[0] && Result >= 0 ) /*0xffe0acd6*/
 {
 sub_FFE0B2E8(64, "TcgPeiEntry processing\n"); /*0xffe0acdf*/
 if ( sub_FFE0B3B4() ) /*0xffe0ace6*/
 return (*(int ( **)(EFI_SYSTEM_TABLE *, void *))(LODWORD(SystemTable->Hdr.Signature) + 24))( /*0xffe0ad14*/
 SystemTable,
 &unk_FFE0DBE8);
 if ( MEMORY[0xFED40000] == 0xFF || !MEMORY[0xFED40000] ) /*0xffe0acfc*/
 return -2147483634; /*0xffe0ad05*/
 return (*(int ( **)(EFI_SYSTEM_TABLE *, void *))(LODWORD(SystemTable->Hdr.Signature) + 24))( /*0xffe0ad03*/
 SystemTable,
 &unk_FFE0DC00);
 }
 sub_FFE0B2E8(0x80000000, "ConfigFlags.TpmSupport == 0x00 || EFI_ERROR( Status )\n"); /*0xffe0ad25*/
 }
 return 0; /*0xffe0ad2c*/
 }
 return result; /*0xffe0ad35*/
}

// LocateProtocolAndHandOff @ 0xffe0ad36 int LocateProtocolAndHandOff(
 int a1,
 int ( ***a2)(_DWORD, void *, _DWORD, _DWORD, _DWORD),
 int a3,
 int a4,
 int a5,
 int a6)
{
 int v6; // eax int v7; // esi v6 = (*a2)[8](a2, &unk_FFE0DB88, 0, 0, &a2); /*0xffe0ad4d*/
 v7 = v6; /*0xffe0ad50*/
 if ( v6 >= 0 ) /*0xffe0ad57*/
 return ((int ( *)(int, int, int, int, int))a2[6])(-19660800, a4, a3, a6, a5); /*0xffe0ad84*/
 sub_FFE0B2E8(0x80000000, "Locate TcgPeiPassThroughToTcm Status == %r\n", v6); /*0xffe0ad64*/
 return v7; /*0xffe0ad8a*/
}

// Return_NotStarted @ 0xffe0ad8d int Return_NotStarted()
{
 return -2147483645; /*0xffe0ad92*/
}

/* -------------------------------------------------------------------------
 * TPM 1.2 command transport and command helpers
 * ------------------------------------------------------------------------- */

// Tpm12Transmit @ 0xffe0ad93 int Tpm12Transmit(int a1, int a2, _DWORD *a3, _DWORD *a4)
{
 _DWORD *v4; // ebx unsigned int Index; // ebp int Status; // eax int v8; // eax int Result; // edx int v10; // edi unsigned int v11; // ecx _DWORD *v12; // esi int v13; // [esp+4h] [ebp-Ch] BYREF _BYTE v14[4]; // [esp+8h] [ebp-8h] BYREF int v15; // [esp+Ch] [ebp-4h]

 v4 = a3; /*0xffe0ad97*/
 if ( a3[1] == -2147483641 && *a3 != 7 ) /*0xffe0ada7*/
 return 0; /*0xffe0ada9*/
 Index = 0; /*0xffe0adbb*/
 v15 = a2; /*0xffe0adbd*/
 Status = (*(int ( **)(int, void *, _DWORD, _DWORD, _BYTE *))(*(_DWORD *)a2 + 32))(a2, &unk_FFE0DB78, 0, 0, v14); /*0xffe0adcb*/
 if ( Status < 0 ) /*0xffe0add3*/
 {
 sub_FFE0B2E8(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status); /*0xffe0ade0*/
 v8 = sub_FFE0B2B7(); /*0xffe0ade8*/
 if ( v8 ) /*0xffe0adef*/
 (*(void ( **)(const char *, int, const char *))(v8 + 4))( /*0xffe0ae00*/
 "e:\\hs\\AmiModulePkg\\TCG2\\Common\\TcgPei\\TcgTisPei.c",
 225,
 "!EFI_ERROR (Status)");
 }
 Result = (*(int ( **)(int, _DWORD **))(*(_DWORD *)a2 + 48))(a2, &a3); /*0xffe0ae11*/
 if ( Result >= 0 ) /*0xffe0ae17*/
 {
 Result = sub_FFE0B46E(&v13); /*0xffe0ae28*/
 if ( Result >= 0 ) /*0xffe0ae2e*/
 {
 v10 = v13; /*0xffe0ae31*/
 v11 = *(_DWORD *)(v13 + 8); /*0xffe0ae35*/
 v12 = (_DWORD *)(v13 + 40); /*0xffe0ae38*/
 if ( v11 ) /*0xffe0ae3d*/
 {
 do /*0xffe0ae53*/
 {
 if ( !v12 ) /*0xffe0ae41*/
 break; /*0xffe0ae41*/
 if ( *v12 > 0x18u ) /*0xffe0ae46*/
 break; /*0xffe0ae46*/
 v12 = (_DWORD *)((char *)v12 + v12[7] + 32); /*0xffe0ae4e*/
 ++Index; /*0xffe0ae50*/
 }
 while ( Index < v11 ); /*0xffe0ae53*/
 }
 sub_FFE0B2E8(64, "NextLocation= %x\n", v12); /*0xffe0ae5d*/
 if ( v4[7] <= 0xFFFFFFDF ) /*0xffe0ae69*/
 {
 Result = sub_FFE0B41F((unsigned int)v12, (_DWORD *)(v10 + 4), v4); /*0xffe0ae82*/
 if ( Result >= 0 ) /*0xffe0ae88*/
 *a4 = (*(_DWORD *)(v10 + 8))++; /*0xffe0ae91*/
 }
 else
 {
 return -2147483639; /*0xffe0ae6b*/
 }
 }
 }
 return Result; /*0xffe0ae9b*/
}

// Tpm12Receive @ 0xffe0aea0 int Tpm12Receive(int *a1, unsigned int a2, int a3, int a4)
{
 int v4; // eax _DWORD v6[6]; // [esp+8h] [ebp-44h] BYREF _DWORD v7[4]; // [esp+20h] [ebp-2Ch] BYREF char v8; // [esp+30h] [ebp-1Ch] BYREF __int16 v9; // [esp+3Ch] [ebp-10h] BYREF int n570425344; // [esp+3Eh] [ebp-Eh]
 int n335544320; // [esp+42h] [ebp-Ah]
 unsigned int v12; // [esp+48h] [ebp-4h] BYREF v6[3] = 4; /*0xffe0aeab*/
 v6[0] = &v9; /*0xffe0aeb2*/
 v6[1] = 10; /*0xffe0aebd*/
 v6[2] = &v12; /*0xffe0aec0*/
 v6[4] = a3; /*0xffe0aec6*/
 v7[0] = &v8; /*0xffe0aecc*/
 v7[2] = a4; /*0xffe0aed2*/
 v6[5] = 20; /*0xffe0aedd*/
 v7[3] = 20; /*0xffe0aee0*/
 v9 = -16128; /*0xffe0aee5*/
 v7[1] = 10; /*0xffe0aef1*/
 n570425344 = 570425344; /*0xffe0aef9*/
 n335544320 = 335544320; /*0xffe0af0f*/
 v4 = *a1; /*0xffe0af1b*/
 v12 = (((a2 << 16) | a2 & 0xFF00) << 8) | ((HIWORD(a2) | a2 & 0xFF0000) >> 8); /*0xffe0af1d*/
 return (*(int ( **)(int, int, int, _DWORD *, int, _DWORD *))(v4 + 12))(v4, a1[1], 3, v6, 2, v7); /*0xffe0af36*/
}

// Tpm12Command_Extend @ 0xffe0af3c int Tpm12Command_Extend(int a1, int a2, char *src, unsigned int i, unsigned int *a5, _DWORD *a6)
{
 int Status; // eax int ReportStatusCodeProtocol; // eax int buf_1; // ecx int Result; // ebx int v11[2]; // [esp+Ch] [ebp-8Ch] BYREF _BYTE v12[20]; // [esp+14h] [ebp-84h] BYREF char v13[20]; // [esp+28h] [ebp-70h] BYREF _DWORD buf[23]; // [esp+3Ch] [ebp-5Ch] BYREF v11[1] = a2; /*0xffe0af53*/
 Status = (*(int ( **)(int, void *, _DWORD, _DWORD, int *))(*(_DWORD *)a2 + 32))(a2, &unk_FFE0DB78, 0, 0, v11); /*0xffe0af61*/
 if ( Status < 0 ) /*0xffe0af69*/
 {
 DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status); /*0xffe0af76*/
 ReportStatusCodeProtocol = GetReportStatusCodeProtocol(); /*0xffe0af7e*/
 if ( ReportStatusCodeProtocol ) /*0xffe0af85*/
 (*(void ( **)(const char *, int, const char *))(ReportStatusCodeProtocol + 4))( /*0xffe0af96*/
 "e:\\hs\\AmiModulePkg\\TCG2\\Common\\TcgPei\\TcgTisPei.c",
 350,
 "!EFI_ERROR (Status)");
 }
 if ( a5[1] == -2147483641 && *a5 != 7 ) /*0xffe0afaf*/
 return 0; /*0xffe0afb1*/
 if ( a5[1] == 3 ) /*0xffe0afbc*/
 {
 (*(void ( **)(unsigned int *, int, _DWORD))(*(_DWORD *)a2 + 84))(a5 + 2, 20, 0); /*0xffe0afc7*/
 return Tpm12Transmit(a1, a2, a5, a6); /*0xffe0afda*/
 }
 else
 {
 Sha1Init(buf); /*0xffe0afec*/
 Sha1Update(buf_1, src, i); /*0xffe0afff*/
 Sha1Final((int)v12, buf); /*0xffe0b00c*/
 memset_TpmCmd((unsigned int)(a5 + 2), v12, 20); /*0xffe0b01d*/
 Result = (*(int ( **)(int, int))v11[0])(v11[0], a2); /*0xffe0b02a*/
 if ( Result >= 0 ) /*0xffe0b031*/
 {
 Result = Tpm12Receive(v11, *a5, (int)(a5 + 2), (int)v13); /*0xffe0b044*/
 if ( Result >= 0 ) /*0xffe0b04a*/
 Result = Tpm12Transmit(a1, a2, a5, a6); /*0xffe0b064*/
 }
 (*(void ( **)(int, int))(v11[0] + 4))(v11[0], a2); /*0xffe0b06c*/
 return Result; /*0xffe0b071*/
 }
}

// Tpm12Command_GetRandom @ 0xffe0b07e int Tpm12Command_GetRandom(int a1, _DWORD *a2, int a3, int a4, int a5, int a6)
{
 int v6; // eax int Status; // eax int v8; // eax _DWORD v10[2]; // [esp+0h] [ebp-18h] BYREF _DWORD v11[2]; // [esp+8h] [ebp-10h] BYREF int v12; // [esp+10h] [ebp-8h] BYREF _DWORD *v13; // [esp+14h] [ebp-4h]

 v6 = *a2; /*0xffe0b08f*/
 v13 = a2; /*0xffe0b097*/
 Status = (*(int ( **)(_DWORD *, void *, _DWORD, _DWORD, int *))(v6 + 32))(a2, &unk_FFE0DB78, 0, 0, &v12); /*0xffe0b09a*/
 if ( Status < 0 ) /*0xffe0b0a2*/
 {
 sub_FFE0B2E8(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status); /*0xffe0b0af*/
 v8 = sub_FFE0B2B7(); /*0xffe0b0b7*/
 if ( v8 ) /*0xffe0b0be*/
 (*(void ( **)(const char *, int, const char *))(v8 + 4))( /*0xffe0b0cf*/
 "e:\\hs\\AmiModulePkg\\TCG2\\Common\\TcgPei\\TcgTisPei.c",
 442,
 "!EFI_ERROR (Status)");
 }
 v10[0] = a4; /*0xffe0b0d8*/
 v10[1] = a3; /*0xffe0b0de*/
 v11[0] = a6; /*0xffe0b0e4*/
 v11[1] = a5; /*0xffe0b0ea*/
 return (*(int ( **)(int, _DWORD *, int, _DWORD *, int, _DWORD *))(v12 + 12))(v12, v13, 1, v10, 1, v11); /*0xffe0b106*/
}

// Tpm12Command_PhysicalPresence @ 0xffe0b10a int Tpm12Command_PhysicalPresence(int a1)
{
 void *v1; // ecx char *v2; // esi int n30000; // ebx int n5; // edi char v5; // al v2 = *(char **)(a1 + 16); /*0xffe0b10f*/
 if ( (*v2 & 0x20) != 0 ) /*0xffe0b116*/
 return 0; /*0xffe0b118*/
 *v2 = 2; /*0xffe0b11e*/
 n30000 = 30000; /*0xffe0b121*/
 while ( 1 ) /*0xffe0b128*/
 {
 n5 = 5; /*0xffe0b128*/
 do /*0xffe0b131*/
 {
 sub_FFE0B37F(v1); /*0xffe0b129*/
 --n5; /*0xffe0b12e*/
 }
 while ( n5 ); /*0xffe0b131*/
 v1 = 0; /*0xffe0b135*/
 if ( (*v2 & 0x20) != 0 && *v2 < 0 ) /*0xffe0b13f*/
 break; /*0xffe0b13f*/
 if ( !--n30000 ) /*0xffe0b144*/
 {
 v5 = 0; /*0xffe0b146*/
 goto LABEL_10; /*0xffe0b146*/
 }
 }
 v5 = *v2 & 0x20; /*0xffe0b159*/
LABEL_10:
 if ( !v5 ) /*0xffe0b14c*/
 return -2147483642; /*0xffe0b14e*/
 return (int)v1; /*0xffe0b155*/
}

// Tpm12Command_GetCapability_SubOwner @ 0xffe0b15d int Tpm12Command_GetCapability_SubOwner(int a1)
{
 return sub_FFE0B58B(*(char **)(a1 + 16)); /*0xffe0b16a*/
}

// Tpm12Command_ForceClear @ 0xffe0b16b int Tpm12Command_ForceClear(int a1, int a2, unsigned int a3, int a4, unsigned int a5, int a6)
{
 return sub_FFE0B786(*(char **)(a1 + 16), a3, a4, a5, a6); /*0xffe0b188*/
}

/* -------------------------------------------------------------------------
 * TPM PEI initialization and device presence
 * ------------------------------------------------------------------------- */

// TpmPeiInit @ 0xffe0b18a int TpmPeiInit(int a1, int *SystemTable)
{
 int Result; // edi int Result; // eax int result; // eax bool v6; // bl bool v7; // [esp+13h] [ebp-21h]
 int Result; // [esp+14h] [ebp-20h] BYREF _BYTE v9[6]; // [esp+18h] [ebp-1Ch] BYREF unsigned __int8 Table; // [esp+1Eh] [ebp-16h]

 Result = 0; /*0xffe0b198*/
 Result = *SystemTable; /*0xffe0b19b*/
 Result = 0; /*0xffe0b1a4*/
 result = (*(int ( **)(int *, void *, _DWORD, _DWORD, int *))(Result + 32))(SystemTable, &SystemTable__0, 0, 0, &Result); /*0xffe0b1a8*/
 if ( result >= 0 && Result ) /*0xffe0b1ba*/
 {
 sub_FFE0B2E8(64, "before getTcgPeiPolicy\n"); /*0xffe0b1c9*/
 (*(void ( **)(int *, _BYTE *))(Result + 4))(SystemTable, v9); /*0xffe0b1d8*/
 if ( Table ) /*0xffe0b1e3*/
 {
 v6 = sub_FFE0B8E5(); /*0xffe0b1fb*/
 sub_FFE0B2E8(64, "CrbSupport = %x \n", v6); /*0xffe0b207*/
 if ( v6 ) /*0xffe0b211*/
 return -2147483634; /*0xffe0b2aa*/
 (*(void ( **)(int *, void *))(*SystemTable + 24))(SystemTable, &unk_FFE0DC30); /*0xffe0b21f*/
 }
 else
 {
 (*(void ( **)(int *, void *))(*SystemTable + 24))(SystemTable, &unk_FFE0DC30); /*0xffe0b1ed*/
 v6 = v7; /*0xffe0b1f0*/
 }
 sub_FFE0B2E8(64, "TpmDevice Ppi Installed\n"); /*0xffe0b22a*/
 sub_FFE0B2E8(64, "TpmPeientry ConfigFlags.DeviceType = %x\n", Table); /*0xffe0b23b*/
 if ( *(_BYTE *)dword_FFE0DC28 == 0xFF || !*(_BYTE *)dword_FFE0DC28 ) /*0xffe0b252*/
 Result = -2147483634; /*0xffe0b257*/
 sub_FFE0B2E8(64, "IsTpmPresent results = %r\n", Result); /*0xffe0b260*/
 sub_FFE0B2E8(64, "IsTpmPresent base = %x\n", dword_FFE0DC28); /*0xffe0b277*/
 sub_FFE0B2E8(64, "IsTpmPresent Access reg = %x\n", *(unsigned __int8 *)dword_FFE0DC28); /*0xffe0b28b*/
 if ( Result >= 0 && Table && v6 ) /*0xffe0b2a0*/
 return -2147483634; /*0xffe0b2a2*/
 else return Result; /*0xffe0b2a6*/
 }
 return result; /*0xffe0b2af*/
}

/* -------------------------------------------------------------------------
 * Debug, delay, and low-level I/O support
 * ------------------------------------------------------------------------- */

// GetReportStatusCodeProtocol @ 0xffe0b2b7 int GetReportStatusCodeProtocol()
{
 int v0; // eax int v2; // [esp+0h] [ebp-8h] BYREF int Result; // [esp+4h] [ebp-4h] BYREF v0 = sub_FFE0CF96(); /*0xffe0b2bc*/
 if ( (*(int ( **)(int, void *, _DWORD, int *, int *))(*(_DWORD *)v0 + 32))(v0, &unk_FFE0DB68, 0, &v2, &Result) >= 0 ) /*0xffe0b2db*/
 return Result; /*0xffe0b2e1*/
 else return 0; /*0xffe0b2dd*/
}

// DebugPrint @ 0xffe0b2e8 int DebugPrint(int a1, const char *a2, ...)
{
 int result; // eax int ( **v3)(int, const char *, char *); // esi va_list va; // [esp+10h] [ebp+Ch] BYREF va_start(va, a2);
 result = GetReportStatusCodeProtocol(); /*0xffe0b2e9*/
 v3 = (int ( **)(int, const char *, char *))result; /*0xffe0b2ee*/
 if ( result ) /*0xffe0b2f2*/
 {
 result = sub_FFE0B976(); /*0xffe0b2f4*/
 if ( (result & a1) != 0 ) /*0xffe0b2ff*/
 return (*v3)(a1, a2, (char *)va); /*0xffe0b30b*/
 }
 return result; /*0xffe0b310*/
}

// DebugAssert @ 0xffe0b312 int DebugAssert(
 int e:__hs__MdePkg__Library__PeiServicesTablePointerLibIdt__PeiServ,
 int n48,
 int PeiServices____((void__)_0))
{
 int result; // eax result = GetReportStatusCodeProtocol(); /*0xffe0b318*/
 if ( result ) /*0xffe0b31f*/
 return (*(int ( **)(int, int, int))(result + 4))( /*0xffe0b327*/
 e:__hs__MdePkg__Library__PeiServicesTablePointerLibIdt__PeiServ,
 n48,
 PeiServices____((void__)_0));
 return result; /*0xffe0b32d*/
}

// MicroSecondDelay @ 0xffe0b330 unsigned int MicroSecondDelay(unsigned int a1)
{
 unsigned int Result; // esi unsigned int n0x400000; // edi unsigned __int32 v3; // ebx unsigned int result; // eax Result = a1 >> 22; /*0xffe0b33d*/
 n0x400000 = a1 & 0x3FFFFF; /*0xffe0b340*/
 do /*0xffe0b378*/
 {
 v3 = n0x400000 + (sub_FFE0BB64(0x508u) & 0xFFFFFF); /*0xffe0b355*/
 n0x400000 = 0x400000; /*0xffe0b357*/
 while ( ((v3 - sub_FFE0BB64(0x508u)) & 0x800000) == 0 ) /*0xffe0b371*/
 _mm_pause(); /*0xffe0b35e*/
 result = Result--; /*0xffe0b373*/
 }
 while ( result ); /*0xffe0b378*/
 return result; /*0xffe0b37a*/
}

// IoWrite32 @ 0xffe0b37f int __thiscall IoWrite32(void *this)
{
 unsigned __int64 v1; // rtt __int64 v3; // [esp+0h] [ebp-8h]

 v3 = sub_FFE0BB90(); /*0xffe0b38d*/
 LODWORD(v1) = v3; /*0xffe0b3a3*/
 HIDWORD(v1) = HIDWORD(v3) % 0xF4240; /*0xffe0b3a3*/
 MicroSecondDelay(v1 / 0xF4240); /*0xffe0b3a8*/
 return 30; /*0xffe0b3b0*/
}

// TpmIsPresent @ 0xffe0b3b4 char TpmIsPresent()
{
 unsigned int Index; // ecx Index = 0; /*0xffe0b3bb*/
 while ( word_FFE0DC3C[Index] != MEMORY[0xFED40F00] || word_FFE0DC3E[Index] != MEMORY[0xFED40F02] ) /*0xffe0b3d6*/
 {
 Index += 2; /*0xffe0b3d8*/
 if ( Index >= 6 ) /*0xffe0b3de*/
 return 0; /*0xffe0b3e3*/
 }
 return 1; /*0xffe0b3e2*/
}

// memset_TpmCmd @ 0xffe0b3e8 void __usercall memset_TpmCmd(unsigned int a1@<edx>, _BYTE *a2, int n20)
{
 int n20_1; // esi _BYTE *v4; // edx _BYTE *v5; // ecx _BYTE *v6; // ecx n20_1 = n20; /*0xffe0b3ed*/
 if ( (unsigned int)a2 >= a1 ) /*0xffe0b3f3*/
 {
 if ( n20 ) /*0xffe0b40e*/
 {
 v6 = &a2[-a1]; /*0xffe0b410*/
 do /*0xffe0b41b*/
 {
 *(_BYTE *)a1 = v6[a1]; /*0xffe0b415*/
 ++a1; /*0xffe0b417*/
 --n20_1; /*0xffe0b418*/
 }
 while ( n20_1 ); /*0xffe0b41b*/
 }
 }
 else
 {
 v4 = (_BYTE *)(n20 + a1 - 1); /*0xffe0b3f7*/
 v5 = &a2[n20 - 1]; /*0xffe0b3f9*/
 if ( n20 ) /*0xffe0b3fd*/
 {
 do /*0xffe0b408*/
 {
 *v4-- = *v5--; /*0xffe0b401*/
 --n20_1; /*0xffe0b405*/
 }
 while ( n20_1 ); /*0xffe0b408*/
 }
 }
}

// Tpm12Command_Init @ 0xffe0b41f int __usercall Tpm12Command_Init@<eax>(unsigned int a1@<edx>, _DWORD *a2, _BYTE *a3)
{
 memset_TpmCmd(a1, a3, 8); /*0xffe0b42b*/
 memset_TpmCmd(a1 + 8, a3 + 8, 20); /*0xffe0b439*/
 memset_TpmCmd(a1 + 28, a3 + 28, 4); /*0xffe0b447*/
 memset_TpmCmd(a1 + 32, a3 + 32, *((_DWORD *)a3 + 7)); /*0xffe0b455*/
 *a2 += *((_DWORD *)a3 + 7) + 32; /*0xffe0b467*/
 return 0; /*0xffe0b466*/
}

// Tpm12Command_Startup @ 0xffe0b46e int Tpm12Command_Startup(_DWORD *a1)
{
 _WORD **v1; // ecx _WORD **v2; // ebp int Result; // edi _WORD *v5; // esi _WORD *v6; // eax __int16 i; // cx v2 = v1; /*0xffe0b474*/
 if ( !a1 ) /*0xffe0b478*/
 return -2147483646; /*0xffe0b47a*/
 Result = -2147483634; /*0xffe0b482*/
 while ( 1 ) /*0xffe0b495*/
 {
 v5 = *v2; /*0xffe0b495*/
 if ( **v2 == 0xFFFF ) /*0xffe0b49b*/
 break; /*0xffe0b49b*/
 v6 = *v2; /*0xffe0b49d*/
 if ( v5 ) /*0xffe0b4a1*/
 {
 for ( i = *v5; i != -1 && i != 4; i = *v6 ) /*0xffe0b4a3*/
 v6 = (_WORD *)((char *)v6 + (unsigned __int16)v6[1]); /*0xffe0b4b3*/
 if ( *v6 != 0xFFFF ) /*0xffe0b4c0*/
 v5 = v6; /*0xffe0b4c2*/
 }
 if ( *v5 == 4 && !sub_FFE0BA03((_BYTE *)v5 + 8, 16) ) /*0xffe0b4d2*/
 {
 Result = 0; /*0xffe0b4e3*/
 *a1 = v5 + 12; /*0xffe0b4e5*/
 }
 *v2 = (_WORD *)((char *)v5 + (unsigned __int16)v5[1]); /*0xffe0b4ed*/
 if ( Result >= 0 ) /*0xffe0b4f2*/
 return Result; /*0xffe0b4f6*/
 }
 return -2147483634; /*0xffe0b4ff*/
}

// Tpm12Command_SaveState @ 0xffe0b502 int __thiscall Tpm12Command_SaveState(char *this)
{
 char *i; // esi int result; // eax for ( i = this; i; --i ) /*0xffe0b507*/
 result = IoWrite32(this); /*0xffe0b509*/
 return result; /*0xffe0b513*/
}

// Tpm12WaitResponse @ 0xffe0b515 char Tpm12WaitResponse(char *a1, char a2)
{
 int n30000; // edi int n5; // esi n30000 = 30000; /*0xffe0b521*/
 while ( 1 ) /*0xffe0b528*/
 {
 n5 = 5; /*0xffe0b528*/
 do /*0xffe0b531*/
 {
 IoWrite32(a1); /*0xffe0b529*/
 --n5; /*0xffe0b52e*/
 }
 while ( n5 ); /*0xffe0b531*/
 if ( !--n30000 ) /*0xffe0b536*/
 break; /*0xffe0b536*/
 if ( *a1 < 0 ) /*0xffe0b53c*/
 return a2 & *a1; /*0xffe0b543*/
 }
 return 0; /*0xffe0b547*/
}

// Tpm12Command_ContinueSelfTest @ 0xffe0b54e int __thiscall Tpm12Command_ContinueSelfTest(int this)
{
 int Result; // edi int Result; // ebx int n5; // esi bool v5; // cf int result; // eax Result = 7500; /*0xffe0b555*/
 Result = 0; /*0xffe0b55a*/
 do /*0xffe0b583*/
 {
 n5 = 5; /*0xffe0b55e*/
 do /*0xffe0b567*/
 {
 IoWrite32((void *)this); /*0xffe0b55f*/
 --n5; /*0xffe0b564*/
 }
 while ( n5 ); /*0xffe0b567*/
 v5 = Result-- != 0; /*0xffe0b56d*/
 result = *(unsigned __int16 *)(this + 25); /*0xffe0b570*/
 Result = v5 + Result - 1; /*0xffe0b573*/
 }
 while ( !(_WORD)result && (Result || Result) ); /*0xffe0b583*/
 return result; /*0xffe0b585*/
}

// Tpm12Command_GetCapability_TpmVersion @ 0xffe0b58b int Tpm12Command_GetCapability_TpmVersion(char *a1)
{
 int n7500; // [esp+0h] [ebp-4h]

 n7500 = 7500; /*0xffe0b58f*/
 if ( !Tpm12WaitResponse(a1, 32) ) /*0xffe0b59b*/
 return -2147483641; /*0xffe0b5a7*/
 *a1 = 32; /*0xffe0b5b1*/
 if ( !Tpm12WaitResponse(a1, 32) ) /*0xffe0b5b9*/
 return 0; /*0xffe0b5b9*/
 do /*0xffe0b5e9*/
 {
 Tpm12Command_SaveState((char *)5); /*0xffe0b5c8*/
 --n7500; /*0xffe0b5d1*/
 }
 while ( Tpm12WaitResponse(a1, 32) && n7500 ); /*0xffe0b5e9*/
 if ( Tpm12WaitResponse(a1, 32) ) /*0xffe0b5f0*/
 return -2147483641; /*0xffe0b5fc*/
 else return 0; /*0xffe0b603*/
}

// Tpm12Command_GetCapability_Deactivated @ 0xffe0b609 int __thiscall Tpm12Command_GetCapability_Deactivated(char *this)
{
 void *v2; // ecx int n2; // ebp int n30000; // esi int n5; // ebx bool v7; // zf if ( !Tpm12WaitResponse(this, 32) ) /*0xffe0b60e*/
 return -2147483629; /*0xffe0b617*/
 n2 = 2; /*0xffe0b623*/
 while ( 1 ) /*0xffe0b624*/
 {
 n30000 = 30000; /*0xffe0b624*/
 *(this + 24) = 64; /*0xffe0b629*/
 do /*0xffe0b644*/
 {
 --n30000; /*0xffe0b62f*/
 n5 = 5; /*0xffe0b630*/
 do /*0xffe0b639*/
 {
 IoWrite32(v2); /*0xffe0b631*/
 --n5; /*0xffe0b636*/
 }
 while ( n5 ); /*0xffe0b639*/
 }
 while ( (*(this + 24) & 0x40) == 0 && n30000 ); /*0xffe0b644*/
 v7 = n30000 == 0; /*0xffe0b646*/
 if ( n30000 ) /*0xffe0b648*/
 break; /*0xffe0b648*/
 if ( !--n2 ) /*0xffe0b64d*/
 {
 v7 = 1; /*0xffe0b64f*/
 break; /*0xffe0b64f*/
 }
 }
 if ( v7 ) /*0xffe0b654*/
 return -2147483641; /*0xffe0b656*/
 else return 0; /*0xffe0b65d*/
}

// Tpm12Command_GetCapability_PermanentFlags @ 0xffe0b661 unsigned int Tpm12Command_GetCapability_PermanentFlags(_BYTE *a1, char *a2, int a3, char a4)
{
 int v4; // esi char v8; // al unsigned __int16 v9; // ax int v10; // ecx char v11; // al v4 = a3; /*0xffe0b667*/
 if ( !a3 )
 return a4 != 0 ? 0x80000002 : 0;
 if ( (*a1 & 0x20) == 0 ) /*0xffe0b686*/
 return -2147483627; /*0xffe0b686*/
 v8 = a4; /*0xffe0b68f*/
 if ( a4 ) /*0xffe0b694*/
 v4 = a3 - 1; /*0xffe0b696*/
 if ( v4 ) /*0xffe0b699*/
 {
LABEL_8:
 v9 = Tpm12Command_ContinueSelfTest((int)a1); /*0xffe0b69b*/
 v10 = v9; /*0xffe0b6a2*/
 if ( !v9 ) /*0xffe0b6a8*/
 return -2147483630; /*0xffe0b6f8*/
 while ( v4 ) /*0xffe0b6ac*/
 {
 v11 = *a2; /*0xffe0b6ae*/
 v10 += 0xFFFF; /*0xffe0b6b0*/
 ++a2; /*0xffe0b6b6*/
 a1[36] = v11; /*0xffe0b6b7*/
 --v4; /*0xffe0b6ba*/
 if ( !(_WORD)v10 ) /*0xffe0b6be*/
 {
 if ( v4 ) /*0xffe0b6c2*/
 goto LABEL_8; /*0xffe0b6c2*/
 break; /*0xffe0b6c2*/
 }
 }
 v8 = a4; /*0xffe0b6c4*/
 }
 if ( v8 ) /*0xffe0b6c9*/
 {
 if ( !Tpm12WaitResponse(a1 + 24, 8) ) /*0xffe0b6d2*/
 return -2147483627; /*0xffe0b6d2*/
 a1[36] = *a2; /*0xffe0b6e1*/
 if ( Tpm12WaitResponse(a1 + 24, 8) ) /*0xffe0b6e4*/
 return -2147483627; /*0xffe0b68d*/
 a1[24] = 32; /*0xffe0b6ed*/
 }
 return 0; /*0xffe0b6f2*/
}

// Tpm12Command_GetCapability_VolatileFlags @ 0xffe0b6ff unsigned int Tpm12Command_GetCapability_VolatileFlags(int a1, _BYTE *a2, _DWORD *a3)
{
 _BYTE *v3; // esi _BYTE *v5; // edi char *v6; // eax unsigned __int16 v7; // ax int v8; // ebx v3 = a2; /*0xffe0b707*/
 v5 = &a2[*a3]; /*0xffe0b70d*/
 if ( a2 >= v5 ) /*0xffe0b711*/
 goto LABEL_9; /*0xffe0b711*/
 v6 = (char *)(a1 + 24); /*0xffe0b713*/
LABEL_3:
 if ( !Tpm12WaitResponse(v6, 16) )
 {
LABEL_9:
 *a3 += v3 - v5; /*0xffe0b75c*/
 return Tpm12WaitResponse((char *)(a1 + 24), 16) != 0 ? 0x80000005 : 0;
 }
 v7 = Tpm12Command_ContinueSelfTest(a1); /*0xffe0b725*/
 v8 = v7; /*0xffe0b72a*/
 if ( v7 ) /*0xffe0b730*/
 {
 while ( v3 < v5 ) /*0xffe0b734*/
 {
 if ( Tpm12WaitResponse((char *)(a1 + 24), 16) ) /*0xffe0b73b*/
 {
 v8 += 0xFFFF; /*0xffe0b747*/
 *v3++ = *(_BYTE *)(a1 + 36); /*0xffe0b74d*/
 if ( (_WORD)v8 ) /*0xffe0b753*/
 continue; /*0xffe0b753*/
 }
 v6 = (char *)(a1 + 24); /*0xffe0b755*/
 if ( v3 < v5 ) /*0xffe0b75a*/
 goto LABEL_3; /*0xffe0b75a*/
 goto LABEL_9; /*0xffe0b75a*/
 }
 goto LABEL_9; /*0xffe0b734*/
 }
 return -2147483630; /*0xffe0b77a*/
}

// Tpm12Command_PhysicalEnable @ 0xffe0b786 signed int Tpm12Command_PhysicalEnable(char *a1, unsigned int a2, int a3, unsigned int a4, int a5)
{
 signed int result; // eax unsigned int Index; // edi unsigned int Index; // esi bool Result; // zf char *v9; // edx unsigned int v11; // [esp+10h] [ebp-8h]

 v11 = a2; /*0xffe0b79a*/
 if ( !a2 || !a3 || !a5 || !a4 ) /*0xffe0b7c1*/
 return -2147483646; /*0xffe0b850*/
 result = Tpm12Command_GetCapability_Deactivated(a1); /*0xffe0b7c7*/
 if ( result < 0 ) /*0xffe0b7ce*/
 return -2147483641; /*0xffe0b7d0*/
 Index = 0; /*0xffe0b7d7*/
 Index = 0; /*0xffe0b7d9*/
 do
 {
 if ( Index >= a2 ) /*0xffe0b7df*/
 break; /*0xffe0b7df*/
 Result = v11-- == 1; /*0xffe0b7e1*/
 v9 = *(char **)(a3 + 8 *Index); /*0xffe0b7e6*/
 result = Result
 ? Tpm12Command_GetCapability_PermanentFlags(a1, v9, *(_DWORD *)(a3 + 8 *Index + 4), 1)
 : Tpm12Command_GetCapability_PermanentFlags(a1, v9, *(_DWORD *)(a3 + 8 *Index + 4), 0);
 ++Index; /*0xffe0b7fe*/
 }
 while ( result >= 0 );
 if ( result >= 0 ) /*0xffe0b806*/
 {
 while ( !Tpm12WaitResponse(a1 + 24, 16) ) /*0xffe0b81e*/
 ; /*0xffe0b813*/
 result = -2147483643; /*0xffe0b823*/
 do /*0xffe0b845*/
 {
 if ( Index >= a4 ) /*0xffe0b82b*/
 break; /*0xffe0b82b*/
 result = Tpm12Command_GetCapability_VolatileFlags((int)a1, *(_BYTE **)(a5 + 8 *Index), (_DWORD *)(a5 + 4 + 8 *Index)); /*0xffe0b839*/
 ++Index; /*0xffe0b83e*/
 }
 while ( result == -2147483643 ); /*0xffe0b845*/
 a1[24] = 64; /*0xffe0b84b*/
 }
 return result; /*0xffe0b855*/
}

// TpmIsPresent_Failure @ 0xffe0b85c bool TpmIsPresent_Failure()
{
 return MEMORY[0xFED40030] != -1 && MEMORY[0xFED40030]; /*0xffe0b88c*/
}

// Tpm12GetPtpInterface @ 0xffe0b890 char Tpm12GetPtpInterface()
{
 char Result; // [esp+6h] [ebp-2h]

 Result = MEMORY[0xFED40030] & 0xF; /*0xffe0b8ac*/
 if ( TpmIsPresent_Failure() ) /*0xffe0b8b3*/
 return Result & 0xF; /*0xffe0b8de*/
 else return sub_FFE0CF93() != 0; /*0xffe0b8c9*/
}

// TpmIsEnabled @ 0xffe0b8e5 bool TpmIsEnabled()
{
 if ( sub_FFE0CF93() ) /*0xffe0b8e8*/
 return 1; /*0xffe0b8f4*/
 return TpmIsPresent_Failure() && Tpm12GetPtpInterface() == 1; /*0xffe0b917*/
}

/* -------------------------------------------------------------------------
 * Board-specific TPM policy and CMOS checks
 * ------------------------------------------------------------------------- */

// InitBoardSpecific @ 0xffe0b919 char InitBoardSpecific()
{
 int Protocol; // eax unsigned int v2; // [esp+0h] [ebp-4h] BYREF v2 = 0; /*0xffe0b91d*/
 sub_FFE0CFE5(&v2); /*0xffe0b924*/
 if ( !v2 ) /*0xffe0b92e*/
 {
 Protocol = GetReportStatusCodeProtocol(); /*0xffe0b930*/
 if ( Protocol ) /*0xffe0b937*/
 (*(void ( **)(const char *, int, const char *))(Protocol + 4))( /*0xffe0b948*/
 "e:\\hs\\PurleySktPkg\\SouthClusterLbg\\Library\\PeiDxeSmmPchPmcLib\\PchPmcLib.c",
 162,
 "PchPwrmBase != 0");
 return 0; /*0xffe0b948*/
 }
 if ( (*(_DWORD *)(v2 + 300) & 0x8000) == 0 ) /*0xffe0b95f*/
 return 0; /*0xffe0b953*/
 DebugPrint(0x80000000, "SkipTpmInitDuringDwrFlow() WARNING: DWR detected - Skipping TPM initialization .. \n");
 return 1; /*0xffe0b950*/
}

// Tpm12CheckCmos @ 0xffe0b976 int Tpm12CheckCmos()
{
 unsigned __int8 v0; // al char Result; // al char n3_1; // cl v0 = __inbyte(0x70u); /*0xffe0b97c*/
 __outbyte(0x70u, v0 & 0x80 | 0x4A); /*0xffe0b981*/
 Result = __inbyte(0x71u); /*0xffe0b988*/
 n3_1 = Result; /*0xffe0b989*/
 if ( (unsigned __int8)Result <= 3u ) /*0xffe0b98e*/
 {
LABEL_4:
 if ( !n3_1 ) /*0xffe0b9a9*/
 return 0; /*0xffe0b9a9*/
 goto LABEL_5; /*0xffe0b9a9*/
 }
 n3_1 = Result; /*0xffe0b990*/
 if ( !Result ) /*0xffe0b998*/
 {
 n3_1 = MEMORY[0xFDAF0490] & 2 | 1; /*0xffe0b9a4*/
 goto LABEL_4; /*0xffe0b9a4*/
 }
LABEL_5:
 if ( n3_1 != -1 )
 return n3_1 != 1 ? -2147483578 : -2147483644;
 return 0; /*0xffe0b9c1*/
}

/* -------------------------------------------------------------------------
 * Allocation and bounded copy helpers
 * ------------------------------------------------------------------------- */

// CopyMem_CheckOverflow @ 0xffe0b9c5 void *CopyMem_CheckOverflow(void *buf, unsigned int count)
{
 int ReportStatusCodeProtocol; // eax if ( count - 1 > -1 - (int)buf ) /*0xffe0b9d6*/
 {
 ReportStatusCodeProtocol = GetReportStatusCodeProtocol(); /*0xffe0b9d8*/
 if ( ReportStatusCodeProtocol ) /*0xffe0b9df*/
 (*(void ( **)(const char *, int, const char *))(ReportStatusCodeProtocol + 4))( /*0xffe0b9ed*/
 "e:\\hs\\MdePkg\\Library\\BaseMemoryLibRepStr\\SetMemWrapper.c",
 54,
 "(Length - 1) <= (0xFFFFFFFF - (UINTN)Buffer)");
 }
 return memset_v2(buf, count, 0); /*0xffe0b9ff*/
}

// FreePool @ 0xffe0ba03 int FreePool(_BYTE *a1, int n16)
{
 int ReportStatusCodeProtocol; // eax int Protocol; // eax int Protocol; // eax if ( a1 == byte_FFE0DB98 ) /*0xffe0ba0f*/
 return 0; /*0xffe0ba11*/
 if ( !a1 ) /*0xffe0ba17*/
 {
 ReportStatusCodeProtocol = GetReportStatusCodeProtocol(); /*0xffe0ba19*/
 if ( ReportStatusCodeProtocol ) /*0xffe0ba20*/
 (*(void ( **)(const char *, int, const char *))(ReportStatusCodeProtocol + 4))( /*0xffe0ba2e*/
 "e:\\hs\\MdePkg\\Library\\BaseMemoryLibRepStr\\CompareMemWrapper.c",
 61,
 "SourceBuffer != ((void *) 0)");
 }
 if ( n16 - 1 > (unsigned int)(-1 - (_DWORD)byte_FFE0DB98) ) /*0xffe0ba45*/
 {
 Protocol = GetReportStatusCodeProtocol(); /*0xffe0ba47*/
 if ( Protocol ) /*0xffe0ba4e*/
 (*(void ( **)(const char *, int, const char *))(Protocol + 4))( /*0xffe0ba5c*/
 "e:\\hs\\MdePkg\\Library\\BaseMemoryLibRepStr\\CompareMemWrapper.c",
 62,
 "(Length - 1) <= (0xFFFFFFFF - (UINTN)DestinationBuffer)");
 }
 if ( n16 - 1 > (unsigned int)(-1 - (_DWORD)a1) ) /*0xffe0ba68*/
 {
 Protocol = GetReportStatusCodeProtocol(); /*0xffe0ba6a*/
 if ( Protocol ) /*0xffe0ba71*/
 (*(void ( **)(const char *, int, const char *))(Protocol + 4))( /*0xffe0ba7f*/
 "e:\\hs\\MdePkg\\Library\\BaseMemoryLibRepStr\\CompareMemWrapper.c",
 63,
 "(Length - 1) <= (0xFFFFFFFF - (UINTN)SourceBuffer)");
 }
 return memcmp_v2(byte_FFE0DB98, a1, n16); /*0xffe0ba94*/
}

// CopyMem_Safe @ 0xffe0ba97 char *CopyMem_Safe(char *dst, char *src, unsigned int count)
{
 int ReportStatusCodeProtocol; // eax int Protocol; // eax if ( count - 1 > -1 - (int)dst ) /*0xffe0baad*/
 {
 ReportStatusCodeProtocol = GetReportStatusCodeProtocol(); /*0xffe0baaf*/
 if ( ReportStatusCodeProtocol ) /*0xffe0bab6*/
 (*(void ( **)(const char *, int, const char *))(ReportStatusCodeProtocol + 4))( /*0xffe0bac4*/
 "e:\\hs\\MdePkg\\Library\\BaseMemoryLibRepStr\\CopyMemWrapper.c",
 56,
 "(Length - 1) <= (0xFFFFFFFF - (UINTN)DestinationBuffer)");
 }
 if ( count - 1 > -1 - (int)src ) /*0xffe0bace*/
 {
 Protocol = GetReportStatusCodeProtocol(); /*0xffe0bad0*/
 if ( Protocol ) /*0xffe0bad7*/
 (*(void ( **)(const char *, int, const char *))(Protocol + 4))( /*0xffe0bae5*/
 "e:\\hs\\MdePkg\\Library\\BaseMemoryLibRepStr\\CopyMemWrapper.c",
 57,
 "(Length - 1) <= (0xFFFFFFFF - (UINTN)SourceBuffer)");
 }
 if ( dst == src ) /*0xffe0baed*/
 return dst; /*0xffe0baef*/
 else return memmove_v2(dst, src, count); /*0xffe0baf9*/
}

// CheckUnaligned16 @ 0xffe0bb06 int CheckUnaligned16(unsigned __int16 *a1)
{
 int Protocol; // eax if ( ((unsigned __int8)a1 & 1) != 0 ) /*0xffe0bb0c*/
 {
 Protocol = GetReportStatusCodeProtocol(); /*0xffe0bb0e*/
 if ( Protocol ) /*0xffe0bb15*/
 (*(void ( **)(const char *, int, const char *))(Protocol + 4))( /*0xffe0bb26*/
 "e:\\hs\\MdePkg\\Library\\BaseIoLibIntrinsic\\IoLib.c",
 151,
 "(Address & 1) == 0");
 }
 return *a1; /*0xffe0bb32*/
}

// CheckUnaligned32 @ 0xffe0bb64 unsigned __int32 __thiscall CheckUnaligned32(unsigned __int16 n1288)
{
 int Protocol; // eax if ( (n1288 & 3) != 0 ) /*0xffe0bb6a*/
 {
 Protocol = GetReportStatusCodeProtocol(); /*0xffe0bb6c*/
 if ( Protocol ) /*0xffe0bb73*/
 (*(void ( **)(const char *, int, const char *))(Protocol + 4))( /*0xffe0bb84*/
 "e:\\hs\\MdePkg\\Library\\BaseIoLibIntrinsic\\IoLibMsc.c",
 193,
 "(Port & 3) == 0");
 }
 return __indword(n1288); /*0xffe0bb8e*/
}

// GetPerformanceCounter @ 0xffe0bb90 __int64 GetPerformanceCounter()
{
 return 107386350; /*0xffe0bbb6*/
}

/* -------------------------------------------------------------------------
 * Measurement extension and SHA-1 implementation
 * ------------------------------------------------------------------------- */

// Tpm12Command_ExtendAll @ 0xffe0bbd7 void *Tpm12Command_ExtendAll(_DWORD *buf, char *src)
{
 int state_d; // edi int state_b; // edx int f_d_b_c; // eax int b_rot30; // edx int new_a; // ebp int a_rot30; // ebx int new_e; // esi int f_b_c_d; // eax int d_rot30; // ebp int new_d; // edi int f_c_d_e; // eax int e_rot30; // esi int new_c; // edx int rnd1_new_b; // eax int rnd1_new_c; // edi int rnd1_new_d; // ebx int f_round1; // eax int rnd1_e_rot; // edx int rnd1_new_a; // ebp int f_round2; // eax int rnd2_c_rot; // ebx int rnd2_new_e; // esi int f_round2b; // eax int rnd2_d_rot; // ebp int rnd2_new_d; // edi int f_round3; // eax int rnd3_e_rot; // esi int rnd3_new_c; // edx int rnd3_new_b; // ebx int f_round4; // eax int rnd4_c_rot; // edx int rnd4_new_a; // ebp int rnd4_new_e; // edi int rnd4_a_rot; // ecx int rnd5_new_b; // ebx int rnd5_d_rot; // ebp int rnd5_new_d; // edi int rnd5_new_a; // ebp int v41; // edx int v42; // ebx in... [27858 chars total]

// Sha1Init @ 0xffe0ce11 void __thiscall Sha1Init(_DWORD *this)
{
 *(this + 6) = 0; /*0xffe0ce11*/
 *(this + 5) = 0; /*0xffe0ce15*/
 *this = 1732584193; /*0xffe0ce19*/
 *(this + 1) = -271733879; /*0xffe0ce1f*/
 *(this + 2) = -1732584194; /*0xffe0ce26*/
 *(this + 3) = 271733878; /*0xffe0ce2d*/
 *(this + 4) = -1009589776; /*0xffe0ce34*/
}

// Sha1Update @ 0xffe0ce3c char *Sha1Update(int buf, char *src, unsigned int i)
{
 int Result; // ebx unsigned int v5; // ecx char *result; // eax int i_1; // esi unsigned int j; // ebx char *src_1; // [esp+10h] [ebp-4h]

 src_1 = src; /*0xffe0ce47*/
 Result = (*(_DWORD *)(buf + 20) >> 3) & 0x3F; /*0xffe0ce53*/
 v5 = *(_DWORD *)(buf + 20) + 8 *i; /*0xffe0ce56*/
 *(_DWORD *)(buf + 20) = v5; /*0xffe0ce5e*/
 if ( v5 < 8 *i ) /*0xffe0ce63*/
 ++*(_DWORD *)(buf + 24); /*0xffe0ce65*/
 *(_DWORD *)(buf + 24) += i >> 29; /*0xffe0ce6d*/
 result = (char *)(Result + i); /*0xffe0ce70*/
 if ( Result + i <= 0x3F ) /*0xffe0ce76*/
 {
 i_1 = 0; /*0xffe0ceb8*/
 }
 else
 {
 i_1 = 64 - Result; /*0xffe0ce7b*/
 CopyMem_Safe((char *)(Result + buf + 28), src, 64 - Result); /*0xffe0ce85*/
 result = (char *)Tpm12Command_ExtendAll((_DWORD *)buf, (char *)(buf + 28)); /*0xffe0ce90*/
 for ( j = i_1 + 63; ; j += 64 ) /*0xffe0ce95*/
 {
 src = src_1; /*0xffe0ceac*/
 if ( j >= i ) /*0xffe0ceb2*/
 break; /*0xffe0ceb2*/
 result = (char *)Tpm12Command_ExtendAll((_DWORD *)buf, &src_1[j - 63]); /*0xffe0cea1*/
 i_1 += 64; /*0xffe0cea6*/
 }
 Result = 0; /*0xffe0ceb4*/
 }
 if ( i != i_1 ) /*0xffe0ceba*/
 return CopyMem_Safe((char *)(Result + buf + 28), &src[i_1], i - i_1); /*0xffe0cec6*/
 return result; /*0xffe0cecc*/
}

// Sha1Final @ 0xffe0ced2 void *Sha1Final(int a1, _DWORD *buf)
{
 unsigned int n0x14; // edi unsigned int i; // edx char src[8]; // [esp+10h] [ebp-8h] BYREF n0x14 = 0; /*0xffe0ced8*/
 for ( i = 0; i < 8; ++i )
 src[i] = *(_DWORD *)((char *)buf + (i < 4 ? 4 : 0) + 20) >> (8 * (3 - (i & 3)));
 Sha1Update((int)buf, ::src, 1u); /*0xffe0cf0e*/
 while ( (buf[5] & 0x1F8) != 0x1C0 ) /*0xffe0cf33*/
 Sha1Update((int)buf, src_0, 1u); /*0xffe0cf1f*/
 Sha1Update((int)buf, src, 8u); /*0xffe0cf3b*/
 do /*0xffe0cf5f*/
 {
 *(_BYTE *)(n0x14 + a1) = buf[n0x14 >> 2] >> (8 * (3 - (n0x14 & 3))); /*0xffe0cf58*/
 ++n0x14; /*0xffe0cf5b*/
 }
 while ( n0x14 < 0x14 ); /*0xffe0cf5f*/
 CopyMem_CheckOverflow(buf + 7, 0x40u); /*0xffe0cf67*/
 CopyMem_CheckOverflow(buf, 0x14u); /*0xffe0cf71*/
 CopyMem_CheckOverflow(buf + 5, 8u); /*0xffe0cf7b*/
 return CopyMem_CheckOverflow(src, 8u); /*0xffe0cf8c*/
}

/* -------------------------------------------------------------------------
 * Chipset, PEI services, boot-mode, and CRC helpers
 * ------------------------------------------------------------------------- */

// GetPchTpm @ 0xffe0cf93 char GetPchTpm()
{
 return 0; /*0xffe0cf95*/
}

// GetSystemConfiguration @ 0xffe0cf96 int GetSystemConfiguration()
{
 int Result; // esi _BYTE v2[2]; // [esp+4h] [ebp-8h] BYREF int v3; // [esp+6h] [ebp-6h]

 sub_FFE0D0B0(v2); /*0xffe0cf9f*/
 Result = *(_DWORD *)(v3 - 4); /*0xffe0cfa7*/
 if ( !Result ) /*0xffe0cfac*/
 DebugAssert( /*0xffe0cfbb*/
 (int)"e:\\hs\\MdePkg\\Library\\PeiServicesTablePointerLibIdt\\PeiServicesTablePointer.c",
 48,
 (int)"PeiServices != ((void *) 0)");
 return Result; /*0xffe0cfc3*/
}

// GetPeiServices @ 0xffe0cfc8 int __thiscall GetPeiServices(void *this)
{
 int ( **v1)(int); // eax v1 = (int ( **)(int))sub_FFE0D0F1(this); /*0xffe0cfc8*/
 return v1[4](5); /*0xffe0cfd3*/
}

// PeiServicesInitMmio @ 0xffe0cfd4 int __thiscall PeiServicesInitMmio(void *this)
{
 int v1; // ebx int Protocol; // eax v1 = GetPeiServices(this) + 1024064; /*0xffe0bb35*/
 if ( (v1 & 1) != 0 ) /*0xffe0bb3a*/
 {
 Protocol = GetReportStatusCodeProtocol(); /*0xffe0bb3c*/
 if ( Protocol ) /*0xffe0bb43*/
 (*(void ( **)(const char *, int, const char *))(Protocol + 4))( /*0xffe0bb54*/
 "e:\\hs\\MdePkg\\Library\\BaseIoLibIntrinsic\\IoLib.c",
 183,
 "(Address & 1) == 0");
 }
 *(_WORD *)v1 = 1280; /*0xffe0bb5f*/
 return 1280; /*0xffe0bb63*/
}

// InitTpmDevice @ 0xffe0cfe5 int __thiscall InitTpmDevice(unsigned int *this)
{
 int Protocol; // eax int v4; // edi int Protocol; // eax if ( this ) /*0xffe0cfea*/
 {
 v4 = sub_FFE0D071(); /*0xffe0d02a*/
 if ( (unsigned __int16)CheckUnaligned16((unsigned __int16 *)v4) == 0xFFFF ) /*0xffe0d03b*/
 {
 Protocol = GetReportStatusCodeProtocol(); /*0xffe0d03d*/
 if ( Protocol ) /*0xffe0d044*/
 (*(void ( **)(const char *, int, const char *))(Protocol + 4))( /*0xffe0d055*/
 "e:\\hs\\PurleySktPkg\\SouthClusterLbg\\Library\\PeiDxeSmmPchCycleDecodingLib\\PchCycleDecodingLib.c",
 303,
 "((BOOLEAN)(0==1))");
 return -2147483645; /*0xffe0d05b*/
 }
 else
 {
 *this = *(_DWORD *)(v4 + 72) & 0xFFFF0000; /*0xffe0d06a*/
 return 0; /*0xffe0d06c*/
 }
 }
 else
 {
 DebugPrint(0x80000000, "PchPwrmBaseGet Error. Invalid pointer.\n"); /*0xffe0cff6*/
 Protocol = GetReportStatusCodeProtocol(); /*0xffe0cffd*/
 if ( Protocol ) /*0xffe0d004*/
 (*(void ( **)(const char *, int, const char *))(Protocol + 4))( /*0xffe0d015*/
 "e:\\hs\\PurleySktPkg\\SouthClusterLbg\\Library\\PeiDxeSmmPchCycleDecodingLib\\PchCycleDecodingLib.c",
 293,
 "((BOOLEAN)(0==1))");
 return -2147483646; /*0xffe0d01b*/
 }
}

// ReadCmos @ 0xffe0d071 int ReadCmos()
{
 int Result; // [esp+4h] [ebp-14h] BYREF _DWORD v2[4]; // [esp+8h] [ebp-10h] BYREF v2[2] = 512; /*0xffe0d07e*/
 v2[0] = 1024000; /*0xffe0d089*/
 v2[3] = 0; /*0xffe0d095*/
 v2[1] = 0; /*0xffe0d09c*/
 sub_FFE0D0D3(0, 0, v2, &Result); /*0xffe0d0a0*/
 return Result; /*0xffe0d0ac*/
}

// ReadIdtr @ 0xffe0d0b0 void *__thiscall ReadIdtr(void *this)
{
 void *this_1; // eax if ( !this ) /*0xffe0d0b6*/
 DebugAssert((int)"e:\\hs\\MdePkg\\Library\\BaseLib\\X86ReadIdtr.c", 37, (int)"Idtr != ((void *) 0)"); /*0xffe0d0c5*/
 this_1 = this; /*0xffe0d0cb*/
 __sidt(this); /*0xffe0d0ce*/
 return this_1; /*0xffe0d0d2*/
}

// CalculateCrc @ 0xffe0d0d3 int *CalculateCrc(int a1, int a2, _DWORD *a3, int *a4)
{
 int v4; // ecx v4 = sub_FFE0D202((int)a3) + (*a3 & 0xFFFFFFF); /*0xffe0d0e7*/
 *a4 = v4; /*0xffe0d0ee*/
 return a4; /*0xffe0d0ed*/
}

// GetBootMode @ 0xffe0d0f1 void *__thiscall GetBootMode(void *this)
{
 int Table; // eax int Status; // eax int Protocol; // eax void *this_1; // [esp+0h] [ebp-4h]

 this_1 = this; /*0xffe0d0f4*/
 Table = GetSystemConfiguration(); /*0xffe0d0f5*/
 Status = (*(int (__stdcall **)(int))(*(_DWORD *)Table + 32))(Table); /*0xffe0d10a*/
 if ( Status < 0 ) /*0xffe0d112*/
 {
 DebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status); /*0xffe0d11f*/
 Protocol = GetReportStatusCodeProtocol(); /*0xffe0d127*/
 if ( Protocol ) /*0xffe0d12e*/
 (*(void ( **)(const char *, int, const char *))(Protocol + 4))( /*0xffe0d13c*/
 "e:\\hs\\MdePkg\\Library\\PeiPcdLib\\PeiPcdLib.c",
 49,
 "!EFI_ERROR (Status)");
 }
 return this_1; /*0xffe0d147*/
}

// GetBootModeHandOff @ 0xffe0d149 int __thiscall GetBootModeHandOff(void *this)
{
 int ( **v2)(void *); // eax v2 = (int ( **)(void *))GetBootMode(this); /*0xffe0d14c*/
 return v2[4](this); /*0xffe0d156*/
}

// GetBootModePrevious @ 0xffe0d158 int __thiscall GetBootModePrevious(void *this)
{
 int ( **v2)(void *); // eax v2 = (int ( **)(void *))GetBootMode(this); /*0xffe0d15b*/
 return v2[5](this); /*0xffe0d165*/
}

// InitializeTpmStack @ 0xffe0d167 int InitializeTpmStack(_DWORD *a1, int n8)
{
 int v3; // [esp+Ch] [ebp-4h]

 v3 = GetBootModePrevious((void *)6); /*0xffe0d197*/
 a1[1] = 16 *n8 + 16; /*0xffe0d1a0*/
 if ( !a1[4] && !a1[5] ) /*0xffe0d1bc*/
 {
 *(_DWORD *)(v3 + 16) = GetBootModeHandOff((void *)5); /*0xffe0d1e1*/
 *(_DWORD *)(v3 + 20) = 0; /*0xffe0d1f8*/
 }
 return 0; /*0xffe0d1fe*/
}

// CalculateCrc16 @ 0xffe0d202 int CalculateCrc16(int a1)
{
 int v2; // [esp+Ch] [ebp-Ch]
 int v3; // [esp+10h] [ebp-8h]
 int Result; // [esp+14h] [ebp-4h]

 if ( *(_DWORD *)(a1 + 12) ) /*0xffe0d217*/
 {
 v3 = *(_DWORD *)(*(_DWORD *)(a1 + 12) + 4 * (unsigned __int16)*(_DWORD *)(a1 + 4) + 255544); /*0xffe0d30d*/
 Result = *(_DWORD *)(*(_DWORD *)(a1 + 12) + 4 * (unsigned __int16)*(_DWORD *)(a1 + 4) + 255560); /*0xffe0d329*/
 }
 else
 {
 v2 = GetBootModePrevious((void *)6); /*0xffe0d22a*/
 if ( *(_DWORD *)(v2 + 4) ) /*0xffe0d230*/
 {
 v3 = *(_DWORD *)(v2 + 16 * (unsigned __int16)*(_DWORD *)(a1 + 4) + 20); /*0xffe0d24b*/
 Result = *(_DWORD *)(v2 + 16 * (unsigned __int16)*(_DWORD *)(a1 + 4) + 16); /*0xffe0d263*/
 }
 else
 {
 InitializeTpmStack(dword_FFE0DC48, 8); /*0xffe0d276*/
 v3 = dword_FFE0DC5C[4 * (unsigned __int16)*(_DWORD *)(a1 + 4)]; /*0xffe0d291*/
 Result = dword_FFE0DC58[4 * (unsigned __int16)*(_DWORD *)(a1 + 4)]; /*0xffe0d2a8*/
 if ( !Result && !v3 ) /*0xffe0d2b5*/
 {
 Result = GetBootModeHandOff((void *)5); /*0xffe0d2e2*/
 v3 = 0; /*0xffe0d2ef*/
 }
 }
 }
 if ( !Result && !v3 ) /*0xffe0d336*/
 return GetBootModeHandOff((void *)5); /*0xffe0d363*/
 return Result; /*0xffe0d37c*/
}