VOID
BalloonTerm(
    IN WDFOBJECT    WdfDevice,
    IN BOOLEAN      bFinal
    )
{
    PDEVICE_CONTEXT     devCtx = GetDeviceContext(WdfDevice);
    PVOID p;

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> BalloonTerm\n");

    VirtIODeviceRemoveStatus(&devCtx->VDevice , VIRTIO_CONFIG_S_DRIVER_OK);

    if(devCtx->DefVirtQueue)
    {
        devCtx->DefVirtQueue->vq_ops->shutdown(devCtx->DefVirtQueue);
        if (bFinal)
        {
           VirtIODeviceDeleteQueue(devCtx->DefVirtQueue, &p);
           MmFreeContiguousMemory(p);
           devCtx->DefVirtQueue = NULL;
        }
    }

    if(devCtx->InfVirtQueue)
    {
        devCtx->InfVirtQueue->vq_ops->shutdown(devCtx->InfVirtQueue);
        if (bFinal)
        {
           VirtIODeviceDeleteQueue(devCtx->InfVirtQueue, &p);
           MmFreeContiguousMemory(p);
           devCtx->InfVirtQueue = NULL;
        }
    }

    if(devCtx->StatVirtQueue)
    {
        devCtx->StatVirtQueue->vq_ops->shutdown(devCtx->StatVirtQueue);
        if (bFinal)
        {
           VirtIODeviceDeleteQueue(devCtx->StatVirtQueue, &p);
           MmFreeContiguousMemory(p);
           devCtx->StatVirtQueue = NULL;
        }
    }

    if (bFinal)
    {
       VirtIODeviceReset(&devCtx->VDevice);
    }
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- BalloonTerm\n");
}
Example #2
0
RPIQ_PAGED_SEGMENT_END

RPIQ_NONPAGED_SEGMENT_BEGIN

/*++

Routine Description:

    RpiqRequestContextCleanup would perform cleanup
        when request object is delete.

Arguments:

    WdfObject - A handle to a framework object in this case
         a WDFRequest

Return Value:

    VOID

--*/
_Use_decl_annotations_
VOID RpiqRequestContextCleanup (
    WDFOBJECT WdfObject
    )
{
    RPIQ_REQUEST_CONTEXT* requestContextPtr =
        RpiqGetRequestContext(WdfObject);
    
    if (requestContextPtr->PropertyMemory) {
        MmFreeContiguousMemory(requestContextPtr->PropertyMemory);
    }
}
Example #3
0
/// <summary>
/// Restore hooked function
/// </summary>
/// <param name="pFunc">Function address</param>
/// <returns>Status code</returns>
NTSTATUS PHRestore( IN PVOID pFunc )
{
    // No CPU support
    if (!g_Data->EPTExecOnlySupported)
        return STATUS_NOT_SUPPORTED;

    PPAGE_HOOK_ENTRY pHookEntry = PHGetHookEntry( pFunc );
    if (pHookEntry == NULL)
        return STATUS_NOT_FOUND;

    // Restore original bytes
    if (PHPageHookCount( pFunc, DATA_PAGE ) > 1)
    {
        // TODO: atomic memory patching, i.e. with other CPUs spinlocked
        ULONG_PTR page_offset = (ULONG_PTR)pFunc - (ULONG_PTR)PAGE_ALIGN( pFunc );
        memcpy( (PUCHAR)pHookEntry->CodePageVA + page_offset, pHookEntry->OriginalData, pHookEntry->OriginalSize );
    }
    // Swap pages
    else
    {
        HOOK_CONTEXT ctx = { 0 };
        ctx.Hook = FALSE;
        ctx.DataPagePFN = pHookEntry->DataPagePFN;
        ctx.CodePagePFN = pHookEntry->CodePagePFN;;
        ctx.Type = pHookEntry->Type;

        KeGenericCallDpc( PHpHookCallbackDPC, &ctx );
    }

    MmFreeContiguousMemory( pHookEntry->CodePageVA );
    RemoveEntryList( &pHookEntry->Link );
    ExFreePoolWithTag( pHookEntry, HB_POOL_TAG );
    
    return STATUS_SUCCESS;
}
Example #4
0
NTSTATUS FreeVmxProcessorData(PVOID VirtualAddress)
{
	if (!VirtualAddress)
		return STATUS_INVALID_PARAMETER;

	MmFreeContiguousMemory(VirtualAddress);
	return STATUS_SUCCESS;
}
void CDmaChannel::FreeBuffer()
{
	if(buffer != NULL)
	{
		MmFreeContiguousMemory(buffer);
		buffer = NULL;
	}
}
Example #6
0
/**
 * Frees memory allocated ysing RTMemContAlloc().
 *
 * @param   pv      Pointer to return from RTMemContAlloc().
 * @param   cb      The cb parameter passed to RTMemContAlloc().
 */
RTR0DECL(void) RTMemContFree(void *pv, size_t cb)
{
    if (pv)
    {
        Assert(cb > 0); NOREF(cb);
        AssertMsg(!((uintptr_t)pv & PAGE_OFFSET_MASK), ("pv=%p\n", pv));
        MmFreeContiguousMemory(pv);
    }
}
Example #7
0
CVirtualizedCpu::~CVirtualizedCpu()
{
	if (NULL != m_hvStack)
	{
		KeSetSystemAffinityThread(PROCID(m_cpuCore));
		(reinterpret_cast<CHyperVisor*>(m_hvStack + 1))->~CHyperVisor();
		MmFreeContiguousMemory(m_hvStack);
	}
}
Example #8
0
int dump_hook_init(PDRIVER_OBJECT drv_obj)
{
	PLDR_DATA_TABLE_ENTRY table;
	PHYSICAL_ADDRESS      high_addr;
	PLIST_ENTRY           entry;
	NTSTATUS              status;
	int                   resl = 0;

	ExInitializeFastMutex(&dump_sync);

	ExAcquireFastMutex(&dump_sync);

	/* find PsLoadedModuleListHead */
	entry = ((PLIST_ENTRY)(drv_obj->DriverSection))->Flink;

	while (entry != drv_obj->DriverSection)
	{
		table = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
		entry = entry->Flink;

		if ( (table->BaseDllName.Length == 0x18) && 
			 (p32(table->BaseDllName.Buffer)[0] == 0x0074006E) )
		{
			ps_loaded_mod_list = pv(table->InLoadOrderLinks.Blink);
			break;
		}
	}

	ExReleaseFastMutex(&dump_sync);

	do
	{
		if (ps_loaded_mod_list == NULL) break;

		status = PsSetLoadImageNotifyRoutine(load_img_routine);
		if (NT_SUCCESS(status) == FALSE) break;

		high_addr.HighPart = 0;
		high_addr.LowPart  = 0xFFFFFFFF;

		dump_mem = MmAllocateContiguousMemory(DUMP_MEM_SIZE, high_addr);
		if (dump_mem == NULL) break;
		dump_mdl = IoAllocateMdl(dump_mem, DUMP_MEM_SIZE, FALSE, FALSE, NULL); 
		if (dump_mdl == NULL) break;

		MmBuildMdlForNonPagedPool(dump_mdl);
		memset(dump_mem, 0, DUMP_MEM_SIZE);
		resl = 1;
	} while (0);

	if (resl == 0) {
		if (dump_mdl != NULL) IoFreeMdl(dump_mdl);
		if (dump_mem != NULL) MmFreeContiguousMemory(dump_mem);
	}
	return resl;	
}
Example #9
0
/// <summary>
/// Revert CPU to non-root mode
/// </summary>
/// <param name="Vcpu">Virtual CPU data</param>
VOID VmxShutdown( IN PVCPU Vcpu )
{
    //DPRINT( "HyperBone: CPU %d: %s: CR3 load count %d\n", CPU_IDX, __FUNCTION__, Vcpu->Cr3Loads );

    __vmx_vmcall( HYPERCALL_UNLOAD, 0, 0, 0 );
    VmxVMCleanup( KGDT64_R3_DATA | RPL_MASK, KGDT64_R3_CMTEB | RPL_MASK );

    EptFreeIdentityMap( &Vcpu->EPT );

    if (Vcpu->VMXON)
        MmFreeContiguousMemory( Vcpu->VMXON );
    if (Vcpu->VMCS)
        MmFreeContiguousMemory( Vcpu->VMCS );
    if (Vcpu->VMMStack)
        MmFreeContiguousMemory( Vcpu->VMMStack );

    Vcpu->VMXON = NULL;
    Vcpu->VMCS = NULL;
    Vcpu->VMMStack = NULL;
}
Example #10
0
static NTSTATUS DumpFilterUnload (PFILTER_EXTENSION filterExtension)
{
	Dump ("DumpFilterUnload type=%d\n", filterExtension->DumpType);

	if (WriteFilterBuffer)
	{
		memset (WriteFilterBuffer, 0, WriteFilterBufferSize);
		MmFreeContiguousMemory (WriteFilterBuffer);
		WriteFilterBuffer = NULL;
	}

	return STATUS_SUCCESS;
}
void
RosKmdGlobal::DdiUnload(
    void)
{
    DbgPrintEx(DPFLTR_IHVVIDEO_ID, DPFLTR_TRACE_LEVEL, "%s\n",
        __FUNCTION__);

    if (s_pVideoMemory != NULL)
    {
        MmFreeContiguousMemory(s_pVideoMemory);
        s_pVideoMemory = NULL;
        s_videoMemorySize = 0;
    }

}
Example #12
0
static void DeleteQueue(struct virtqueue **ppq)
{
    PVOID p;
    struct virtqueue *pq = *ppq;

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "--> %s\n", __FUNCTION__);

    if (pq)
    {
        VirtIODeviceDeleteQueue(pq, &p);
        *ppq = NULL;
        MmFreeContiguousMemory(p);
    }

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "<-- %s\n", __FUNCTION__);
}
Example #13
0
VOID
HalFreeCommonBuffer(
    IN PADAPTER_OBJECT AdapterObject,
    IN ULONG Length,
    IN PHYSICAL_ADDRESS LogicalAddress,
    IN PVOID VirtualAddress,
    IN BOOLEAN CacheEnabled
    )
