Newer
Older
AMI-Aptio-BIOS-Reversed / FpgaLoaderPeim / FpgaLoaderPeim.c
@Ajax Dong Ajax Dong 2 days ago 20 KB Init
/**
 * @file FpgaLoaderPeim.c
 * @brief FPGA Loader PEIM - Decompiled from FpgaLoaderPeim.efi (IA32)
 *
 *This is a reconstructed C representation of the FPGA bitstream loader PEIM
 *from the Purley platform. The driver loads FPGA bitstreams via the MRC
 * (Memory Reference Code) hooks PPIs, manages MP services for BSP/AP
 *coordination, performs PEI-phase locking, and triggers warm reset after
 *FPGA programming.
 *
 *Binary info:
 *MD5: fdd9dee7b3135cc8c394c8873fcefcb8
 *SHA256: 0f9c118dd3f96178aea2975ce1294f063ca75226b90529b131f60496b6a2a76a
 *Size: 0x2f20 bytes
 *Arch: IA32 (32-bit)
 *Total functions: 41 (39 named, 2 anonymous -> renamed via debug strings)
 *
 *Key flow:
 *1. FpgaConfigurationGetValues() - reads/creates config HOB
 *2. FpgaGetPcdProtocol() - obtains PCD protocol for platform settings
 *3. Locate PPIs: ChipServices, MPServices, CoreServices
 *4. FpgaMpServicesData() - enumerates processors, finds BSP socket
 *5. Per-socket bitstream load via FpgaLoadBitstream() with retry (max 3)
 *6. FpgaConfigurationSetValues() - persists updated config to HOB
 *7. FpgaDisableUnusedSockets() - power off unused FPGA sockets
 *8. Set BIOS scratchpad bit 5 -> warm reset
 *9. FpgaPeiLock() on subsequent boots (FPGA already active)
 */

#include "FpgaLoaderPeim.h"

//
// Global variables (.data segment at 0xffd6b964 - 0xffd6ba64)
//
UINT32 dword_FFD6BA38; // PCD protocol UINT32 dword_FFD6BA3C; // (unused alignment)
UINT32 dword_FFD6BA40; // Chip Services PPI UINT32 dword_FFD6BA44; // MP processor data buffer UINT32 dword_FFD6BA48; // MP Services PPI UINT32 dword_FFD6BA4C; // BSP Socket number UINT32 dword_FFD6BA50; // Number of processors UINT32 dword_FFD6BA54; // BSP Index UINT32 dword_FFD6BA58; // Core Services PPI

// ============================================================
// FpgaLoaderEntry
// ============================================================

