Newer
Older
AMI-Aptio-BIOS-Reversed / F0E9D620-3E9F-4F6B-8F26-6214FEAB6690 / F0E9D620-3E9F-4F6B-8F26-6214FEAB6690.c
@Ajax Dong Ajax Dong 2 days ago 29 KB Init
/*
 *F0E9D620-3E9F-4F6B-8F26-6214FEAB6690.c
 *F0E9D620-3E9F-4F6B-8F26-6214FEAB6690 PEI module decompiled from IDA
 */

#include "F0E9D620-3E9F-4F6B-8F26-6214FEAB6690.h"

// j_ProtocolTeardown @ 0x1a6cc
// attributes: thunk __int64 j_ProtocolTeardown(__int64 a1)
{
 return ProtocolTeardown(a1);
}

// _ModuleEntryPoint @ 0x1a6d4 EFI_STATUS ModuleEntryPoint(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
 __int64 Protocol; // [rsp+40h] [rbp+18h] BYREF EarlyInit((__int64)ImageHandle, SystemTable); /*0x1a6e4*/
 (*(void ( **)(EFI_HANDLE, __int64 *, __int64 *))(BootServices + 152))(ImageHandle, qword_3B0, &Protocol); /*0x1a6ff*/
 *(_QWORD *)(Protocol + 88) = j_ProtocolTeardown; /*0x1a717*/
 return DxeDriverEntryPoint((__int64)ImageHandle, SystemTable); /*0x1a725*/
}

// EarlyInit @ 0x1a72c
// write access to const memory has been detected, the output may be wrong!
__int64 EarlyInit(__int64 ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
 EFI_BOOT_SERVICES *BootServices; // r9 EFI_RUNTIME_SERVICES *RuntimeServices; // rax BootServices = SystemTable->BootServices; /*0x1a730*/
 RuntimeServices = SystemTable->RuntimeServices; /*0x1a734*/
 ::ImageHandle = ImageHandle; /*0x1a738*/
 ::SystemTable = (__int64)SystemTable; /*0x1a73f*/
 ::BootServices = (__int64)BootServices; /*0x1a756*/
 ::RuntimeServices = (__int64)RuntimeServices; /*0x1a75d*/
 ((void ( *)(__int64 *, _QWORD, __int64 *))BootServices->LocateProtocol)(qword_2D0, 0, &qword_473C0); /*0x1a764*/
 dword_140(qword_300, 0, &qword_473D0); /*0x1a782*/
 dword_140(qword_2E0, 0, &qword_473D8); /*0x1a79f*/
 dword_140(qword_330, 0, &qword_473B8); /*0x1a7bc*/
 return dword_140(qword_340, 0, &qword_473C8);
}

// DxeDriverEntryPrepare @ 0x1a7e4 unsigned __int64 DxeDriverEntryPrepare(__int64 a1)
{
 __int64 n6; // [rsp+50h] [rbp+8h] BYREF __int64 Status; // [rsp+58h] [rbp+10h] BYREF __int64 v5; // [rsp+60h] [rbp+18h] BYREF __int64 v6; // [rsp+68h] [rbp+20h] BYREF if ( *(_WORD *)(a1 + 9610) != 4156 ) /*0x1a7fa*/
 return 0x8000000000000003uLL; /*0x1a7fa*/
 (*(void ( **)(_QWORD, __int64 *, __int64 *, __int64 *, __int64 *))(*(_QWORD *)(a1 + 11184) + 112LL))( /*0x1a82b*/
 *(_QWORD *)(a1 + 11184),
 &v6,
 &v5,
 &n6,
 &Status);
 if ( *(_WORD *)(a1 + 9608) == 4217 && *(_WORD *)(a1 + 9610) == 4156 && *(_WORD *)(a1 + 9612) == 4819 && n6 == 6 ) /*0x1a85b*/
 return 0x8000000000000003uLL; /*0x1a7fc*/
 else return -(__int64)(Status != 0) & 0x8000000000000003uLL; /*0x1a873*/
}

// DxeDriverEntryPoint @ 0x1a880
// write access to const memory has been detected, the output may be wrong!
__int64 DxeDriverEntryPoint(__int64 ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
 __int64 result; // rax __int64 ImageHandle_1; // [rsp+80h] [rbp+8h] BYREF __int64 ImageHandle_2; // [rsp+88h] [rbp+10h] BYREF __int64 Protocol; // [rsp+90h] [rbp+18h] BYREF ImageHandle_1 = ImageHandle; /*0x1a887*/
 ImageHandle_2 = ImageHandle; /*0x1a890*/
 SystemTable_0 = (__int64)SystemTable; /*0x1a8a5*/
 result = (*(__int64 ( **)(__int64 *, __int64 *, _UNKNOWN **, _QWORD))(BootServices + 328))( /*0x1a8bd*/
 &ImageHandle_2,
 qword_350,
 &off_1D78,
 0);
 ImageHandle_0 = ImageHandle; /*0x1a8cb*/
 ImageHandle_1 = ImageHandle_2; /*0x1a8d2*/
 if ( result >= 0 ) /*0x1a8dc*/
 {
 result = (*(__int64 ( **)(__int64 *, __int64 *, __int64 ( **)(), __int64 *, _UNKNOWN **, __int64 *, __int64 ( **)(), __int64 *, _UNKNOWN **, __int64 *, _UNKNOWN **, __int64 *, __int64 ( **)(int, int, int, int, __int64, __int64), _QWORD))(BootServices + 328))( /*0x1a977*/
 &ImageHandle_1,
 qword_360,
 &off_E98,
 qword_390,
 &off_1B28,
 qword_370,
 &off_1AA0,
 qword_3A0,
 &off_1B38,
 qword_380,
 &off_E78,
 qword_320,
 &off_1B48,
 0);
 if ( result >= 0 ) /*0x1a980*/
 {
 if ( SystemTable->Hdr.Revision >= (unsigned int)Cfg_2000a ) /*0x1a98d*/
 result = (*(__int64 ( **)(__int64 *, __int64 *, __int64 *, _QWORD))(BootServices + 328))( /*0x1a9af*/
 &ImageHandle_1,
 qword_310,
 qword_1AB8,
 0);
 if ( result >= 0 ) /*0x1a9b8*/
 {
 result = (*(__int64 ( **)(__int64, __int64 *, __int64 *, __int64, _QWORD, int))(BootServices + 280))( /*0x1a9ed*/
 ImageHandle_1,
 qword_3B0,
 &Protocol,
 ImageHandle_1,
 0,
 2);
 if ( result >= 0 ) /*0x1a9f6*/
 {
 *(_QWORD *)(Protocol + 88) = ProtocolTeardown; /*0x1aa0a*/
 result = (*(__int64 ( **)(__int64, __int64, void (*)()))(BootServices + 80))( /*0x1aa31*/
 513,
 16,
 ProtocolBootCallback);
 if ( result >= 0 ) /*0x1aa37*/
 return PxeStructInit(); /*0x1aa39*/
 }
 }
 }
 }
 return result; /*0x1aa46*/
}