/*++

Routine Description:

    This function frees a common buffer and all of the resouces it uses.

Arguments:

    AdapterObject - Supplies a pointer to the adapter object used by this
        device.

    Length - Supplies the length of the common buffer. This should be the same
        value used for the allocation of the buffer.

    LogicalAddress - Supplies the logical address of the common buffer.  This
        must be the same value return by HalAllocateCommonBuffer.

    VirtualAddress - Supplies the virtual address of the common buffer.  This
        must be the same value return by HalAllocateCommonBuffer.

    CacheEnable - Indicates whether the memeory is cached or not.

Return Value:

    None

--*/

{
    UNREFERENCED_PARAMETER( AdapterObject );
    UNREFERENCED_PARAMETER( Length );
    UNREFERENCED_PARAMETER( LogicalAddress );
    UNREFERENCED_PARAMETER( CacheEnabled );

    MmFreeContiguousMemory (VirtualAddress);

}
void
RosKmdGlobal::DdiUnload(
    void)
{
    DbgPrintEx(DPFLTR_IHVVIDEO_ID, DPFLTR_TRACE_LEVEL, "%s\n",
        __FUNCTION__);

    if (s_pVideoMemory != NULL)
    {
        MmFreeContiguousMemory(s_pVideoMemory);
        s_pVideoMemory = NULL;
        s_videoMemorySize = 0;
    }

    NT_ASSERT(s_pDriverObject);
    WPP_CLEANUP(s_pDriverObject);
    s_pDriverObject = nullptr;
}
Example #15
0
File: vcpu.c Project: HideSand/ksm
void vcpu_free(struct vcpu *vcpu)
{
	if (vcpu->stack)
		MmFreeContiguousMemory(vcpu->stack);

	if (vcpu->vmcs)
		ExFreePool(vcpu->vmcs);

	if (vcpu->vmxon)
		ExFreePool(vcpu->vmxon);

	if (vcpu->ve)
		ExFreePool(vcpu->ve);

	if (vcpu->idt.base)
		ExFreePool((void *)vcpu->idt.base);

	ept_exit(&vcpu->ept);
	ExFreePool(vcpu);
}
Example #16
0
/**
 * Allocates physical contiguous memory (below 4GB).
 * The allocation is page aligned and its contents is undefined.
 *
 * @returns Pointer to the memory block. This is page aligned.
 * @param   pPhys   Where to store the physical address.
 * @param   cb      The allocation size in bytes. This is always
 *                  rounded up to PAGE_SIZE.
 */