int FpgaLoaderEntry(int a1, void *a2)
{
 int Values; // eax void *v4; // ecx int Values_1; // esi int PcdProtocol; // eax int Status; // ebx int DebugLib; // eax unsigned __int8 ErrorLevel; // bl unsigned __int8 ErrorLevel; // bh bool v12; // zf int ErrorLevel; // eax int Index; // edi int n4_1; // ebp unsigned __int8 v16; // bl int Index; // ebp int Index; // ebx int n4; // edi unsigned __int8 Protocol; // al int v21; // eax unsigned __int8 v22; // [esp+16h] [ebp-36h]
 char v23; // [esp+17h] [ebp-35h]
 void ( **v25)(_DWORD, int); // [esp+1Ch] [ebp-30h] BYREF _BYTE v26[4]; // [esp+20h] [ebp-2Ch] BYREF _BYTE Table[2]; // [esp+24h] [ebp-28h] BYREF unsigned __int8 v28; // [esp+26h] [ebp-26h]
 unsigned __int8 ErrorLevel; // [esp+27h] [ebp-25h]
 char v30; // [esp+28h] [ebp-24h]
 unsigned __int8 v31; // [esp+29h] [ebp-23h]
 unsigned __int8 v32; // [esp+2Ah] [ebp-22h]
 _BYTE v33[33]; // [esp+2Bh] [ebp-21h]

 Values = FpgaConfigurationGetValues(Table);
 Values_1 = Values;
 if ( Values )
 {
 FpgaDebugPrint(0x80000000, "FPGA Loader,FpgaConfigurationGetValues failed, return it's error!, %r\n", Values);
 return Values_1;
 }
 if ( !Table[0] )
 {
 FpgaDebugPrint(0x80000000, "FPGA Loader,FpgaConfigurationGetValues global enable is False!\n");
 return -2147483645;
 }
 if ( !v28 )
 {
 FpgaDebugPrint(0x80000000, "FPGA Loader,FpgaConfigurationGetValues no FPGA sockets present!\n");
 return -2147483645;
 }
 PcdProtocol = FpgaGetPcdProtocol(v4);
 dword_FFD6BA38 = (*(int ( **)(int))(PcdProtocol + 16))(12);
 Status = (*(int ( **)(void *, void *, _DWORD, _DWORD, int *))(*(_DWORD *)a2 + 32))(
 a2,
 &unk_FFD6B9D4,
 0,
 0,
 &dword_FFD6BA40);
 if ( Status < 0 )
 {
 FpgaDebugPrint(0x80000000, "FPGA Loader, Find MRC Hooks Chip Services Ppi failed, return it's error!\n");
 FpgaDebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
 DebugLib = FpgaGetDebugLib();
 if ( DebugLib )
 (*(void ( **)(const char *, int, const char *))(DebugLib + 4))(
 "e:\\hs\\PurleySktPkg\\Pei\\FpgaLoader\\FpgaLoader.c",
 692,
 "!EFI_ERROR (Status)");
 return Status;
 }
 ErrorLevel = v32;
 if ( v32 && (ErrorLevel = v28, (v32 & v28) != 0) )
 {
 FpgaDebugPrint(0x80000000, "FPGA Loader, FpgaSktActive = %X! \n", ErrorLevel);
 FpgaDebugPrint(0x80000000, "FPGA Loader, FpgaSktPresent = %X! \n", ErrorLevel);
 FpgaDebugPrint(0x80000000, "FPGA Loader, FpgaPlatformEnabled = %X! \n", ErrorLevel);
 Status = (*(int ( **)(void *, void *, _DWORD, _DWORD, int *))(*(_DWORD *)a2 + 32))(
 a2,
 &unk_FFD6B9C4,
 0,
 0,
 &dword_FFD6BA48);
 if ( Status )
 {
 FpgaDebugPrint(0x80000000, "FPGA Loader, find Mp services PPI failed, return it's error!\n");
 return Status;
 }
 Status = (*(int ( **)(void *, int, int *, _BYTE *))dword_FFD6BA48)(a2, dword_FFD6BA48, &dword_FFD6BA50, v26);
 v12 = Status == 0;
 if ( Status >= 0 )
 {
 Status = FpgaMpServicesData(a2);
 v12 = Status == 0;
 }
 if ( !v12 )
 {
 FpgaDebugPrint(0x80000000, "FPGA Loader, FpgaMpServicesData failed, return it's error!, %r\n", Status);
 return Status;
 }
 Status = (*(int ( **)(void *, void *, _DWORD, _DWORD, int *))(*(_DWORD *)a2 + 32))(
 a2,
 &unk_FFD6BA14,
 0,
 0,
 &dword_FFD6BA58);
 if ( Status < 0 )
 {
 FpgaDebugPrint(0x80000000, "FPGA Loader, Find MRC Hooks Core Services PPI failed, return it's error!\n");
 FpgaDebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
 ErrorLevel = FpgaGetDebugLib();
 if ( ErrorLevel )
 (*(void ( **)(const char *, int, const char *))(ErrorLevel + 4))(
 "e:\\hs\\PurleySktPkg\\Pei\\FpgaLoader\\FpgaLoader.c",
 742,
 "!EFI_ERROR (Status)");
 return Status;
 }
 (*(void ( **)(int, int, _DWORD, int))(dword_FFD6BA58 + 32))(dword_FFD6BA38, 144, 0, 255);
 v30 = 0;
 if ( ((*(int ( **)(int, _DWORD, _DWORD, int))(dword_FFD6BA40 + 4))(
 dword_FFD6BA38,
 (unsigned __int8)dword_FFD6BA4C,
 0,
 318914724)
 & 0x20) == 0 )
 {
 Index = 0;
 while ( 1 )
 {
 v23 = 0;
 Index = 0;
 n4 = 4;
 do
 {
 v22 = 1 << Index;
 FpgaDebugPrint(
 0x80000000,
 "FPGA Loader, Retry %d, Socket %d, Mask %02x, Started!\n",
 Index,
 Index,
 (unsigned __int8)(1 << Index));
 if ( ((unsigned __int8)(1 << Index) & v28) != 0 )
 {
 if ( (v22 & v32) != 0 )
 {
 Protocol = v33[Index];
 if ( Protocol == 0xFF || (v22 & v31) != 0 )
 {
 FpgaDebugPrint(
 0x80000000,
 "FPGA Loader, Socket %d has no GUID assigned or has already programmed, skipping it!\n",
 Index);
 v30 |= v22;
 v33[Index + 8] = 1;
 v31 |= 1 << Index;
 }
 else
 {
 v23 = 1;
 FpgaDebugPrint(0x80000000, "FPGA Loader, Socket %d : BitStreamGuidIndex = %x !\n", Index, Protocol);
 }
 }
 else
 {
 v33[Index] = -1;
 v30 |= 1 << Index;
 v33[Index + 8] = 4;
 }
 }
 else
 {
 v33[Index] = -1;
 }
 ++Index;
 --n4;
 }
 while ( n4 );
 if ( v23 == 1 )
 FpgaLoadBitstream((int)a2, Table);
 if ( v31 == v28 || v31 == v32 )
 break;
 if ( (unsigned int)++Index >= 3 )
 goto LABEL_49;
 }
 FpgaDebugPrint(0x80000000, "FPGA Loader,All enabled sockets programmed! Exiting retry loop\n");
LABEL_49:
 FpgaDebugPrint(0x80000000, "FPGA Loader, Updating configuration values!\n");
 FpgaConfigurationSetValues(Table);
 FpgaDisableUnusedSockets(Table);
 FpgaDebugPrint(
 0x80000000,
 "Fpga Loader, Set the biosscratchpad1 bit5 to indicate bitstream download was attempted.\n");
 v21 = (*(int ( **)(int, _DWORD, _DWORD, int))(dword_FFD6BA40 + 4))(
 dword_FFD6BA38,
 (unsigned __int8)dword_FFD6BA4C,
 0,
 318914724);
 (*(void ( **)(int, _DWORD, _DWORD, int, int))(dword_FFD6BA40 + 8))(
 dword_FFD6BA38,
 (unsigned __int8)dword_FFD6BA4C,
 0,
 318914724,
 v21 | 0x20);
 FpgaDebugPrint(0x80000000, "FPGA Loader, Warm Reset!!\n");
 (*(void ( **)(void *, void *, _DWORD, _DWORD, void ( ***)(_DWORD, int)))(*(_DWORD *)a2 + 32))(
 a2,
 &unk_FFD6B9E4,
 0,
 0,
 &v25);
 (*v25)(v25, 1);
 while ( 1 )
 ;
 }
 FpgaDebugPrint(0x80000000, "FPGA Loader, FpgaConfigurationGetValues FPGA already active!\n");
 Index = 0;
 n4_1 = 4;
 do
 {
 v16 = 1 << Index;
 if ( (ErrorLevel & (unsigned __int8)(1 << Index)) == 1 << Index )
 v33[Index + 8] = 0;
 if ( (ErrorLevel & v16) != (v28 & v16) )
 {
 FpgaDebugPrint(0x80000000, "FPGA Loader,FpgaConfigurationGetValues Sockets[%x] active != present \n", Index);
 v33[Index] = -1;
 v30 |= v16;
 v33[Index + 8] = 9;
 }
 ++Index;
 --n4_1;
 }
 while ( n4_1 );
 FpgaDebugPrint(0x80000000, "FPGA Loader, Updating configuration values!\n");
 FpgaConfigurationSetValues(Table);
 FpgaDisableUnusedSockets(Table);
 FpgaPeiLock();
 return -2147483628;
 }
 else
 {
 FpgaDisableUnusedSockets(Table);
 return -2147483645;
 }
}