// PxeStructInit @ 0x1aa4c
// write access to const memory has been detected, the output may be wrong!
__int64 PxeStructInit()
{
 __int64 n96; // rbx __int64 result; // rax __int64 Result; // r11 _BYTE *v3; // rax n96 = 96; /*0x1aa59*/
 result = (*(__int64 ( **)(__int64, __int64, __int64 *))(BootServices + 64))(4, 96, &qword_47380); /*0x1aa6b*/
 Result = result; /*0x1aa74*/
 if ( result >= 0 ) /*0x1aa77*/
 {
 v3 = 0; /*0x1aa7d*/
 do /*0x1aa90*/
 {
 --n96; /*0x1aa84*/
 *v3++ = 0; /*0x1aa87*/
 }
 while ( n96 ); /*0x1aa90*/
 UndiCallbackDispatch_0 = (__int64 ( *)(_QWORD, _QWORD, _QWORD))UndiCallbackDispatch; /*0x1aab5*/
 qword_47388 = 0; /*0x1aab9*/
 strcpy((char *)&_ImageBase, "!PXE "); /*0x1aac0*/
 n2 = 2; /*0x1aad3*/
 LOWORD(n4099) = 4099; /*0x1aad7*/
 word_A = 0; /*0x1aadb*/
 *(_DWORD *)&word_C = 1073792506; /*0x1aae0*/
 LOWORD(word_18) = 0; /*0x1aaeb*/
 n256 = 256; /*0x1aaf3*/
 *(_DWORD *)word_1C = 1380533072; /*0x1aafb*/
 HIBYTE(word_4) = 0; /*0x1ab21*/
 return Result; /*0x1ab1e*/
 }
 return result; /*0x1ab24*/
}

// ProtocolBootCallback @ 0x1ab2c void ProtocolBootCallback()
{
 ; /*0x1ab2c*/
}

// ProtocolTeardown @ 0x1abc4 __int64 ProtocolTeardown(__int64 a1)
{
 __int64 result; // rax unsigned __int64 i; // rbx __int64 Result; // r11 unsigned __int64 i_1; // [rsp+98h] [rbp+10h] BYREF __int64 v6; // [rsp+A0h] [rbp+18h] BYREF result = (*(__int64 ( **)(_QWORD, _QWORD, _QWORD, unsigned __int64 *, __int64 *))(BootServices + 312))( /*0x1abf0*/
 0,
 0,
 0,
 &i_1,
 &v6);
 if ( result >= 0 ) /*0x1abf9*/
 {
 for ( i = 0; i < i_1; ++i ) /*0x1ac09*/
 (*(void ( **)(_QWORD, __int64, _QWORD))(BootServices + 272))(*(_QWORD *)(v6 + 8 *i), a1, 0); /*0x1ac24*/
 if ( v6 ) /*0x1ac42*/
 (*(void (**)(void))(BootServices + 72))(); /*0x1ac4b*/
 result = (*(__int64 ( **)(_QWORD))(BootServices + 72))(0); /*0x1ac69*/
 if ( result >= 0 ) /*0x1ac6f*/
 {
 result = (*(__int64 ( **)(_QWORD))(BootServices + 112))(0); /*0x1ac83*/
 if ( result >= 0 ) /*0x1ac89*/
 {
 result = (*(__int64 ( **)(__int64, __int64 *, _UNKNOWN **, __int64 *, __int64 ( **)(), __int64 *, _UNKNOWN **, __int64 *, __int64 ( **)(), __int64 *, _UNKNOWN **, __int64 *, _UNKNOWN **, __int64 *, __int64 ( **)(int, int, int, int, __int64, __int64), _QWORD))(BootServices + 336))( /*0x1ad38*/
 a1,
 qword_350,
 &off_1D78,
 qword_360,
 &off_E98,
 qword_390,
 &off_1B28,
 qword_370,
 &off_1AA0,
 qword_3A0,
 &off_1B38,
 qword_380,
 &off_E78,
 qword_320,
 &off_1B48,
 0);
 Result = result; /*0x1ad3e*/
 if ( result >= 0 ) /*0x1ad44*/
 {
 if ( *(_DWORD *)(SystemTable + 8) >= (unsigned int)SnpCheckFwRevision ) /*0x1ad54*/
 return (*(__int64 ( **)(__int64, __int64 *, __int64 *, _QWORD))(BootServices + 336))( /*0x1ad77*/
 a1,
 qword_310,
 qword_1AB8,
 0);
 return Result; /*0x1ad7a*/
 }
 }
 }
 }
 return result; /*0x1ad91*/
}

// UndiChildProtocolAlloc @ 0x1bd4c __int64 UndiChildProtocolAlloc(__int16 n4686, __int16 n4687, __int64 *a3, __int64 *a4)
{
 _QWORD *v9; // rbx _QWORD *v10; // rdi __int64 Buffer; // rax __int64 Buffer; // rax if ( !a4 ) /*0x1bd75*/
 return 0x8000000000000002uLL; /*0x1bd81*/
 v9 = (_QWORD *)UtlMemAlloc(); /*0x1bd8b*/
 if ( v9 ) /*0x1bd91*/
 {
 v10 = (_QWORD *)UtlMemAlloc(); /*0x1bd98*/
 if ( v10 ) /*0x1bd9e*/
 {
 Buffer = UtlMemAllocPool(v9, qword_260, 0, 21); /*0x1bdb3*/
 if ( Buffer ) /*0x1bdbe*/
 {
 *(_BYTE *)(Buffer + 18) = 0; /*0x1bdd0*/
 *(_WORD *)(Buffer + 19) = n4686; /*0x1bdd4*/
 Buffer = UtlMemAllocPool(v10, qword_260, 0, 21); /*0x1bdd9*/
 *(_BYTE *)(Buffer + 18) = 0; /*0x1bdde*/
 *(_WORD *)(Buffer + 19) = n4687; /*0x1bde2*/
 *a3 = (__int64)v9; /*0x1bde7*/
 *a4 = (__int64)v10; /*0x1bded*/
 return 0; /*0x1bdf0*/
 }
 UtlMemFree(v10); /*0x1bdf2*/
 }
 UtlMemFree(v9); /*0x1bdfa*/
 }
 return 0x8000000000000009uLL; /*0x1be18*/
}