RTR0DECL(void *) RTMemContAlloc(PRTCCPHYS pPhys, size_t cb)
{
    /*
     * validate input.
     */
    Assert(VALID_PTR(pPhys));
    Assert(cb > 0);

    /*
     * Allocate and get physical address.
     * Make sure the return is page aligned.
     */
    PHYSICAL_ADDRESS MaxPhysAddr;
    MaxPhysAddr.HighPart = 0;
    MaxPhysAddr.LowPart = 0xffffffff;
    cb = RT_ALIGN_Z(cb, PAGE_SIZE);
    void *pv = MmAllocateContiguousMemory(cb, MaxPhysAddr);
    if (pv)
    {
        if (!((uintptr_t)pv & PAGE_OFFSET_MASK))    /* paranoia */
        {
            PHYSICAL_ADDRESS PhysAddr = MmGetPhysicalAddress(pv);
            if (!PhysAddr.HighPart)                 /* paranoia */
            {
                *pPhys = (RTCCPHYS)PhysAddr.LowPart;
                return pv;
            }

            /* failure */
            AssertMsgFailed(("MMAllocContiguousMemory returned high address! PhysAddr=%RX64\n", (uint64_t)PhysAddr.QuadPart));
        }
        else
            AssertMsgFailed(("MMAllocContiguousMemory didn't return a page aligned address - %p!\n", pv));

        MmFreeContiguousMemory(pv);
    }

    return NULL;
}
Example #17
0
/// <summary>
/// Release Guest to Host page mappings
/// </summary>
/// <param name="pEPT">CPU EPT data</param>
/// <returns>Status code</returns>
NTSTATUS EptFreeIdentityMap( IN PEPT_DATA pEPT )
{
    if (pEPT->PML4Ptr == NULL)
        return STATUS_SUCCESS;

    pEPT->PML4Ptr = NULL;
    while (!IsListEmpty( &pEPT->PageList ))
    {
        PLIST_ENTRY pListEntry = pEPT->PageList.Flink;
        PEPT_PAGES_ENTRY pEntry = CONTAINING_RECORD( pListEntry, EPT_PAGES_ENTRY, link );
        for (ULONG i = 0; i < pEntry->count; i++)
            if (pEntry->pages[i] != NULL)
                MmFreeContiguousMemory( pEntry->pages[i] );

        RemoveEntryList( pListEntry );
        ExFreePoolWithTag( pListEntry, HB_POOL_TAG );
    }

    // Reset used preallocations
    pEPT->Preallocations = 0;
    return STATUS_SUCCESS;
}
Example #18
0
NTSTATUS
DriverDeviceControl(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{

    NTSTATUS           Status = STATUS_UNSUCCESSFUL;
    PIO_STACK_LOCATION IrpSp;
    ULONG              IOControlCode = 0;
    ULONG              dwBytesWritten = 0;
    PCHAR              pInBuf = NULL, pOutBuf = NULL;
    unsigned int       _cpu_thread_id = 0;
    unsigned int       new_cpu_thread_id = 0;
    ULONG              _num_active_cpus = 0;
    KAFFINITY          _kaffinity = 0;
    UINT32             core_id = 0;

    //
    // Get the current IRP stack location of this request
    //
    IrpSp = IoGetCurrentIrpStackLocation (Irp);
    IOControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;

    DbgPrint( "[chipsec] >>>>>>>>>> IOCTL >>>>>>>>>>\n" );
    DbgPrint( "[chipsec] DeviceObject = 0x%x IOCTL = 0x%x\n", DeviceObject, IOControlCode );
    DbgPrint( "[chipsec] InputBufferLength = 0x%x, OutputBufferLength = 0x%x\n", IrpSp->Parameters.DeviceIoControl.InputBufferLength, IrpSp->Parameters.DeviceIoControl.OutputBufferLength );

    //
    // CPU thread ID
    // 
    _num_active_cpus = KeQueryActiveProcessorCount( NULL );
    _kaffinity       = KeQueryActiveProcessors();
    _cpu_thread_id   = KeGetCurrentProcessorNumber();
    DbgPrint( "[chipsec] Active CPU threads         : %d (KeNumberProcessors = %d)\n", _num_active_cpus, KeNumberProcessors );
    DbgPrint( "[chipsec] Active CPU mask (KAFFINITY): 0x%08X\n", _kaffinity );
    DbgPrint( "[chipsec] Current CPU thread         : %d\n", _cpu_thread_id );

    //
    // Switch on the IOCTL code that is being requested by the user.  If the
    // operation is a valid one for this device do the needful.
    //
    Irp -> IoStatus.Information = 0;
    switch( IOControlCode )
      {
        case READ_PCI_CFG_REGISTER:
          {
            DWORD val;
            BYTE size = 0;
            WORD bdf[4];
            BYTE bus = 0, dev = 0, fun = 0, off = 0;
            DbgPrint( "[chipsec] > READ_PCI_CFG_REGISTER\n" );

            RtlCopyBytes( bdf,Irp->AssociatedIrp.SystemBuffer, 4*sizeof(WORD) );
            RtlCopyBytes( &size, (BYTE*)Irp->AssociatedIrp.SystemBuffer + 4*sizeof(WORD), sizeof(BYTE) );
            bus = (UINT8)bdf[0];
            dev = (UINT8)bdf[1];
            fun = (UINT8)bdf[2];
            off = (UINT8)bdf[3];

            if( 1 != size && 2 != size && 4 != size)
              {
              DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" );
              Status = STATUS_INVALID_PARAMETER;
              break;
              }
            val = ReadPCICfg( bus, dev, fun, off, size );             

            IrpSp->Parameters.Read.Length = size;
            RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (VOID*)&val, size );
            DbgPrint( "[chipsec][READ_PCI_CFG_REGISTER] B/D/F: %#04x/%#04x/%#04x, OFFSET: %#04x, value = %#010x (size = 0x%x)\n", bus, dev, fun, off, val, size );

            dwBytesWritten = IrpSp->Parameters.Read.Length;
            Status = STATUS_SUCCESS;
            break;
          }
        case WRITE_PCI_CFG_REGISTER:
          {
            DWORD val = 0;
            WORD bdf[6];
            BYTE bus = 0, dev = 0, fun = 0, off = 0;
            BYTE size = 0;
            DbgPrint( "[chipsec] > WRITE_PCI_CFG_REGISTER\n" );

            RtlCopyBytes( bdf, Irp->AssociatedIrp.SystemBuffer, 6 * sizeof(WORD) );
            bus = (UINT8)bdf[0];
            dev = (UINT8)bdf[1];
            fun = (UINT8)bdf[2];
            off = (UINT8)bdf[3];
            RtlCopyBytes( &size, (BYTE*)Irp->AssociatedIrp.SystemBuffer + 6*sizeof(WORD), sizeof(BYTE) );

            val = ((DWORD)bdf[5] << 16) | bdf[4];
            DbgPrint( "[chipsec][WRITE_PCI_CFG_REGISTER] B/D/F: %#02x/%#02x/%#02x, OFFSET: %#02x, value = %#010x (size = %#02x)\n", bus, dev, fun, off, val, size );
            WritePCICfg( bus, dev, fun, off, size, val );

            Status = STATUS_SUCCESS;
            break;
          }
        case IOCTL_READ_PHYSMEM:
          {
            UINT32 len = 0;
            PVOID virt_addr;
            PHYSICAL_ADDRESS phys_addr = { 0x0, 0x0 };

            DbgPrint( "[chipsec] > IOCTL_READ_PHYSMEM\n" );
            if( !Irp->AssociatedIrp.SystemBuffer ||
                IrpSp->Parameters.DeviceIoControl.InputBufferLength < 3*sizeof(UINT32))
              {
                DbgPrint( "[chipsec][IOCTL_READ_PHYSMEM] ERROR: STATUS_INVALID_PARAMETER\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }

            pInBuf = Irp->AssociatedIrp.SystemBuffer;
            pOutBuf = Irp->AssociatedIrp.SystemBuffer;

            phys_addr.HighPart = ((UINT32*)pInBuf)[0];
            phys_addr.LowPart  = ((UINT32*)pInBuf)[1];
            len                = ((UINT32*)pInBuf)[2];
            if( !len ) len = 4;

            if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength < len )
              {
                DbgPrint( "[chipsec][IOCTL_READ_PHYSMEM] ERROR: STATUS_BUFFER_TOO_SMALL\n" );
                Status = STATUS_BUFFER_TOO_SMALL;
                break;
              }

            __try
              {
                Status = _read_phys_mem( phys_addr, len, pOutBuf );
              }
            __except (EXCEPTION_EXECUTE_HANDLER)
              {
                Status = GetExceptionCode();
                DbgPrint( "[chipsec][IOCTL_READ_PHYSMEM] ERROR: exception code 0x%X\n", Status );
                break;
              }

            if( NT_SUCCESS(Status) )
              {
                DbgPrint( "[chipsec][IOCTL_READ_PHYSMEM] Contents:\n" );
                _dump_buffer( (unsigned char *)pOutBuf, min(len,0x100) );
                dwBytesWritten = len;
              }
            break;
          }
        case IOCTL_WRITE_PHYSMEM:
          {
            UINT32 len = 0;
            PVOID virt_addr = 0;
            PHYSICAL_ADDRESS phys_addr = { 0x0, 0x0 };

            DbgPrint( "[chipsec] > IOCTL_WRITE_PHYSMEM\n" );
            if( Irp->AssociatedIrp.SystemBuffer )
              {
                pInBuf = Irp->AssociatedIrp.SystemBuffer;
                pOutBuf = Irp->AssociatedIrp.SystemBuffer;

                if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < 3*sizeof(UINT32) )
                  {
                    DbgPrint( "[chipsec][IOCTL_WRITE_PHYSMEM] ERROR: STATUS_INVALID_PARAMETER\n" );
                    Status = STATUS_INVALID_PARAMETER;
                    break;
                  }

                phys_addr.HighPart = ((UINT32*)pInBuf)[0];
                phys_addr.LowPart  = ((UINT32*)pInBuf)[1];
                len                = ((UINT32*)pInBuf)[2];
                ((UINT32*)pInBuf) += 3;

                if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < len + 3*sizeof(UINT32) )
                  {
                    DbgPrint( "[chipsec][IOCTL_WRITE_PHYSMEM] ERROR: STATUS_INVALID_PARAMETER\n" );
                    Status = STATUS_INVALID_PARAMETER;
                    break;
                  }

                DbgPrint( "[chipsec][IOCTL_WRITE_PHYSMEM] Writing contents:\n" );
                _dump_buffer( (unsigned char *)pInBuf, min(len,0x100) );

                __try
                  {
                    Status = _write_phys_mem( phys_addr, len, pInBuf );
                  }
                __except (EXCEPTION_EXECUTE_HANDLER)
                  {
                    Status = GetExceptionCode();
                    DbgPrint( "[chipsec][IOCTL_WRITE_PHYSMEM] ERROR: exception code 0x%X\n", Status );
                    break;
                  }

                break;
              }
          }
        case IOCTL_ALLOC_PHYSMEM:
          {
            SIZE_T NumberOfBytes = 0;
            PVOID va = 0;
            PHYSICAL_ADDRESS HighestAcceptableAddress = { 0xFFFFFFFF, 0xFFFFFFFF };

            DbgPrint( "[chipsec] > IOCTL_ALLOC_PHYSMEM\n" );
            pInBuf  = Irp->AssociatedIrp.SystemBuffer;
            pOutBuf = Irp->AssociatedIrp.SystemBuffer;
            if( !pInBuf || IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(UINT64) + sizeof(UINT32))
              {
                DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }
            RtlCopyBytes( &HighestAcceptableAddress.QuadPart, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(UINT64) );
            RtlCopyBytes( &NumberOfBytes, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(UINT64), sizeof(UINT32) );
            DbgPrint( "[chipsec] Allocating: NumberOfBytes = 0x%X, PhysAddr = 0x%I64x", NumberOfBytes, HighestAcceptableAddress.QuadPart );
            va = MmAllocateContiguousMemory( NumberOfBytes, HighestAcceptableAddress );
            if( !va )
              {
                DbgPrint( "[chipsec] ERROR: STATUS_UNSUCCESSFUL - could not allocate memory\n" );
                Status = STATUS_UNSUCCESSFUL;
              }
            else if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 2*sizeof(UINT64) )
              {
                DbgPrint( "[chipsec] ERROR: STATUS_BUFFER_TOO_SMALL - should be at least 2*UINT64\n" );
                Status = STATUS_BUFFER_TOO_SMALL;
              }
            else
              {
                PHYSICAL_ADDRESS pa   = MmGetPhysicalAddress( va );
                DbgPrint( "[chipsec] Allocated Buffer: VirtAddr = 0x%I64x, PhysAddr = 0x%I64x\n", (UINT64)va, pa.QuadPart );
                ((UINT64*)pOutBuf)[0] = (UINT64)va;
                ((UINT64*)pOutBuf)[1] = pa.QuadPart;

                IrpSp->Parameters.Read.Length = 2*sizeof(UINT64);
                dwBytesWritten = IrpSp->Parameters.Read.Length;
                Status = STATUS_SUCCESS;
              }

            break;
          }

        case IOCTL_FREE_PHYSMEM:
          {
            UINT64 va = 0x0;
            pInBuf  = Irp->AssociatedIrp.SystemBuffer;
            pOutBuf = Irp->AssociatedIrp.SystemBuffer;

            DbgPrint( "[chipsec] > IOCTL_FREE_PHYSMEM\n" );
            if( !Irp->AssociatedIrp.SystemBuffer ||
                IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(UINT64))
            {
               DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" );
               Status = STATUS_INVALID_PARAMETER;
               break;
            }

            RtlCopyBytes( &va, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(UINT64) );
            DbgPrint( "[chipsec][IOCTL_FREE_PHYSMEM] Virtual address of the memory being freed: 0x%I64X\n", va );
            MmFreeContiguousMemory( (PVOID)va );

            IrpSp->Parameters.Read.Length = 0;
            dwBytesWritten = IrpSp->Parameters.Read.Length;
            Status = STATUS_SUCCESS;
            break;
          }

        case IOCTL_GET_PHYSADDR:
          {
            UINT64 va = 0x0;
            PHYSICAL_ADDRESS pa = { 0x0, 0x0 };

            pInBuf  = Irp->AssociatedIrp.SystemBuffer;
            pOutBuf = Irp->AssociatedIrp.SystemBuffer;

            DbgPrint( "[chipsec] > IOCTL_GET_PHYSADDR\n" );
            if( !Irp->AssociatedIrp.SystemBuffer ||
                IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(UINT64))
            {
               DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" );
               Status = STATUS_INVALID_PARAMETER;
               break;
            }

            if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(UINT64))
            {
               DbgPrint( "[chipsec] ERROR: STATUS_BUFFER_TOO_SMALL\n" );
               Status = STATUS_BUFFER_TOO_SMALL;
               break;
            }

            RtlCopyBytes( &va, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(UINT64) );
            pa = MmGetPhysicalAddress( (PVOID)va );

            DbgPrint( "[chipsec][IOCTL_GET_PHYSADDR] Traslated virtual address 0x%I64X to physical: 0x%I64X\n", va, pa.QuadPart, pa.LowPart);
            RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (void*)&pa, sizeof(UINT64) );
            IrpSp->Parameters.Read.Length = sizeof(UINT64);
            dwBytesWritten = IrpSp->Parameters.Read.Length;
            Status = STATUS_SUCCESS;
            break;
          }

        case IOCTL_MAP_IO_SPACE:
          {
            PVOID va  = 0x0;
            PHYSICAL_ADDRESS pa = { 0x0, 0x0 };
            unsigned int len = 0;
            unsigned int cache_type = 0;

            pInBuf  = Irp->AssociatedIrp.SystemBuffer;
            pOutBuf = Irp->AssociatedIrp.SystemBuffer;

            DbgPrint( "[chipsec] > IOCTL_MAP_IO_SPACE\n" );
            if( !Irp->AssociatedIrp.SystemBuffer ||
                IrpSp->Parameters.DeviceIoControl.InputBufferLength != 3*8)
            {
               DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" );
               Status = STATUS_INVALID_PARAMETER;
               break;
            }

            if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(UINT64))
            {
               DbgPrint( "[chipsec] ERROR: STATUS_BUFFER_TOO_SMALL\n" );
               Status = STATUS_BUFFER_TOO_SMALL;
               break;
            }

            RtlCopyBytes( &pa,         (BYTE*)Irp->AssociatedIrp.SystemBuffer + 0x00, 0x8 );
            RtlCopyBytes( &len,        (BYTE*)Irp->AssociatedIrp.SystemBuffer + 0x08, 0x4 );
            RtlCopyBytes( &cache_type, (BYTE*)Irp->AssociatedIrp.SystemBuffer + 0x10, 0x4 );

            va = MmMapIoSpace(pa, len, cache_type);

            DbgPrint( "[chipsec][IOCTL_MAP_IO_SPACE] Mapping physical address 0x%016llX to virtual 0x%016llX\n", pa, va);
            RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (void*)&va, sizeof(va) );
            IrpSp->Parameters.Read.Length = sizeof(va);
            dwBytesWritten = sizeof(va);
            Status = STATUS_SUCCESS;
            break;
          }

        case IOCTL_LOAD_UCODE_PATCH:
          {
            PVOID ucode_buf = NULL;
            UINT64 ucode_start = 0;
            UINT16 ucode_size = 0;
            UINT32 _eax = 0, _edx = 0;
            int CPUInfo[4] = {-1};

            DbgPrint("[chipsec] > IOCTL_LOAD_UCODE_UPDATE\n" );

            if( !Irp->AssociatedIrp.SystemBuffer ||
                IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(BYTE) + sizeof(UINT16) )
            {
               DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER (input buffer size < 3)\n" );
               Status = STATUS_INVALID_PARAMETER;
               break;
            }

            RtlCopyBytes( &new_cpu_thread_id, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(BYTE) );
            if( new_cpu_thread_id >= _num_active_cpus ) new_cpu_thread_id = 0;
            KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) );
            DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] Changed CPU thread to %d\n", KeGetCurrentProcessorNumber() );

            RtlCopyBytes( &ucode_size, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(BYTE), sizeof(UINT16) );
            DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] Ucode update size = 0x%X\n", ucode_size );

            if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < ucode_size + sizeof(BYTE) + sizeof(UINT16) )
              {
                DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER (input buffer size < ucode_size + 3)\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }

            ucode_buf = ExAllocatePoolWithTag( NonPagedPool, ucode_size, 0x3184 );
            if( !ucode_buf )
              {
                DbgPrint( "[chipsec] ERROR: couldn't allocate pool for ucode binary\n" );
                break;
              }           
            RtlCopyBytes( ucode_buf, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(BYTE) + sizeof(UINT16), ucode_size );
            ucode_start = (UINT64)ucode_buf;
            DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] ucode update address = 0x%p (eax = 0x%08X, edx = 0x%08X)\n", ucode_start, (UINT32)(ucode_start & 0xFFFFFFFF), (UINT32)((ucode_start >> 32) & 0xFFFFFFFF) );
            DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] ucode update contents:\n" );
            _dump_buffer( (unsigned char *)ucode_buf, min(ucode_size,0x100) );

            // --
            // -- trigger CPU ucode patch update
            // -- pInBuf points to the beginning of ucode update binary
            // --
            _wrmsr( MSR_IA32_BIOS_UPDT_TRIG, (UINT32)((ucode_start >> 32) & 0xFFFFFFFF), (UINT32)(ucode_start & 0xFFFFFFFF) );

            ExFreePoolWithTag( ucode_buf, 0x3184 );

            // --
            // -- check if patch was loaded
            // --
            // -- need to clear IA32_BIOS_SIGN_ID MSR first
            // -- CPUID will deposit an update ID value in 64-bit MSR at address MSR_IA32_BIOS_SIGN_ID
            // -- read IA32_BIOS_SIGN_ID MSR to check patch ID != 0
            // --
            DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] checking ucode update was loaded..\n" );
            DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] clear IA32_BIOS_SIGN_ID, CPUID EAX=1, read back IA32_BIOS_SIGN_ID\n" );
            _wrmsr( MSR_IA32_BIOS_SIGN_ID, 0, 0 );
            __cpuid(CPUInfo, 1);
            _rdmsr( MSR_IA32_BIOS_SIGN_ID, &_eax, &_edx );
            DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] RDMSR( IA32_BIOS_SIGN_ID=0x8b ) = 0x%08x%08x\n", _edx, _eax );
            if( 0 != _edx ) DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] Microcode update loaded (ID != 0)\n" );
            else            DbgPrint( "[chipsec] ERROR: Microcode update failed\n" );

            Status = STATUS_SUCCESS;
            break;
          }
        case IOCTL_WRMSR:
          {

            UINT32 msrData[3];
            UINT32 _eax = 0, _edx = 0;
            unsigned int _msr_addr;

            DbgPrint("[chipsec] > IOCTL_WRMSR\n");

            pInBuf = Irp->AssociatedIrp.SystemBuffer;
            if( !pInBuf )
              {
	        DbgPrint( "[chipsec][IOCTL_WRMSR] ERROR: NO data provided\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }
            if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(BYTE) + 3*sizeof(UINT32) )
              {
                DbgPrint( "[chipsec][IOCTL_WRMSR] ERROR: STATUS_INVALID_PARAMETER (input buffer size < sizeof(BYTE) + 3*sizeof(UINT32))\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }

            RtlCopyBytes( &new_cpu_thread_id, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(BYTE) );
            if( new_cpu_thread_id >= _num_active_cpus ) new_cpu_thread_id = 0;
            KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) );
            DbgPrint( "[chipsec][IOCTL_WRMSR] Changed CPU thread to %d\n", KeGetCurrentProcessorNumber() );

            RtlCopyBytes( msrData, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(BYTE), 3 * sizeof(UINT32) );
            _msr_addr = msrData[0];
            _eax      = msrData[1];
            _edx      = msrData[2];
            DbgPrint( "[chipsec][IOCTL_WRMSR] WRMSR( 0x%x ) <-- 0x%08x%08x\n", _msr_addr, _edx, _eax );

            // --
            // -- write MSR
            // --
            __try
              {
                _wrmsr( _msr_addr, _edx, _eax );
              }
            __except (EXCEPTION_EXECUTE_HANDLER)
              {
                Status = GetExceptionCode();
                DbgPrint( "[chipsec][IOCTL_WRMSR] ERROR: exception code 0x%X\n", Status );
                break;
              }

            // --
            // -- read MSR to check if it was written
            // --
//            _rdmsr( _msr_addr, &_eax, &_edx );
//            DbgPrint( "[chipsec][IOCTL_WRMSR] RDMSR( 0x%x ) --> 0x%08x%08x\n", _msr_addr, _edx, _eax );

            Status = STATUS_SUCCESS;
            break;
          }
        case IOCTL_RDMSR:
          {
            UINT32 msrData[1];
            UINT32 _eax = 0;
            UINT32 _edx = 0;
            UINT32 _msr_addr = 0;

            DbgPrint("[chipsec] > IOCTL_RDMSR\n");

            pInBuf  = Irp->AssociatedIrp.SystemBuffer;
            pOutBuf = Irp->AssociatedIrp.SystemBuffer;
            if( !pInBuf )
              {
                DbgPrint( "[chipsec] ERROR: No input provided\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }
            if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(BYTE) + sizeof(UINT32) )
              {
                DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER - input buffer size < sizeof(BYTE) + sizeof(UINT32)\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }

            RtlCopyBytes( &new_cpu_thread_id, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(BYTE) );
            if( new_cpu_thread_id >= _num_active_cpus ) new_cpu_thread_id = 0;
            KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) );
            DbgPrint( "[chipsec][IOCTL_RDMSR] Changed CPU thread to %d\n", KeGetCurrentProcessorNumber() );

            RtlCopyBytes( msrData, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(BYTE), sizeof(UINT32) );
            _msr_addr = msrData[0];

            __try
              {
                _rdmsr( _msr_addr, &_eax, &_edx );
              }
            __except( EXCEPTION_EXECUTE_HANDLER )
              {
                Status = GetExceptionCode();
                DbgPrint( "[chipsec][IOCTL_RDMSR] ERROR: exception code 0x%X\n", Status );
                break;
              }
            DbgPrint( "[chipsec][IOCTL_RDMSR] RDMSR( 0x%x ) --> 0x%08x%08x\n", _msr_addr, _edx, _eax );

            if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= 2*sizeof(UINT32) )
              {
                IrpSp->Parameters.Read.Length = 2*sizeof(UINT32);
                RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (VOID*)&_eax, sizeof(UINT32) );
                RtlCopyBytes( ((UINT8*)Irp->AssociatedIrp.SystemBuffer) + sizeof(UINT32), (VOID*)&_edx, sizeof(UINT32) );

                dwBytesWritten = 2*sizeof(UINT32);
                Status = STATUS_SUCCESS;
              }
            else
              {
                DbgPrint( "[chipsec] ERROR: STATUS_BUFFER_TOO_SMALL - should be at least 2 UINT32\n" );
                Status = STATUS_BUFFER_TOO_SMALL;
              }

            break;
          }
        case READ_IO_PORT:
          {
            DWORD value;
            BYTE size = 0;
            WORD io_port;
            DbgPrint( "[chipsec] > READ_IO_PORT\n" );

            RtlCopyBytes( &io_port, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(WORD) );
            RtlCopyBytes( &size, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(WORD), sizeof(BYTE) );
            if( 1 != size && 2 != size && 4 != size)
              {
              DbgPrint( "[chipsec][READ_IO_PORT] ERROR: STATUS_INVALID_PARAMETER\n" );
              Status = STATUS_INVALID_PARAMETER;
              break;
              }

            __try
              {
                value = ReadIOPort( io_port, size );             
              }
            __except( EXCEPTION_EXECUTE_HANDLER )
              {
                Status = GetExceptionCode();
                DbgPrint( "[chipsec][READ_IO_PORT] ERROR: exception code 0x%X\n", Status );
                break;
              }

            IrpSp->Parameters.Read.Length = size;
            RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (VOID*)&value, size );
            DbgPrint( "[chipsec][READ_IO_PORT] I/O Port %#04x, value = %#010x (size = %#02x)\n", io_port, value, size );

            dwBytesWritten = IrpSp->Parameters.Read.Length;
            Status = STATUS_SUCCESS;
            break;
          }
        case WRITE_IO_PORT:
          {
            DWORD value = 0;
            WORD io_port = 0;
            BYTE size = 0;
            DbgPrint( "[chipsec] > WRITE_IO_PORT\n" );

            RtlCopyBytes( &io_port, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(WORD) );
            RtlCopyBytes( &value, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(WORD), sizeof(DWORD) );
            RtlCopyBytes( &size, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(WORD) + sizeof(DWORD), sizeof(BYTE) );
            DbgPrint( "[chipsec][WRITE_IO_PORT] I/O Port %#04x, value = %#010x (size = %#02x)\n", io_port, value, size );

            __try
              {
                WriteIOPort( value, io_port, size );
              }
            __except( EXCEPTION_EXECUTE_HANDLER )
              {
                Status = GetExceptionCode();
                DbgPrint( "[chipsec][WRITE_IO_PORT] ERROR: exception code 0x%X\n", Status );
                break;
              }

            Status = STATUS_SUCCESS;
            break;
          }
        case GET_CPU_DESCRIPTOR_TABLE:
          {
            BYTE dt_code = 0;
            DESCRIPTOR_TABLE_RECORD dtr;
            PDESCRIPTOR_TABLE_RECORD pdtr = &dtr;
            PHYSICAL_ADDRESS dt_pa;

            DbgPrint( "[chipsec] > GET_CPU_DESCRIPTOR_TABLE\n" );

            RtlCopyBytes( &new_cpu_thread_id, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(BYTE) );
            if( new_cpu_thread_id >= _num_active_cpus ) new_cpu_thread_id = 0;
            KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) );
            DbgPrint( "[chipsec][GET_CPU_DESCRIPTOR_TABLE] Changed CPU thread to %d\n", KeGetCurrentProcessorNumber() );
            RtlCopyBytes( &dt_code, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(BYTE), sizeof(BYTE) );
            DbgPrint( "[chipsec][GET_CPU_DESCRIPTOR_TABLE] Descriptor table: %x\n", dt_code );

            switch( dt_code )
              {
                case CPU_DT_CODE_GDTR:  { _store_gdtr( (void*)pdtr ); break; }
                case CPU_DT_CODE_LDTR:  { _store_ldtr( (void*)pdtr ); break; }
                case CPU_DT_CODE_IDTR:
                default:                { _store_idtr( (void*)pdtr ); break; }
              }

            DbgPrint( "[chipsec][GET_CPU_DESCRIPTOR_TABLE] Descriptor table register contents:\n" );
            _dump_buffer( (unsigned char *)pdtr, sizeof(DESCRIPTOR_TABLE_RECORD) );
            DbgPrint( "[chipsec][GET_CPU_DESCRIPTOR_TABLE] IDTR: Limit = 0x%04x, Base = 0x%I64x\n", dtr.limit, dtr.base );

            dt_pa = MmGetPhysicalAddress( (PVOID)dtr.base );
            DbgPrint( "[chipsec][GET_CPU_DESCRIPTOR_TABLE] Descriptor table PA: 0x%I64X (0x%08X_%08X)\n", dt_pa.QuadPart, dt_pa.HighPart, dt_pa.LowPart );

            IrpSp->Parameters.Read.Length = sizeof(DESCRIPTOR_TABLE_RECORD) + sizeof(dt_pa.QuadPart);
            RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (void*)pdtr, sizeof(DESCRIPTOR_TABLE_RECORD) );    
            RtlCopyBytes( (UINT8*)Irp->AssociatedIrp.SystemBuffer + sizeof(DESCRIPTOR_TABLE_RECORD), (VOID*)&dt_pa.QuadPart, sizeof(dt_pa.QuadPart) );    

            dwBytesWritten = IrpSp->Parameters.Read.Length;
            Status = STATUS_SUCCESS;
            break;
          }
        case IOCTL_SWSMI:
          {
            CPU_REG_TYPE gprs[6] = {0};
            CPU_REG_TYPE _rax = 0, _rbx = 0, _rcx = 0, _rdx = 0, _rsi = 0, _rdi = 0;
            unsigned int _smi_code_data = 0;

            DbgPrint("[chipsec] > IOCTL_SWSMI\n");
            pInBuf = Irp->AssociatedIrp.SystemBuffer;
            if( !pInBuf )
              {
	        DbgPrint( "[chipsec] ERROR: NO data provided\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }
            if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(UINT16) + sizeof(gprs) )
              {
                DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER (input buffer size < sizeof(UINT16) + sizeof(gprs))\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }
            RtlCopyBytes( &_smi_code_data, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(UINT16) );
            RtlCopyBytes( gprs, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(UINT16), sizeof(gprs) );
            _rax = gprs[ 0 ];
            _rbx = gprs[ 1 ];
            _rcx = gprs[ 2 ];
            _rdx = gprs[ 3 ];
            _rsi = gprs[ 4 ];
            _rdi = gprs[ 5 ];
            DbgPrint( "[chipsec][IOCTL_SWSMI] SW SMI to ports 0x%X-0x%X <- 0x%04X\n", 0xB2, 0xB3, _smi_code_data );
            DbgPrint( "                       RAX = 0x%I64x\n", _rax );
            DbgPrint( "                       RBX = 0x%I64x\n", _rbx );
            DbgPrint( "                       RCX = 0x%I64x\n", _rcx );
            DbgPrint( "                       RDX = 0x%I64x\n", _rdx );
            DbgPrint( "                       RSI = 0x%I64x\n", _rsi );
            DbgPrint( "                       RDI = 0x%I64x\n", _rdi );
            // --
            // -- send SMI using port 0xB2
            // --
            __try
              {
                _swsmi( _smi_code_data, _rax, _rbx, _rcx, _rdx, _rsi, _rdi );
              }
            __except( EXCEPTION_EXECUTE_HANDLER )
              {
                Status = GetExceptionCode();
                break;
              }
            Status = STATUS_SUCCESS;
            break;
          }
        case IOCTL_CPUID:
          {
            DWORD CPUInfo[4] = {-1};
            DWORD gprs[2] = {0};
            DWORD _rax = 0, _rcx = 0;
            //CPU_REG_TYPE gprs[6];
            //CPU_REG_TYPE _rax = 0, _rbx = 0, _rcx = 0, _rdx = 0, _rsi = 0, _rdi = 0;

            DbgPrint("[chipsec] > IOCTL_CPUID\n");
            pInBuf = Irp->AssociatedIrp.SystemBuffer;
            if( !pInBuf )
              {
	        DbgPrint( "[chipsec] ERROR: NO data provided\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }
            if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(gprs) )
              {
                DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER (input buffer size < %d)\n", sizeof(gprs) );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }
            RtlCopyBytes( gprs, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(gprs) );
            _rax = gprs[ 0 ];
            _rcx = gprs[ 1 ];
            DbgPrint( "[chipsec][IOCTL_CPUID] CPUID:\n" );
            DbgPrint( "                       EAX = 0x%08X\n", _rax );
            DbgPrint( "                       ECX = 0x%08X\n", _rcx );

            __cpuidex( CPUInfo, _rax, _rcx );

            DbgPrint( "[chipsec][IOCTL_CPUID] CPUID returned:\n" );
            DbgPrint( "                       EAX = 0x%08X\n", CPUInfo[0] );
            DbgPrint( "                       EBX = 0x%08X\n", CPUInfo[1] );
            DbgPrint( "                       ECX = 0x%08X\n", CPUInfo[2] );
            DbgPrint( "                       EDX = 0x%08X\n", CPUInfo[3] );

            IrpSp->Parameters.Read.Length = sizeof(CPUInfo);
            RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (void*)CPUInfo, sizeof(CPUInfo) );    

            dwBytesWritten = IrpSp->Parameters.Read.Length;
            Status = STATUS_SUCCESS;
            break;
          }

        case IOCTL_WRCR:
          {
            UINT64 val64 = 0;
            CPU_REG_TYPE value = 0;
            WORD cr_reg = 0;
            DbgPrint( "[chipsec] > WRITE_CR\n" );

            if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < (sizeof(cr_reg) + sizeof(val64) + sizeof(BYTE)))
            {
                 Status = STATUS_INVALID_PARAMETER;
                 break;
            }

            RtlCopyBytes( &cr_reg, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(cr_reg) );
            RtlCopyBytes( &val64, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(cr_reg), sizeof(val64) );
            new_cpu_thread_id = *((BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(cr_reg) + sizeof(val64));
            if( new_cpu_thread_id >= _num_active_cpus )
            {
            //    new_cpu_thread_id = 0;
                 Status = STATUS_INVALID_PARAMETER;
                 break;
            }

            KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) );
            value = (CPU_REG_TYPE)val64;
            DbgPrint( "[chipsec][WRITE_CR] CR Reg %#04x, value = %#010x \n", cr_reg, value );

            switch (cr_reg) {
            case 0: WriteCR0(value);
                Status = STATUS_SUCCESS;
                break;
            case 2: WriteCR2(value);
                Status = STATUS_SUCCESS;
                break;
            case 3: WriteCR3(value);
                Status = STATUS_SUCCESS;
                break;
            case 4: WriteCR4(value);
                Status = STATUS_SUCCESS;
                break;
            case 8:
#if defined(_M_AMD64)
                WriteCR8(value);
                Status = STATUS_SUCCESS;
                break;
#endif
            default:
                Status = STATUS_INVALID_PARAMETER;
                break;
            }

            if( !NT_SUCCESS(Status) ) {
                break;
            }

            dwBytesWritten = 0;
            Status = STATUS_SUCCESS;
            break;
          }
        case IOCTL_RDCR:
          {
            UINT64 val64 = 0;
            CPU_REG_TYPE value = 0;
            WORD cr_reg = 0;
            DbgPrint( "[chipsec] > READ_CR\n" );

            if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < (sizeof(cr_reg)+sizeof(BYTE))
             || IrpSp->Parameters.DeviceIoControl.OutputBufferLength < (sizeof(val64))
              )
            {
                 Status = STATUS_INVALID_PARAMETER;
                 break;
            }

            RtlCopyBytes( &cr_reg, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(cr_reg) );
            new_cpu_thread_id = *((BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(cr_reg));
            if( new_cpu_thread_id >= _num_active_cpus )
            {
            //    new_cpu_thread_id = 0;
                 Status = STATUS_INVALID_PARAMETER;
                 break;
            }

            KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) );

            switch (cr_reg) {
            case 0: value = ReadCR0();
                Status = STATUS_SUCCESS;
                break;
            case 2: value = ReadCR2();
                Status = STATUS_SUCCESS;
                break;
            case 3: value = ReadCR3();
                Status = STATUS_SUCCESS;
                break;
            case 4: value = ReadCR4();
                Status = STATUS_SUCCESS;
                break;
            case 8:
#if defined(_M_AMD64)
                value = ReadCR8();
                Status = STATUS_SUCCESS;
                break;
#endif
            default:
                Status = STATUS_INVALID_PARAMETER;
                break;
            }
            
            if( !NT_SUCCESS(Status) ) {
                break;
            }

            val64 = value;
            RtlCopyBytes( (BYTE*)Irp->AssociatedIrp.SystemBuffer, &val64, sizeof(val64) );
            dwBytesWritten = sizeof(val64);

            DbgPrint( "[chipsec][READ_CR] CR Reg %#04x, value = %#010x \n", cr_reg, value );

            Status = STATUS_SUCCESS;
            break;

          }
        case IOCTL_HYPERCALL:
          {
            CPU_REG_TYPE regs[11] = {0};
            CPU_REG_TYPE result = 0;

            DbgPrint("[chipsec] > IOCTL_HYPERCALL\n");
            pInBuf = Irp->AssociatedIrp.SystemBuffer;

            if( !Irp->AssociatedIrp.SystemBuffer ||
                IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(regs))
            {
                DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
            }

            if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(result))
            {
               DbgPrint( "[chipsec] ERROR: STATUS_BUFFER_TOO_SMALL\n" );
               Status = STATUS_BUFFER_TOO_SMALL;
               break;
            }

            RtlCopyBytes( regs, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(regs) );
            DbgPrint( "[chipsec][IOCTL_HYPERCALL] HYPERCALL:\n" );
            #if defined(_M_AMD64)
            DbgPrint( "    RCX = 0x%016llX  RDX = 0x%016llX\n", regs[0], regs[1] );
            DbgPrint( "    R8  = 0x%016llX  R9  = 0x%016llX\n", regs[2], regs[3] );
            DbgPrint( "    R10 = 0x%016llX  R11 = 0x%016llX\n", regs[4], regs[5] );
            DbgPrint( "    RAX = 0x%016llX  RBX = 0x%016llX\n", regs[6], regs[7] );
            DbgPrint( "    RDI = 0x%016llX  RSI = 0x%016llX\n", regs[8], regs[9] );
            #endif
            #if defined(_M_IX86)
            DbgPrint( "    EAX = 0x%08X  EBX = 0x%08X  ECX = 0x%08X\n", regs[6], regs[7], regs[0] );
            DbgPrint( "    EDX = 0x%08X  ESI = 0x%08X  EDI = 0x%08X\n", regs[1], regs[8], regs[9] );
            #endif
            DbgPrint( "    XMM0-XMM5 buffer VA = 0x%016llX\n", regs[9] );

            __try
              {
                result = hypercall(regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], regs[6], regs[7], regs[8], regs[9], regs[10], &hypercall_page);
              }
            __except( EXCEPTION_EXECUTE_HANDLER )
              {
                Status = GetExceptionCode();
                DbgPrint( "[chipsec][IOCTL_HYPERCALL] ERROR: exception code 0x%X\n", Status );
                break;
              }

            DbgPrint( "[chipsec][IOCTL_HYPERCALL] returned: 0x%016llX\n", result);

            IrpSp->Parameters.Read.Length = sizeof(result);
            RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (void*)&result, sizeof(result) );

            dwBytesWritten = IrpSp->Parameters.Read.Length;
            Status = STATUS_SUCCESS;
            break;
          }

        default:
            DbgPrint( "[chipsec] ERROR: invalid IOCTL\n");
            Status = STATUS_NOT_IMPLEMENTED;
            break;

      } // -- switch