// ============================================================
// FpgaConfigurationGetValues
// ============================================================

int __thiscall FpgaConfigurationGetValues(char *this)
{
 char *v3; // esi _BYTE *v4; // ecx char *v5; // edx char v6; // al int Index; // esi int n4; // edi char *v9; // [esp+4h] [ebp-4h] BYREF if ( FpgaConfigurationGetHob(&v9) >= 0 )
 {
 v3 = v9;
 v4 = this + 7;
 v5 = v9 + 19;
 *(this + 2) = v9[2];
 *(this + 3) = v3[3];
 *(this + 4) = v3[4];
 *(this + 5) = v3[5];
 *(this + 6) = v3[6];
 *this = *v3;
 *(this + 1) = v3[1];
 *(this + 31) = v3[31];
 *(this + 32) = v3[32];
 v6 = v3[37];
 Index = v3 - this;
 *(this + 37) = v6;
 n4 = 4;
 do
 {
 *v4 = v4[Index];
 v4[8] = *(v5 - 4);
 v4[12] = *v5;
 v4[16] = v5[4];
 v4[20] = v5[8];
 v4[4] = *(v5 - 8);
 v4[26] = v5[14];
 ++v4;
 ++v5;
 --n4;
 }
 while ( n4 );
 return 0;
 }
 else
 {
 FpgaDebugPrint(0x80000000, "FpgaConfigurationGetValues-> HOB error, return EFI_NOT_FOUND!\n");
 return -2147483634;
 }
}

