1 /*
2 * PROJECT: ReactOS Kernel&Driver SDK
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Hardware Resources Arbiter Library
5 * COPYRIGHT: Copyright 2020 Vadim Galyant <vgal@rambler.ru>
6 */
7
8 /* INCLUDES *******************************************************************/
9
10 #include <ntifs.h>
11 #include <ndk/rtlfuncs.h>
12 #include "arbiter.h"
13
14 #define NDEBUG
15 #include <debug.h>
16
17 /* GLOBALS ********************************************************************/
18
19 /* DATA **********************************************************************/
20
21 /* FUNCTIONS ******************************************************************/
22
23 CODE_SEG("PAGE")
24 NTSTATUS
25 NTAPI
ArbTestAllocation(_In_ PARBITER_INSTANCE Arbiter,_In_ PLIST_ENTRY ArbitrationList)26 ArbTestAllocation(
27 _In_ PARBITER_INSTANCE Arbiter,
28 _In_ PLIST_ENTRY ArbitrationList)
29 {
30 PAGED_CODE();
31
32 UNIMPLEMENTED;
33 return STATUS_NOT_IMPLEMENTED;
34 }
35
36 CODE_SEG("PAGE")
37 NTSTATUS
38 NTAPI
ArbRetestAllocation(_In_ PARBITER_INSTANCE Arbiter,_In_ PLIST_ENTRY ArbitrationList)39 ArbRetestAllocation(
40 _In_ PARBITER_INSTANCE Arbiter,
41 _In_ PLIST_ENTRY ArbitrationList)
42 {
43 PAGED_CODE();
44
45 UNIMPLEMENTED;
46 return STATUS_NOT_IMPLEMENTED;
47 }
48
49 CODE_SEG("PAGE")
50 NTSTATUS
51 NTAPI
ArbCommitAllocation(_In_ PARBITER_INSTANCE Arbiter)52 ArbCommitAllocation(
53 _In_ PARBITER_INSTANCE Arbiter)
54 {
55 PAGED_CODE();
56
57 UNIMPLEMENTED;
58 return STATUS_NOT_IMPLEMENTED;
59 }
60
61 CODE_SEG("PAGE")
62 NTSTATUS
63 NTAPI
ArbRollbackAllocation(_In_ PARBITER_INSTANCE Arbiter)64 ArbRollbackAllocation(
65 _In_ PARBITER_INSTANCE Arbiter)
66 {
67 PAGED_CODE();
68
69 UNIMPLEMENTED;
70 return STATUS_NOT_IMPLEMENTED;
71 }
72
73 /* FIXME: the prototype is not correct yet. */
74 CODE_SEG("PAGE")
75 NTSTATUS
76 NTAPI
ArbAddReserved(_In_ PARBITER_INSTANCE Arbiter)77 ArbAddReserved(
78 _In_ PARBITER_INSTANCE Arbiter)
79 {
80 PAGED_CODE();
81
82 UNIMPLEMENTED;
83 return STATUS_NOT_IMPLEMENTED;
84 }
85
86 CODE_SEG("PAGE")
87 NTSTATUS
88 NTAPI
ArbPreprocessEntry(_In_ PARBITER_INSTANCE Arbiter,_Inout_ PARBITER_ALLOCATION_STATE ArbState)89 ArbPreprocessEntry(
90 _In_ PARBITER_INSTANCE Arbiter,
91 _Inout_ PARBITER_ALLOCATION_STATE ArbState)
92 {
93 PAGED_CODE();
94
95 return STATUS_SUCCESS;
96 }
97
98 CODE_SEG("PAGE")
99 NTSTATUS
100 NTAPI
ArbAllocateEntry(_In_ PARBITER_INSTANCE Arbiter,_Inout_ PARBITER_ALLOCATION_STATE ArbState)101 ArbAllocateEntry(
102 _In_ PARBITER_INSTANCE Arbiter,
103 _Inout_ PARBITER_ALLOCATION_STATE ArbState)
104 {
105 PAGED_CODE();
106
107 UNIMPLEMENTED;
108 return STATUS_NOT_IMPLEMENTED;
109 }
110
111 CODE_SEG("PAGE")
112 BOOLEAN
113 NTAPI
ArbGetNextAllocationRange(_In_ PARBITER_INSTANCE Arbiter,_Inout_ PARBITER_ALLOCATION_STATE ArbState)114 ArbGetNextAllocationRange(
115 _In_ PARBITER_INSTANCE Arbiter,
116 _Inout_ PARBITER_ALLOCATION_STATE ArbState)
117 {
118 PAGED_CODE();
119
120 UNIMPLEMENTED;
121 return FALSE;
122 }
123
124 CODE_SEG("PAGE")
125 BOOLEAN
126 NTAPI
ArbFindSuitableRange(_In_ PARBITER_INSTANCE Arbiter,_Inout_ PARBITER_ALLOCATION_STATE ArbState)127 ArbFindSuitableRange(
128 _In_ PARBITER_INSTANCE Arbiter,
129 _Inout_ PARBITER_ALLOCATION_STATE ArbState)
130 {
131 PAGED_CODE();
132
133 UNIMPLEMENTED;
134 return FALSE;
135 }
136
137 CODE_SEG("PAGE")
138 VOID
139 NTAPI
ArbAddAllocation(_In_ PARBITER_INSTANCE Arbiter,_Inout_ PARBITER_ALLOCATION_STATE ArbState)140 ArbAddAllocation(
141 _In_ PARBITER_INSTANCE Arbiter,
142 _Inout_ PARBITER_ALLOCATION_STATE ArbState)
143 {
144 PAGED_CODE();
145
146 UNIMPLEMENTED;
147 }
148
149 CODE_SEG("PAGE")
150 VOID
151 NTAPI
ArbBacktrackAllocation(_In_ PARBITER_INSTANCE Arbiter,_Inout_ PARBITER_ALLOCATION_STATE ArbState)152 ArbBacktrackAllocation(
153 _In_ PARBITER_INSTANCE Arbiter,
154 _Inout_ PARBITER_ALLOCATION_STATE ArbState)
155 {
156 PAGED_CODE();
157
158 UNIMPLEMENTED;
159 }
160
161 /* FIXME: the prototype is not correct yet. */
162 CODE_SEG("PAGE")
163 NTSTATUS
164 NTAPI
ArbOverrideConflict(_In_ PARBITER_INSTANCE Arbiter)165 ArbOverrideConflict(
166 _In_ PARBITER_INSTANCE Arbiter)
167 {
168 PAGED_CODE();
169
170 UNIMPLEMENTED;
171 return STATUS_NOT_IMPLEMENTED;
172 }
173
174 CODE_SEG("PAGE")
175 NTSTATUS
176 NTAPI
ArbBootAllocation(_In_ PARBITER_INSTANCE Arbiter,_In_ PLIST_ENTRY ArbitrationList)177 ArbBootAllocation(
178 _In_ PARBITER_INSTANCE Arbiter,
179 _In_ PLIST_ENTRY ArbitrationList)
180 {
181 PAGED_CODE();
182
183 UNIMPLEMENTED;
184 return STATUS_NOT_IMPLEMENTED;
185 }
186
187 /* FIXME: the prototype is not correct yet. */
188 CODE_SEG("PAGE")
189 NTSTATUS
190 NTAPI
ArbQueryConflict(_In_ PARBITER_INSTANCE Arbiter)191 ArbQueryConflict(
192 _In_ PARBITER_INSTANCE Arbiter)
193 {
194 PAGED_CODE();
195
196 UNIMPLEMENTED;
197 return STATUS_NOT_IMPLEMENTED;
198 }
199
200 /* FIXME: the prototype is not correct yet. */
201 CODE_SEG("PAGE")
202 NTSTATUS
203 NTAPI
ArbStartArbiter(_In_ PARBITER_INSTANCE Arbiter)204 ArbStartArbiter(
205 _In_ PARBITER_INSTANCE Arbiter)
206 {
207 PAGED_CODE();
208
209 UNIMPLEMENTED;
210 return STATUS_NOT_IMPLEMENTED;
211 }
212
213 CODE_SEG("PAGE")
214 NTSTATUS
215 NTAPI
ArbAddOrdering(_Out_ PARBITER_ORDERING_LIST OrderList,_In_ UINT64 MinimumAddress,_In_ UINT64 MaximumAddress)216 ArbAddOrdering(
217 _Out_ PARBITER_ORDERING_LIST OrderList,
218 _In_ UINT64 MinimumAddress,
219 _In_ UINT64 MaximumAddress)
220 {
221 PAGED_CODE();
222
223 UNIMPLEMENTED;
224 return STATUS_NOT_IMPLEMENTED;
225 }
226
227 CODE_SEG("PAGE")
228 NTSTATUS
229 NTAPI
ArbPruneOrdering(_Out_ PARBITER_ORDERING_LIST OrderingList,_In_ UINT64 MinimumAddress,_In_ UINT64 MaximumAddress)230 ArbPruneOrdering(
231 _Out_ PARBITER_ORDERING_LIST OrderingList,
232 _In_ UINT64 MinimumAddress,
233 _In_ UINT64 MaximumAddress)
234 {
235 PAGED_CODE();
236
237 UNIMPLEMENTED;
238 return STATUS_NOT_IMPLEMENTED;
239 }
240
241 CODE_SEG("PAGE")
242 NTSTATUS
243 NTAPI
ArbInitializeOrderingList(_Out_ PARBITER_ORDERING_LIST OrderList)244 ArbInitializeOrderingList(
245 _Out_ PARBITER_ORDERING_LIST OrderList)
246 {
247 PAGED_CODE();
248
249 UNIMPLEMENTED;
250 return STATUS_NOT_IMPLEMENTED;
251 }
252
253 CODE_SEG("PAGE")
254 VOID
255 NTAPI
ArbFreeOrderingList(_Out_ PARBITER_ORDERING_LIST OrderList)256 ArbFreeOrderingList(
257 _Out_ PARBITER_ORDERING_LIST OrderList)
258 {
259 PAGED_CODE();
260
261 UNIMPLEMENTED;
262 }
263
264 CODE_SEG("PAGE")
265 NTSTATUS
266 NTAPI
ArbBuildAssignmentOrdering(_Inout_ PARBITER_INSTANCE ArbInstance,_In_ PCWSTR OrderName,_In_ PCWSTR ReservedOrderName,_In_ PARB_TRANSLATE_ORDERING TranslateOrderingFunction)267 ArbBuildAssignmentOrdering(
268 _Inout_ PARBITER_INSTANCE ArbInstance,
269 _In_ PCWSTR OrderName,
270 _In_ PCWSTR ReservedOrderName,
271 _In_ PARB_TRANSLATE_ORDERING TranslateOrderingFunction)
272 {
273 PAGED_CODE();
274
275 UNIMPLEMENTED;
276 return STATUS_SUCCESS;
277 }
278
279 CODE_SEG("PAGE")
280 NTSTATUS
281 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)282 ArbInitializeArbiterInstance(
283 _Inout_ PARBITER_INSTANCE Arbiter,
284 _In_ PDEVICE_OBJECT BusDeviceObject,
285 _In_ CM_RESOURCE_TYPE ResourceType,
286 _In_ PCWSTR ArbiterName,
287 _In_ PCWSTR OrderName,
288 _In_ PARB_TRANSLATE_ORDERING TranslateOrderingFunction)
289 {
290 NTSTATUS Status;
291
292 PAGED_CODE();
293
294 DPRINT("ArbInitializeArbiterInstance: '%S'\n", ArbiterName);
295
296 ASSERT(Arbiter->UnpackRequirement != NULL);
297 ASSERT(Arbiter->PackResource != NULL);
298 ASSERT(Arbiter->UnpackResource != NULL);
299 ASSERT(Arbiter->MutexEvent == NULL);
300 ASSERT(Arbiter->Allocation == NULL);
301 ASSERT(Arbiter->PossibleAllocation == NULL);
302 ASSERT(Arbiter->AllocationStack == NULL);
303
304 Arbiter->Signature = ARBITER_SIGNATURE;
305 Arbiter->BusDeviceObject = BusDeviceObject;
306
307 Arbiter->MutexEvent = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_ARBITER);
308 if (!Arbiter->MutexEvent)
309 {
310 DPRINT1("ArbInitializeArbiterInstance: STATUS_INSUFFICIENT_RESOURCES\n");
311 return STATUS_INSUFFICIENT_RESOURCES;
312 }
313
314 KeInitializeEvent(Arbiter->MutexEvent, SynchronizationEvent, TRUE);
315
316 Arbiter->AllocationStack = ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, TAG_ARB_ALLOCATION);
317 if (!Arbiter->AllocationStack)
318 {
319 DPRINT1("ArbInitializeArbiterInstance: STATUS_INSUFFICIENT_RESOURCES\n");
320 ExFreePoolWithTag(Arbiter->MutexEvent, TAG_ARBITER);
321 return STATUS_INSUFFICIENT_RESOURCES;
322 }
323
324 Arbiter->AllocationStackMaxSize = PAGE_SIZE;
325
326 Arbiter->Allocation = ExAllocatePoolWithTag(PagedPool, sizeof(RTL_RANGE_LIST), TAG_ARB_RANGE);
327 if (!Arbiter->Allocation)
328 {
329 DPRINT1("ArbInitializeArbiterInstance: STATUS_INSUFFICIENT_RESOURCES\n");
330 ExFreePoolWithTag(Arbiter->AllocationStack, TAG_ARB_ALLOCATION);
331 ExFreePoolWithTag(Arbiter->MutexEvent, TAG_ARBITER);
332 return STATUS_INSUFFICIENT_RESOURCES;
333 }
334
335 Arbiter->PossibleAllocation = ExAllocatePoolWithTag(PagedPool, sizeof(RTL_RANGE_LIST), TAG_ARB_RANGE);
336 if (!Arbiter->PossibleAllocation)
337 {
338 DPRINT1("ArbInitializeArbiterInstance: STATUS_INSUFFICIENT_RESOURCES\n");
339 ExFreePoolWithTag(Arbiter->Allocation, TAG_ARB_RANGE);
340 ExFreePoolWithTag(Arbiter->AllocationStack, TAG_ARB_ALLOCATION);
341 ExFreePoolWithTag(Arbiter->MutexEvent, TAG_ARBITER);
342 return STATUS_INSUFFICIENT_RESOURCES;
343 }
344
345 RtlInitializeRangeList(Arbiter->Allocation);
346 RtlInitializeRangeList(Arbiter->PossibleAllocation);
347
348 Arbiter->Name = ArbiterName;
349 Arbiter->ResourceType = ResourceType;
350 Arbiter->TransactionInProgress = FALSE;
351
352 if (!Arbiter->TestAllocation)
353 Arbiter->TestAllocation = ArbTestAllocation;
354
355 if (!Arbiter->RetestAllocation)
356 Arbiter->RetestAllocation = ArbRetestAllocation;
357
358 if (!Arbiter->CommitAllocation)
359 Arbiter->CommitAllocation = ArbCommitAllocation;
360
361 if (!Arbiter->RollbackAllocation)
362 Arbiter->RollbackAllocation = ArbRollbackAllocation;
363
364 if (!Arbiter->AddReserved)
365 Arbiter->AddReserved = ArbAddReserved;
366
367 if (!Arbiter->PreprocessEntry)
368 Arbiter->PreprocessEntry = ArbPreprocessEntry;
369
370 if (!Arbiter->AllocateEntry)
371 Arbiter->AllocateEntry = ArbAllocateEntry;
372
373 if (!Arbiter->GetNextAllocationRange)
374 Arbiter->GetNextAllocationRange = ArbGetNextAllocationRange;
375
376 if (!Arbiter->FindSuitableRange)
377 Arbiter->FindSuitableRange = ArbFindSuitableRange;
378
379 if (!Arbiter->AddAllocation)
380 Arbiter->AddAllocation = ArbAddAllocation;
381
382 if (!Arbiter->BacktrackAllocation)
383 Arbiter->BacktrackAllocation = ArbBacktrackAllocation;
384
385 if (!Arbiter->OverrideConflict)
386 Arbiter->OverrideConflict = ArbOverrideConflict;
387
388 if (!Arbiter->BootAllocation)
389 Arbiter->BootAllocation = ArbBootAllocation;
390
391 if (!Arbiter->QueryConflict)
392 Arbiter->QueryConflict = ArbQueryConflict;
393
394 if (!Arbiter->StartArbiter)
395 Arbiter->StartArbiter = ArbStartArbiter;
396
397 Status = ArbBuildAssignmentOrdering(Arbiter, OrderName, OrderName, TranslateOrderingFunction);
398 if (NT_SUCCESS(Status))
399 {
400 return STATUS_SUCCESS;
401 }
402
403 DPRINT1("ArbInitializeArbiterInstance: Status %X\n", Status);
404
405 return Status;
406 }
407