Example #19
0
DECLHIDDEN(int) rtR0MemObjNativeFree(RTR0MEMOBJ pMem)
{
    PRTR0MEMOBJNT pMemNt = (PRTR0MEMOBJNT)pMem;

    /*
     * Deal with it on a per type basis (just as a variation).
     */
    switch (pMemNt->Core.enmType)
    {
    case RTR0MEMOBJTYPE_LOW:
#ifndef IPRT_TARGET_NT4
        if (pMemNt->fAllocatedPagesForMdl)
        {
            Assert(pMemNt->Core.pv && pMemNt->cMdls == 1 && pMemNt->apMdls[0]);
            MmUnmapLockedPages(pMemNt->Core.pv, pMemNt->apMdls[0]);
            pMemNt->Core.pv = NULL;
            if (pMemNt->pvSecureMem)
            {
                MmUnsecureVirtualMemory(pMemNt->pvSecureMem);
                pMemNt->pvSecureMem = NULL;
            }

            MmFreePagesFromMdl(pMemNt->apMdls[0]);
            ExFreePool(pMemNt->apMdls[0]);
            pMemNt->apMdls[0] = NULL;
            pMemNt->cMdls = 0;
            break;
        }
#endif
        AssertFailed();
        break;

    case RTR0MEMOBJTYPE_PAGE:
        Assert(pMemNt->Core.pv);
        ExFreePool(pMemNt->Core.pv);
        pMemNt->Core.pv = NULL;

        Assert(pMemNt->cMdls == 1 && pMemNt->apMdls[0]);
        IoFreeMdl(pMemNt->apMdls[0]);
        pMemNt->apMdls[0] = NULL;
        pMemNt->cMdls = 0;
        break;

    case RTR0MEMOBJTYPE_CONT:
        Assert(pMemNt->Core.pv);
        MmFreeContiguousMemory(pMemNt->Core.pv);
        pMemNt->Core.pv = NULL;

        Assert(pMemNt->cMdls == 1 && pMemNt->apMdls[0]);
        IoFreeMdl(pMemNt->apMdls[0]);
        pMemNt->apMdls[0] = NULL;
        pMemNt->cMdls = 0;
        break;

    case RTR0MEMOBJTYPE_PHYS:
        /* rtR0MemObjNativeEnterPhys? */
        if (!pMemNt->Core.u.Phys.fAllocated)
        {
#ifndef IPRT_TARGET_NT4
            Assert(!pMemNt->fAllocatedPagesForMdl);
#endif
            /* Nothing to do here. */
            break;
        }
    /* fall thru */

    case RTR0MEMOBJTYPE_PHYS_NC:
#ifndef IPRT_TARGET_NT4
        if (pMemNt->fAllocatedPagesForMdl)
        {
            MmFreePagesFromMdl(pMemNt->apMdls[0]);
            ExFreePool(pMemNt->apMdls[0]);
            pMemNt->apMdls[0] = NULL;
            pMemNt->cMdls = 0;
            break;
        }
#endif
        AssertFailed();
        break;

    case RTR0MEMOBJTYPE_LOCK:
        if (pMemNt->pvSecureMem)
        {
            MmUnsecureVirtualMemory(pMemNt->pvSecureMem);
            pMemNt->pvSecureMem = NULL;
        }
        for (uint32_t i = 0; i < pMemNt->cMdls; i++)
        {
            MmUnlockPages(pMemNt->apMdls[i]);
            IoFreeMdl(pMemNt->apMdls[i]);
            pMemNt->apMdls[i] = NULL;
        }
        break;

    case RTR0MEMOBJTYPE_RES_VIRT:
        /*            if (pMemNt->Core.u.ResVirt.R0Process == NIL_RTR0PROCESS)
                    {
                    }
                    else
                    {
                    }*/
        AssertMsgFailed(("RTR0MEMOBJTYPE_RES_VIRT\n"));
        return VERR_INTERNAL_ERROR;
        break;

    case RTR0MEMOBJTYPE_MAPPING:
    {
        Assert(pMemNt->cMdls == 0 && pMemNt->Core.pv);
        PRTR0MEMOBJNT pMemNtParent = (PRTR0MEMOBJNT)pMemNt->Core.uRel.Child.pParent;
        Assert(pMemNtParent);
        if (pMemNtParent->cMdls)
        {
            Assert(pMemNtParent->cMdls == 1 && pMemNtParent->apMdls[0]);
            Assert(     pMemNt->Core.u.Mapping.R0Process == NIL_RTR0PROCESS
                        ||   pMemNt->Core.u.Mapping.R0Process == RTR0ProcHandleSelf());
            MmUnmapLockedPages(pMemNt->Core.pv, pMemNtParent->apMdls[0]);
        }
        else
        {
            Assert(     pMemNtParent->Core.enmType == RTR0MEMOBJTYPE_PHYS
                        &&   !pMemNtParent->Core.u.Phys.fAllocated);
            Assert(pMemNt->Core.u.Mapping.R0Process == NIL_RTR0PROCESS);
            MmUnmapIoSpace(pMemNt->Core.pv, pMemNt->Core.cb);
        }
        pMemNt->Core.pv = NULL;
        break;
    }

    default:
        AssertMsgFailed(("enmType=%d\n", pMemNt->Core.enmType));
        return VERR_INTERNAL_ERROR;
    }

    return VINF_SUCCESS;
}
Example #20
0
// This runs at a lower IRQL, so it can use the kernel memory functions
void processCreationMonitor(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create)
{
    PEPROCESS proc = NULL;
    void *PeHeaderVirt = NULL;
    uint16 numExecSections = 0;
    uint8 *pePtr = NULL;
    PHYSICAL_ADDRESS phys = {0};
    char *procName;
    uint32 imageSize, translations = (uint32) translationArr;
    
    NTSTATUS status = STATUS_SUCCESS;
    HANDLE periodMeasureThreadHandle = NULL;
    OBJECT_ATTRIBUTES objectAttributes = {0};
    
    // Set to anywhere inthe 4GB range
    highestMemoryAddress.LowPart = ~0;
    
    // Get the 8.3 image name
    PsLookupProcessByProcessId(ProcessId, &proc);
    procName = PsGetProcessImageFileName(proc);
    
    // Check if this is the target process
    if(strncmp(TargetAppName, procName, strlen(TargetAppName)) == 0)
    {
        if (Create && VDEBUG) DbgPrint("New Process Created! %s\r\n", procName); 
        if (!Create && VDEBUG) DbgPrint("Application quitting %s\r\n", procName);   
            
        // Retrieve virtual pointer to the PE header for target application (in PE context)
        PeHeaderVirt = PsGetProcessSectionBaseAddress(proc);
        //DbgPrint("Virt: %x", PeHeaderVirt);
        
        // Begin critical section
        // Attach to the target process and grab its CR3 value to use later
        KeStackAttachProcess(proc, &apcstate); 
        
        if (Create)
        {
            __asm
            {
                push eax
                mov eax, cr3
                mov targetCR3, eax
                pop eax
            }   
        }
        
        phys = MmGetPhysicalAddress(PeHeaderVirt);            
        KeUnstackDetachProcess(&apcstate);
        // End critical section
        
        targetPePhys = phys;
        targetPeVirt = PeHeaderVirt;
        targetProc = proc;
        
        if (Create)
        {
            targetPePtr = peMapInImageHeader(phys);
            imageSize = peGetImageSize(targetPePtr);
            if (VDEBUG) DbgPrint("Image Size: %x bytes Num Entries %d\r\n", imageSize, sizeof(TlbTranslation) * (imageSize / PAGE_SIZE));
            DbgPrint("Virt %x - %x %x\r\n", PeHeaderVirt, (uint32) PeHeaderVirt + imageSize, targetCR3);
        
            // Ensure Windows doesn't reuse the physical pages
            LockedMdl = pagingLockProcessMemory(PeHeaderVirt, imageSize, proc, &apcstate);
            if(LockedMdl == NULL && VDEBUG)
            {
                DbgPrint("Unable to lock memory\r\n");
            }
            appsize = imageSize;
            appCopy = (uint8 *) MmAllocateContiguousMemory(imageSize, highestMemoryAddress);
            RtlZeroMemory((void *) appCopy, imageSize);
            copyPe(proc, &apcstate, PeHeaderVirt, appCopy, imageSize);
            translationArr = allocateAndFillTranslationArray(PeHeaderVirt, 
                                                             appCopy, 
                                                             imageSize, 
                                                             proc, 
                                                             &apcstate);
                                                             
            translations = (uint32) translationArr;
            // VMCALL to start the TLB splitting
        	__asm
        	{
        		PUSHAD
        		MOV		EAX, VMCALL_INIT_SPLIT
                MOV     EBX, translations
        
        		_emit 0x0F		// VMCALL
        		_emit 0x01
        		_emit 0xC1
        
        		POPAD
        	}
            
            if (VDEBUG) DbgPrint("Checksum of proc: %x\r\n", 
                             peChecksumExecSections(targetPePtr, PeHeaderVirt, 
                                                    proc, &apcstate, targetPhys));
                             
            //pePrintSections(pePtr);
                             
#ifdef PERIODIC_MEASURE
            /* Set up periodic measurement thread */
            KeInitializeEvent(&periodicMeasureThreadWakeUp, NotificationEvent, FALSE); //returns void
            InitializeObjectAttributes(&objectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); //returns void
        
            periodicMeasureThreadExecute = 1; //allows thread to execute
            status = PsCreateSystemThread(&periodMeasureThreadHandle,
                            THREAD_ALL_ACCESS, &objectAttributes, NULL, NULL,
                            periodicMeasurePe, NULL);
            status = ObReferenceObjectByHandle(periodMeasureThreadHandle, 0, NULL,
                                               KernelMode, &periodicMeasureThread, NULL);
            ZwClose(periodMeasureThreadHandle); //don't need the handle anymore, ref will remain valid
#endif

        }
        else
        {
            translations = (uint32) translationArr;
            // VMCALL to stop TLB splitting
        	__asm
        	{
        		PUSHAD
        		MOV		EAX, VMCALL_END_SPLIT
                MOV     EBX, translations
        
        		_emit 0x0F		// VMCALL
        		_emit 0x01
        		_emit 0xC1
        
        		POPAD
        	}
            if (LockedMdl != NULL)
            {
               pagingUnlockProcessMemory(proc, &apcstate, LockedMdl);
            }
            
            if (appCopy != NULL)
            {
                MmFreeContiguousMemory((PVOID) appCopy);
            }
            
            if (translationArr != NULL)
            {
                freeTranslationArray(translationArr);
            }

            targetCR3 = 0;
            
#ifdef PERIODIC_MEASURE
            /* Stop the periodic measurement thread */
            periodicMeasureThreadExecute = 0; // Apply brakes
            KeSetEvent(&periodicMeasureThreadWakeUp, 0, TRUE); // Cancel any current wait in the thread
            /* Wait for thread to stop */
            KeWaitForSingleObject(periodicMeasureThread, 
                                  Executive, 
                                  KernelMode, 
                                  FALSE, 
                                  NULL); 
        
            ObDereferenceObject(periodicMeasureThread);
#endif
            peMapOutImageHeader(targetPePtr);
            targetPeVirt = NULL;
        }
        return;        
    }
Example #21
0
PVOID
HalAllocateCommonBuffer(
    IN PADAPTER_OBJECT AdapterObject,
    IN ULONG Length,
    OUT PPHYSICAL_ADDRESS LogicalAddress,
    IN BOOLEAN CacheEnabled
    )
/*++

Routine Description:

    This function allocates the memory for a common buffer and maps so that it
    can be accessed by a master device and the CPU.

Arguments:

    AdapterObject - Supplies a pointer to the adapter object used by this
        device.

    Length - Supplies the length of the common buffer to be allocated.

    LogicalAddress - Returns the logical address of the common buffer.

    CacheEnable - Indicates whether the memeory is cached or not.

Return Value:

    Returns the virtual address of the common buffer.  If the buffer cannot be
    allocated then NULL is returned.

--*/

{

    PVOID virtualAddress;
    PVOID virtualAddress2;
    PHYSICAL_ADDRESS physicalAddress;

    UNREFERENCED_PARAMETER( CacheEnabled );

    //
    // Assume below 16M
    //

    physicalAddress.HighPart = 0;
    physicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS-1;

    //
    // If the caller support 32bit addresses, and it's a master let
    // it have any memory below 4G
    //

    if (AdapterObject->Dma32BitAddresses  &&  AdapterObject->MasterDevice) {
        physicalAddress.LowPart = 0xFFFFFFFF;
    }

    virtualAddress = MmAllocateContiguousMemory(
        Length,
        physicalAddress
        );

    if (virtualAddress == NULL) {
        return(NULL);
    }

    *LogicalAddress = MmGetPhysicalAddress(virtualAddress);

    if (HalpBusType != MACHINE_TYPE_ISA || AdapterObject->MasterDevice) {
        return(virtualAddress);
    }

    //
    // This is an ISA system the common buffer cannot cross a 64 K bountry.
    //

    if ((LogicalAddress->LowPart + Length & ~0xFFFF) ==
        (LogicalAddress->LowPart & ~0xFFFF)) {

        //
        // This buffer is ok so return it.
        //

        return(virtualAddress);

    }

    //
    // Try to allocate a buffer agian and see if this is good.
    //

    virtualAddress2 = MmAllocateContiguousMemory(
        Length,
        physicalAddress
        );

    //
    // Free the first buffer.
    //

    MmFreeContiguousMemory(virtualAddress);

    if (virtualAddress2 == NULL) {
        return(NULL);
    }

    *LogicalAddress = MmGetPhysicalAddress(virtualAddress2);

    if ((LogicalAddress->LowPart + Length & ~0xFFFF) ==
        (LogicalAddress->LowPart & ~0xFFFF)) {

        //
        // This buffer is ok so return it.
        //

        return(virtualAddress2);

    }

    //
    // Try our best but just could not do it.  Free the buffer.
    //
   
    MmFreeContiguousMemory(virtualAddress2);

    return(NULL);
}
Example #22
0
/// <summary>
/// Execute VMLAUNCH
/// </summary>
/// <param name="Vcpu">Virtyal CPU data</param>
VOID VmxSubvertCPU( IN PVCPU Vcpu )
{
    PHYSICAL_ADDRESS phys = { 0 };
    phys.QuadPart = MAXULONG64;

    //
    // Initialize all the VMX-related MSRs by reading their value
    //
    for (ULONG i = 0; i <= VMX_MSR( MSR_IA32_VMX_VMCS_ENUM ); i++)
        Vcpu->MsrData[i].QuadPart = __readmsr( MSR_IA32_VMX_BASIC + i );

    // Secondary controls, if present
    if (g_Data->Features.SecondaryControls)
        Vcpu->MsrData[VMX_MSR( MSR_IA32_VMX_PROCBASED_CTLS2 )].QuadPart = __readmsr( MSR_IA32_VMX_PROCBASED_CTLS2 );

    // True MSRs, if present
    if (g_Data->Features.TrueMSRs)
        for (ULONG i = VMX_MSR( MSR_IA32_VMX_TRUE_PINBASED_CTLS ); i <= VMX_MSR( MSR_IA32_VMX_TRUE_ENTRY_CTLS ); i++)
            Vcpu->MsrData[i].QuadPart = __readmsr( MSR_IA32_VMX_BASIC + i );

    // VMFUNC, if present
    if(g_Data->Features.VMFUNC)
        Vcpu->MsrData[VMX_MSR( MSR_IA32_VMX_VMFUNC )].QuadPart = __readmsr( MSR_IA32_VMX_VMFUNC );

    Vcpu->VMXON    = MmAllocateContiguousMemory( sizeof( VMX_VMCS ), phys );
    Vcpu->VMCS     = MmAllocateContiguousMemory( sizeof( VMX_VMCS ), phys );
    Vcpu->VMMStack = MmAllocateContiguousMemory( KERNEL_STACK_SIZE,  phys );

    if (!Vcpu->VMXON || !Vcpu->VMCS || !Vcpu->VMMStack)
    {
        DPRINT( "HyperBone: CPU %d: %s: Failed to allocate memory\n", CPU_IDX, __FUNCTION__ );
        goto failed;
    }

    UtilProtectNonpagedMemory( Vcpu->VMXON,    sizeof( VMX_VMCS ), PAGE_READWRITE );
    UtilProtectNonpagedMemory( Vcpu->VMCS,     sizeof( VMX_VMCS ), PAGE_READWRITE );
    UtilProtectNonpagedMemory( Vcpu->VMMStack, KERNEL_STACK_SIZE,  PAGE_READWRITE );

    RtlZeroMemory( Vcpu->VMXON,    sizeof( VMX_VMCS ) );
    RtlZeroMemory( Vcpu->VMCS,     sizeof( VMX_VMCS ) );
    RtlZeroMemory( Vcpu->VMMStack, KERNEL_STACK_SIZE );

    // Attempt to enter VMX root mode on this processor.
    if (VmxEnterRoot( Vcpu ))
    {
        // Initialize the VMCS, both guest and host state.
        VmxSetupVMCS( Vcpu );

        // Setup EPT
        if(g_Data->Features.EPT)
        {
            if (!NT_SUCCESS( EptBuildIdentityMap( &Vcpu->EPT ) ))
            {
                DPRINT( "HyperBone: CPU %d: %s: Failed to build EPT identity map\n", CPU_IDX, __FUNCTION__ );
                goto failedvmxoff;
            }

            EptEnable( Vcpu->EPT.PML4Ptr );
        }

        // Record that VMX is now enabled
        Vcpu->VmxState = VMX_STATE_TRANSITION;

        // Setup various VMCS fields by VmxSetupVmcs. This will cause the
        // processor to jump to the return address of RtlCaptureContext in
        // VmxInitializeCPU, which called us.
        InterlockedIncrement( &g_Data->vcpus );
        int res = __vmx_vmlaunch();
        InterlockedDecrement( &g_Data->vcpus );

        // If we got here, either VMCS setup failed in some way, or the launch
        // did not proceed as planned. Because VmxEnabled is not set to 1, this
        // will correctly register as a failure.
        Vcpu->VmxState = VMX_STATE_OFF;

        DPRINT( "HyperBone: CPU %d: %s: __vmx_vmlaunch failed with result %d\n", CPU_IDX, __FUNCTION__, res );

failedvmxoff:
        __vmx_off();
    }

failed:;
    if (Vcpu->VMXON)
        MmFreeContiguousMemory( Vcpu->VMXON );
    if (Vcpu->VMCS)
        MmFreeContiguousMemory( Vcpu->VMCS );
    if (Vcpu->VMMStack)
        MmFreeContiguousMemory( Vcpu->VMMStack );

    Vcpu->VMXON    = NULL;
    Vcpu->VMCS     = NULL;
    Vcpu->VMMStack = NULL;
}