// ============================================================
// FpgaConfigurationSetValues
// ============================================================

int __thiscall FpgaConfigurationSetValues(_BYTE *this)
{
 char *v3; // ecx _BYTE *v4; // esi _BYTE *v5; // edx char v6; // al _BYTE *v7; // edi int n4; // ecx char *v9; // [esp+4h] [ebp-4h] BYREF if ( FpgaConfigurationGetHob(&v9) >= 0 )
 {
 v3 = v9;
 v4 = this + 19;
 v9[2] = *(this + 2);
 v5 = v3 + 7;
 v3[3] = *(this + 3);
 v3[4] = *(this + 4);
 v3[5] = *(this + 5);
 v3[6] = *(this + 6);
 v3[1] = *(this + 1);
 v3[31] = *(this + 31);
 v3[32] = *(this + 32);
 v6 = *(this + 37);
 v7 = (_BYTE *)(this - v3);
 v3[37] = v6;
 n4 = 4;
 do
 {
 *v5 = v5[(_DWORD)v7];
 v5[8] = *(v4 - 4);
 v5[12] = *v4;
 v5[16] = v4[4];
 v5[20] = v4[8];
 v5[4] = *(v4 - 8);
 v5[26] = v4[14];
 ++v5;
 ++v4;
 --n4;
 }
 while ( n4 );
 return 0;
 }
 else
 {
 FpgaDebugPrint(0x80000000, "FpgaConfigurationSetValues-> HOB error, return EFI_NOT_FOUND!\n");
 return -2147483634;
 }
}

// ============================================================
// FpgaConfigurationGetHob
// ============================================================