// UndiChildProtocolRegister @ 0x1be24 __int64 UndiChildProtocolRegister(
 __int64 a1,
 __int64 a2,
 __int64 a3,
 __int16 n4680,
 __int16 n4681,
 __int16 n4679,
 __int16 n80,
 __int16 n140,
 int a9,
 __int16 n4410)
{
 __int64 v11; // rbx _BYTE *v12; // rcx __int64 n15; // rax _BYTE *v14; // rax _QWORD *v15; // rsi _QWORD *v17; // [rsp+30h] [rbp-28h] BYREF _QWORD *v18; // [rsp+38h] [rbp-20h] BYREF _BYTE v19[2]; // [rsp+40h] [rbp-18h] BYREF __int16 n80_1; // [rsp+42h] [rbp-16h]
 __int16 n140_1; // [rsp+44h] [rbp-14h]
 __int16 n4410_1; // [rsp+46h] [rbp-12h]
 char v23; // [rsp+4Ch] [rbp-Ch]
 __int16 n4679_1; // [rsp+4Dh] [rbp-Bh]
 _UNKNOWN *retaddr; // [rsp+58h] [rbp+0h] BYREF if ( &retaddr == (_UNKNOWN **)word_28 ) /*0x1be42*/
 v11 = 0x8000000000000002uLL; /*0x1be61*/
 else v11 = UndiChildProtocolAlloc(n4680, n4681, (__int64 *)&v17, (__int64 *)&v18); /*0x1be5c*/
 if ( v11 >= 0 ) /*0x1be6e*/
 {
 v12 = v19; /*0x1be79*/
 n15 = 15; /*0x1be7e*/
 do /*0x1be8b*/
 {
 *v12++ = 0; /*0x1be81*/
 --n15; /*0x1be87*/
 }
 while ( n15 ); /*0x1be8b*/
 n80_1 = n80; /*0x1be9d*/
 n140_1 = n140; /*0x1bead*/
 n4410_1 = n4410; /*0x1bebf*/
 v23 = 0; /*0x1bed7*/
 n4679_1 = n4679; /*0x1bedc*/
 v14 = UtlBuildTlv((__int64)v17, v19, 15, 15, 0, 0); /*0x1bee1*/
 v15 = v18; /*0x1bee6*/
 if ( v14 ) /*0x1beee*/
 v11 = UtlInstallProtocol(a1, (__int64)&qword_1D48, 1u, (__int64)v17, v18); /*0x1bf1b*/
 else v11 = 0x8000000000000009uLL; /*0x1bef0*/
 UtlMemFree(v17); /*0x1bf23*/
 UtlMemFree(v15); /*0x1bf2b*/
 }
 return v11; /*0x1bf3d*/
}

// UtlMemAllocStruct @ 0x46058 __int64 UtlMemAllocStruct(_QWORD *a1, __int64 a2, ...)
{
 _DWORD *v2; // rdi int v5; // ebx _DWORD *v6; // rax va_list Index; // r8 unsigned int v8; // ebx _QWORD *v9; // rax _QWORD *v10; // rsi _BYTE *v11; // rcx __int64 v12; // rax __int64 v13; // r11 __int64 v14; // rcx __int64 v15; // r10 __int64 v16; // rax __int64 v17; // rcx __int64 Result[9]; // [rsp+20h] [rbp-48h] BYREF _DWORD *v20; // [rsp+80h] [rbp+18h] BYREF va_list va; // [rsp+80h] [rbp+18h]
 va_list va1; // [rsp+88h] [rbp+20h] BYREF va_start(va1, a2);
 va_start(va, a2);
 v20 = va_arg(va1, _DWORD *); /*0x46058*/
 v2 = v20; /*0x46073*/
 v5 = 0; /*0x46080*/
 v6 = v20; /*0x46083*/
 if ( !v20 ) /*0x46089*/
 return 0; /*0x46089*/
 va_copy(Index, va); /*0x4608f*/
 do /*0x4609d*/
 {
 ++Index; /*0x46095*/
 v5 = v5 + *v6 - 4; /*0x46099*/
 v6 = *Index; /*0x4609d*/
 }
 while ( *Index ); /*0x4609d*/
 if ( !v5 ) /*0x460a8*/
 return 0; /*0x460a8*/
 v8 = v5 + 24; /*0x460ae*/
 v9 = (_QWORD *)UtlStrCmp(4, v8); /*0x460b8*/
 v10 = v9; /*0x460bd*/
 if ( !v9 ) /*0x460c3*/
 return 0; /*0x46158*/
 v11 = (char *)v9 + 20; /*0x460cd*/
 *v9 = *a1; /*0x460d9*/
 v12 = a1[1]; /*0x460dc*/
 *((_DWORD *)v10 + 4) = v8; /*0x460e0*/
 v10[1] = v12; /*0x460e3*/
 do /*0x46108*/
 {
 UtlMemCpy(v11, (_BYTE *)v2 + 4, (unsigned int)(*v2 - 4)); /*0x460f6*/
 v11 = (_BYTE *)(v15 + v14); /*0x460ff*/
 v2 = *(_DWORD **)(v13 + 8); /*0x46102*/
 }
 while ( v2 ); /*0x46108*/
 UtlMemCpy(v11, &qword_1A630, 4); /*0x46117*/
 v16 = _ImageBase(0, v10, a2, Result); /*0x46131*/
 v17 = Result[0]; /*0x46133*/
 if ( v16 < 0 ) /*0x46142*/
 v17 = 0; /*0x46142*/
 Result[0] = v17; /*0x46146*/
 (*(void ( **)(_QWORD *))(BootServices + 72))(v10); /*0x4614e*/
 return Result[0]; /*0x4615a*/
}

