2020-03-26 14:45:59 +00:00
|
|
|
/*
|
2022-01-10 03:35:45 +00:00
|
|
|
* PROJECT: ReactOS Kernel&Driver SDK
|
|
|
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
|
|
|
* PURPOSE: Hardware Resources Arbiter Library
|
|
|
|
* COPYRIGHT: Copyright 2020 Vadim Galyant <vgal@rambler.ru>
|
2020-03-26 14:45:59 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *******************************************************************/
|
|
|
|
|
2020-04-09 18:37:01 +00:00
|
|
|
#include <ntifs.h>
|
2022-01-10 03:35:45 +00:00
|
|
|
#include <ndk/rtlfuncs.h>
|
2020-03-26 14:45:59 +00:00
|
|
|
#include "arbiter.h"
|
|
|
|
|
2020-04-09 18:37:01 +00:00
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
2020-03-26 14:45:59 +00:00
|
|
|
/* GLOBALS ********************************************************************/
|
|
|
|
|
|
|
|
/* DATA **********************************************************************/
|
|
|
|
|
|
|
|
/* FUNCTIONS ******************************************************************/
|
|
|
|
|
2022-01-10 03:35:45 +00:00
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ArbTestAllocation(
|
|
|
|
_In_ PARBITER_INSTANCE Arbiter,
|
|
|
|
_In_ PLIST_ENTRY ArbitrationList)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ArbRetestAllocation(
|
|
|
|
_In_ PARBITER_INSTANCE Arbiter,
|
|
|
|
_In_ PLIST_ENTRY ArbitrationList)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ArbCommitAllocation(
|
|
|
|
_In_ PARBITER_INSTANCE Arbiter)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ArbRollbackAllocation(
|
|
|
|
_In_ PARBITER_INSTANCE Arbiter)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: the prototype is not correct yet. */
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ArbAddReserved(
|
|
|
|
_In_ PARBITER_INSTANCE Arbiter)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ArbPreprocessEntry(
|
|
|
|
_In_ PARBITER_INSTANCE Arbiter,
|
|
|
|
_Inout_ PARBITER_ALLOCATION_STATE ArbState)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ArbAllocateEntry(
|
|
|
|
_In_ PARBITER_INSTANCE Arbiter,
|
|
|
|
_Inout_ PARBITER_ALLOCATION_STATE ArbState)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
ArbGetNextAllocationRange(
|
|
|
|
_In_ PARBITER_INSTANCE Arbiter,
|
|
|
|
_Inout_ PARBITER_ALLOCATION_STATE ArbState)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
ArbFindSuitableRange(
|
|
|
|
_In_ PARBITER_INSTANCE Arbiter,
|
|
|
|
_Inout_ PARBITER_ALLOCATION_STATE ArbState)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
ArbAddAllocation(
|
|
|
|
_In_ PARBITER_INSTANCE Arbiter,
|
|
|
|
_Inout_ PARBITER_ALLOCATION_STATE ArbState)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
ArbBacktrackAllocation(
|
|
|
|
_In_ PARBITER_INSTANCE Arbiter,
|
|
|
|
_Inout_ PARBITER_ALLOCATION_STATE ArbState)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: the prototype is not correct yet. */
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ArbOverrideConflict(
|
|
|
|
_In_ PARBITER_INSTANCE Arbiter)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ArbBootAllocation(
|
|
|
|
_In_ PARBITER_INSTANCE Arbiter,
|
|
|
|
_In_ PLIST_ENTRY ArbitrationList)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: the prototype is not correct yet. */
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ArbQueryConflict(
|
|
|
|
_In_ PARBITER_INSTANCE Arbiter)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME: the prototype is not correct yet. */
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ArbStartArbiter(
|
|
|
|
_In_ PARBITER_INSTANCE Arbiter)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ArbAddOrdering(
|
|
|
|
_Out_ PARBITER_ORDERING_LIST OrderList,
|
|
|
|
_In_ UINT64 MinimumAddress,
|
|
|
|
_In_ UINT64 MaximumAddress)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ArbPruneOrdering(
|
|
|
|
_Out_ PARBITER_ORDERING_LIST OrderingList,
|
|
|
|
_In_ UINT64 MinimumAddress,
|
|
|
|
_In_ UINT64 MaximumAddress)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ArbInitializeOrderingList(
|
|
|
|
_Out_ PARBITER_ORDERING_LIST OrderList)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
ArbFreeOrderingList(
|
|
|
|
_Out_ PARBITER_ORDERING_LIST OrderList)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
CODE_SEG("PAGE")
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ArbBuildAssignmentOrdering(
|
|
|
|
_Inout_ PARBITER_INSTANCE ArbInstance,
|
|
|
|
_In_ PCWSTR OrderName,
|
|
|
|
_In_ PCWSTR ReservedOrderName,
|
|
|
|
_In_ PARB_TRANSLATE_ORDERING TranslateOrderingFunction)
|
|
|
|
{
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
CODE_SEG("PAGE")
|
2020-03-26 14:45:59 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ArbInitializeArbiterInstance(
|
|
|
|
_Inout_ PARBITER_INSTANCE Arbiter,
|
|
|
|
_In_ PDEVICE_OBJECT BusDeviceObject,
|
|
|
|
_In_ CM_RESOURCE_TYPE ResourceType,
|
|
|
|
_In_ PCWSTR ArbiterName,
|
|
|
|
_In_ PCWSTR OrderName,
|
|
|
|
_In_ PARB_TRANSLATE_ORDERING TranslateOrderingFunction)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
2022-01-10 03:35:45 +00:00
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
DPRINT("ArbInitializeArbiterInstance: '%S'\n", ArbiterName);
|
|
|
|
|
|
|
|
ASSERT(Arbiter->UnpackRequirement != NULL);
|
|
|
|
ASSERT(Arbiter->PackResource != NULL);
|
|
|
|
ASSERT(Arbiter->UnpackResource != NULL);
|
|
|
|
ASSERT(Arbiter->MutexEvent == NULL);
|
|
|
|
ASSERT(Arbiter->Allocation == NULL);
|
|
|
|
ASSERT(Arbiter->PossibleAllocation == NULL);
|
|
|
|
ASSERT(Arbiter->AllocationStack == NULL);
|
|
|
|
|
|
|
|
Arbiter->Signature = ARBITER_SIGNATURE;
|
|
|
|
Arbiter->BusDeviceObject = BusDeviceObject;
|
|
|
|
|
|
|
|
Arbiter->MutexEvent = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_ARBITER);
|
|
|
|
if (!Arbiter->MutexEvent)
|
|
|
|
{
|
|
|
|
DPRINT1("ArbInitializeArbiterInstance: STATUS_INSUFFICIENT_RESOURCES\n");
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
KeInitializeEvent(Arbiter->MutexEvent, SynchronizationEvent, TRUE);
|
|
|
|
|
|
|
|
Arbiter->AllocationStack = ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, TAG_ARB_ALLOCATION);
|
|
|
|
if (!Arbiter->AllocationStack)
|
|
|
|
{
|
|
|
|
DPRINT1("ArbInitializeArbiterInstance: STATUS_INSUFFICIENT_RESOURCES\n");
|
|
|
|
ExFreePoolWithTag(Arbiter->MutexEvent, TAG_ARBITER);
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
Arbiter->AllocationStackMaxSize = PAGE_SIZE;
|
|
|
|
|
|
|
|
Arbiter->Allocation = ExAllocatePoolWithTag(PagedPool, sizeof(RTL_RANGE_LIST), TAG_ARB_RANGE);
|
|
|
|
if (!Arbiter->Allocation)
|
|
|
|
{
|
|
|
|
DPRINT1("ArbInitializeArbiterInstance: STATUS_INSUFFICIENT_RESOURCES\n");
|
|
|
|
ExFreePoolWithTag(Arbiter->AllocationStack, TAG_ARB_ALLOCATION);
|
|
|
|
ExFreePoolWithTag(Arbiter->MutexEvent, TAG_ARBITER);
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
Arbiter->PossibleAllocation = ExAllocatePoolWithTag(PagedPool, sizeof(RTL_RANGE_LIST), TAG_ARB_RANGE);
|
|
|
|
if (!Arbiter->PossibleAllocation)
|
|
|
|
{
|
|
|
|
DPRINT1("ArbInitializeArbiterInstance: STATUS_INSUFFICIENT_RESOURCES\n");
|
|
|
|
ExFreePoolWithTag(Arbiter->Allocation, TAG_ARB_RANGE);
|
|
|
|
ExFreePoolWithTag(Arbiter->AllocationStack, TAG_ARB_ALLOCATION);
|
|
|
|
ExFreePoolWithTag(Arbiter->MutexEvent, TAG_ARBITER);
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
RtlInitializeRangeList(Arbiter->Allocation);
|
|
|
|
RtlInitializeRangeList(Arbiter->PossibleAllocation);
|
|
|
|
|
|
|
|
Arbiter->Name = ArbiterName;
|
|
|
|
Arbiter->ResourceType = ResourceType;
|
|
|
|
Arbiter->TransactionInProgress = FALSE;
|
|
|
|
|
|
|
|
if (!Arbiter->TestAllocation)
|
|
|
|
Arbiter->TestAllocation = ArbTestAllocation;
|
|
|
|
|
|
|
|
if (!Arbiter->RetestAllocation)
|
|
|
|
Arbiter->RetestAllocation = ArbRetestAllocation;
|
|
|
|
|
|
|
|
if (!Arbiter->CommitAllocation)
|
|
|
|
Arbiter->CommitAllocation = ArbCommitAllocation;
|
|
|
|
|
|
|
|
if (!Arbiter->RollbackAllocation)
|
|
|
|
Arbiter->RollbackAllocation = ArbRollbackAllocation;
|
|
|
|
|
|
|
|
if (!Arbiter->AddReserved)
|
|
|
|
Arbiter->AddReserved = ArbAddReserved;
|
|
|
|
|
|
|
|
if (!Arbiter->PreprocessEntry)
|
|
|
|
Arbiter->PreprocessEntry = ArbPreprocessEntry;
|
|
|
|
|
|
|
|
if (!Arbiter->AllocateEntry)
|
|
|
|
Arbiter->AllocateEntry = ArbAllocateEntry;
|
|
|
|
|
|
|
|
if (!Arbiter->GetNextAllocationRange)
|
|
|
|
Arbiter->GetNextAllocationRange = ArbGetNextAllocationRange;
|
|
|
|
|
|
|
|
if (!Arbiter->FindSuitableRange)
|
|
|
|
Arbiter->FindSuitableRange = ArbFindSuitableRange;
|
|
|
|
|
|
|
|
if (!Arbiter->AddAllocation)
|
|
|
|
Arbiter->AddAllocation = ArbAddAllocation;
|
|
|
|
|
|
|
|
if (!Arbiter->BacktrackAllocation)
|
|
|
|
Arbiter->BacktrackAllocation = ArbBacktrackAllocation;
|
|
|
|
|
|
|
|
if (!Arbiter->OverrideConflict)
|
|
|
|
Arbiter->OverrideConflict = ArbOverrideConflict;
|
|
|
|
|
|
|
|
if (!Arbiter->BootAllocation)
|
|
|
|
Arbiter->BootAllocation = ArbBootAllocation;
|
|
|
|
|
|
|
|
if (!Arbiter->QueryConflict)
|
|
|
|
Arbiter->QueryConflict = ArbQueryConflict;
|
|
|
|
|
|
|
|
if (!Arbiter->StartArbiter)
|
|
|
|
Arbiter->StartArbiter = ArbStartArbiter;
|
|
|
|
|
|
|
|
Status = ArbBuildAssignmentOrdering(Arbiter, OrderName, OrderName, TranslateOrderingFunction);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
DPRINT1("ArbInitializeArbiterInstance: Status %X\n", Status);
|
2020-03-26 14:45:59 +00:00
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|