int __thiscall FpgaConfigurationGetHob(char **this)
{
 _WORD *HobList; // eax int v4; // ecx int v5; // ecx _WORD *HobByType; // esi int v7; // ecx char *v8; // esi int v9; // ecx int Hob; // eax int Hob_1; // esi unsigned int n4_1; // ebx _BYTE *v13; // eax int Index; // ecx char *Variable; // edi char v16; // al char buf[40]; // [esp+10h] [ebp-28h] BYREF if ( !this )
 return -2147483646;
 HobList = (_WORD *)FpgaGetHobList();
 HobByType = FpgaFindHobByType(v4, HobList);
 if ( HobByType )
 {
 do
 {
 if ( FpgaHobGuidMatch(v5, (int)(HobByType + 4)) )
 break;
 HobByType = FpgaFindHobByType(v7, (_WORD *)((char *)HobByType + (unsigned __int16)HobByType[1]));
 }
 while ( HobByType );
 if ( HobByType )
 {
 v8 = (char *)(HobByType + 12);
LABEL_8:
 *this = v8;
 return 0;
 }
 }
 FpgaDebugPrint(0x80000000, "FPGA Configuration Get HOB-> HOB is not found, create it!\n");
 FpgaZeroMem((int)buf, 0x26u);
 Hob = FpgaCreateHob(v9, 62);
 Hob_1 = Hob;
 if ( Hob )
 {
 FpgaHobInitGuid((void *)(Hob + 8));
 if ( Hob_1 != -24 )
 {
 v8 = FpgaCopyMem((char *)(Hob_1 + 24), buf, 0x26u);
 if ( v8 )
 {
 FpgaDebugPrint(0x80000000, "FPGA Configuration Get HOB-> create it worked, init it!\n");
 n4_1 = 0;
 *(_WORD *)(v8 + 5) = -256;
 *(_DWORD *)(v8 + 1) = 0;
 v13 = v8 + 15;
 *(_WORD *)(v8 + 31) = 0;
 v8[37] = 0;
 Index = 4;
 do
 {
 *(v13 - 8) = -1;
 *v13 = 11;
 v13[8] = -1;
 v13[12] = -1;
 *(v13 - 4) = 0;
 v13[18] = 0;
 ++v13;
 --Index;
 }
 while ( Index );
 Variable = (char *)FpgaGetVariable();
 if ( Variable )
 {
 FpgaDebugPrint(0x80000000, "FPGA Configuration Get HOB-> Vaiable found use it!\n");
 v8[6] = *Variable;
 v8[31] = Variable[13];
 v8[32] = Variable[14];
 v8[37] = Variable[19];
 do
 {
 v8[n4_1 + 23] = Variable[n4_1 + 5];
 v8[n4_1 + 27] = Variable[n4_1 + 9];
 v16 = Variable[n4_1 + 1];
 if ( v16 )
 {
 if ( v16 == -1 )
 v8[n4_1 + 7] = -1;
 else v8[n4_1 + 7] = v16 - 1;
 }
 v8[n4_1 + 33] = Variable[n4_1 + 15];
 ++n4_1;
 }
 while ( n4_1 < 4 );
 }
 *v8 = 1;
 goto LABEL_8;
 }
 }
 }
 FpgaDebugPrint(0x80000000, "FPGA Configuration Get HOB-> HOB IS NULL, could not create!\n");
 return -2147483634;
}

// ============================================================
// FpgaMpServicesData
// ============================================================