// UtlStrCatMemPool @ 0x46168 __int64 UtlStrCatMemPool()
{
 (*(void ( **)(__int64 *, _QWORD, __int64 *))(BootServices + 320))(&qword_2B0[2], 0, &qword_473E0); /*0x4619f*/
 return 0; /*0x4627a*/
}

// UtlMemPoolAlloc @ 0x46280 __int16 *UtlMemPoolAlloc()
{
 __int64 *v0; // rbp __int64 *v1; // rax __int64 v2; // rdx __int16 *i_2; // rax __int16 *i_1; // rbx __int16 n71; // dx __int64 v7; // rcx __int16 *i; // rax __int16 *k_1; // rdi unsigned __int64 j; // rsi unsigned __int64 v11; // rax __int16 *k_2; // rax __int16 n38; // dx __int64 v14; // rcx __int16 *k; // rax unsigned __int16 n85; // ax __int16 *k_3; // rdi __int16 *k_4; // rax __int16 n38_1; // dx __int64 v20; // rcx __int16 *m; // rax char v22; // dl __int16 *n; // rcx unsigned __int16 n0x41; // ax v0 = &qword_1B60[1]; /*0x4629b*/
 v1 = &qword_1B60[1]; /*0x462a2*/
 v2 = 0; /*0x462a5*/
 do /*0x462bd*/
 {
 v1 = (__int64 *)((char *)v1 + 2); /*0x462b7*/
 ++v2; /*0x462ba*/
 }
 while ( *(_WORD *)v1 ); /*0x462bd*/
 i_2 = (__int16 *)UtlStrCmp(4, 8 *v2 + 100); /*0x462d0*/
 i_1 = i_2; /*0x462d5*/
 if ( !i_2 ) /*0x462db*/
 return 0; /*0x462dd*/
 n71 = 71; /*0x462eb*/
 do /*0x46301*/
 {
 *i_2++ = n71; /*0x462f3*/
 n71 = *(__int16 *)((char *)i_2 + (char *)L"GUID=" - (char *)i_1); /*0x462f9*/
 }
 while ( n71 ); /*0x46301*/
 *i_2 = 0; /*0x46303*/
 v7 = 0; /*0x46307*/
 for ( i = i_1; *i; ++v7 ) /*0x4630d*/
 ++i; /*0x46313*/
 k_1 = &i_1[v7]; /*0x4631f*/
 for ( j = 0; j < 0x10; ++j ) /*0x46323*/
 {
 v11 = UtlBufferFill(k_1, 160, *((unsigned __int8 *)&qword_1D48 + j + 16), 2); /*0x46342*/
 k_1 += v11; /*0x4634a*/
 }
 k_2 = k_1; /*0x46360*/
 n38 = 38; /*0x46366*/
 do /*0x46376*/
 {
 *k_2++ = n38; /*0x46368*/
 n38 = *(__int16 *)((char *)k_2 + (char *)L"&NAME=" - (char *)k_1); /*0x4636e*/
 }
 while ( n38 ); /*0x46376*/
 *k_2 = 0; /*0x46378*/
 v14 = 0; /*0x4637c*/
 for ( k = k_1; *k; ++v14 ) /*0x46382*/
 ++k; /*0x46388*/
 n85 = 85; /*0x46394*/
 k_3 = &k_1[v14]; /*0x4639b*/
 while ( n85 ) /*0x463cc*/
 {
 v0 = (__int64 *)((char *)v0 + 2); /*0x463bd*/
 k_3 += UtlBufferFill(k_3, 160, n85, 4); /*0x463c0*/
 n85 = *(_WORD *)v0; /*0x463c4*/
 }
 k_4 = k_3; /*0x463d5*/
 n38_1 = 38; /*0x463d8*/
 do /*0x463eb*/
 {
 *k_4++ = n38_1; /*0x463dd*/
 n38_1 = *(__int16 *)((char *)k_4 + (char *)L"&PATH=" - (char *)k_3); /*0x463e3*/
 }
 while ( n38_1 ); /*0x463eb*/
 *k_4 = 0; /*0x463ed*/
 v20 = 0; /*0x463f1*/
 for ( m = k_3; *m; ++v20 ) /*0x463f7*/
 ++m; /*0x463fd*/
 k_3[v20] = 0; /*0x46409*/
 v22 = 0; /*0x4640e*/
 for ( n = i_1; *n; ++n ) /*0x46414*/
 {
 n0x41 = *n; /*0x4641a*/
 if ( *n == 61 ) /*0x46421*/
 {
 v22 = 1; /*0x46423*/
 }
 else if ( n0x41 == 38 ) /*0x4642a*/
 {
 v22 = 0; /*0x4642c*/
 }
 else if ( v22 && n0x41 >= 0x41u && n0x41 <= 0x46u ) /*0x46440*/
 {
 *n = n0x41 + 32; /*0x46446*/
 }
 }
 return i_1; /*0x46464*/
}

// UtlStrStrWide @ 0x46470 bool UtlStrStrWide(_WORD *a1, _WORD *a2, _WORD *GUID_, __int16 *&NAME_)
{
 _WORD *v6; // rdi _WORD *v7; // r11 bool result; // al _WORD *v9; // rbx _WORD *v10; // rax __int64 v11; // r11 unsigned __int64 v12; // r11 v6 = UtlStrStr(a1, GUID_); /*0x46490*/
 result = v6 /*0x464f4*/
 && (v9 = UtlStrStr(a2, v7)) != 0
 && UtlStrStr(v6, &NAME_)
 && (v10 = UtlStrStr(v9, &NAME_)) != 0
 && (v12 = (v11 - (__int64)v6) >> 1, v12 == v10 - v9)
 && UtlStrNCpy(v6, v9, v12) == 0;
 return result; /*0x46501*/
}

// UtlParseUrlParam @ 0x46508 char UtlParseUrlParam(__int64 a1)
{
 __int64 Result; // rax __int64 v3; // rbx char Protocol; // di Result = sub_46280(&qword_1D48 + 2, &qword_1B60[1], 0); /*0x4652b*/
 v3 = Result; /*0x46530*/
 if ( Result ) /*0x46536*/
 {
 Protocol = sub_46470(a1, Result, L"GUID=", L"&NAME="); /*0x46551*/
 if ( Protocol ) /*0x46556*/
 Protocol = sub_46470(a1, v3, L"&NAME=", L"&PATH="); /*0x46571*/
 (*(void ( **)(__int64))(BootServices + 72))(v3); /*0x4657e*/
 LOBYTE(Result) = Protocol; /*0x46581*/
 }
 return Result; /*0x4658e*/
}

