HalpIommuMapLogical

INT64 __fastcall HalpIommuMapLogical(INT64 a1, INT64 a2, INT64 a3, INT64 a4, UINT64 a5, INT64 a6){
  int v6; 
  unsigned __int64 v7; 
  unsigned int v8; 
  unsigned __int64 v9; 
  UINT64 v10; 
  int v11; 
  __int64 v12; 
  int v14; 
  UINT64 v15; 
  unsigned int v16; 
  unsigned __int64 v17; 
  __int64 v18; 
  __int64 v19; 
  unsigned __int64 v20; 
  unsigned __int8 v21; 
  unsigned __int64 v22; 
  void *v23; 
  PHYSICAL_ADDRESS PhysicalAddress; 
  void *v25; 
  unsigned int v26; 
  __int64 v27; 
  int v28; 
  void *v29; 
  unsigned int v30; 
  int v31; 
  INT64 v32; 
  __int64 v33; 
  unsigned int v35; 
  char v36; 
  unsigned int v37; 
  unsigned __int64 BaseAddress; 
  PVOID BaseAddressa; 
  UINT64 v40; 
  INT64 v41; 
  INT64 v42; 
  __int128 v43[3]; 
  v6 = *(_DWORD *)(a2 + 28);
  v7 = *(_QWORD *)(a2 + 16);
  v8 = 0;
  v9 = a6;
  v10 = 0i64;
  v41 = a4;
  v36 = v6;
  v11 = 1 << v6;
  LODWORD(v12) = 0;
  v37 = 1 << v6;
  v43[0] = v7;
  memset(&v43[1], 0, 32);
  v35 = 0;
  v42 = a6;
  v40 = 0i64;
  if( !a5 )
    return 0i64;
  while( 1 )
  {
    v14 = *(_DWORD *)(a2 + 24);
    if( (unsigned int)v12 < v14 - 1 )
    {
      v15 = (unsigned int)v12;
      while( 1 )
      {
        v16 = *(_DWORD *)(a2 + 4 * v15 + 36);
        v17 = v7 + (1 << v16 << v6);
        if( v16 < 0x40 )
          v18 = (1i64 << v16) - 1;
        else
          LODWORD(v18) = -1;
        v19 = (unsigned int)v18 & (unsigned int)(v9 >> *(_DWORD *)(a2 + 4 * v15 + 60));
        BaseAddress = (unsigned int)v19;
        v20 = *(_QWORD *)(v17 + 8 * v19);
        if( !v20 )
        {
          KeAcquireSpinLockRaiseToDpc((UINT64 *)(a2 + 8), v15);
          v22 = v21;
          if( !*(_QWORD *)(v17 + 8i64 * (unsigned int)v19) )
          {
            v23 = (void *)HalpIommuAllocateAndZeroPageTable(a2, (unsigned int)(v12 + 1), 0i64);
            *(_QWORD *)(v17 + 8i64 * (unsigned int)v19) = v23;
            if( !v23 )
            {
              KxReleaseSpinLock((UINT64 *)(a2 + 8));
              __writecr8(v22);
              return 3221225626i64;
            }
            PhysicalAddress = MmGetPhysicalAddress(v23);
            v25 = (void *)(v7 + (unsigned int)((_DWORD)v19 << v36));
            (**(void(__fastcall ***)(void *, _QWORD, PHYSICAL_ADDRESS))(a2 + 88))(
              v25,
              (unsigned int)(*(_DWORD *)(a2 + 24) - v12 - 1),
              PhysicalAddress);
            if( !HalpIommuPageTableCacheCoherent )
              KeInvalidateRangeAllCachesNoIpi(v25, v37);
          }
          KxReleaseSpinLock((UINT64 *)(a2 + 8));
          __writecr8(v22);
          v14 = *(_DWORD *)(a2 + 24);
          LOBYTE(v6) = v36;
          v20 = *(_QWORD *)(v17 + 8 * BaseAddress);
        }
        v9 = a6;
        v12 = (unsigned int)(v12 + 1);
        v7 = v20;
        v15 = (unsigned int)v12;
        *((_QWORD *)v43 + v12) = v20;
        if( (unsigned int)v12 >= v14 - 1 )
        {
          v10 = v40;
          v11 = v37;
          v8 = v35;
          break;
        }
      }
    }
    v26 = *(_DWORD *)(a2 + 4i64 * (unsigned int)v12 + 36);
    if( v26 < 0x40 )
      v27 = (1i64 << v26) - 1;
    else
      LODWORD(v27) = -1;
    v28 = v27 & (v9 >> *(_DWORD *)(a2 + 4i64 * (unsigned int)v12 + 60));
    v29 = (void *)(v7 + (unsigned int)(v28 << v6));
    v30 = (1 << *(_DWORD *)(a2 + 4i64 * (unsigned int)(v14 - 1) + 36)) - v28;
    BaseAddressa = v29;
    if( (unsigned int)a5 - v8 <= v30 )
      v30 = a5 - v8;
    v31 = (*(__int64(__fastcall **)(void *, INT64, __int64, _QWORD))(*(_QWORD *)(a2 + 88) + 16i64))(
            v29,
            v41 + 8i64 * v8,
            3i64,
            v30);
    v10 += (unsigned int)(v31 << 12);
    v40 = v10;
    if( v31 != v30 )
      break;
    if( !HalpIommuPageTableCacheCoherent )
      KeInvalidateRangeAllCachesNoIpi(BaseAddressa, v11 * v30);
    v8 = v30 + v35;
    v32 = v9 + ((unsigned __int64)v30 << 12);
    v35 += v30;
    if( (_DWORD)v12 )
    {
      do
      {
        v33 = (unsigned int)(v12 - 1);
        if( ((1i64 << *(_DWORD *)(a2 + 4 * v33 + 60)) & v32) == (v9 & (1i64 << *(_DWORD *)(a2 + 4 * v33 + 60))) )
          break;
        LODWORD(v12) = v12 - 1;
      }
      while( (_DWORD)v33 );
    }
    v9 += (unsigned __int64)v30 << 12;
    a6 = v32;
    v7 = *((_QWORD *)v43 + (unsigned int)v12);
    if( v8 >= a5 )
      return 0i64;
    LOBYTE(v6) = v36;
  }
  HalpIommuUnmapLogicalRange(a2, &v40, v42);
  return 3221225485i64;
}

Referenced by:

HalpIommuDomainMapLogical