int __thiscall FpgaMpServicesData(void *this)
{
 int result; // eax unsigned int Index; // esi int v4; // edi int Status; // esi int DebugLib; // eax result = (*(int ( **)(void *, int, int *))(*(_DWORD *)this + 76))(this, 24 *dword_FFD6BA50, &dword_FFD6BA44);
 if ( result >= 0 )
 {
 Index = 0;
 if ( dword_FFD6BA50 )
 {
 v4 = 0;
 while ( 1 )
 {
 result = (*(int ( **)(void *, int, unsigned int, int))(dword_FFD6BA48 + 4))(
 this,
 dword_FFD6BA48,
 Index,
 v4 + dword_FFD6BA44);
 if ( result < 0 )
 break;
 ++Index;
 v4 += 24;
 if ( Index >= dword_FFD6BA50 )
 goto LABEL_6;
 }
 }
 else
 {
LABEL_6:
 Status = (*(int ( **)(void *, int, int *))(dword_FFD6BA48 + 24))(this, dword_FFD6BA48, &dword_FFD6BA54);
 FpgaDebugPrint(0x80000000, "BSP Index is: %X\n", dword_FFD6BA54);
 if ( Status < 0 )
 {
 FpgaDebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
 DebugLib = FpgaGetDebugLib();
 if ( DebugLib )
 (*(void ( **)(const char *, int, const char *))(DebugLib + 4))(
 "e:\\hs\\PurleySktPkg\\Pei\\FpgaLoader\\FpgaLoader.c",
 102,
 "!EFI_ERROR (Status)");
 }
 dword_FFD6BA4C = *(_DWORD *)(24 *dword_FFD6BA54 + dword_FFD6BA44 + 12);
 FpgaDebugPrint(0x80000000, "BSP Socket is: %X\n", dword_FFD6BA4C);
 return Status;
 }
 }
 return result;
}

// ============================================================
// FpgaGetPcdProtocol
// ============================================================

void *__thiscall FpgaGetPcdProtocol(void *this)
{
 int PeiServices; // eax int Status; // eax int DebugLib; // eax void *this_1; // [esp+0h] [ebp-4h]

 this_1 = this;
 PeiServices = FpgaGetPeiServices();
 Status = (*(int (__stdcall **)(int))(*(_DWORD *)PeiServices + 32))(PeiServices);
 if ( Status < 0 )
 {
 FpgaDebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
 DebugLib = FpgaGetDebugLib();
 if ( DebugLib )
 (*(void ( **)(const char *, int, const char *))(DebugLib + 4))(
 "e:\\hs\\MdePkg\\Library\\PeiPcdLib\\PeiPcdLib.c",
 49,
 "!EFI_ERROR (Status)");
 }
 return this_1;
}

// ============================================================
// FpgaPeiLock
// ============================================================

int FpgaPeiLock()
{
 int v0; // esi unsigned int ErrorLevel; // ebx char Index; // al int v3; // eax char v5; // [esp+Ch] [ebp-4h]

 v0 = dword_FFD6BA38;
 FpgaDebugPrint(0x80000000, "FPGA Loader, Perform PEI lock.\n");
 ErrorLevel = *(_DWORD *)(v0 + 246472);
 v5 = 0;
 FpgaDebugPrint(0x80000000, "FPGA Loader, FpgaPresentBitMap = %X\n", ErrorLevel);
 if ( ErrorLevel )
 {
 Index = 0;
 do
 {
 if ( (ErrorLevel & 1) != 0 )
 {
 v3 = (*(int ( **)(int, char, _DWORD, int))(dword_FFD6BA40 + 4))(v0, v5, 0, 335561260);
 (*(void ( **)(int, char, _DWORD, int, int))(dword_FFD6BA40 + 8))(v0, v5, 0, 335561260, v3 | 1);
 Index = v5;
 }
 ++Index;
 ErrorLevel >>= 1;
 v5 = Index;
 }
 while ( ErrorLevel );
 }
 return 0;
}

// ============================================================
// FpgaDisableUnusedSockets
// ============================================================