// UtlParseUrlStr @ 0x46594 bool UtlParseUrlStr(__int64 a1, __int64 a2, int n1416, __int64 a4, __int64 a5)
{
 const __int16 *GUID_00000000000000000000000000000000&NAME_0000&PATH_00; // rdi const __int16 *GUID_00000000000000000000000000000000&NAME_0000&PATH_00_1; // rax __int64 Index; // rbx __int64 v9; // rbx __int64 v10; // rbp __int64 v12; // rax __int64 Index; // rax __int64 Result; // rbx GUID_00000000000000000000000000000000&NAME_0000&PATH_00 = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=00"; /*0x465ad*/
 GUID_00000000000000000000000000000000&NAME_0000&PATH_00_1 = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=00"; /*0x465ba*/
 Index = 0; /*0x465bd*/
 do /*0x465c7*/
 {
 ++GUID_00000000000000000000000000000000&NAME_0000&PATH_00_1; /*0x465c0*/
 ++Index; /*0x465c4*/
 }
 while ( *GUID_00000000000000000000000000000000&NAME_0000&PATH_00_1 ); /*0x465c7*/
 v9 = 2 *Index + 66; /*0x465cd*/
 v10 = UtlStrCmp(4, v9); /*0x465f8*/
 UtlCrc32Calc( /*0x465fb*/
 v10,
 v9,
 (int)L"%s&OFFSET=0&WIDTH=%016LX",
 L"GUID=00000000000000000000000000000000&NAME=0000&PATH=00",
 1416);
 if ( !v10 ) /*0x46603*/
 return 0; /*0x46603*/
 v12 = word_18(0, v10, a4, 1416); /*0x46633*/
 if ( v12 < 0 ) /*0x46648*/
 a5 = 0; /*0x46648*/
 (*(void ( **)(__int64))(BootServices + 72))(v10); /*0x4664c*/
 if ( !a5 ) /*0x46652*/
 return 0; /*0x46605*/
 Index = 0; /*0x46654*/
 do /*0x4665e*/
 {
 ++GUID_00000000000000000000000000000000&NAME_0000&PATH_00; /*0x46657*/
 ++Index; /*0x4665b*/
 }
 while ( *GUID_00000000000000000000000000000000&NAME_0000&PATH_00 ); /*0x4665e*/
 Result = UtlStrCatMemPool(); /*0x4667c*/
 (*(void ( **)(__int64))(BootServices + 72))(a5); /*0x4667f*/
 return Result != 0; /*0x4669c*/
}

// UtlMemAlloc @ 0x466a4 _QWORD *UtlMemAlloc()
{
 _QWORD *v0; // rbx __int64 v2; // rax v0 = (_QWORD *)UtlAllocZero(4, 24); /*0x466b7*/
 if ( !v0 ) /*0x466bd*/
 return 0; /*0x466bd*/
 v2 = UtlAllocZero(4, 512); /*0x466cd*/
 *v0 = v2; /*0x466d2*/
 if ( !v2 ) /*0x466d8*/
 {
 (*(void ( **)(_QWORD *))(BootServices + 72))(v0); /*0x466e4*/
 return 0; /*0x466c1*/
 }
 v0[2] = 0; /*0x466e9*/
 v0[1] = 512; /*0x466ee*/
 return v0; /*0x466f9*/
}

// UtlMemFree @ 0x46700 __int64 UtlMemFree(_QWORD *a1)
{
 if ( *a1 ) /*0x46709*/
 (*(void (**)(void))(BootServices + 72))(); /*0x46718*/
 return (*(__int64 ( **)(_QWORD *))(BootServices + 72))(a1);
}

// UtlMemDup @ 0x46730 _BYTE *UtlMemDup(__int64 *a1, __int64 a2)
{
 unsigned __int64 Result; // rdx _BYTE *result; // rax __int64 Result; // rcx Result = a1[1]; /*0x46741*/
 if ( a2 + a1[2] > Result ) /*0x4674f*/
 {
 result = UtlMemAllocAligned(4, Result, Result + a2 + 512, (_BYTE *)*a1); /*0x46761*/
 if ( !result ) /*0x46769*/
 return result; /*0x46769*/
 *a1 = (__int64)result; /*0x4676b*/
 a1[1] += a2 + 512; /*0x46775*/
 }
 Result = a1[2]; /*0x46779*/
 result = (_BYTE *)(Result + *a1); /*0x46780*/
 a1[2] = a2 + Result; /*0x46786*/
 return result; /*0x4678f*/
}

// UtlBuildTlv @ 0x46798 _BYTE *UtlBuildTlv(__int64 a1, _BYTE *a2, char a3, __int64 a4, char a5, char a6)
{
 _BYTE *v8; // rax

 *a2 = a3; /*0x467a6*/
 a2[1] = (a6 << 7) | (a4 + a5) & 0x7F; /*0x467c5*/
 v8 = (_BYTE *)sub_46730(a1, ((_BYTE)a4 + a5) & 0x7F); /*0x467cb*/
 return UtlMemCpy(v8, a2, a4); /*0x467de*/
}

// UtlMemAllocPool @ 0x468b0 _BYTE *UtlMemAllocPool(__int64 a1, __int64 *a2, __int64 a3, char n21)
{
 _BYTE *v4; // r8 __int64 n18; // rax _BYTE v7[2]; // [rsp+30h] [rbp-28h] BYREF __int64 v8; // [rsp+32h] [rbp-26h]
 __int64 v9; // [rsp+3Ah] [rbp-1Eh]

 v4 = v7; /*0x468ba*/
 n18 = 18; /*0x468bf*/
 do /*0x468cd*/
 {
 *v4++ = 0; /*0x468c2*/
 --n18; /*0x468c9*/
 }
 while ( n18 ); /*0x468cd*/
 v8 = *a2; /*0x468da*/
 v9 = a2[1]; /*0x468e8*/
 return UtlBuildTlv(a1, v7, 95, 18, n21 - 18, 0); /*0x468fe*/
}

