1 /*
2 * Copyright (c) 1998-2021 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 *
30 */
31
32 #define TEST_HEADERS 0
33 #define IOKIT_ENABLE_SHARED_PTR
34
35 #if TEST_HEADERS
36
37 #include <libkern/OSByteOrder.h>
38 #include <libkern/c++/OSArray.h>
39 #include <libkern/c++/OSAllocation.h>
40 #include <libkern/c++/OSBoolean.h>
41 #include <libkern/c++/OSBoundedArray.h>
42 #include <libkern/c++/OSBoundedArrayRef.h>
43 #include <libkern/c++/OSBoundedPtr.h>
44 #include <libkern/c++/OSCollection.h>
45 #include <libkern/c++/OSCollectionIterator.h>
46 #include <libkern/c++/OSContainers.h>
47 #include <libkern/c++/OSCPPDebug.h>
48 #include <libkern/c++/OSData.h>
49 #include <libkern/c++/OSDictionary.h>
50 #include <libkern/c++/OSEndianTypes.h>
51 #include <libkern/c++/OSIterator.h>
52 #include <libkern/c++/OSKext.h>
53 #include <libkern/c++/OSLib.h>
54 #include <libkern/c++/OSMetaClass.h>
55 #include <libkern/c++/OSNumber.h>
56 #include <libkern/c++/OSObject.h>
57 #include <libkern/c++/OSOrderedSet.h>
58 #include <libkern/c++/OSSerialize.h>
59 #include <libkern/c++/OSSet.h>
60 #include <libkern/c++/OSSharedPtr.h>
61 #include <libkern/c++/OSString.h>
62 #include <libkern/c++/OSSymbol.h>
63 #include <libkern/c++/OSUnserialize.h>
64 #include <libkern/c++/OSValueObject.h>
65 #include <libkern/crypto/aes.h>
66 #include <libkern/crypto/aesxts.h>
67 #include <libkern/crypto/crypto_internal.h>
68 #include <libkern/crypto/des.h>
69 #include <libkern/crypto/md5.h>
70 #include <libkern/crypto/register_crypto.h>
71 #include <libkern/crypto/sha1.h>
72 #include <libkern/crypto/sha2.h>
73 #include <libkern/kernel_mach_header.h>
74 #include <libkern/kext_request_keys.h>
75 #include <libkern/kxld.h>
76 #include <libkern/kxld_types.h>
77 #include <libkern/locks.h>
78 #include <libkern/mkext.h>
79 #include <libkern/OSAtomic.h>
80 #include <libkern/OSBase.h>
81 #include <libkern/OSDebug.h>
82 #include <libkern/OSKextLib.h>
83 #include <libkern/OSKextLibPrivate.h>
84 #include <libkern/OSReturn.h>
85 #include <libkern/OSSerializeBinary.h>
86 #include <libkern/OSTypes.h>
87 #include <libkern/prelink.h>
88 #include <libkern/stack_protector.h>
89 #include <libkern/sysctl.h>
90 #include <libkern/tree.h>
91 #include <libkern/zconf.h>
92 #include <libkern/zlib.h>
93
94 #include <IOKit/AppleKeyStoreInterface.h>
95 #include <IOKit/assert.h>
96 #include <IOKit/IOBSD.h>
97 #include <IOKit/IOBufferMemoryDescriptor.h>
98 #include <IOKit/IOCatalogue.h>
99 #include <IOKit/IOCommand.h>
100 #include <IOKit/IOCommandGate.h>
101 #include <IOKit/IOCommandPool.h>
102 #include <IOKit/IOCommandQueue.h>
103 #include <IOKit/IOConditionLock.h>
104 #include <IOKit/IOCPU.h>
105 //#include <IOKit/IODataQueue.h>
106 #include <IOKit/IODataQueueShared.h>
107 #include <IOKit/IODeviceMemory.h>
108 #include <IOKit/IODeviceTreeSupport.h>
109 #include <IOKit/IODMACommand.h>
110 #include <IOKit/IODMAController.h>
111 #include <IOKit/IODMAEventSource.h>
112 #include <IOKit/IOEventSource.h>
113 #include <IOKit/IOFilterInterruptEventSource.h>
114 #include <IOKit/IOHibernatePrivate.h>
115 #include <IOKit/IOInterleavedMemoryDescriptor.h>
116 #include <IOKit/IOInterruptAccounting.h>
117 #include <IOKit/IOInterruptAccountingPrivate.h>
118 #include <IOKit/IOInterruptController.h>
119 #include <IOKit/IOInterruptEventSource.h>
120 #include <IOKit/IOInterrupts.h>
121 #include <IOKit/IOKernelReporters.h>
122 #include <IOKit/IOKernelReportStructs.h>
123 #include <IOKit/IOKitDebug.h>
124 #include <IOKit/IOKitDiagnosticsUserClient.h>
125 #include <IOKit/IOKitKeys.h>
126 #include <IOKit/IOKitKeysPrivate.h>
127 #include <IOKit/IOKitServer.h>
128 #include <IOKit/IOLib.h>
129 #include <IOKit/IOLocks.h>
130 #include <IOKit/IOLocksPrivate.h>
131 #include <IOKit/IOMapper.h>
132 #include <IOKit/IOMemoryCursor.h>
133 #include <IOKit/IOMemoryDescriptor.h>
134 #include <IOKit/IOMessage.h>
135 #include <IOKit/IOMultiMemoryDescriptor.h>
136 #include <IOKit/IONotifier.h>
137 #include <IOKit/IONVRAM.h>
138 #include <IOKit/IOPlatformExpert.h>
139 #include <IOKit/IOPolledInterface.h>
140 #include <IOKit/IORangeAllocator.h>
141 #include <IOKit/IORegistryEntry.h>
142 #include <IOKit/IOReportMacros.h>
143 #include <IOKit/IOReportTypes.h>
144 #include <IOKit/IOReturn.h>
145 #include <IOKit/IOService.h>
146 #include <IOKit/IOServicePM.h>
147 #include <IOKit/IOSharedDataQueue.h>
148 #include <IOKit/IOSharedLock.h>
149 #include <IOKit/IOStatistics.h>
150 #include <IOKit/IOStatisticsPrivate.h>
151 #include <IOKit/IOSubMemoryDescriptor.h>
152 #include <IOKit/IOSyncer.h>
153 #include <IOKit/IOTimerEventSource.h>
154 #include <IOKit/IOTimeStamp.h>
155 #include <IOKit/IOTypes.h>
156 #include <IOKit/IOUserClient.h>
157 #include <IOKit/IOWorkLoop.h>
158 #include <IOKit/nvram/IONVRAMController.h>
159 #include <IOKit/OSMessageNotification.h>
160 #include <IOKit/platform/AppleMacIO.h>
161 #include <IOKit/platform/AppleMacIODevice.h>
162 #include <IOKit/platform/AppleNMI.h>
163 #include <IOKit/platform/ApplePlatformExpert.h>
164 #include <IOKit/power/IOPwrController.h>
165 #include <IOKit/pwr_mgt/IOPM.h>
166 #include <IOKit/pwr_mgt/IOPMinformee.h>
167 #include <IOKit/pwr_mgt/IOPMinformeeList.h>
168 #include <IOKit/pwr_mgt/IOPMLibDefs.h>
169 #include <IOKit/pwr_mgt/IOPMlog.h>
170 #include <IOKit/pwr_mgt/IOPMPowerSource.h>
171 #include <IOKit/pwr_mgt/IOPMPowerSourceList.h>
172 #include <IOKit/pwr_mgt/IOPMpowerState.h>
173 #include <IOKit/pwr_mgt/IOPMPrivate.h>
174 #include <IOKit/pwr_mgt/IOPowerConnection.h>
175 #include <IOKit/pwr_mgt/RootDomain.h>
176 #include <IOKit/rtc/IORTCController.h>
177 #include <IOKit/system.h>
178 #include <IOKit/system_management/IOWatchDogTimer.h>
179 #include <math.h>
180
181 #endif /* TEST_HEADERS */
182
183 #include <sys/sysctl.h>
184 #include <libkern/c++/OSData.h>
185 #include <IOKit/IOService.h>
186 #include <IOKit/IOUserClient.h>
187 #include "Tests.h"
188
189
190 #if DEVELOPMENT || DEBUG
191
192 #include <IOKit/IOWorkLoop.h>
193 #include <IOKit/IOTimerEventSource.h>
194 #include <IOKit/IOInterruptEventSource.h>
195 #include <IOKit/IOCommandGate.h>
196 #include <IOKit/IOPlatformExpert.h>
197 #include <IOKit/IOSharedDataQueue.h>
198 #include <IOKit/IODataQueueShared.h>
199 #include <IOKit/IOServiceStateNotificationEventSource.h>
200 #include <IOKit/IOKitKeysPrivate.h>
201 #include <IOKit/IOKitServer.h>
202 #include <IOKit/IOBSD.h>
203 #include <kern/ipc_kobject.h>
204 #include <libkern/Block.h>
205 #include <libkern/Block_private.h>
206 #include <libkern/c++/OSAllocation.h>
207 #include <libkern/c++/OSBoundedArray.h>
208 #include <libkern/c++/OSBoundedArrayRef.h>
209 #include <libkern/c++/OSBoundedPtr.h>
210 #include <libkern/c++/OSSharedPtr.h>
211 #include <os/cpp_util.h>
212
213 static uint64_t gIOWorkLoopTestDeadline;
214
215 static void
TESAction(OSObject * owner,IOTimerEventSource * tes)216 TESAction(OSObject * owner, IOTimerEventSource * tes)
217 {
218 if (mach_absolute_time() < gIOWorkLoopTestDeadline) {
219 tes->setTimeout(1, kMicrosecondScale);
220 }
221 }
222
223 static int
IOWorkLoopTest(int newValue)224 IOWorkLoopTest(int newValue)
225 {
226 IOReturn err;
227 uint32_t idx;
228 OSSharedPtr<IOWorkLoop> wl;
229 OSSharedPtr<IOTimerEventSource> tes;
230 OSSharedPtr<IOInterruptEventSource> ies;
231
232 wl = IOWorkLoop::workLoop();
233 assert(wl);
234 tes = IOTimerEventSource::timerEventSource(kIOTimerEventSourceOptionsPriorityWorkLoop, wl.get(), &TESAction);
235 assert(tes);
236 err = wl->addEventSource(tes.get());
237 assert(kIOReturnSuccess == err);
238 clock_interval_to_deadline(100, kMillisecondScale, &gIOWorkLoopTestDeadline);
239 for (idx = 0; mach_absolute_time() < gIOWorkLoopTestDeadline; idx++) {
240 tes->setTimeout(idx & 1023, kNanosecondScale);
241 }
242 tes->cancelTimeout();
243 wl->removeEventSource(tes.get());
244
245 int value = 3;
246
247 tes = IOTimerEventSource::timerEventSource(kIOTimerEventSourceOptionsDefault, wl.get(), ^(IOTimerEventSource * tes){
248 kprintf("wl %p, value %d\n", wl.get(), value);
249 });
250 err = wl->addEventSource(tes.get());
251 assert(kIOReturnSuccess == err);
252
253 value = 2;
254 tes->setTimeout(1, kNanosecondScale);
255 IOSleep(1);
256 wl->removeEventSource(tes.get());
257
258 ies = IOInterruptEventSource::interruptEventSource(wl.get(), NULL, 0, ^void (IOInterruptEventSource *sender, int count){
259 kprintf("ies block %p, %d\n", sender, count);
260 });
261
262 assert(ies);
263 kprintf("ies %p\n", ies.get());
264 err = wl->addEventSource(ies.get());
265 assert(kIOReturnSuccess == err);
266 ies->interruptOccurred(NULL, NULL, 0);
267 IOSleep(1);
268 ies->interruptOccurred(NULL, NULL, 0);
269 IOSleep(1);
270 wl->removeEventSource(ies.get());
271
272 return 0;
273 }
274
275 static int
OSCollectionTest(int newValue)276 OSCollectionTest(int newValue)
277 {
278 OSSharedPtr<OSArray> array = OSArray::withCapacity(8);
279 array->setObject(kOSBooleanTrue);
280 array->setObject(kOSBooleanFalse);
281 array->setObject(kOSBooleanFalse);
282 array->setObject(kOSBooleanTrue);
283 array->setObject(kOSBooleanFalse);
284 array->setObject(kOSBooleanTrue);
285
286 __block unsigned int index;
287 index = 0;
288 array->iterateObjects(^bool (OSObject * obj) {
289 kprintf("%d:%d ", index, (obj == kOSBooleanTrue) ? 1 : (obj == kOSBooleanFalse) ? 0 : 2);
290 index++;
291 return false;
292 });
293 kprintf("\n");
294
295 OSSharedPtr<OSDictionary> dict = IOService::resourceMatching("hello");
296 assert(dict);
297 index = 0;
298 dict->iterateObjects(^bool (const OSSymbol * sym, OSObject * obj) {
299 OSString * str = OSDynamicCast(OSString, obj);
300 assert(str);
301 kprintf("%d:%s=%s\n", index, sym->getCStringNoCopy(), str->getCStringNoCopy());
302 index++;
303 return false;
304 });
305
306 OSSharedPtr<OSSerializer> serializer = OSSerializer::withBlock(^bool (OSSerialize * s){
307 return gIOBSDUnitKey->serialize(s);
308 });
309 assert(serializer);
310 IOService::getPlatform()->setProperty("OSSerializer_withBlock", serializer.get());
311
312 OSSharedPtr<OSString> ab = OSString::withCString("abcdef", 2);
313 assert(strcmp(ab->getCStringNoCopy(), "ab") == 0);
314 OSSharedPtr<OSString> defgh = OSString::withCString("defgh", 10);
315 assert(strcmp(defgh->getCStringNoCopy(), "defgh") == 0);
316 OSSharedPtr<OSString> zyxwvut = OSString::withCString("zyxwvut", 7);
317 assert(strcmp(zyxwvut->getCStringNoCopy(), "zyxwvut") == 0);
318
319 return 0;
320 }
321
322 static int
OSAllocationTests(int)323 OSAllocationTests(int)
324 {
325 OSAllocation<int> ints(100, OSAllocateMemory);
326 assert(ints);
327
328 {
329 int counter = 0;
330 for (int& i : ints) {
331 i = counter++;
332 }
333 }
334
335 {
336 int counter = 0;
337 for (int& i : ints) {
338 assert(i == counter);
339 ++counter;
340 }
341 }
342
343 OSAllocation<int> arrayZero(100, OSAllocateMemoryZero);
344 assert(arrayZero);
345 for (const auto& i : arrayZero) {
346 assert(i == 0);
347 }
348
349 // Make sure we can have two-level OSAllocations
350 {
351 OSAllocation<OSAllocation<int> > testArray(10, OSAllocateMemory);
352 for (int i = 0; i < 10; i++) {
353 testArray[i] = OSAllocation<int>(10, OSAllocateMemory);
354 for (int j = 0; j < 10; ++j) {
355 testArray[i][j] = i + j;
356 }
357 }
358
359 for (int i = 0; i < 10; i++) {
360 for (int j = 0; j < 10; ++j) {
361 assert(testArray[i][j] == i + j);
362 }
363 }
364 }
365
366 return 0;
367 }
368
369 static int
OSDataAllocationTests(int)370 OSDataAllocationTests(int)
371 {
372 OSDataAllocation<int> ints(100, OSAllocateMemory);
373 assert(ints);
374
375 {
376 int counter = 0;
377 for (int& i : ints) {
378 i = counter++;
379 }
380 }
381
382 {
383 int counter = 0;
384 for (const int& i : ints) {
385 assert(i == counter);
386 ++counter;
387 }
388 }
389
390 OSDataAllocation<int> arrayZero(100, OSAllocateMemoryZero);
391 assert(arrayZero);
392 for (const auto& i : arrayZero) {
393 assert(i == 0);
394 }
395
396 return 0;
397 }
398
399 static int
OSBoundedArrayTests(int)400 OSBoundedArrayTests(int)
401 {
402 OSBoundedArray<int, 5> ints = {0, 1, 2, 3, 4};
403 assert(ints.size() == 5);
404
405 {
406 int counter = 0;
407 for (int& i : ints) {
408 i = counter++;
409 }
410 }
411
412 {
413 int counter = 0;
414 for (int& i : ints) {
415 assert(i == counter);
416 ++counter;
417 }
418 }
419
420 return 0;
421 }
422
423 static int
OSBoundedArrayRefTests(int)424 OSBoundedArrayRefTests(int)
425 {
426 OSBoundedArray<int, 5> storage = {0, 1, 2, 3, 4};
427 OSBoundedArrayRef<int> ints(storage);
428 assert(ints);
429
430 {
431 int counter = 0;
432 for (int& i : ints) {
433 i = counter++;
434 }
435 }
436
437 {
438 int counter = 0;
439 for (int& i : ints) {
440 assert(i == counter);
441 ++counter;
442 }
443 }
444
445 return 0;
446 }
447
448 class OSArraySubclass : public OSArray {
449 OSDeclareDefaultStructors(OSArraySubclass);
450 public:
451 static OSSharedPtr<OSArraySubclass> withCapacity(unsigned int inCapacity);
452 virtual unsigned int iteratorSize() const APPLE_KEXT_OVERRIDE;
453 };
454
455 OSDefineMetaClassAndStructors(OSArraySubclass, OSArray);
456
457 OSSharedPtr<OSArraySubclass>
withCapacity(unsigned int inCapacity)458 OSArraySubclass::withCapacity(unsigned int inCapacity)
459 {
460 OSSharedPtr<OSArraySubclass> me = OSMakeShared<OSArraySubclass>();
461
462 if (me && !me->initWithCapacity(inCapacity)) {
463 return nullptr;
464 }
465
466 return me;
467 }
468
469 unsigned int
iteratorSize() const470 OSArraySubclass::iteratorSize() const
471 {
472 unsigned int result = 64;
473 // Has to be larger than the OSArray iterator size to prevent out-of-bounds writes
474 assert(result >= OSArray::iteratorSize());
475 return result;
476 }
477
478 class OSCISubclass : public OSCollectionIterator {
479 OSDeclareDefaultStructors(OSCISubclass);
480 public:
481 static OSSharedPtr<OSCISubclass> withCollection(const OSCollection * inColl);
482 };
483
484 OSDefineMetaClassAndStructors(OSCISubclass, OSCollectionIterator);
485
486 OSSharedPtr<OSCISubclass>
withCollection(const OSCollection * inColl)487 OSCISubclass::withCollection(const OSCollection * inColl)
488 {
489 OSSharedPtr<OSCISubclass> me = OSMakeShared<OSCISubclass>();
490
491 if (me && !me->initWithCollection(inColl)) {
492 return nullptr;
493 }
494
495 return me;
496 }
497
498 static int
OSCollectionIteratorTests(int)499 OSCollectionIteratorTests(int)
500 {
501 OSSharedPtr<OSArray> array = OSArray::withCapacity(0);
502 OSSharedPtr<OSString> firstObj = OSString::withCString("test object");
503 OSSharedPtr<OSString> secondObj = OSString::withCString("test object 2");
504 OSObject * current = NULL;
505 OSSharedPtr<OSCollectionIterator> osci = NULL;
506 OSSharedPtr<OSCISubclass> osciSubclass = NULL;
507 size_t index = 0;
508 array->setObject(firstObj);
509 array->setObject(secondObj);
510
511 // Test iteration over a normal OSArray
512 osci = OSCollectionIterator::withCollection(array.get());
513 assert(osci != NULL);
514
515 index = 0;
516 while ((current = osci->getNextObject()) != NULL) {
517 if (index == 0) {
518 assert(current == firstObj);
519 } else if (index == 1) {
520 assert(current == secondObj);
521 } else {
522 panic("index out of range");
523 }
524 index++;
525 }
526
527 // Test iteration with a OSCollectionIterator subclass over a normal OSArray
528 osciSubclass = OSCISubclass::withCollection(array.get());
529 assert(osciSubclass != NULL);
530
531 index = 0;
532 while ((current = osciSubclass->getNextObject()) != NULL) {
533 if (index == 0) {
534 assert(current == firstObj);
535 } else if (index == 1) {
536 assert(current == secondObj);
537 } else {
538 panic("index out of range");
539 }
540 index++;
541 }
542
543 // Create the OSArray subclass
544 OSSharedPtr<OSArraySubclass> arraySubclass = OSArraySubclass::withCapacity(0);
545 arraySubclass->setObject(firstObj);
546 arraySubclass->setObject(secondObj);
547 // Test iteration over a subclassed OSArray, with a large iterator size
548 osci = OSCollectionIterator::withCollection(arraySubclass.get());
549 assert(osci != NULL);
550
551 index = 0;
552 while ((current = osci->getNextObject()) != NULL) {
553 if (index == 0) {
554 assert(current == firstObj);
555 } else if (index == 1) {
556 assert(current == secondObj);
557 } else {
558 panic("index out of range");
559 }
560 index++;
561 }
562
563 // Test iteration with a OSCollectionIterator subclass over a subclassed OSArray,
564 // with a large iterator size.
565 osciSubclass = OSCISubclass::withCollection(arraySubclass.get());
566 assert(osciSubclass != NULL);
567
568 index = 0;
569 while ((current = osciSubclass->getNextObject()) != NULL) {
570 if (index == 0) {
571 assert(current == firstObj);
572 } else if (index == 1) {
573 assert(current == secondObj);
574 } else {
575 panic("index out of range");
576 }
577 index++;
578 }
579
580 return 0;
581 }
582
583 static int
OSBoundedPtrTests(int)584 OSBoundedPtrTests(int)
585 {
586 int array[5] = {55, 66, 77, 88, 99};
587 OSBoundedPtr<int> begin(&array[0], &array[0], &array[5]);
588 OSBoundedPtr<int> end(&array[5], &array[0], &array[5]);
589
590 {
591 int counter = 0;
592 for (OSBoundedPtr<int> b = begin; b != end; ++b) {
593 *b = counter++;
594 }
595 }
596
597 {
598 int counter = 0;
599 for (OSBoundedPtr<int> b = begin; b != end; ++b) {
600 assert(*b == counter);
601 ++counter;
602 }
603 }
604
605 return 0;
606 }
607
608 static int
OSValueObjectTests(int)609 OSValueObjectTests(int)
610 {
611 struct TrivialTestType {
612 int a;
613 bool b;
614 float c;
615 };
616
617 class NonTrivialConstructorTestType
618 {
619 public:
620 NonTrivialConstructorTestType() = default;
621 int a = 3;
622 bool b = true;
623 float c = 999.f;
624 };
625
626 constexpr auto nearlyEqual = [](float a, float b)
627 {
628 constexpr float epsilon = 0.000001f;
629 const auto diff = a - b;
630 return (diff >= -epsilon) && (diff <= epsilon);
631 };
632
633 // test simple built-in type
634 {
635 using T = int;
636 OSSharedPtr<OSValueObject<T> > test = OSValueObject<T>::create();
637 assert(test);
638 if (test) {
639 assert(test->getRef() == 0);
640 assert(test->isEqualTo(0));
641 assert(test->getBytesNoCopy());
642 assert(test->getBytesNoCopy() == test->getMutableBytesNoCopy());
643 assert(test->getLength() == sizeof(T));
644 }
645 }
646
647 // test trivial aggregate type
648 {
649 using T = TrivialTestType;
650 OSSharedPtr<OSValueObject<T> > test = OSValueObject<T>::create();
651 assert(test);
652 if (test) {
653 const auto *const bytes = reinterpret_cast<const uint8_t*>(test->getBytesNoCopy());
654 bool bytesAreZero = true;
655 for (size_t byteIndex = 0; byteIndex < test->getLength(); byteIndex++) {
656 bytesAreZero &= bytes[byteIndex] == 0;
657 }
658 assert(bytesAreZero);
659 }
660 }
661
662 // test aggregate type with non-trivial constructor
663 {
664 using T = NonTrivialConstructorTestType;
665 OSSharedPtr<OSValueObject<T> > test = OSValueObject<T>::create();
666 assert(test);
667 if (test) {
668 const T other;
669 assert(test->isEqualTo(other));
670 assert(test->getRef().a == other.a);
671 assert(test->getRef().b == other.b);
672 assert(nearlyEqual(test->getRef().c, other.c));
673 }
674 }
675
676 // test copying of OSValueObject
677 {
678 using T = NonTrivialConstructorTestType;
679 OSSharedPtr<OSValueObject<T> > test1;
680 T valueCopy;
681 {
682 T value; // declared in sub-scope to ensure instance-independence when it falls out of scope
683 value.a = 1;
684 value.b = true;
685 value.c = 3.f;
686 valueCopy = value;
687 test1 = OSValueObject<T>::withValue(value);
688 assert(test1);
689 if (test1) {
690 assert(test1->isEqualTo(value));
691 assert(test1->getRef().a == value.a);
692 assert(test1->getRef().b == value.b);
693 assert(nearlyEqual(test1->getRef().c, value.c));
694 }
695 valueCopy.a = 100;
696 test1->getMutableRef().a = valueCopy.a;
697 }
698 if (test1) {
699 OSSharedPtr<OSValueObject<T> > test2 = OSValueObject<T>::withValueObject(test1.get());
700 if (test2) {
701 assert(test2->isEqualTo(test1.get()));
702 assert(test2->getRef().a == valueCopy.a);
703 assert(test2->getRef().b == valueCopy.b);
704 assert(nearlyEqual(test2->getRef().c, valueCopy.c));
705 }
706 }
707 }
708
709 return KERN_SUCCESS;
710 }
711
712
713 static int
IOSharedDataQueue_44636964(__unused int newValue)714 IOSharedDataQueue_44636964(__unused int newValue)
715 {
716 OSSharedPtr<IOSharedDataQueue> sd = IOSharedDataQueue::withCapacity(DATA_QUEUE_ENTRY_HEADER_SIZE + sizeof(UInt64));
717 UInt64 data = 0x11223344aa55aa55;
718 UInt32 data2 = 0x44332211;
719 UInt32 size = sizeof(UInt32);
720 /* enqueue moves tail to end */
721 sd->enqueue(&data, sizeof(UInt64));
722 /* dequeue moves head to end */
723 sd->dequeue(&data, &size);
724 /* Tail wraps around, head is still at end */
725 sd->enqueue(&data2, sizeof(UInt32));
726 /* something in the queue so peek() should return non-null */
727 assert(sd->peek() != NULL);
728 return KERN_SUCCESS;
729 }
730
731 #if 0
732 #include <IOKit/IOUserClient.h>
733 class TestUserClient : public IOUserClient
734 {
735 OSDeclareDefaultStructors(TestUserClient);
736 virtual void stop( IOService *provider) APPLE_KEXT_OVERRIDE;
737 virtual bool finalize(IOOptionBits options) APPLE_KEXT_OVERRIDE;
738 virtual IOReturn externalMethod( uint32_t selector,
739 IOExternalMethodArguments * arguments,
740 IOExternalMethodDispatch * dispatch,
741 OSObject * target,
742 void * reference ) APPLE_KEXT_OVERRIDE;
743 };
744
745 void
746 TestUserClient::stop( IOService *provider)
747 {
748 kprintf("TestUserClient::stop\n");
749 }
750 bool
751 TestUserClient::finalize(IOOptionBits options)
752 {
753 kprintf("TestUserClient::finalize\n");
754 return true;
755 }
756 IOReturn
757 TestUserClient::externalMethod( uint32_t selector,
758 IOExternalMethodArguments * arguments,
759 IOExternalMethodDispatch * dispatch,
760 OSObject * target,
761 void * reference )
762 {
763 getProvider()->terminate();
764 IOSleep(500);
765 return 0;
766 }
767 OSDefineMetaClassAndStructors(TestUserClient, IOUserClient);
768 #endif
769
770 static int
IOServiceTest(int newValue)771 IOServiceTest(int newValue)
772 {
773 OSSharedPtr<OSDictionary> matching;
774 IONotifier * note;
775 __block IOService * found;
776
777 #if 0
778 found = new IOService;
779 found->init();
780 found->setName("IOTestUserClientProvider");
781 found->attach(IOService::getPlatform());
782 found->setProperty("IOUserClientClass", "TestUserClient");
783 found->registerService();
784 #endif
785
786 matching = IOService::serviceMatching("IOPlatformExpert");
787 assert(matching);
788 found = nullptr;
789 note = IOService::addMatchingNotification(gIOMatchedNotification, matching.get(), 0,
790 ^bool (IOService * newService, IONotifier * notifier) {
791 kprintf("found %s, %d\n", newService->getName(), newService->getRetainCount());
792 found = newService;
793 found->retain();
794 return true;
795 }
796 );
797 assert(note);
798 assert(found);
799 note->remove();
800
801 note = found->registerInterest(gIOBusyInterest,
802 ^IOReturn (uint32_t messageType, IOService * provider,
803 void * messageArgument, size_t argSize) {
804 kprintf("%p messageType 0x%08x %p\n", provider, messageType, messageArgument);
805 return kIOReturnSuccess;
806 }).detach();
807 assert(note);
808 IOSleep(1 * 1000);
809 note->remove();
810 found->release();
811
812 return 0;
813 }
814
815 static void
OSStaticPtrCastTests()816 OSStaticPtrCastTests()
817 {
818 // const& overload
819 {
820 OSSharedPtr<OSDictionary> const dict = OSMakeShared<OSDictionary>();
821 OSSharedPtr<OSCollection> collection = OSStaticPtrCast<OSCollection>(dict);
822 assert(collection == dict);
823 }
824 {
825 OSSharedPtr<OSDictionary> const dict = nullptr;
826 OSSharedPtr<OSCollection> collection = OSStaticPtrCast<OSCollection>(dict);
827 assert(collection == nullptr);
828 }
829 // && overload
830 {
831 OSSharedPtr<OSDictionary> dict = OSMakeShared<OSDictionary>();
832 OSDictionary* oldDict = dict.get();
833 OSSharedPtr<OSCollection> collection = OSStaticPtrCast<OSCollection>(os::move(dict));
834 assert(collection.get() == oldDict);
835 assert(dict == nullptr);
836 }
837 {
838 OSSharedPtr<OSDictionary> dict = nullptr;
839 OSSharedPtr<OSCollection> collection = OSStaticPtrCast<OSCollection>(os::move(dict));
840 assert(collection == nullptr);
841 assert(dict == nullptr);
842 }
843 }
844
845 static void
OSConstPtrCastTests()846 OSConstPtrCastTests()
847 {
848 // const& overload
849 {
850 OSSharedPtr<OSDictionary const> const dict = OSMakeShared<OSDictionary>();
851 OSSharedPtr<OSDictionary> dict2 = OSConstPtrCast<OSDictionary>(dict);
852 assert(dict2 == dict);
853 }
854 {
855 OSSharedPtr<OSDictionary const> const dict = OSMakeShared<OSDictionary>();
856 OSSharedPtr<OSDictionary const> dict2 = OSConstPtrCast<OSDictionary const>(dict);
857 assert(dict2 == dict);
858 }
859 {
860 OSSharedPtr<OSDictionary const> const dict = nullptr;
861 OSSharedPtr<OSDictionary> dict2 = OSConstPtrCast<OSDictionary>(dict);
862 assert(dict2 == nullptr);
863 }
864 {
865 OSSharedPtr<OSDictionary const> const dict = nullptr;
866 OSSharedPtr<OSDictionary const> dict2 = OSConstPtrCast<OSDictionary const>(dict);
867 assert(dict2 == nullptr);
868 }
869
870 // && overload
871 {
872 OSSharedPtr<OSDictionary const> dict = OSMakeShared<OSDictionary>();
873 OSDictionary const* oldDict = dict.get();
874 OSSharedPtr<OSDictionary> dict2 = OSConstPtrCast<OSDictionary>(os::move(dict));
875 assert(dict == nullptr);
876 assert(dict2 == oldDict);
877 }
878 {
879 OSSharedPtr<OSDictionary const> dict = nullptr;
880 OSSharedPtr<OSDictionary> dict2 = OSConstPtrCast<OSDictionary>(os::move(dict));
881 assert(dict == nullptr);
882 assert(dict2 == nullptr);
883 }
884 }
885
886 static void
OSDynamicPtrCastTests()887 OSDynamicPtrCastTests()
888 {
889 OSSharedPtr<OSDictionary> const dict = OSMakeShared<OSDictionary>();
890 {
891 OSSharedPtr<OSCollection> collection = OSDynamicPtrCast<OSCollection>(dict);
892 assert(collection != nullptr);
893 }
894 {
895 OSSharedPtr<OSArray> array = OSDynamicPtrCast<OSArray>(dict);
896 assert(array == nullptr);
897 assert(dict != nullptr);
898 }
899 {
900 OSTaggedSharedPtr<OSCollection, OSCollection> taggedDict(dict.get(), OSRetain);
901 OSTaggedSharedPtr<OSCollection, OSCollection> collection = OSDynamicPtrCast<OSCollection>(taggedDict);
902 assert(collection != nullptr);
903 }
904 {
905 OSTaggedSharedPtr<OSCollection, OSCollection> taggedDict(dict.get(), OSRetain);
906 OSTaggedSharedPtr<OSArray, OSCollection> array = OSDynamicPtrCast<OSArray>(taggedDict);
907 assert(array == nullptr);
908 assert(dict != nullptr);
909 }
910 {
911 OSSharedPtr<OSCollection> collection = OSDynamicPtrCast<OSCollection>(dict);
912 assert(collection.get() == OSDynamicCast(OSDictionary, dict.get()));
913 OSSharedPtr<OSDictionary> newDict = OSDynamicPtrCast<OSDictionary>(os::move(collection));
914 assert(collection == nullptr);
915 assert(newDict != nullptr);
916 assert(newDict.get() == dict.get());
917 }
918 }
919
920
921 class IOTestUserNotification : public IOUserNotification
922 {
923 OSDeclareDefaultStructors(IOTestUserNotification);
924 };
925
926 OSDefineMetaClassAndStructors(IOTestUserNotification, IOUserNotification)
927
928 struct IOUserNotificationTestThreadArgs {
929 IOTestUserNotification * userNotify;
930 IOLock * lock;
931 size_t * completed;
932 size_t iterations;
933 };
934
935 static bool
IOUserNotificationMatchingHandler(void * target __unused,void * ref __unused,IOService * newService __unused,IONotifier * notifier __unused)936 IOUserNotificationMatchingHandler( void * target __unused,
937 void * ref __unused, IOService * newService __unused, IONotifier * notifier __unused )
938 {
939 return true;
940 }
941
942 static void
IOUserNotificationTestThread(void * arg,wait_result_t result __unused)943 IOUserNotificationTestThread(void * arg, wait_result_t result __unused)
944 {
945 IOUserNotificationTestThreadArgs * threadArgs = (IOUserNotificationTestThreadArgs *)arg;
946
947 OSSharedPtr<OSDictionary> dict = OSDictionary::withCapacity(0);
948 OSSharedPtr<OSString> rootPath = OSString::withCStringNoCopy(":/");
949 dict->setObject(gIOPathMatchKey, rootPath);
950
951 for (size_t i = 0; i < threadArgs->iterations; i++) {
952 if (i % 2 == 0) {
953 IONotifier * notify = IOService::addMatchingNotification( gIOWillTerminateNotification, dict.get(),
954 &IOUserNotificationMatchingHandler, NULL );
955 threadArgs->userNotify->setNotification(notify);
956 } else {
957 threadArgs->userNotify->setNotification(NULL);
958 }
959 }
960
961 threadArgs->userNotify->setNotification(NULL);
962
963 IOLockLock(threadArgs->lock);
964 *threadArgs->completed = *threadArgs->completed + 1;
965 IOLockWakeup(threadArgs->lock, (event_t)threadArgs->completed, true);
966 IOLockUnlock(threadArgs->lock);
967 }
968
969 static int
IOUserNotificationTests(__unused int newValue)970 IOUserNotificationTests(__unused int newValue)
971 {
972 constexpr size_t numThreads = 10;
973 constexpr size_t numIterations = 500000;
974 OSSharedPtr<IOTestUserNotification> userNotify = OSMakeShared<IOTestUserNotification>();
975 IOLock * lock = IOLockAlloc();
976 size_t threadsCompleted;
977 size_t i = 0;
978 thread_t threads[numThreads];
979 kern_return_t kr;
980 bool result;
981
982 struct IOUserNotificationTestThreadArgs threadArgs = {
983 .userNotify = userNotify.get(),
984 .lock = lock,
985 .completed = &threadsCompleted,
986 .iterations = numIterations,
987 };
988
989 result = userNotify->init();
990 assert(result);
991
992 for (i = 0; i < numThreads; i++) {
993 kr = kernel_thread_start(&IOUserNotificationTestThread, (void *)&threadArgs, &threads[i]);
994 assert(kr == KERN_SUCCESS);
995 }
996
997 IOLockLock(lock);
998 while (threadsCompleted < numThreads) {
999 IOLockSleep(lock, &threadsCompleted, THREAD_UNINT);
1000 IOLog("%s: Threads completed: %zu/%zu\n", __func__, threadsCompleted, numThreads);
1001 }
1002 IOLockUnlock(lock);
1003
1004 for (i = 0; i < numThreads; i++) {
1005 thread_deallocate(threads[i]);
1006 }
1007
1008 userNotify->setNotification(NULL);
1009
1010 IOLockFree(lock);
1011
1012 return KERN_SUCCESS;
1013 }
1014
1015 static void
IOServiceMatchingSharedPtrTests()1016 IOServiceMatchingSharedPtrTests()
1017 {
1018 OSSharedPtr<const OSSymbol> name = OSSymbol::withCString("name");
1019 OSSharedPtr<const OSSymbol> value = OSSymbol::withCString("value");
1020
1021 {
1022 OSSharedPtr<OSDictionary> table;
1023 OSSharedPtr<OSDictionary> result = IOService::serviceMatching("name", table);
1024 assert(result);
1025 assert(result->getRetainCount() == 1);
1026
1027 table = result;
1028 assert(table->getRetainCount() == 2);
1029 OSSharedPtr<OSDictionary> result2 = IOService::serviceMatching("name", table);
1030 assert(result2);
1031 assert(result2 == table);
1032 assert(result2->getRetainCount() == 3);
1033 }
1034
1035 {
1036 OSSharedPtr<OSDictionary> table;
1037 OSSharedPtr<OSDictionary> result = IOService::serviceMatching(name.get(), table);
1038 assert(result);
1039 assert(result->getRetainCount() == 1);
1040
1041 table = result;
1042 assert(table->getRetainCount() == 2);
1043 OSSharedPtr<OSDictionary> result2 = IOService::serviceMatching(name.get(), table);
1044 assert(result2);
1045 assert(result2 == table);
1046 assert(result2->getRetainCount() == 3);
1047 }
1048
1049 {
1050 OSSharedPtr<OSDictionary> table;
1051 OSSharedPtr<OSDictionary> result = IOService::nameMatching("name", table);
1052 assert(result);
1053 assert(result->getRetainCount() == 1);
1054
1055 table = result;
1056 assert(table->getRetainCount() == 2);
1057 OSSharedPtr<OSDictionary> result2 = IOService::nameMatching("name", table);
1058 assert(result2);
1059 assert(result2 == table);
1060 assert(result2->getRetainCount() == 3);
1061 }
1062
1063 {
1064 OSSharedPtr<OSDictionary> table;
1065 OSSharedPtr<OSDictionary> result = IOService::nameMatching(name.get(), table);
1066 assert(result);
1067 assert(result->getRetainCount() == 1);
1068
1069 table = result;
1070 assert(table->getRetainCount() == 2);
1071 OSSharedPtr<OSDictionary> result2 = IOService::nameMatching(name.get(), table);
1072 assert(result2);
1073 assert(result2 == table);
1074 assert(result2->getRetainCount() == 3);
1075 }
1076
1077 {
1078 OSSharedPtr<OSDictionary> table;
1079 OSSharedPtr<OSDictionary> result = IOService::resourceMatching("name", table);
1080 assert(result);
1081 assert(result->getRetainCount() == 1);
1082
1083 table = result;
1084 assert(table->getRetainCount() == 2);
1085 OSSharedPtr<OSDictionary> result2 = IOService::resourceMatching("name", table);
1086 assert(result2);
1087 assert(result2 == table);
1088 assert(result2->getRetainCount() == 3);
1089 }
1090
1091 {
1092 OSSharedPtr<OSDictionary> table;
1093 OSSharedPtr<OSDictionary> result = IOService::resourceMatching(name.get(), table);
1094 assert(result);
1095 assert(result->getRetainCount() == 1);
1096
1097 table = result;
1098 assert(table->getRetainCount() == 2);
1099 OSSharedPtr<OSDictionary> result2 = IOService::resourceMatching(name.get(), table);
1100 assert(result2);
1101 assert(result2 == table);
1102 assert(result2->getRetainCount() == 3);
1103 }
1104
1105 {
1106 OSSharedPtr<OSDictionary> table;
1107 OSSharedPtr<OSDictionary> result = IOService::propertyMatching(name.get(), value.get(), table);
1108 assert(result);
1109 assert(result->getRetainCount() == 1);
1110
1111 table = result;
1112 assert(table->getRetainCount() == 2);
1113 OSSharedPtr<OSDictionary> result2 = IOService::propertyMatching(name.get(), value.get(), table);
1114 assert(result2);
1115 assert(result2 == table);
1116 assert(result2->getRetainCount() == 3);
1117 }
1118
1119 {
1120 OSSharedPtr<OSDictionary> table;
1121 OSSharedPtr<OSDictionary> result = IOService::registryEntryIDMatching(12, table);
1122 assert(result);
1123 assert(result->getRetainCount() == 1);
1124
1125 table = result;
1126 assert(table->getRetainCount() == 2);
1127 OSSharedPtr<OSDictionary> result2 = IOService::registryEntryIDMatching(12, table);
1128 assert(result2);
1129 assert(result2 == table);
1130 assert(result2->getRetainCount() == 3);
1131 }
1132 }
1133
1134 static int
OSSharedPtrTests(int)1135 OSSharedPtrTests(int)
1136 {
1137 OSDynamicPtrCastTests();
1138 OSConstPtrCastTests();
1139 OSStaticPtrCastTests();
1140 IOServiceMatchingSharedPtrTests();
1141 return 0;
1142 }
1143
1144 static int
IOServiceStateNotificationTests(int)1145 IOServiceStateNotificationTests(int)
1146 {
1147 IOService * service = IOService::getSystemStateNotificationService();
1148 OSSharedPtr<OSString> str = OSString::withCString(kIOSystemStateClamshellKey);
1149 kern_return_t kr = service->StateNotificationItemCreate(str.get(), NULL);
1150 assert(kIOReturnSuccess == kr);
1151
1152 void (^sendClam)(OSBoolean * state) = ^void (OSBoolean * state) {
1153 OSSharedPtr<OSDictionary> value;
1154 kern_return_t kr;
1155
1156 value = OSDictionary::withCapacity(4);
1157 value->setObject("value", state);
1158 kr = IOService::getSystemStateNotificationService()->StateNotificationItemSet(str.get(), value.get());
1159 assert(kIOReturnSuccess == kr);
1160 };
1161 sendClam(kOSBooleanTrue);
1162 IOSleep(100);
1163 sendClam(kOSBooleanFalse);
1164
1165 str = OSString::withCString("test");
1166 OSSharedPtr<OSArray> array = OSArray::withCapacity(4);
1167 array->setObject(str.get());
1168 IOStateNotificationListenerRef listenerRef;
1169 kr = service->stateNotificationListenerAdd(array.get(), &listenerRef, ^kern_return_t () {
1170 IOLog("test handler\n");
1171 kern_return_t kr;
1172 OSDictionary * dict;
1173 kr = service->StateNotificationItemCopy(str.get(), &dict);
1174 if (kIOReturnSuccess == kr) {
1175 OSSharedPtr<OSSerialize> s = OSSerialize::withCapacity(4096);
1176 dict->serialize(s.get());
1177 IOLog("test handler %s\n", s->text());
1178 }
1179 return kIOReturnSuccess;
1180 });
1181 assert(kIOReturnSuccess == kr);
1182
1183 OSSharedPtr<IOEventSource> es =
1184 IOServiceStateNotificationEventSource::serviceStateNotificationEventSource(
1185 service, array.get(),
1186 ^void () {
1187 IOLog("test es handler\n");
1188 kern_return_t kr;
1189 OSDictionary * dict;
1190 kr = service->StateNotificationItemCopy(str.get(), &dict);
1191 if (kIOReturnSuccess == kr) {
1192 OSSharedPtr<OSSerialize> s = OSSerialize::withCapacity(4096);
1193 dict->serialize(s.get());
1194 IOLog("test es handler %s\n", s->text());
1195 }
1196 });
1197 assert(es);
1198 IOService::getPlatform()->getWorkLoop()->addEventSource(es.get());
1199 es->enable();
1200 IOSleep(30 * 1000);
1201 IOService::getPlatform()->getWorkLoop()->removeEventSource(es.get());
1202
1203 return kIOReturnSuccess;
1204 }
1205
1206 static int
IOMallocPageableTests(int)1207 IOMallocPageableTests(int)
1208 {
1209 vm_size_t size = 0;
1210 vm_size_t alignment = 0;
1211
1212 for (size = 0; size <= 4 * page_size; size += 64) {
1213 for (alignment = 1; alignment <= page_size; alignment <<= 1) {
1214 uintptr_t alignMask = alignment - 1;
1215 void * addr = IOMallocPageable(size, alignment);
1216 if (addr == NULL) {
1217 IOLog("IOMallocPageable(size=%u, alignment=%u) failed\n", (uint32_t)size, (uint32_t)alignment);
1218 return kIOReturnError;
1219 }
1220 if (((uintptr_t)addr & alignMask) != 0) {
1221 IOLog("IOMallocPageable(size=%u, alignment=%u) returned unaligned pointer %p\n", (uint32_t)size, (uint32_t)alignment, addr);
1222 return kIOReturnError;
1223 }
1224 IOFreePageable(addr, size);
1225
1226 addr = IOMallocPageableZero(size, alignment);
1227 if (addr == NULL) {
1228 IOLog("IOMallocPageableZero(size=%u, alignment=%u) failed\n", (uint32_t)size, (uint32_t)alignment);
1229 return kIOReturnError;
1230 }
1231 if (((uintptr_t)addr & alignMask) != 0) {
1232 IOLog("IOMallocPageableZero(size=%u, alignment=%u) returned unaligned pointer %p\n", (uint32_t)size, (uint32_t)alignment, addr);
1233 return kIOReturnError;
1234 }
1235 for (char * ptr = (char *)addr; ptr < (char *)addr + size; ptr++) {
1236 if (*ptr != 0) {
1237 IOLog("IOMallocPageableZero(size=%u, alignment=%u) -> %p, byte at %p is nonzero\n", (uint32_t)size, (uint32_t)alignment, addr, ptr);
1238 }
1239 }
1240 IOFreePageable(addr, size);
1241 }
1242 }
1243
1244 return kIOReturnSuccess;
1245 }
1246
1247
1248 #endif /* DEVELOPMENT || DEBUG */
1249
1250 #ifndef __clang_analyzer__
1251 // All the scary things that this function is doing, such as the intentional
1252 // overrelease of an OSData, are hidden from the static analyzer.
1253 static int
sysctl_iokittest(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1254 sysctl_iokittest(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1255 {
1256 int error;
1257 int newValue, changed;
1258
1259 error = sysctl_io_number(req, 0, sizeof(int), &newValue, &changed);
1260 if (error) {
1261 return error;
1262 }
1263
1264 #if DEVELOPMENT || DEBUG
1265 if (changed && (66 == newValue)) {
1266 IOReturn ret;
1267 OSSharedPtr<IOWorkLoop> wl = IOWorkLoop::workLoop();
1268 OSSharedPtr<IOCommandGate> cg = IOCommandGate::commandGate(wl.get());
1269 ret = wl->addEventSource(cg.get());
1270
1271 struct x {
1272 uint64_t h;
1273 uint64_t l;
1274 };
1275 struct x y;
1276
1277 y.h = 0x1111111122222222;
1278 y.l = 0x3333333344444444;
1279
1280 kprintf("ret1 %d\n", ret);
1281 ret = cg->runActionBlock(^(){
1282 printf("hello %d 0x%qx\n", wl->inGate(), y.h);
1283 return 99;
1284 });
1285 kprintf("ret %d\n", ret);
1286 }
1287
1288 if (changed && (999 == newValue)) {
1289 OSSharedPtr<OSData> data = OSData::withCapacity(16);
1290 data->release();
1291 }
1292
1293 if (changed && (newValue >= 6666) && (newValue <= 6669)) {
1294 OSSharedPtr<OSIterator> iter;
1295 IOService * service;
1296
1297 service = NULL;
1298 OSSharedPtr<OSDictionary> matchingDict = IOService::nameMatching("XHC1");
1299 iter = IOService::getMatchingServices(matchingDict.get());
1300 if (iter && (service = (IOService *) iter->getNextObject())) {
1301 if (newValue == 6666) {
1302 IOLog("terminating 0x%qx\n", service->getRegistryEntryID());
1303 service->terminate();
1304 } else if (newValue == 6667) {
1305 IOLog("register 0x%qx\n", service->getRegistryEntryID());
1306 service->registerService();
1307 }
1308 }
1309 if (service) {
1310 return 0;
1311 }
1312 }
1313
1314
1315 if (changed && (555 == newValue)) {
1316 IOServiceStateNotificationTests(newValue);
1317 }
1318
1319 if (changed && newValue) {
1320 error = IOWorkLoopTest(newValue);
1321 assert(KERN_SUCCESS == error);
1322 error = IOServiceTest(newValue);
1323 assert(KERN_SUCCESS == error);
1324 error = OSCollectionTest(newValue);
1325 assert(KERN_SUCCESS == error);
1326 error = OSCollectionIteratorTests(newValue);
1327 assert(KERN_SUCCESS == error);
1328 error = OSAllocationTests(newValue);
1329 assert(KERN_SUCCESS == error);
1330 error = OSDataAllocationTests(newValue);
1331 assert(KERN_SUCCESS == error);
1332 error = OSBoundedArrayTests(newValue);
1333 assert(KERN_SUCCESS == error);
1334 error = OSBoundedArrayRefTests(newValue);
1335 assert(KERN_SUCCESS == error);
1336 error = OSBoundedPtrTests(newValue);
1337 assert(KERN_SUCCESS == error);
1338 error = OSValueObjectTests(newValue);
1339 assert(KERN_SUCCESS == error);
1340 error = IOMemoryDescriptorTest(newValue);
1341 assert(KERN_SUCCESS == error);
1342 error = OSSharedPtrTests(newValue);
1343 assert(KERN_SUCCESS == error);
1344 error = IOSharedDataQueue_44636964(newValue);
1345 assert(KERN_SUCCESS == error);
1346 error = IOUserNotificationTests(newValue);
1347 assert(KERN_SUCCESS == error);
1348 error = IOMallocPageableTests(newValue);
1349 assert(KERN_SUCCESS == error);
1350 }
1351 #endif /* DEVELOPMENT || DEBUG */
1352
1353 return error;
1354 }
1355
1356 SYSCTL_PROC(_kern, OID_AUTO, iokittest,
1357 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
1358 NULL, 0, sysctl_iokittest, "I", "");
1359 #endif // __clang_analyzer__
1360
1361 #if DEVELOPMENT || DEBUG
1362
1363 /*
1364 * A simple wrapper around an IOService. This terminates the IOService in free().
1365 */
1366 class TestIOServiceHandle : public OSObject
1367 {
1368 OSDeclareDefaultStructors(TestIOServiceHandle);
1369 public:
1370 static TestIOServiceHandle * withService(IOService * service);
1371
1372 private:
1373 bool initWithService(IOService * service);
1374 virtual void free() APPLE_KEXT_OVERRIDE;
1375
1376 IOService * fService;
1377 };
1378
1379 OSDefineMetaClassAndStructors(TestIOServiceHandle, OSObject);
1380
1381 TestIOServiceHandle *
withService(IOService * service)1382 TestIOServiceHandle::withService(IOService * service)
1383 {
1384 TestIOServiceHandle * handle = new TestIOServiceHandle;
1385 if (handle && !handle->initWithService(service)) {
1386 return NULL;
1387 }
1388 return handle;
1389 }
1390
1391 bool
initWithService(IOService * service)1392 TestIOServiceHandle::initWithService(IOService * service)
1393 {
1394 fService = service;
1395 fService->retain();
1396 return true;
1397 }
1398
1399 void
free()1400 TestIOServiceHandle::free()
1401 {
1402 if (fService) {
1403 fService->terminate();
1404 OSSafeReleaseNULL(fService);
1405 }
1406 }
1407
1408 /*
1409 * Set up test IOServices. See the available services in xnu/iokit/Tests/TestServices.
1410 *
1411 * xnu darwintests use this sysctl to make these test services available. A send right is pushed
1412 * to the task that called the sysctl, which when deallocated removes the service. This ensures
1413 * that the registry isn't polluted by misbehaving tests.
1414 *
1415 * Since this sysctl allows callers to instantiate arbitrary classes based on their class name,
1416 * this can be a security concern. Tests that call this sysctl need the
1417 * kIOServiceTestServiceManagementEntitlementKey entitlement.
1418 */
1419 static int
sysctl_iokit_test_service_setup(struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)1420 sysctl_iokit_test_service_setup(struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1421 {
1422 char classname[128] = {0};
1423 IOService * service; // must not release
1424 OSObject * obj = NULL; // must release
1425 IOService * provider = NULL; // must not release
1426 TestIOServiceHandle * handle = NULL; // must release
1427 mach_port_name_t name __unused;
1428 int error;
1429
1430 if (!IOTaskHasEntitlement(current_task(), kIOServiceTestServiceManagementEntitlementKey)) {
1431 error = EPERM;
1432 goto finish;
1433 }
1434
1435 error = sysctl_handle_string(oidp, classname, sizeof(classname), req);
1436 if (error != 0) {
1437 goto finish;
1438 }
1439
1440 /*
1441 * All test services currently attach to IOResources.
1442 */
1443 provider = IOService::getResourceService();
1444 if (!provider) {
1445 IOLog("Failed to find IOResources\n");
1446 error = ENOENT;
1447 goto finish;
1448 }
1449
1450 obj = OSMetaClass::allocClassWithName(classname);
1451 if (!obj) {
1452 IOLog("Failed to alloc class %s\n", classname);
1453 error = ENOENT;
1454 goto finish;
1455 }
1456
1457 service = OSDynamicCast(IOService, obj);
1458
1459 if (!service) {
1460 IOLog("Instance of class %s is not an IOService\n", classname);
1461 error = EINVAL;
1462 goto finish;
1463 }
1464
1465 if (!service->init()) {
1466 IOLog("Failed to initialize %s\n", classname);
1467 error = EINVAL;
1468 goto finish;
1469 }
1470
1471 if (!service->attach(provider)) {
1472 IOLog("Failed to attach %s\n", classname);
1473 error = EINVAL;
1474 goto finish;
1475 }
1476
1477 if (!service->start(provider)) {
1478 IOLog("Failed to start %s\n", classname);
1479 error = EINVAL;
1480 goto finish;
1481 }
1482
1483 handle = TestIOServiceHandle::withService(service);
1484 if (!handle) {
1485 IOLog("Failed to create service handle\n");
1486 error = ENOMEM;
1487 goto finish;
1488 }
1489 name = iokit_make_send_right(current_task(), handle, IKOT_IOKIT_OBJECT);
1490
1491 error = 0;
1492
1493 finish:
1494
1495 OSSafeReleaseNULL(obj);
1496 OSSafeReleaseNULL(handle);
1497 return error;
1498 }
1499
1500
1501 SYSCTL_PROC(_kern, OID_AUTO, iokit_test_service_setup,
1502 CTLTYPE_STRING | CTLFLAG_WR | CTLFLAG_KERN | CTLFLAG_LOCKED,
1503 NULL, 0, sysctl_iokit_test_service_setup, "-", "");
1504
1505 #endif /* DEVELOPMENT || DEBUG */
1506
1507
1508 static __unused void
CastCompileTest(OSObject * obj)1509 CastCompileTest(OSObject *obj)
1510 {
1511 IOService * service1 = OSDynamicCast(IOService, obj);
1512 if (service1) {
1513 service1->terminate();
1514 }
1515 IOService *service2 = OSRequiredCast(IOService, obj);
1516 if (service2) {
1517 service2->terminate();
1518 }
1519 }
1520