int __thiscall FpgaDisableUnusedSockets(_BYTE *this)
{
 unsigned __int8 Index; // bl int Result; // edi int Status; // esi int v5; // ecx int ErrorLevel; // eax int PeiServices; // eax int Status; // eax int DebugLib; // eax int Status; // eax unsigned __int8 n4_1; // [esp+10h] [ebp-8h]
 int v13; // [esp+14h] [ebp-4h] BYREF Index = 0;
 Result = -2147483645;
 n4_1 = 0;
 Status = 0;
 do
 {
 if ( ((unsigned __int8)(1 << Status) & *(this + 2)) != 0 )
 {
 v5 = (unsigned __int8)*(this + 6);
 if ( ((1 << Status) & v5) == 0 )
 {
 FpgaDebugPrint(
 0x80000000,
 "FpgaPlatformEnabled = 0x%X. FpgaBitStreamStatus = 0x%X.\n",
 v5,
 (unsigned __int8)*(this + Status + 15));
 FpgaDebugPrint(0x80000000, "Disable Fpga Socket[%x]!!!\n", Status);
 ErrorLevel = (*(int ( **)(int, unsigned __int8, int, _DWORD))(dword_FFD6BA40 + 12))(dword_FFD6BA38, n4_1, 182, 0);
 if ( ErrorLevel )
 FpgaDebugPrint(0x80000000, "Socket[%x ]mailbox command REMOVE_MCP fail return : 0x%x.\n", Status, ErrorLevel);
 PeiServices = FpgaGetPeiServices();
 Status = (*(int ( **)(int, void *, _DWORD, _DWORD, int *))(*(_DWORD *)PeiServices + 32))(
 PeiServices,
 &unk_FFD6B9F4,
 0,
 0,
 &v13);
 if ( Status < 0 )
 {
 FpgaDebugPrint(0x80000000, "\nASSERT_EFI_ERROR (Status = %r)\n", Status);
 DebugLib = FpgaGetDebugLib();
 if ( DebugLib )
 (*(void ( **)(const char *, int, const char *))(DebugLib + 4))(
 "e:\\hs\\PurleyPlatPkg\\Library\\FpgaPlatformHooksLib\\FpgaPlatformHooksLib.c",
 176,
 "!EFI_ERROR (Status)");
 }
 Status = (*(int ( **)(unsigned __int8))(v13 + 80))(n4_1);
 Result = Status;
 if ( Status < 0 )
 FpgaDebugPrint(0x80000000, "Socket[%x ] Fpga Power off fail return status = %r.\n", Status, Status);
 }
 }
 ++Index;
 ++Status;
 n4_1 = Index;
 }
 while ( Index < 4u );
 return Result;
}

// ============================================================
// FpgaLoadBitstream
// ============================================================