// UtlAllocRegisterProto @ 0x46904 unsigned __int64 UtlAllocRegisterProto(__int64 a1, __int64 a2, _BYTE *a3, _QWORD *a4, _BYTE **a5, _BYTE *a6)
{
 __int64 v8; // rcx _BYTE *v9; // r13 __int64 Buffer; // r10 int v11; // ebp unsigned __int64 v12; // r10 unsigned __int64 v13; // rsi char v14; // di unsigned __int64 v15; // r12 _BYTE *i; // rbx char v17; // r11 char n93; // al __int64 v19; // rcx _BYTE *v20; // rcx __int16 *v21; // rdx __int64 v22; // r8 _BYTE *i_1; // rdx __int64 v25; // rax _BYTE **v26; // rdi _BYTE *i_2; // r11 __int64 v28; // rax char v29; // r9 __int64 v31; // rax __int64 Buffer; // r11 __int64 v33; // r11 __int64 Index; // rcx _BYTE *v35; // r13 int v36; // ebp __int64 v37; // rcx unsigned __int64 Index; // rsi __int64 Buffer; // r12 int v40; // r10d __int64 Buffer; // [rsp+60h] [rbp+8h] BYREF __int16 v43; // [rsp+68h] [rbp+10h] BYREF v43 = a2; /*0x46909*/
 Buffer = a1; /*0x4690e*/
 UtlMemCpy(a6, a3, 4); /*0x4693c*/
 v9 = (_BYTE *)(v8 + 4); /*0x46941*/
 v11 = Buffer; /*0x46950*/
 UtlMemCpy(&Buffer, a3, Buffer); /*0x46953*/
 v13 = v12; /*0x46958*/
 v14 = 0; /*0x46963*/
 v15 = Buffer & 0xFFFFFF; /*0x46969*/
 for ( i = a3 + 4; ; i += v25 ) /*0x46970*/
 {
 if ( v13 >= v15 ) /*0x46977*/
 return 0x800000000000000EuLL; /*0x46977*/
 UtlMemCpy(v9, i, i[1] & 0x7F); /*0x4698c*/
 n93 = *i; /*0x46995*/
 v19 = i[1] & 0x7F; /*0x46997*/
 v9 += v19; /*0x4699a*/
 v11 += v19; /*0x4699d*/
 if ( *i == 14 ) /*0x469a2*/
 break; /*0x469a2*/
 if ( n93 == 1 || n93 == 93 ) /*0x469d5*/
 {
 v20 = i + 2; /*0x469d7*/
 if ( i + 2 == (_BYTE *)&v43 ) /*0x469e3*/
 goto LABEL_16; /*0x469e3*/
 v21 = &v43; /*0x469e5*/
 v22 = 1; /*0x469ea*/
 do /*0x469fc*/
 {
 if ( *v20 != *(_BYTE *)v21 ) /*0x469f1*/
 break; /*0x469f1*/
 ++v20; /*0x469f3*/
 v21 = (__int16 *)((char *)v21 + 1); /*0x469f6*/
 --v22; /*0x469f9*/
 }
 while ( v22 ); /*0x469fc*/
 if ( (unsigned __int8)*v20 == (unsigned __int64)*(unsigned __int8 *)v21 ) /*0x46a04*/
LABEL_16:
 v17 = 1; /*0x46a0e*/
 else v17 = 0; /*0x46a09*/
 }
 if ( v14 ) /*0x46a14*/
 goto LABEL_18; /*0x46a14*/
LABEL_24:
 v25 = i[1] & 0x7F; /*0x46a44*/
 v13 += v25; /*0x46a4b*/
 }
 if ( *(_QWORD *)(i + 2) != 0x4569431277F2EA2FLL || *(_QWORD *)(i + 10) != 0xE2B78DCD3A58C485uLL ) /*0x469bc*/
 {
 v14 = 0; /*0x469c3*/
 goto LABEL_24; /*0x469c6*/
 }
 v14 = 1; /*0x469be*/
LABEL_18:
 if ( !v17 ) /*0x46a19*/
 goto LABEL_24; /*0x46a19*/
 i_1 = (_BYTE *)*a4; /*0x46a1b*/
 if ( ((i[1] ^ *(_BYTE *)(*a4 + 1LL)) & 0x7F) != 0 ) /*0x46a26*/
 goto LABEL_24; /*0x46a26*/
 if ( (i_1[1] & 0x7F) != 0 ? UtlMemMove(i, i_1, i_1[1] & 0x7F) : 0LL )
 goto LABEL_24; /*0x46a42*/
 v26 = a5; /*0x46a56*/
 if ( a5 )
 {
 i_2 = *a5; /*0x46a67*/
 v28 = i[1] & 0x7F; /*0x46a6a*/
 v13 += v28; /*0x46a6d*/
 i += v28; /*0x46a70*/
 if ( v13 >= v15 ) /*0x46a76*/
 return 0x800000000000000EuLL; /*0x46a76*/
 v29 = i_2[1] & 0x7F; /*0x46a80*/
 do
 {
 if ( v29 == (i[1] & 0x7F) && !((i_2[1] & 0x7F) != 0 ? UtlMemMove(i, i_2, i_2[1] & 0x7F) : 0LL) )
 break; /*0x46aab*/
 v31 = i[1] & 0x7F; /*0x46ab1*/
 v13 += v31; /*0x46ab4*/
 i += v31; /*0x46ab7*/
 }
 while ( v13 < v15 );
 if ( v13 >= v15 ) /*0x46ac2*/
 return 0x800000000000000EuLL; /*0x46b66*/
 }
 Buffer = *(_BYTE *)(*a4 + 1LL) & 0x7F; /*0x46ad7*/
 UtlMemCpy(v9, (_BYTE *)(*a4 + Buffer), a4[2] - Buffer); /*0x46ae2*/
 Index = a4[2] - v33; /*0x46aeb*/
 v35 = &v9[Index]; /*0x46aee*/
 v36 = Index + v11; /*0x46af1*/
 if ( v26 ) /*0x46af7*/
 {
 UtlMemCpy(v35, i, i[1] & 0x7F); /*0x46b08*/
 v37 = i[1] & 0x7F; /*0x46b11*/
 v35 += v37; /*0x46b14*/
 v36 += v37; /*0x46b17*/
 }
 Index = (i[1] & 0x7F) + v13; /*0x46b24*/
 Buffer = v15 - Index; /*0x46b27*/
 UtlMemCpy(v35, &a3[Index], Buffer); /*0x46b31*/
 LODWORD(Buffer) = (v40 ^ (Buffer + v36)) & 0xFFFFFF ^ v40; /*0x46b58*/
 UtlMemCpy(a6, &Buffer, 4); /*0x46b5d*/
 return 0; /*0x46b75*/
}

