ReactOS 0.4.17-dev-804-g023d8af
arbmem.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: PnP manager Root Memory Arbiter
5 * COPYRIGHT: Copyright 2025-2026 Justin Miller <justin.miller@reactos.org>
6 */
7
8/* INCLUDES *****************************************************************/
9
10#include <ntoskrnl.h>
11#define NDEBUG
12#include <debug.h>
13
14/* GLOBALS *******************************************************************/
15
17
25
31
32/* The last address a card that only wires up 24 address lines can reach. */
33#define MEMORY_24_BIT_MAX_ADDRESS 0xFFFFFF
34
35/* FUNCTIONS *****************************************************************/
36
63static
66 _In_ UCHAR SourceType,
69 _Out_ PUCHAR TranslatedType)
70{
72
73 PAGED_CODE();
74
75 if (SourceType == CmResourceTypeMemory || SourceType == CmResourceTypeMemoryLarge)
76 AddressSpace = 0; /* System memory */
77 else if (SourceType == CmResourceTypePort)
78 AddressSpace = 1; /* I/O port space */
79 else
81
84
85 /* The HAL reports back the space it landed in; only these two are expected. */
86 if (AddressSpace == 1)
87 {
88 *TranslatedType = CmResourceTypePort;
89 }
90 else if (AddressSpace == 0)
91 {
92 *TranslatedType = (SourceType == CmResourceTypeMemoryLarge)
95 }
96 else
97 {
99 }
100
101 return STATUS_SUCCESS;
102}
103
133static
135NTAPI
137 _In_ PIO_RESOURCE_DESCRIPTOR IoDescriptor,
138 _Out_ PUINT64 OutMinimumAddress,
139 _Out_ PUINT64 OutMaximumAddress,
140 _Out_ PUINT64 OutLength,
141 _Out_ PUINT64 OutAlignment)
142{
143 PAGED_CODE();
144
145 *OutLength = RtlIoDecodeMemIoResource(IoDescriptor,
146 OutAlignment,
147 OutMinimumAddress,
148 OutMaximumAddress);
149
150 if (*OutAlignment == 0)
151 *OutAlignment = 1;
152
153 if (IoDescriptor->Type == CmResourceTypeMemory &&
154 (IoDescriptor->Flags & CM_RESOURCE_MEMORY_24) &&
155 *OutMaximumAddress > MEMORY_24_BIT_MAX_ADDRESS)
156 {
157 *OutMaximumAddress = MEMORY_24_BIT_MAX_ADDRESS;
158 }
159
160 return STATUS_SUCCESS;
161}
162
183static
185NTAPI
187 _In_ PIO_RESOURCE_DESCRIPTOR IoDescriptor,
190{
191 PAGED_CODE();
192
193 CmDescriptor->Type = IoDescriptor->Type;
194 CmDescriptor->Flags = IoDescriptor->Flags;
195 CmDescriptor->ShareDisposition = IoDescriptor->ShareDisposition;
196
197 CmDescriptor->u.Generic.Start.QuadPart = Start;
198 CmDescriptor->u.Generic.Length = IoDescriptor->u.Generic.Length;
199
200 return STATUS_SUCCESS;
201}
202
222static
224NTAPI
228 _Out_ PUINT64 OutLength)
229{
230 PAGED_CODE();
231
232 *OutLength = RtlCmDecodeMemIoResource(CmDescriptor, Start);
233
234 return STATUS_SUCCESS;
235}
236
257static
258INT32
259NTAPI
261 _In_ PIO_RESOURCE_DESCRIPTOR IoDescriptor)
262{
264 UINT64 Minimum, Maximum, AlignedMinimum;
265 UINT64 Span, Placements;
266
267 PAGED_CODE();
268
269 Length = RtlIoDecodeMemIoResource(IoDescriptor, &Alignment, &Minimum, &Maximum);
270
271 if (Alignment == 0)
272 Alignment = 1;
273
274 /* Round the window's base up to the first address the device can sit at. */
275 AlignedMinimum = (Minimum + Alignment - 1) & ~(Alignment - 1);
276 if (AlignedMinimum < Minimum || AlignedMinimum > Maximum)
277 return -1;
278
279 /* Count in addresses above the base, so a full-width window cannot overflow. */
280 Span = Maximum - AlignedMinimum;
281
282 if (Length != 0)
283 {
284 if (Length - 1 > Span)
285 return -1;
286
287 Span -= Length - 1;
288 }
289
290 Placements = Span / Alignment + 1;
291 return (INT32)min(Placements, MAXLONG);
292}
293
313static
315NTAPI
317 _Out_ PIO_RESOURCE_DESCRIPTOR OutIoDescriptor,
318 _In_ PIO_RESOURCE_DESCRIPTOR IoDescriptor)
319{
320 UCHAR SourceType;
321 UCHAR MinimumType;
323
324 PAGED_CODE();
325
326 *OutIoDescriptor = *IoDescriptor;
327
328 SourceType = IoDescriptor->Type;
329 if (SourceType != CmResourceTypePort &&
330 SourceType != CmResourceTypeMemory &&
331 SourceType != CmResourceTypeMemoryLarge)
332 {
333 return STATUS_SUCCESS;
334 }
335
336 MinimumType = SourceType;
337 MaximumType = SourceType;
338
340 IoDescriptor->u.Generic.MinimumAddress,
341 &OutIoDescriptor->u.Generic.MinimumAddress,
342 &MinimumType)) ||
344 IoDescriptor->u.Generic.MaximumAddress,
345 &OutIoDescriptor->u.Generic.MaximumAddress,
346 &MaximumType)))
347 {
348 OutIoDescriptor->Type = CmResourceTypeNull;
349 }
350 else
351 {
352 OutIoDescriptor->Type = MaximumType;
353 }
354
355 return STATUS_SUCCESS;
356}
357
381static
383NTAPI
385 _In_ PARBITER_INSTANCE Arbiter,
387{
388 PAGED_CODE();
389
390 if (ArbState->Entry != NULL && (ArbState->Entry->Flags & ARBITER_FLAG_BOOT_CONFIG))
391 ArbState->RangeAvailableAttributes |= ARBITER_RANGE_BOOT_ALLOCATED;
392
393 return ArbiterLibFindSuitableRange(Arbiter, ArbState);
394}
395
414NTAPI
416{
418
419 PAGED_CODE();
420
421 IopRootMemArbiter.Name = L"RootMemory";
427
429 NULL,
432 L"Root",
434 if (!NT_SUCCESS(Status))
435 {
436 DPRINT1("IopArbMemInitialize: Failed with %X\n", Status);
437 return Status;
438 }
439
441 if (!NT_SUCCESS(Status))
442 {
443 DPRINT1("IopArbMemInitialize: Reserving page 0 failed with %X\n", Status);
444 }
445
446 return Status;
447}
#define PAGED_CODE()
static _Out_opt_ PULONGLONG _Out_opt_ PULONGLONG MinimumAddress
static _Out_opt_ PULONGLONG Start
static _Out_opt_ PULONGLONG _Out_opt_ PULONGLONG _Out_opt_ PULONGLONG MaximumAddress
unsigned char BOOLEAN
Definition: actypes.h:127
COMPILER_DEPENDENT_UINT64 UINT64
Definition: actypes.h:131
NTSTATUS NTAPI ArbiterLibInitializeInstance(_Inout_ PARBITER_INSTANCE Arbiter, _In_ PDEVICE_OBJECT BusDeviceObject, _In_ CM_RESOURCE_TYPE ResourceType, _In_ PCWSTR ArbiterName, _In_ PCWSTR OrderName, _In_ PARB_TRANSLATE_ORDERING TranslateOrderingFunction)
Definition: arbiter.c:237
BOOLEAN NTAPI ArbiterLibFindSuitableRange(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
Finds a free range of the current candidate window in the arbiter's tentative allocation list.
Definition: range.c:520
#define ARBITER_RANGE_BOOT_ALLOCATED
Definition: arbiter.h:46
static NTSTATUS IopArbMemTranslateAddress(_In_ UCHAR SourceType, _In_ PHYSICAL_ADDRESS SourceAddress, _Out_ PPHYSICAL_ADDRESS TranslatedAddress, _Out_ PUCHAR TranslatedType)
Translates one bus-relative address to a system-physical one on the ISA bus, and reports the space it...
Definition: arbmem.c:65
#define MEMORY_24_BIT_MAX_ADDRESS
Definition: arbmem.c:33
static NTSTATUS NTAPI IopArbMemPackResource(_In_ PIO_RESOURCE_DESCRIPTOR IoDescriptor, _In_ UINT64 Start, _Out_ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor)
Materialises the arbiter's chosen placement as an assigned CM descriptor. The PackResource callback o...
Definition: arbmem.c:186
static NTSTATUS NTAPI IopArbMemTranslateOrdering(_Out_ PIO_RESOURCE_DESCRIPTOR OutIoDescriptor, _In_ PIO_RESOURCE_DESCRIPTOR IoDescriptor)
Translates one registry allocation-ordering window from the bus-relative addresses it is written in i...
Definition: arbmem.c:316
ULONGLONG NTAPI RtlIoDecodeMemIoResource(_In_ PIO_RESOURCE_DESCRIPTOR Descriptor, _Out_opt_ PULONGLONG Alignment, _Out_opt_ PULONGLONG MinimumAddress, _Out_opt_ PULONGLONG MaximumAddress)
Definition: memres.c:79
static NTSTATUS NTAPI IopArbMemUnpackRequirements(_In_ PIO_RESOURCE_DESCRIPTOR IoDescriptor, _Out_ PUINT64 OutMinimumAddress, _Out_ PUINT64 OutMaximumAddress, _Out_ PUINT64 OutLength, _Out_ PUINT64 OutAlignment)
Extracts the placement window from one memory requirement. The UnpackRequirement callback of the Root...
Definition: arbmem.c:136
ULONGLONG NTAPI RtlCmDecodeMemIoResource(_In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor, _Out_opt_ PULONGLONG Start)
Definition: memres.c:58
ARBITER_INSTANCE IopRootMemArbiter
Definition: pnpinit.c:26
static NTSTATUS NTAPI IopArbMemUnpackResource(_In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor, _Out_ PUINT64 Start, _Out_ PUINT64 OutLength)
Reads the placement back out of an already-assigned descriptor (a firmware boot configuration,...
Definition: arbmem.c:225
static BOOLEAN NTAPI IopArbMemFindSuitableRange(_In_ PARBITER_INSTANCE Arbiter, _Inout_ PARBITER_ALLOCATION_STATE ArbState)
The Root Memory arbiter's FindSuitableRange: the engine search, incremented for a device asking to ke...
Definition: arbmem.c:384
static INT32 NTAPI IopArbMemScoreRequirement(_In_ PIO_RESOURCE_DESCRIPTOR IoDescriptor)
Scores how constrained a requirement is: the number of distinct aligned addresses it could be placed ...
Definition: arbmem.c:260
NTSTATUS NTAPI IopArbMemInitialize(VOID)
Initialize the RootMemoryArbiter.
Definition: arbmem.c:415
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
unsigned __int64 * PUINT64
Definition: basetsd.h:181
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define L(x)
Definition: resources.c:13
union Alignment_ Alignment
Status
Definition: gdiplustypes.h:24
BOOLEAN NTAPI HalTranslateBusAddress(IN INTERFACE_TYPE InterfaceType, IN ULONG BusNumber, IN PHYSICAL_ADDRESS BusAddress, IN OUT PULONG AddressSpace, OUT PPHYSICAL_ADDRESS TranslatedAddress)
Definition: bus.c:140
#define ULL(a, b)
Definition: format_msg.c:27
#define min(a, b)
Definition: monoChain.cc:55
#define CM_RESOURCE_MEMORY_24
Definition: cmtypes.h:127
NTSYSAPI NTSTATUS NTAPI RtlAddRange(_Inout_ PRTL_RANGE_LIST RangeList, _In_ ULONGLONG Start, _In_ ULONGLONG End, _In_ UCHAR Attributes, _In_ ULONG Flags, _In_opt_ PVOID UserData, _In_opt_ PVOID Owner)
#define _Out_opt_
Definition: no_sal2.h:214
#define _Inout_
Definition: no_sal2.h:162
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:395
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define CmResourceTypeNull
Definition: restypes.h:103
#define CmResourceTypeMemory
Definition: restypes.h:106
@ Isa
Definition: restypes.h:122
#define CmResourceTypePort
Definition: restypes.h:104
@ MaximumType
Definition: arc.h:154
#define STATUS_SUCCESS
Definition: shellext.h:65
PARB_UNPACK_RESOURCE UnpackResource
Definition: arbiter.h:302
PARB_SCORE_REQUIREMENT ScoreRequirement
Definition: arbiter.h:303
PRTL_RANGE_LIST Allocation
Definition: arbiter.h:292
PARB_UNPACK_REQUIREMENT UnpackRequirement
Definition: arbiter.h:300
PARB_FIND_SUITABLE_RANGE FindSuitableRange
Definition: arbiter.h:316
PARB_PACK_RESOURCE PackResource
Definition: arbiter.h:301
int32_t INT32
Definition: typedefs.h:58
unsigned char UCHAR
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
uint64_t ULONGLONG
Definition: typedefs.h:67
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define MAXLONG
Definition: umtypes.h:116
_Must_inspect_result_ _In_ WDFIORESLIST _In_ PIO_RESOURCE_DESCRIPTOR Descriptor
Definition: wdfresource.h:342
#define CmResourceTypeMemoryLarge
Definition: cmtypes.h:231
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG _Out_ PPHYSICAL_ADDRESS TranslatedAddress
Definition: iofuncs.h:2275
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2274
#define ARBITER_FLAG_BOOT_CONFIG
Definition: iotypes.h:4631
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS SourceAddress
Definition: iotypes.h:1127