int FpgaLoadBitstream(int a1, _BYTE *a2)
{
 int ErrorLevel; // eax int Result; // edi int n38_1; // eax char *AlignedPages; // eax int AlignedPages_1; // ebp unsigned int i; // edi char v10; // bl char v11; // al int ErrorLevel; // eax void *v13; // ecx unsigned int Buffer; // eax int v15; // ecx unsigned int n38_2; // eax int src_2; // eax int ErrorLevel; // eax int Result; // esi double ErrorLevel; // [esp-4h] [ebp-24h]
 char *src; // [esp+10h] [ebp-10h] BYREF int src_1; // [esp+14h] [ebp-Ch] BYREF unsigned int n38; // [esp+18h] [ebp-8h] BYREF int v24; // [esp+1Ch] [ebp-4h]

 v24 = a1;
 ErrorLevel = FpgaFvLibN4PeGet((int)&unk_FFD6B974, (int *)&src, (int *)&n38);
 Result = ErrorLevel;
 if ( ErrorLevel )
 {
 FpgaDebugPrint(0x80000000, "Fpga Loader, FpgaFvLibN4PeGet returned error, %r\n", ErrorLevel);
 return Result;
 }
 FpgaDebugPrint(0x80000000, "N4PE Date : %x \n", *((_DWORD *)src + 2));
 FpgaDebugPrint(0x80000000, "N4PE BuildNumber : %x \n", *((unsigned __int16 *)src + 29));
 FpgaDebugPrint(0x80000000, "N4PE Size : %x \n", *((_DWORD *)src + 4));
 FpgaDebugPrint(0x80000000, "N4PE MajorRevisionID : %x \n", *((unsigned __int16 *)src + 3));
 FpgaDebugPrint(0x80000000, "N4PE MinorHeaderVersion : %x \n", *(unsigned __int16 *)src);
 n38_1 = *((_DWORD *)src + 4);
 if ( n38 != n38_1 )
 {
 FpgaDebugPrint(
 0x80000000,
 "Fpga Loader, FpgaFvLibLoaderGet returned different size, header->%^04x, returned->%04x\n",
 n38_1,
 n38);
 return -2147483644;
 }
 AlignedPages = (char *)FpgaAllocateAlignedPages(0x40u, 0x40000u);
 AlignedPages_1 = (int)AlignedPages;
 if ( !AlignedPages )
 return -2147483639;
 FpgaCopyMem(AlignedPages, src, n38);
 for ( i = 0; i < 4; ++i )
 {
 v10 = 1 << i;
 if ( ((unsigned __int8)(1 << i) & a2[5]) == 0 )
 {
 v11 = a2[i + 7];
 if ( v11 != -1 )
 {
 if ( v11 )
 {
 if ( v11 != 1 )
 {
 ErrorLevel = -2147483645;
LABEL_16:
 FpgaDebugPrint(0x80000000, "Fpga Loader, FpgaFvLibBitStreamGet returned error, %r\n", ErrorLevel);
 a2[i + 7] = -1;
 a2[4] |= v10;
 a2[i + 15] = 5;
 continue;
 }
 v13 = &unk_FFD6B964;
 }
 else
 {
 v13 = &unk_FFD6B984;
 }
 ErrorLevel = FpgaFvLibN4PeGet((int)v13, &src_1, (int *)&n38);
 if ( ErrorLevel )
 goto LABEL_16;
 LODWORD(ErrorLevel) = src_1;
 FpgaDebugPrint(0x80000000, "BBS ID : %g \n", ErrorLevel);
 FpgaDebugPrint(0x80000000, "BBS Size : %x \n", *(_DWORD *)(src_1 + 16));
 FpgaDebugPrint(0x80000000, "BBS Data Structure Version : %x \n", *(unsigned __int16 *)(src_1 + 20));
 FpgaDebugPrint(0x80000000, "BBS Flags : %x \n", *(unsigned __int16 *)(src_1 + 22));
 if ( n38 == *(_DWORD *)(src_1 + 16) )
 {
 Buffer = FpgaAllocateAlignedPages(1u, 8u);
 v15 = Buffer;
 if ( !Buffer )
 return -2147483639;
 *(_DWORD *)Buffer = AlignedPages_1;
 *(_WORD *)(Buffer + 8) = 2;
 *(_WORD *)(Buffer + 10) = 0;
 n38_2 = n38;
 *(_DWORD *)(v15 + 4) = AlignedPages_1 >> 31;
 *(_DWORD *)(v15 + 12) = n38_2;
 src_2 = src_1;
 *(_DWORD *)(v15 + 24) = 0;
 *(_DWORD *)(v15 + 28) = 0;
 *(_QWORD *)(v15 + 16) = src_2;
 ErrorLevel = sub_FFD69194(v24, i, v15);
 if ( ErrorLevel )
 {
 FpgaDebugPrint(0x80000000, "Fpga Loader, FpgaLoaderLoadParmRegister returned error, %r\n", ErrorLevel);
 a2[i + 7] = -1;
 a2[4] |= v10;
 a2[i + 15] = 6;
 }
 }
 else
 {
 FpgaDebugPrint(0x80000000, "Fpga Loader, FpgaFvLibBitStreamGet returned error, %r\n", 0);
 a2[i + 7] = -1;
 a2[4] |= v10;
 a2[i + 15] = 8;
 }
 }
 }
 }
 (*(void ( **)(int, int, _DWORD, int))(dword_FFD6BA58 + 32))(dword_FFD6BA38, 145, 0, 255);
 Result = sub_FFD692A1(v24, a2);
 if ( Result )
 {
 (*(void ( **)(int, int, _DWORD, int))(dword_FFD6BA58 + 32))(dword_FFD6BA38, 146, 0, 255);
 FpgaDebugPrint(0x80000000, "Fpga Loader, FpgaLoaderLoadTriggerRegister returned error, %r\n", Result);
 }
 return Result;
}