// UtlInstallProtocol @ 0x46b88 __int64 UtlInstallProtocol(__int64 a1, __int64 a2, unsigned __int16 n0x1235, _QWORD *a4, ...)
{
 _BYTE *v6; // rsi _BYTE *v7; // rdi __int64 result; // rax __int64 v9; // rax __int64 Buffer; // rbp __int64 Result; // rbx unsigned int n20; // r13d char v13; // r14 _BYTE *v14; // rbx _BYTE **v15; // rdi unsigned int n20_1; // r15d _BYTE *v17; // r12 __int64 v18; // r10 _BYTE *v19; // r8 __int64 v20; // [rsp+20h] [rbp-68h]
 _BYTE *v21; // [rsp+38h] [rbp-50h] BYREF _BYTE *v22; // [rsp+40h] [rbp-48h]
 _BYTE **v26; // [rsp+B0h] [rbp+28h] BYREF va_list va; // [rsp+B0h] [rbp+28h]
 va_list va1; // [rsp+B8h] [rbp+30h] BYREF va_start(va1, a4);
 va_start(va, a4);
 v26 = va_arg(va1, _BYTE **); /*0x46b88*/
 v6 = 0; /*0x46bb8*/
 v21 = 0; /*0x46bbd*/
 v7 = 0; /*0x46bc8*/
 result = (*(__int64 ( **)(_QWORD, __int64, _BYTE **, _QWORD))&word_1C[2])(0, a1, &v21, 0); /*0x46bcd*/
 if ( result == 0x8000000000000005uLL ) /*0x46bdd*/
 {
 v9 = UtlAllocZero(4, (__int64)v21); /*0x46beb*/
 Buffer = v9; /*0x46bf0*/
 if ( !v9 ) /*0x46bf6*/
 return 0x8000000000000009uLL; /*0x46bf8*/
 Result = (*(__int64 ( **)(_QWORD, __int64, _BYTE **, __int64, __int64))&word_1C[2])(0, a1, &v21, v9, v20); /*0x46c1f*/
 if ( Result >= 0 ) /*0x46c25*/
 {
 v21 += a4[2]; /*0x46c3a*/
 v7 = (_BYTE *)UtlStrCmp(4, (__int64)v21); /*0x46c44*/
 v22 = v7; /*0x46c47*/
 if ( v7 && (v6 = (_BYTE *)UtlStrCmp(4, (__int64)v21)) != 0 ) /*0x46c75*/
 {
 n20 = 20; /*0x46c77*/
 UtlMemCpy(v7, (_BYTE *)Buffer, 20); /*0x46c86*/
 v13 = 0; /*0x46c8e*/
 v14 = v7 + 20; /*0x46c91*/
 if ( *(_DWORD *)(Buffer + 16) <= 0x14u ) /*0x46c98*/
 goto LABEL_16; /*0x46c98*/
 v15 = v26; /*0x46c9e*/
 n20_1 = *(_DWORD *)(Buffer + 16); /*0x46ca6*/
 do /*0x46d47*/
 {
 v17 = (_BYTE *)(Buffer + n20); /*0x46cba*/
 UtlMemCpy((_BYTE ***)va, v17, 4); /*0x46cc0*/
 n20 += *(_DWORD *)v17 & 0xFFFFFF; /*0x46ccf*/
 if ( v17[3] == 2 /*0x46d06*/
 && (UtlAllocRegisterProto((__int64)&qword_1D48, n0x1235, v17, a4, v15, v6) & 0x8000000000000000uLL) == 0LL )
 {
 v13 = 1; /*0x46d08*/
 v17 = v6; /*0x46d0b*/
 }
 UtlMemCpy((_BYTE ***)va, v17, 4); /*0x46d1f*/
 UtlMemCpy(v14, v17, (unsigned int)v26 & 0xFFFFFF); /*0x46d3c*/
 v14 += v18; /*0x46d41*/
 }
 while ( n20 < n20_1 ); /*0x46d47*/
 v7 = v22; /*0x46d4d*/
 if ( v13 ) /*0x46d5d*/
 {
 v19 = v22; /*0x46d62*/
 v21 = (_BYTE *)(v14 - v22); /*0x46d68*/
 *((_DWORD *)v22 + 4) = (_DWORD)v14 - (_DWORD)v22; /*0x46d6d*/
 Result = UndiCallbackDispatch_0(0, a1, v19); /*0x46d7d*/
 }
 else
 {
LABEL_16:
 Result = 0x800000000000000EuLL; /*0x46d82*/
 }
 }
 else
 {
 Result = 0x8000000000000009uLL; /*0x46c51*/
 }
 }
 (*(void ( **)(__int64))(BootServices + 72))(Buffer); /*0x46d96*/
 if ( v7 ) /*0x46d9c*/
 (*(void ( **)(_BYTE *))(BootServices + 72))(v7); /*0x46da8*/
 if ( v6 ) /*0x46dae*/
 (*(void ( **)(_BYTE *))(BootServices + 72))(v6); /*0x46dba*/
 return Result; /*0x46dbd*/
 }
 return result; /*0x46dc8*/
}

// UtlConfigHash @ 0x46dd8 unsigned __int16 UtlConfigHash(__int64 a1, __int64 a2, __int64 a3, _BYTE *eng)
{
 _BYTE *v6; // rax __int64 Index; // rdx _BYTE *v8; // rdi unsigned __int16 result; // ax __int64 v10; // rsi _BYTE *v11; // rbx _BYTE *v12; // r9 __int64 v13; // rax __int64 v14; // [rsp+20h] [rbp-38h]
 __int64 v15; // [rsp+28h] [rbp-30h]
 __int64 v16; // [rsp+30h] [rbp-28h]
 __int64 v17; // [rsp+38h] [rbp-20h]
 unsigned __int16 Result; // [rsp+68h] [rbp+10h] BYREF Result = a2; /*0x46de7*/
 if ( eng ) /*0x46e00*/
 {
 Index = 0; /*0x46e09*/
 if ( *eng ) /*0x46e0c*/
 {
 do /*0x46e14*/
 ++Index; /*0x46e11*/
 while ( eng[Index] ); /*0x46e14*/
 }
 v6 = UtlStrCpy(4, Index + 1, eng); /*0x46e25*/
 }
 else
 {
 v6 = (_BYTE *)UtlConfigCalcHash(a1, a2, a3, 0, v14, v15, v16, v17); /*0x46e02*/
 }
 v8 = v6; /*0x46e2a*/
 if ( !v6 ) /*0x46e30*/
 return 0; /*0x46e32*/
 v10 = 0x8000000000000002uLL; /*0x46e3b*/
 v11 = v6; /*0x46e45*/
 if ( *v6 ) /*0x46e48*/
 {
 do /*0x46eb3*/
 {
 v12 = v11; /*0x46e4d*/
 if ( *v11 ) /*0x46e50*/
 {
 do /*0x46e5d*/
 {
 if ( *v11 == 59 ) /*0x46e58*/
 break; /*0x46e58*/
 ++v11; /*0x46e5a*/
 }
 while ( *v11 ); /*0x46e5d*/
 if ( *v11 ) /*0x46e62*/
 *v11++ = 0; /*0x46e67*/
 }
 if ( Result ) /*0x46e84*/
 v13 = ((__int64 ( *)(_QWORD, __int64, _QWORD, _BYTE *, __int64, _QWORD))UndiCallbackDispatch_0)( /*0x46ea8*/
 0,
 a1,
 Result,
 v12,
 a3,
 0);
 else v13 = ((__int64 ( *)(_QWORD, __int64, unsigned __int16 *, _BYTE *, _QWORD, __int64, _QWORD))_ImageBase)( /*0x46e9a*/
 0,
 a1,
 &Result,
 v12,
 0,
 a3,
 0);
 v10 = v13; /*0x46eae*/
 }
 while ( v13 >= 0 && *v11 ); /*0x46eb3*/
 }
 (*(void ( **)(_BYTE *))(BootServices + 72))(v8); /*0x46ec2*/
 result = 0; /*0x46ec8*/
 if ( v10 >= 0 ) /*0x46ecc*/
 return Result; /*0x46ece*/
 return result; /*0x46ee2*/
}

// UtlConfigSaveToNvm @ 0x46eec __int64 UtlConfigSaveToNvm(__int64 a1, __int64 a2, _BYTE *n91393, __int64 a4)
{
 unsigned __int16 v5; // r13 __int64 Result; // rbx __int64 v8; // rdx char *v9; // rsi __int64 v10; // r8 __int64 v11; // r9 __int64 n91393_3; // rax __int64 n91393_1; // r9 _BYTE *n91393_2; // r8 __int64 n91393_4; // r12 _BYTE *v16; // rdi __int64 v18; // [rsp+20h] [rbp-48h]
 __int64 v19; // [rsp+20h] [rbp-48h]
 __int64 v20; // [rsp+28h] [rbp-40h]
 __int64 v21; // [rsp+28h] [rbp-40h]
 __int64 v22; // [rsp+30h] [rbp-38h]
 __int64 v23; // [rsp+30h] [rbp-38h]
 __int64 v24; // [rsp+38h] [rbp-30h]
 __int64 v25; // [rsp+38h] [rbp-30h]
 __int64 v26; // [rsp+40h] [rbp-28h]

 v5 = a2; /*0x46f07*/
 Result = 0; /*0x46f0e*/
 v9 = (char *)UtlConfigCalcHash(a1, a2, (__int64)n91393, a4, v18, v20, v22, v24); /*0x46f15*/
 if ( v9 ) /*0x46f1b*/
 {
 n91393_3 = UtlParseTokenStrWide(L"PlatformLang", v8, v10, v11, v19, v21, v23, v25, v26); /*0x46f28*/
 n91393_1 = 91393; /*0x46f2d*/
 n91393_2 = ::n91393; /*0x46f37*/
 n91393_4 = n91393_3; /*0x46f3d*/
 if ( n91393 ) /*0x46f40*/
 n91393_2 = n91393; /*0x46f40*/
 if ( n91393_3 ) /*0x46f47*/
 n91393_1 = n91393_3; /*0x46f47*/
 v16 = UtlParseTokenStrSafe(v9, 0, n91393_2, n91393_1); /*0x46f5c*/
 if ( v16 ) /*0x46f62*/
 {
 if ( n4099(0, v16, a1, v5) == 0x8000000000000005uLL ) /*0x46fad*/
 {
 Result = UtlStrCmp(4, 0); /*0x46fbc*/
 if ( Result ) /*0x46fc2*/
 {
 if ( n4099(0, v16, a1, v5) < 0 ) /*0x46ff4*/
 {
 (*(void ( **)(__int64))(BootServices + 72))(Result); /*0x47000*/
 Result = 0; /*0x47003*/
 }
 }
 }
 }
 (*(void ( **)(char *))(BootServices + 72))(v9); /*0x4700f*/
 if ( n91393_4 ) /*0x47015*/
 (*(void ( **)(__int64))(BootServices + 72))(n91393_4); /*0x47021*/
 if ( v16 ) /*0x47027*/
 (*(void ( **)(_BYTE *))(BootServices + 72))(v16); /*0x47033*/
 }
 return Result; /*0x4704a*/
}

// UtlConfigCalcHash @ 0x47054 __int64 UtlConfigCalcHash(__int64 a1, __int64 a2, _BYTE *n91393)
{
 __int64 v5; // rax __int64 Result; // rbx __int64 v7; // [rsp+38h] [rbp+10h] BYREF __int64 v8; // [rsp+40h] [rbp+18h] BYREF v8 = 0; /*0x47060*/
 if ( word_18(0, a1, &v7, &v8) != 0x8000000000000005uLL ) /*0x4708d*/
 return 0; /*0x4708d*/
 v5 = UtlStrCmp(4, v8); /*0x4709d*/
 Result = v5; /*0x470a2*/
 if ( !v5 ) /*0x470a8*/
 return 0; /*0x470a8*/
 if ( word_18(0, a1, v5, &v8) < 0 ) /*0x470c5*/
 {
 (*(void ( **)(__int64))(BootServices + 72))(Result); /*0x470d1*/
 return 0; /*0x47091*/
 }
 return Result; /*0x470de*/
}