SCSIControllerDriverKit

RSS for tag

Develop drivers for SCSI protocol-based devices.

Posts under SCSIControllerDriverKit tag

44 Posts

Post

Replies

Boosts

Views

Activity

Archive Fails: Conflict with Existing KEXT Developer ID Certificate
Hi everyone, We're trying to prepare a DriverKit App for a client test, and we've run into an unavoidable signing conflict that seems to be caused by the Xcode Archive process itself. Background & Environment: Environment: macOS 15.6.1, Xcode 16.4 Our project consists of a main App Target and a DEXT Target. Both the Debug and Release configurations for both targets are set to Xcode's default: Automatically manage signing. Our developer account holds a valid, active Developer ID Application (With Kext) certificate, which we use for signing our legacy KEXT. The Action That Triggers Failure: From this clean state, we execute Product -> Archive. The Archive process fails during the signing validation phase and presents the following three errors, completely halting the process: There is a problem with the request entity - You already have a current Developer ID Application Managed (With Kext) certificate... No profiles for 'com.company.Acxxx.driver' were found... No profiles for 'com.company.Acxxx.app' were found... This error seems to indicate that the Xcode Archive process: Ignores the project's Release configuration (even the default 'Auto' setting). Attempts to automatically create a new, standard Developer ID certificate for us. This action conflicts with the existing (With Kext) certificate in our account, causing the entire Archive process to fail. The "Failed Experiment" to Resolve This: To work around this automation conflict, we tried the solution: configuring a fully manual signing process for the Release configuration to explicitly tell Xcode to use our existing KEXT certificate. Our Steps: We disabled automatic signing for both the App and DEXT targets for the Release configuration and manually assigned the Developer ID Provisioning Profiles created for our Developer ID (With Kext) certificate. The New Problem: After doing this, the Signing Certificate field for the DEXT Target's Signing & Capabilities interface now shows None, accompanied by the misleading warning about needing a DriverKit development profile. The Outcome: This None issue now prevents us from even starting the Archive process, as the project fails to build due to the incorrect signing configuration. We've tried every debugging step — including rebuilding profiles, validating the keychain, and clearing caches — but nothing resolves this None issue. Our Dilemma: State A (Fully Automatic Signing): The Archive process fails due to the KEXT certificate conflict. State B (Manual Release Signing): The project fails to build due to the Signing Certificate: None issue, preventing us from initiating an Archive. For a development team holding a KEXT Developer ID certificate, how should an Xcode project be configured when migrating to DriverKit, so that the Archive process: Does not trigger the flawed automation logic that attempts to create a new certificate? And, does not fall into the Signing Certificate: None configuration trap? Related Forum Threads We've Studied: https://developer.apple.com/forums/thread/781932 https://developer.apple.com/forums/thread/751490 https://developer.apple.com/forums/thread/767152 https://developer.apple.com/forums/thread/721563 Best Reagrds, Charles
2
0
827
Dec ’25
INQUIRY command is ILLEGAL REQUEST
I am developing a DriverKit driver with the goal of sending vendor-specific commands to a USB storage device. I have successfully created the DriverKit driver, and when I connect the USB storage device, it appears correctly in IORegistryExplorer. My driver class inherits from IOUserSCSIPeripheralDeviceType00 in the SCSIPeripheralsDriverKit framework. I also created a UserClient class that inherits from IOUserClient, and from its ExternalMethod I tried sending an INQUIRY command as a basic test to confirm that command transmission works. However, the device returns an ILLEGAL REQUEST (Sense Key 0x5 / ASC 0x20). Could someone advise what I might be doing wrong? Below are the logs output from the driver: 2025-11-14 21:00:43.573730+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] Driver - NewUserClient() - Finished. 2025-11-14 21:00:43.573733+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - Start() 2025-11-14 21:00:43.573807+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - Start() - Finished. 2025-11-14 21:00:43.574249+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - ExternalMethod() called 2025-11-14 21:00:43.574258+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - ----- SCSICmdINQUIRY ----- 2025-11-14 21:00:43.574268+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - command.fRequestedByteCountOfTransfer = 512 2025-11-14 21:00:43.575980+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - SCSICmdINQUIRY() UserSendCDB fCompletionStatus = 0x0 2025-11-14 21:00:43.575988+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - SCSICmdINQUIRY() UserSendCDB fServiceResponse = 0x2 2025-11-14 21:00:43.575990+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - SCSICmdINQUIRY() UserSendCDB fSenseDataValid = 0x1 2025-11-14 21:00:43.575992+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - SCSICmdINQUIRY() UserSendCDB VALID_RESPONSE_CODE = 0x70 2025-11-14 21:00:43.575994+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - SCSICmdINQUIRY() UserSendCDB SENSE_KEY = 0x5 2025-11-14 21:00:43.575996+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - SCSICmdINQUIRY() UserSendCDB ADDITIONAL_SENSE_CODE = 0x20 2025-11-14 21:00:43.575998+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - SCSICmdINQUIRY() UserSendCDB ADDITIONAL_SENSE_CODE_QUALIFIER = 0x0 Here is the UserClient class: class SampleDriverKitUserClient: public IOUserClient { public: virtual bool init(void) override; virtual kern_return_t Start(IOService* provider) override; virtual kern_return_t Stop(IOService* provider) override; virtual void free(void) override; virtual kern_return_t ExternalMethod( uint64_t selector, IOUserClientMethodArguments* arguments, const IOUserClientMethodDispatch* dispatch, OSObject* target, void* reference) override; void SCSICmdINQUIRY(SampleDriverKitDriver *driver) LOCALONLY; }; Here is the part that sends the INQUIRY command: void SampleDriverKitUserClient::SCSICmdINQUIRY(SampleDriverKitDriver *driver) { kern_return_t kr = KERN_SUCCESS; SCSIType00OutParameters command = {}; UInt8 dataBuffer[512] = {0}; SCSI_Sense_Data senseData = {0}; Log("----- SCSICmdINQUIRY -----"); SetCommandCDB(&command.fCommandDescriptorBlock, 0x12, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); command.fLogicalUnitNumber = 0; command.fTimeoutDuration = 10000; // milliseconds command.fRequestedByteCountOfTransfer = sizeof(dataBuffer); Log("command.fRequestedByteCountOfTransfer = %lld", command.fRequestedByteCountOfTransfer); command.fBufferDirection = kIOMemoryDirectionIn; command.fDataTransferDirection = kSCSIDataTransfer_FromTargetToInitiator; command.fDataBufferAddr = reinterpret_cast<uint64_t>(dataBuffer); command.fSenseBufferAddr = reinterpret_cast<uint64_t>(&senseData); command.fSenseLengthRequested = sizeof(senseData); if( driver ) { SCSIType00InParameters response = {}; kr = driver->UserSendCDB(command, &response); if( kr != KERN_SUCCESS ) { Log("SCSICmdINQUIRY() UserSendCDB failed (0x%x)", kr); return; } Log("SCSICmdINQUIRY() UserSendCDB fCompletionStatus = 0x%x", response.fCompletionStatus); Log("SCSICmdINQUIRY() UserSendCDB fServiceResponse = 0x%x", response.fServiceResponse); Log("SCSICmdINQUIRY() UserSendCDB fSenseDataValid = 0x%x", response.fSenseDataValid); Log("SCSICmdINQUIRY() UserSendCDB VALID_RESPONSE_CODE = 0x%x", senseData.VALID_RESPONSE_CODE); Log("SCSICmdINQUIRY() UserSendCDB SENSE_KEY = 0x%x", senseData.SENSE_KEY); Log("SCSICmdINQUIRY() UserSendCDB ADDITIONAL_SENSE_CODE = 0x%x", senseData.ADDITIONAL_SENSE_CODE); Log("SCSICmdINQUIRY() UserSendCDB ADDITIONAL_SENSE_CODE_QUALIFIER = 0x%x", senseData.ADDITIONAL_SENSE_CODE_QUALIFIER); if( response.fServiceResponse == kSCSIServiceResponse_TASK_COMPLETE ) { Log("SCSICmdINQUIRY() UserSendCDB complete success!!"); } for( int i=0; i < 5; i++ ) { Log("data [%04d]=0x%x [%04d]=0x%x [%04d]=0x%x [%04d]=0x%x [%04d]=0x%x [%04d]=0x%x [%04d]=0x%x [%04d]=0x%x", i*8+0, dataBuffer[i*8+0], i*8+1, dataBuffer[i*8+1], i*8+2, dataBuffer[i*8+2], i*8+3, dataBuffer[i*8+3], i*8+4, dataBuffer[i*8+4], i*8+5, dataBuffer[i*8+5], i*8+6, dataBuffer[i*8+6], i*8+7, dataBuffer[i*8+7] ); } char vendorID[9] = {0}; memcpy(vendorID, &dataBuffer[8], 8); Log("vendorID = %s",vendorID); char productID[17] = {0}; memcpy(productID, &dataBuffer[16], 16); Log("productID = %s",productID); } } My environment is: MacBook Pro (M2), macOS 15.6 If anyone has insight into what causes the ILLEGAL REQUEST, or what I am missing when using IOUserSCSIPeripheralDeviceType00 and UserSendCDB, I would greatly appreciate your help. Thank you.
1
0
661
Nov ’25
Architectural Performance Difference in External Storage I/O Between Intel and Apple Silicon Macs
Hi everyone, We are in the process of migrating a legacy KEXT for our external multi-disk RAID enclosure to the modern DriverKit framework. During the performance validation of our KEXT, we observed a large and consistent maximum throughput difference between Intel-based Macs and Apple Silicon-based Macs. We would like to share our findings and hope to discuss with others in the community to see if you have had similar experiences that could confirm or correct our understanding. The Observation: A Consistent Performance Gap When using the exact same external RAID hardware (an 8-HDD RAID 5 array), driven by our mature KEXT, we see the following results in high-throughput benchmarks (AJA System Test, large sequential writes): On a 2020 Intel-based Mac: We consistently achieve a throughput of ~2500 MB/s. On modern M-series Macs (from M1 to M4): The throughput is consistently capped at ~1500 MB/s. This performance difference of nearly 40% is significant and is present across the entire Apple Silicon product line. Our Hypothesis: A Shift in Architectural Design Philosophy Since the KEXT and external hardware are identical in both tests, we believe this performance difference is not a bug but a fundamental platform architecture distinction. Our hypothesis is as follows: 1. The Intel Mac Era ("Dedicated Throughput") The Intel-based Macs we tested use a dedicated, discrete Intel Thunderbolt controller chip. This chip has its own dedicated PCIe lanes and resources, and its design appears to be singularly focused on maximizing raw, sustained data throughput for external peripherals. 2. The Apple Silicon Era ("Integrated Efficiency") In contrast, M-series Macs use a deeply integrated I/O controller inside the SoC. This controller must share resources, such as the total unified memory bandwidth and the chip's overall power budget, with all other functional units (CPU, GPU, etc.). We speculate that the design priority for this integrated I/O controller has shifted from "maximizing single-task raw throughput" to "maximizing overall system efficiency, multi-task responsiveness, and low latency." As a result, in a pure, single-task storage benchmark, its performance ceiling may be lower than that of the older, dedicated-chip architecture. Our Question to the Community: Is our understanding correct? Have other developers of high-performance storage drivers or peripherals also observed a similar performance ceiling for external storage on Apple Silicon Macs, when compared to high-end Intel Macs? We believe that understanding this as a deliberate architectural trade-off is crucial for setting realistic performance targets for our DEXT. Our current goal has been adjusted to have our DEXT match the KEXT's ~1500 MB/s on the M-series platform. Any insights, confirmations, or corrections from the community or Apple engineers would be greatly appreciated. Thank you very much! Charles
1
0
596
Nov ’25
DriverKit IOUserSCSIPeripheralDeviceType00: kernel panic when setPowerState exceeds 20 seconds
We have an IOUserSCSIPeripheralDeviceType00 class DEXT supporting USB attached devices. With some high-capacity drives, the default setPowerState can exceed 20s to complete. This triggers a kernel panic, although this drive behavior is not unexpected. With a kernel extension implementing similar functionality we see no such problem as it appears from reading of Apple open source the timeout was 100s. What changes will allow setPowerState to complete without the kernel panic? kernel panic report excerpt attached. panic-full-2025-09-04-063127.0003.txt
3
0
491
Oct ’25
Implementing Hardware Interrupt Handling with InterruptOccurred in DriverKit
Hello everyone, I’m working on implementing hardware interrupt handling in DriverKit and came across the InterruptOccurred method in IOInterruptDispatchSource. I noticed that its declaration ends with a TYPE macro: virtual void InterruptOccurred(OSAction* action, uint64_t count, uint64_t time) TYPE(IOInterruptDispatchSource::InterruptOccurred); This structure seems similar to how Timer Events are set up, where an event is linked to a callback and triggered by a timer. I’m attempting to use a similar approach, but for hardware-triggered interrupts rather than timer events. I’m currently in the trial-and-error phase of the implementation, but if anyone has a working example or reference on how to properly implement and register InterruptOccurred, it would be greatly appreciated! Best regards, Charles
3
0
584
May ’25
macOS Hang After Implementing UserMapHBAData()
Hi everyone, I was following the Video Modernize PCI and SCSI drivers with DriverKit and the Document to implement UserMapHBAData(), and here’s my current implementation: // kern_return_t DRV_MAIN_CLASS_NAME::UserMapHBAData_Impl(uint32_t *uniqueTaskID) kern_return_t IMPL(DRV_MAIN_CLASS_NAME, UserMapHBAData) { Log("UserMapHBAData() - Start"); // Define the vm_page_size explicitly const uint32_t vm_page_size = 4096; kern_return_t ret; IOBufferMemoryDescriptor *buffer = nullptr; IOMemoryMap *memMap = nullptr; void *taskData = nullptr; // Create a buffer for HBA-specific task data ret = IOBufferMemoryDescriptor::Create(kIOMemoryDirectionOutIn, ivars->fTaskDataSize, vm_page_size, &buffer); __Require((kIOReturnSuccess == ret), Exit); // Map memory to the driver extension's memory space ret = buffer->CreateMapping(0, 0, 0, 0, 0, &memMap); __Require((kIOReturnSuccess == ret), Exit); // Retrieve mapped memory address taskData = reinterpret_cast<void *>(memMap->GetAddress()); __Require(taskData, Exit); // WARNING: Potential leak of an object stored into 'buffer' // WARNING: Potential leak of an object stored into 'memMap' // Assign a unique task ID ivars->fTaskID++; // ERROR: No member named 'fTaskID' in 'DriverKitAcxxx_IVars' ivars->fTaskArray[ivars->fTaskID] = taskData; *uniqueTaskID = ivars->fTaskID; Log("UserMapHBAData() - End"); return kIOReturnSuccess; Exit: // Cleanup in case of failure if (memMap) { memMap->free(); // Correct method for releasing memory maps } if (buffer) { buffer->free(); // Correct method for releasing buffer memory } LogErr("ret = 0x%0x", ret); Log("UserMapHBAData() - End"); return ret; } For reference, in KEXT, memory allocation is typically done using: IOBufferMemoryDescriptor *buffer = IOBufferMemoryDescriptor::inTaskWithOptions( kernel_task, // Task in which memory is allocated kIODirectionOutIn, // Direction (read/write) 1024, // Size of the buffer in bytes 4); // Alignment requirements However, after installing the dext, macOS hangs, and I have to do a hardware reset. After rebooting, the sysctl list output shows: % sectl list 1 extension(s) --- com.apple.system_extension.driver_extension enabled active teamID bundleID (version) name [state] * - com.accusys.DriverKitAcxxx (5.0/11) com.accusys.DriverKitAcxxx [activated waiting for user] Questions: What could be causing macOS to halt? How should I approach debugging and resolving this issue? Looking forward to your insights, any suggestions would be greatly appreciated! Best regards, Charles
7
0
914
May ’25
How to setup DriverKit Timer Event with OSAction Callback Binding
Hello Everyone, I'm encountering an issue while setting up a timer event in DriverKit and would appreciate any guidance. Here's my current implementation: void DRV_MAIN_CLASS_NAME::SetupEventTimer() { // 1. Create dispatch queue kern_return_t ret = IODispatchQueue::Create("TimerQueue", 0, 0, &ivars->dispatchQueue); if (ret != kIOReturnSuccess) { LogErr("Failed to create dispatch queue: 0x%x", ret); return; } // 2. Create timer source ret = IOTimerDispatchSource::Create(ivars->dispatchQueue, &ivars->dispatchSource); if (ret != kIOReturnSuccess) { LogErr("Failed to create timer: 0x%x", ret); OSSafeReleaseNULL(ivars->dispatchQueue); return; } /*! * @brief Create an instance of OSAction. * @discussion Methods to allocate an OSAction instance are generated for each method defined in a class with * a TYPE attribute, so there should not be any need to directly call OSAction::Create(). * @param target OSObject to receive the callback. This object will be retained until the OSAction is * canceled or freed. * @param targetmsgid Generated message ID for the target method. * @param msgid Generated message ID for the method invoked by the receiver of the OSAction * to generate the callback. * @param referenceSize Size of additional state structure available to the creator of the OSAction * with GetReference. * @param action Created OSAction with +1 retain count to be released by the caller. * @return kIOReturnSuccess on success. See IOReturn.h for error codes. */ // 3: Create an OSAction for the TimerOccurred method // THIS IS WHERE I NEED HELP OSAction* timerAction = nullptr; ret = OSAction::Create(this, 0, 0, 0, &timerAction); if (ret != kIOReturnSuccess) { LogErr("Failed to create OSAction: 0x%x", ret); goto cleanup; } // 4. Set handler ret = ivars->dispatchSource->SetHandler(timerAction); if (ret != kIOReturnSuccess) { LogErr("Failed to set handler: 0x%x", ret); goto cleanup; } // 5. Schedule timer (1 second) uint64_t deadline = mach_absolute_time() + NSEC_PER_SEC; ivars->dispatchSource->WakeAtTime(0, deadline, 0); cleanup: if (ret != kIOReturnSuccess) { OSSafeReleaseNULL(timerAction); OSSafeReleaseNULL(ivars->dispatchSource); OSSafeReleaseNULL(ivars->dispatchQueue); } } Problem: The code runs but the OSAction callback binding seems incorrect (Step 3). According to the OSAction documentation, I need to use the TYPE macro to properly bind the callback method. But I try to use TYPE(DRV_MAIN_CLASS_NAME::TimerOccurred) kern_return_t TimerOccurred() LOCALONLY; TYPE(TimerOccurred) kern_return_t TimerOccurred() LOCALONLY; kern_return_t TimerOccurred() TYPE(DRV_MAIN_CLASS_NAME::TimerOccurred) LOCALONLY; All results in Out-of-line definition of 'TimerOccurred' does not match any declaration in 'DRV_MAIN_CLASS_NAME' Questions: What is the correct way to declare a timer callback method using TYPE? How to get the values targetmsgid & msgid generated by Xcode? Any help would be greatly appreciated! Best Regards, Charles
6
0
624
Apr ’25
Why UserInitializeTargetForID() not be invoked after UserCreateTargetForID() successfully?
Hello Everyone, I am trying to create a Fake SCSI target based on SCSIControllerDriverKit.framework and inherent from IOUserSCSIParallelInterfaceController, here is the code kern_return_t IMPL(DRV_MAIN_CLASS_NAME, Start) { ... // Programmatically create a null SCSI Target SCSIDeviceIdentifier nullTargetID = 0; // Example target ID, adjust as needed ret = UserCreateTargetForID(nullTargetID, nullptr); if (ret != kIOReturnSuccess) { Log("Failed to create Null SCSI Target for ID %llu", nullTargetID); return ret; } ... } According the document UserCreateTargetForID, after creating a TargetID successfully, the framework will call the UserInitializeTargetForID() The document said: As part of the UserCreateTargetForID call, the kernel calls several APIs like UserInitializeTargetForID which run on the default dispatch queue of the dext. But after UserCreateTargetForID created, why the UserInitializeTargetForID() not be invoked automatically? Here is the part of log show init() - Start init() - End Start() - Start Start() - try 1 times UserCreateTargetForID() - Start Allocating resources for Target ID 0 UserCreateTargetForID() - End Start() - Finished. UserInitializeController() - Start - PCI vendorID: 0x14d6, deviceID: 0x626f. - BAR0: 0x1, BAR1: 0x200004. - GetBARInfo() - BAR1 - MemoryIndex: 0, Size: 262144, Type: 0. UserInitializeController() - End UserStartController() - Start - msiInterruptIndex : 0x00000000 - interruptType info is 0x00010000 - PCI Dext interrupt final value, return status info is 0x00000000 UserStartController() - End Any assistance would be greatly appreciated! Thank you in advance for your support. Best regards, Charles
1
0
644
Mar ’25
The Map() of IOBufferMemoryDescriptor failure and cause the DriverKit Start() repeat
Hello Everyone, I am trying to develop a DriverKit for RAID system, using PCIDriverKit & SCSIControllerDriverKit framework. The driver can detect the Vendor ID and Device ID. But before communicating to the RAID system, I would like to simulate a virtual Volume using a memory block to talk with macOS. In the UserInitializeController(), I allocated a 512K memory for a IOBufferMemoryDescriptor* volumeBuffer, but fail to use Map() to map memory for volumeBuffer. result = ivars->volumeBuffer->Map( 0, // Options: Use default 0, // Offset: Start of the buffer ivars->volumeSize, // Length: Must not exceed buffer size 0, // Flags: Use default nullptr, // Address space: Default address space &mappedAddress // Output parameter ); Log("Memory mapped completed at address: 0x%llx", mappedAddress); // this line never run The Log for Map completed never run, just restart to run the Start() and makes this Driver re-run again and again, in the end, the driver eat out macOS's memory and system halt. Are the parameters for Map() error? or I should not put this code in UserInitializeController()? Any help is appreciated! Thanks in advance. Charles
0
0
522
Mar ’25
DriverKit CppUserClient Searching for dext service but Failed opening service with error: 0xe00002c7
Hi Everybody, Follow Communicating between a DriverKit extension and a client app to migrate our kext to dext. The dext might have been loaded successfully by using the command systemextensionsctl list, the dext is loaded and enabled. % sectl list 1 extension(s) --- com.apple.system_extension.driver_extension enabled active teamID bundleID (version) name [state] * * K3TDMD9Y6B com.accusys.scsidriver (1.0/1) com.accusys.scsidriver [activated enabled] We try to use the CppUserClient.cpp to communicate with the dext, but can not get the dext service. The debug message as below: Failed opening service with error: 0xe00002c7. Here is the part of CppUserClient.cpp static const char* dextIdentifier = "com.accusys.scsidriver"; kern_return_t ret = kIOReturnSuccess; io_iterator_t iterator = IO_OBJECT_NULL; io_service_t service = IO_OBJECT_NULL; ret = IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching("IOUserServer"), &iterator); printf("dextIdentifier = %s\n", dextIdentifier); printf("IOServiceNameMatching return = %d\n", ret); if (ret != kIOReturnSuccess) { printf("Unable to find service for identifier with error: 0x%08x.\n", ret); PrintErrorDetails(ret); } printf("Searching for dext service...\n"); while ((service = IOIteratorNext(iterator)) != IO_OBJECT_NULL) { // Open a connection to this user client as a server to that client, and store the instance in "service" ret = IOServiceOpen(service, mach_task_self_, kIOHIDServerConnectType, &connection); if (ret == kIOReturnSuccess) { printf("\tOpened service.\n"); break; } else { printf("\tFailed opening service with error: 0x%08x.\n", ret); } IOObjectRelease(service); } IOObjectRelease(iterator); if (service == IO_OBJECT_NULL) { printf("Failed to match to device.\n"); return EXIT_FAILURE; } The console output message is dextIdentifier = com.accusys.scsidriver IOServiceNameMatching return = 0 Searching for dext service... Failed opening service with error: 0xe00002c7. Failed opening service with error: 0xe00002c7. Failed opening service with error: 0xe00002c7. Failed opening service with error: 0xe00002c7. Failed to match to device. Here is the log show message fredapp start UserInitializeController pcitest: fredapp pci vendorID: 14d6 deviceID: 626f fredapp nnnnnew configuaration read32 0x10 info: 1 fredapp nnnnnew configuaration read32 0x14 info: 80100004 fredapp new 128 before enable busmaster ReqMSGport_info 0x00000040 : fffff pcitest: fredapp 131 pci ConfigurationRead16 busmaster value 0 pcitest: fredapp 134 Enable BusMaster and IO space done...... locate 139 fredapp MemoryWrite32 function done...... fredapp new 143 after enable busmaster ReqMSGport_info 0x00000040 : 0 fredapp newwww before GetBARInfo memoryIndex1 info is: 5 fredapp GetBARInfo 1 kernel return status is: 0 fredapp GetBARInfo memoryIndex1 info is: 0 fredapp GetBARInfo barSize1 info is: 262144 fredapp GetBARInfo barType1 info is: 0 fredapp GetBARInfo result0 info is: 3758097136 fredapp GetBARInfo memoryIndex0 info is: 0 fredapp GetBARInfo barSize0 info is: 0 fredapp GetBARInfo barType0 info is: 0 pcitest: newwww fredapp againnnn test ReqMSGport info: 8 fredapp Start MPIO_Init_Prepare fredapp end MPIO_Init_Prepare. fredapp call 741 Total_memory_size: 1bb900 fredapp Start MemoryAllocationForAME_Module. fredapp IOBufferMemoryDescriptor create return status info is kIOReturnSuc fredapp IOBufferMemoryDescriptor virtualAddressSegment address info: 0x1 fredapp virtualAddressSegment length info: 0x00080000 fredapp end IOBufferMemoryDescriptor Create. fredapp dmaSpecification maxAddressBits: 0x00000000 fredapp dmaSpecification maxAddressBits: 0x00000027 fredapp IODMACommand create return status info is kIOReturnSuccess fredapp end IODMACommand Create. fredapp PrepareForDMA return status info is kIOReturnSuccess fredapp PrepareForDMA return status info is 0x00000000 fredapp Allocate memory PrepareforDMA return flags info: 0x00000003 fredapp Allocate memory PrepareforDMA return segmentsCount info: 0x00000 fredapp Allocate memory PrepareforDMA return physicalAddressSegment info: fredapp IOBufferMemoryDescriptor virtualAddressSegment address info-2: 0 fredapp verify data success init() - Finished. fredapp start UserGetDMASpecification fredapp end UserGetDMASpecification fredapp start UserMapHBAData fredapp end UserMapHBAData fredapp start UserStartController fredapp interruptType info is 0x00010000 fredapp PCI Dext interrupt final value return status info is 0x00000000 Any suggestions? Best Regards, Charles
6
0
1k
Jan ’25
SCSIPeripheralsDriverKit/IOUserSCSIPeripheralDeviceType00 Error:kIOReturnUnsupported (0xe00002c7)
I am using SCSIPeripheralsDriverKit/IOUserSCSIPeripheralDeviceType00 to develop a Dext driver, which has only two classes: MyUserSCSIPeripheralDeviceType00 and MyUserClient, MyUserClient is responsible for receiving APP commands and passing them to MyUserSCSIPeripheralDeviceType00->UserSendCDB(), After the device is connected to the computer, the driver can match the device and start, calling MyUserSCSIPeripheralDeviceType00-->init(), MyUserSCSIPeripheralDeviceType00-->Start(), Any command sent by the APP to MyUserSCSIPeripheralDeviceType00 will return a failure: kIOReturnUnsupported (0xe00002c7), including UserSendCDB(), UserReportMediumBlockSize(), <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>IOKitPersonalities</key> <dict> <key>MySCSIDriver</key> <dict> <key>CFBundleIdentifier</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleIdentifierKernel</key> <string>com.apple.kpi.iokit</string> <key>IOClass</key> <string>IOUserService</string> <key>IOMatchCategory</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>IOProviderClass</key> <string>IOSCSIPeripheralDeviceNub</string> <key>IOResourceMatch</key> <string>IOKit</string> <key>IOUserClass</key> <string>MyUserSCSIPeripheralDeviceType00</string> <key>IOUserServerName</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>UserClientProperties</key> <dict> <key>IOClass</key> <string>IOUserUserClient</string> <key>IOUserClass</key> <string>MyUserClient</string> </dict> <key>bConfigurationValue</key> <integer>1</integer> <key>bInterfaceNumber</key> <integer>0</integer> <key>bcdDevice</key> <integer>1</integer> <key>idProduct</key> <string>*</string> <key>idVendor</key> <integer>12345</integer> <key>Peripheral Device Type</key> <integer>0</integer> <key>IOKitDebug</key> <integer>65535</integer> </dict> </dict> </dict> </plist> This is the method that receives client calls kern_return_t MyUserSCSIPeripheralDeviceType00::HandleExternalStruct(IOUserClientMethodArguments* arguments) { kern_return_t ret = kIOReturnSuccess; SCSIType00OutParameters command; SCSIType00InParameters response; SCSI_Sense_Data sense; UInt64 fSenseAddr = (intptr_t)&sense; bzero((void *)&command, sizeof(SCSIType00OutParameters)); bzero((void *)&response, sizeof(SCSIType00InParameters)); bool test = TEST_UNIT_READY(&command, &response, fSenseAddr); // test is true ret = this->UserSendCDB(command, &response); // ret is kIOReturnUnsupported (0xe00002c7) UInt64 blockSize; kern_return_t sizeRet = this->UserReportMediumBlockSize(&blockSize); // sizeRet is kIOReturnUnsupported (0xe00002c7) }; // Not called. As per the documentation, this should be called during enumeration. kern_return_t IMPL(I4UserSCSIPeripheralDeviceType00, UserDetermineDeviceCharacteristics) { // *result = true; return kIOReturnSuccess; }
0
0
881
Apr ’24
Need an assistance to fetch the PCI devices information using PCIDrivers
I'm currently working on developing a PCI driver using PCIDriverKit, but I'm encountering challenges, particularly with the driver's extension. I need some insights on the APIs and methods to follow the best practices in generating PCI drivers for retrieving PCI devices information and running NVMe commands on the devices.
3
0
1.5k
Feb ’24
Is SCSIPeripheralsDriverKit on board?
I've try to develop a dext to send SCSI commands to some storage products, but when I try to implements SCSIPeripheralsDriverKit/IOUserSCSIPeripheralDeviceType00 interface, I... just don't know how to do it, I tried to convert kext way to Driverkit way, but I always block by error warnings. After I google a lots of solutions, I was wondering is this feature working? or Is there any samples or guideline?
0
0
707
Jun ’23
How to access dmaaddress (Physical Address) in DriverKit?
I am trying to use IOUserBlockStorageDevice in DriverKit to simulate a fake device (Implementing a Ram Disk). Currently I'm confused on how to use the dmaaddress in the following interface virtual kern_return_t DoAsyncReadWrite (bool isRead, uint32_t requestID, uint64_t dmaAddr, uint64_t size, uint64_t lba, uint64_t numOfBlocks, IOUserStorageOptions options) = 0; According to https://github.com/briancabbott/macOS-system-projects/blob/19310aa5c7b7507408261a22a2e8f46f9d478a88/Resources/Code/apple-oss-distributions/IOStorageFamily/IOUserBlockStorageDevice_kext.cpp Before calling "DoAsyncReadWrite", kernel allocate a segment of physical memory by using "IODMAcommand::genIOVMSegments". This segment's physical address is pass to DoAsyncReadWrite as parameter "dmaAddr". To implement a correct ram disk, we need to "transform" this physical address to virtual so that we can "Read" or "Write" on this physical address. I tried to use "IOMemoryDescriptor" to access this dmaAddr. In IOKit, I belive I can use interface such as "withPhysicalAddress" to access the memory. However, such interface is not exist while using driverkit, all interface that I can use in DriverKit IOMemoryDescriptor is : -kern_return_t GetLength(uint64_t * returnLength) LOCALONLY; // apparently not this one -virtual kern_return_t CreateMapping( uint64_t options, uint64_t address, uint64_t offset, uint64_t length, uint64_t alignment, IOMemoryMap ** map); // Maybe this one with kIOMemoryFixedAddress option? // But I get Segment Fault while calling this with CreateMapping( kIOMemoryFixedAddress , dmaaddr, 0, size, 0, &map); // Or getting error return while calling CreateMapping with same paramters after IOBufferMemoryDescriptor::Create // Also, output iomemorymap is not used here, which is quiet strange. static kern_return_t CreateSubMemoryDescriptor(uint64_t memoryDescriptorCreateOptions, uint64_t offset, uint64_t length, IOMemoryDescriptor * ofDescriptor, IOMemoryDescriptor ** memory) attribute((availability(driverkit,introduced=20.0))); // Seems not this, it create “sub“ memory descriptor static kern_return_t CreateWithMemoryDescriptors(uint64_t memoryDescriptorCreateOptions, uint32_t withDescriptorsCount, IOMemoryDescriptor * const withDescriptors[32], IOMemoryDescriptor ** memory) attribute((availability(driverkit,introduced=20.0))); // Seems not this, it don’t take any dmaaddr as parameter. and a private function kern_return_t Map( uint64_t options, uint64_t address, uint64_t length, uint64_t alignment, uint64_t * returnAddress, uint64_t * returnLength) LOCALONLY; // Maybe this one? But the header file don’t show any description on this function and we are not sure what parameters should we pass. // Currently I've test Map( kIOMemoryFixedAddress , dmaaddr, size, 0, &returnAddress, &returnLength) but get error return. It seems that I've made some mistake on using IOMemoryDescriptor? How to correct access a dmaaddress? I've also tried class "IODMACommand", but also get unexpected behavior. Another question is how to read / write buffer after I create correct mapping. While implementing kext, IOMemoryDescriptor can use "readBytes" or "writeBytes" to read or write memory that IOMemoryDescriptor maps to. However, DriverKit don’t have interface of "readBytes" or "writeBytes". Maybe I can directly access buffer by casting the IOMemoryDescriptor::Map "returnAddress" to void? (I haven't tried it yet cause "Map" always failed now QQ) Thanks for everyone's help.
2
1
2.5k
Feb ’23
Sending SCSI commands to USB mass storage device
Our device is USB Mass stroage device. We want to send a specific SCSI command to a USB drive in Mac OS X. Have any demo app that uses IOUserSCSIPeripheralDeviceType00 in SCSIPeripheralsDriverKit? We want to use below SCSI command, but have no demo program. https://developer.apple.com/documentation/scsiperipheralsdriverkit/3946437-inquiry https://developer.apple.com/documentation/scsiperipheralsdriverkit/iouserscsiperipheraldevicetype00/3946461-usersendcdb
0
2
933
Nov ’22
SCSIControllerDriverKit: Process gets stuck on UserCreateTargetForID.
Context: We are working on migration of the driver, which is currently represented as a kernel extension, to the DriverKit framework. The driver works with Thunderbolt RAID storage devices. When connected through the Thunderbolt interface to the host, the device itself presents in the OS as a PCI device. The main function of our driver (.kext) is to create a "virtual" SCSI device in the OS for each virtual RAID array. So that the OS can work with these SCSI drives as usual disk storage.  We use https://developer.apple.com/documentation/scsicontrollerdriverkit to migrate this functionality in the dext version of the driver. Current issue: When a device is connected - the dext driver cannot create a SCSI drive in the OS. Technically our dext tries to create a SCSI drive using the UserCreateTargetForID method. On this step the OS sends the first SCSI command “Test Unit Ready ''to the device to check if it is a SCSI device. We process this command in an additional thread  separated from the main process of the dext (as it is recommended in the DriverKit documentation). We can see in the logs that the device receives this command and responses but when our dext sends this response to the OS the process is stuck in the waiting mode. How can we understand why it happens and fix it? More details: We are migrating functionality of an already existing “.kext” driver. We checked logs of the kext driver of this step: 15:06:17.902539+0700 Target device try to create for idx:0 15:06:17.902704+0700 Send command 0 for target 0 len 0 15:06:18.161777+0700 Complete command: 0 for target: 0 Len: 0 status: 0 flags: 0 15:06:18.161884+0700 Send command 18 for target 0 len 6 15:06:18.161956+0700 Complete command: 18 for target: 0 Len: 6 status: 0 flags: 0 15:06:18.162010+0700 Send command 18 for target 0 len 44 15:06:18.172972+0700 Complete command: 18 for target: 0 Len: 44 status: 0 flags: 0 15:06:18.275501+0700 Send command 18 for target 0 len 36 15:06:18.275584+0700 Complete command: 18 for target: 0 Len: 36 status: 0 flags: 0 15:06:18.276257+0700 Target device created for idx:0 We can see a successful message “Target device created for idx:0” In the the dext logs of the same step: We do not see the “Send command 18 for target 0 len 6” as we have in the kext logs  no log of the successful result “Target device created for idx:0” 15:54:10.903466+0700 Try to create target for 0 UUID 432421434863538456 15:54:10.903633+0700 UserDoesHBAPerformAutoSense 15:54:10.903763+0700 UserInitializeTargetForID 15:54:10.903876+0700 UserDoesHBASupportMultiPathing 15:54:10.904200+0700 UserProcessParallelTask start. 15:54:10.904298+0700 Sent command : 0 len 0 for target 0 15:54:11.163003+0700 Disable interrupts. 15:54:11.163077+0700 Complete cmd : 0 for target: 0 len: 0  status: 0 flags: 0 15:54:11.163085+0700 Enable interrupts. Will appreciate any help
3
1
1.4k
Nov ’22
Where is SCSIControllerDriverKit now?
Hi there! There was a presentation of the SCSI support in DriverKit on 2020 WWDC: https://developer.apple.com/videos/play/wwdc2020/10210/ Currently, the Xcode 12.4 (latest) has nothing regarding SCSI in DriverKit folders. Documentation says it is still in beta: https://developer.apple.com/documentation/scsicontrollerdriverkit So I've downloaded xcode 12.5 beta, where the driverkit 20.4 beta resides (according to https://developer.apple.com/support/xcode/) And what we have there? Just Kernel.framework/Versions/A/Headers/DriverKit/IOReturn.h 65:#define sub_iokit_scsi err_sub(16) And nothing more! So, the question is: do we have any way to use SCSI devices now on BigSur? Could I develop something for it with DriverKit, or should I use kext-approach for now, and wait for SCSI DriverKit support to be released indeed?
4
0
2.5k
Oct ’22
Archive Fails: Conflict with Existing KEXT Developer ID Certificate
Hi everyone, We're trying to prepare a DriverKit App for a client test, and we've run into an unavoidable signing conflict that seems to be caused by the Xcode Archive process itself. Background & Environment: Environment: macOS 15.6.1, Xcode 16.4 Our project consists of a main App Target and a DEXT Target. Both the Debug and Release configurations for both targets are set to Xcode's default: Automatically manage signing. Our developer account holds a valid, active Developer ID Application (With Kext) certificate, which we use for signing our legacy KEXT. The Action That Triggers Failure: From this clean state, we execute Product -> Archive. The Archive process fails during the signing validation phase and presents the following three errors, completely halting the process: There is a problem with the request entity - You already have a current Developer ID Application Managed (With Kext) certificate... No profiles for 'com.company.Acxxx.driver' were found... No profiles for 'com.company.Acxxx.app' were found... This error seems to indicate that the Xcode Archive process: Ignores the project's Release configuration (even the default 'Auto' setting). Attempts to automatically create a new, standard Developer ID certificate for us. This action conflicts with the existing (With Kext) certificate in our account, causing the entire Archive process to fail. The "Failed Experiment" to Resolve This: To work around this automation conflict, we tried the solution: configuring a fully manual signing process for the Release configuration to explicitly tell Xcode to use our existing KEXT certificate. Our Steps: We disabled automatic signing for both the App and DEXT targets for the Release configuration and manually assigned the Developer ID Provisioning Profiles created for our Developer ID (With Kext) certificate. The New Problem: After doing this, the Signing Certificate field for the DEXT Target's Signing & Capabilities interface now shows None, accompanied by the misleading warning about needing a DriverKit development profile. The Outcome: This None issue now prevents us from even starting the Archive process, as the project fails to build due to the incorrect signing configuration. We've tried every debugging step — including rebuilding profiles, validating the keychain, and clearing caches — but nothing resolves this None issue. Our Dilemma: State A (Fully Automatic Signing): The Archive process fails due to the KEXT certificate conflict. State B (Manual Release Signing): The project fails to build due to the Signing Certificate: None issue, preventing us from initiating an Archive. For a development team holding a KEXT Developer ID certificate, how should an Xcode project be configured when migrating to DriverKit, so that the Archive process: Does not trigger the flawed automation logic that attempts to create a new certificate? And, does not fall into the Signing Certificate: None configuration trap? Related Forum Threads We've Studied: https://developer.apple.com/forums/thread/781932 https://developer.apple.com/forums/thread/751490 https://developer.apple.com/forums/thread/767152 https://developer.apple.com/forums/thread/721563 Best Reagrds, Charles
Replies
2
Boosts
0
Views
827
Activity
Dec ’25
INQUIRY command is ILLEGAL REQUEST
I am developing a DriverKit driver with the goal of sending vendor-specific commands to a USB storage device. I have successfully created the DriverKit driver, and when I connect the USB storage device, it appears correctly in IORegistryExplorer. My driver class inherits from IOUserSCSIPeripheralDeviceType00 in the SCSIPeripheralsDriverKit framework. I also created a UserClient class that inherits from IOUserClient, and from its ExternalMethod I tried sending an INQUIRY command as a basic test to confirm that command transmission works. However, the device returns an ILLEGAL REQUEST (Sense Key 0x5 / ASC 0x20). Could someone advise what I might be doing wrong? Below are the logs output from the driver: 2025-11-14 21:00:43.573730+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] Driver - NewUserClient() - Finished. 2025-11-14 21:00:43.573733+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - Start() 2025-11-14 21:00:43.573807+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - Start() - Finished. 2025-11-14 21:00:43.574249+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - ExternalMethod() called 2025-11-14 21:00:43.574258+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - ----- SCSICmdINQUIRY ----- 2025-11-14 21:00:43.574268+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - command.fRequestedByteCountOfTransfer = 512 2025-11-14 21:00:43.575980+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - SCSICmdINQUIRY() UserSendCDB fCompletionStatus = 0x0 2025-11-14 21:00:43.575988+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - SCSICmdINQUIRY() UserSendCDB fServiceResponse = 0x2 2025-11-14 21:00:43.575990+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - SCSICmdINQUIRY() UserSendCDB fSenseDataValid = 0x1 2025-11-14 21:00:43.575992+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - SCSICmdINQUIRY() UserSendCDB VALID_RESPONSE_CODE = 0x70 2025-11-14 21:00:43.575994+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - SCSICmdINQUIRY() UserSendCDB SENSE_KEY = 0x5 2025-11-14 21:00:43.575996+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - SCSICmdINQUIRY() UserSendCDB ADDITIONAL_SENSE_CODE = 0x20 2025-11-14 21:00:43.575998+0900 0x26e9 Default 0x0 0 0 kernel: (SampleDriverKitApp.SampleDriverKitDriver.dext) [DEBUG] UserClient - SCSICmdINQUIRY() UserSendCDB ADDITIONAL_SENSE_CODE_QUALIFIER = 0x0 Here is the UserClient class: class SampleDriverKitUserClient: public IOUserClient { public: virtual bool init(void) override; virtual kern_return_t Start(IOService* provider) override; virtual kern_return_t Stop(IOService* provider) override; virtual void free(void) override; virtual kern_return_t ExternalMethod( uint64_t selector, IOUserClientMethodArguments* arguments, const IOUserClientMethodDispatch* dispatch, OSObject* target, void* reference) override; void SCSICmdINQUIRY(SampleDriverKitDriver *driver) LOCALONLY; }; Here is the part that sends the INQUIRY command: void SampleDriverKitUserClient::SCSICmdINQUIRY(SampleDriverKitDriver *driver) { kern_return_t kr = KERN_SUCCESS; SCSIType00OutParameters command = {}; UInt8 dataBuffer[512] = {0}; SCSI_Sense_Data senseData = {0}; Log("----- SCSICmdINQUIRY -----"); SetCommandCDB(&command.fCommandDescriptorBlock, 0x12, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); command.fLogicalUnitNumber = 0; command.fTimeoutDuration = 10000; // milliseconds command.fRequestedByteCountOfTransfer = sizeof(dataBuffer); Log("command.fRequestedByteCountOfTransfer = %lld", command.fRequestedByteCountOfTransfer); command.fBufferDirection = kIOMemoryDirectionIn; command.fDataTransferDirection = kSCSIDataTransfer_FromTargetToInitiator; command.fDataBufferAddr = reinterpret_cast<uint64_t>(dataBuffer); command.fSenseBufferAddr = reinterpret_cast<uint64_t>(&senseData); command.fSenseLengthRequested = sizeof(senseData); if( driver ) { SCSIType00InParameters response = {}; kr = driver->UserSendCDB(command, &response); if( kr != KERN_SUCCESS ) { Log("SCSICmdINQUIRY() UserSendCDB failed (0x%x)", kr); return; } Log("SCSICmdINQUIRY() UserSendCDB fCompletionStatus = 0x%x", response.fCompletionStatus); Log("SCSICmdINQUIRY() UserSendCDB fServiceResponse = 0x%x", response.fServiceResponse); Log("SCSICmdINQUIRY() UserSendCDB fSenseDataValid = 0x%x", response.fSenseDataValid); Log("SCSICmdINQUIRY() UserSendCDB VALID_RESPONSE_CODE = 0x%x", senseData.VALID_RESPONSE_CODE); Log("SCSICmdINQUIRY() UserSendCDB SENSE_KEY = 0x%x", senseData.SENSE_KEY); Log("SCSICmdINQUIRY() UserSendCDB ADDITIONAL_SENSE_CODE = 0x%x", senseData.ADDITIONAL_SENSE_CODE); Log("SCSICmdINQUIRY() UserSendCDB ADDITIONAL_SENSE_CODE_QUALIFIER = 0x%x", senseData.ADDITIONAL_SENSE_CODE_QUALIFIER); if( response.fServiceResponse == kSCSIServiceResponse_TASK_COMPLETE ) { Log("SCSICmdINQUIRY() UserSendCDB complete success!!"); } for( int i=0; i < 5; i++ ) { Log("data [%04d]=0x%x [%04d]=0x%x [%04d]=0x%x [%04d]=0x%x [%04d]=0x%x [%04d]=0x%x [%04d]=0x%x [%04d]=0x%x", i*8+0, dataBuffer[i*8+0], i*8+1, dataBuffer[i*8+1], i*8+2, dataBuffer[i*8+2], i*8+3, dataBuffer[i*8+3], i*8+4, dataBuffer[i*8+4], i*8+5, dataBuffer[i*8+5], i*8+6, dataBuffer[i*8+6], i*8+7, dataBuffer[i*8+7] ); } char vendorID[9] = {0}; memcpy(vendorID, &dataBuffer[8], 8); Log("vendorID = %s",vendorID); char productID[17] = {0}; memcpy(productID, &dataBuffer[16], 16); Log("productID = %s",productID); } } My environment is: MacBook Pro (M2), macOS 15.6 If anyone has insight into what causes the ILLEGAL REQUEST, or what I am missing when using IOUserSCSIPeripheralDeviceType00 and UserSendCDB, I would greatly appreciate your help. Thank you.
Replies
1
Boosts
0
Views
661
Activity
Nov ’25
Architectural Performance Difference in External Storage I/O Between Intel and Apple Silicon Macs
Hi everyone, We are in the process of migrating a legacy KEXT for our external multi-disk RAID enclosure to the modern DriverKit framework. During the performance validation of our KEXT, we observed a large and consistent maximum throughput difference between Intel-based Macs and Apple Silicon-based Macs. We would like to share our findings and hope to discuss with others in the community to see if you have had similar experiences that could confirm or correct our understanding. The Observation: A Consistent Performance Gap When using the exact same external RAID hardware (an 8-HDD RAID 5 array), driven by our mature KEXT, we see the following results in high-throughput benchmarks (AJA System Test, large sequential writes): On a 2020 Intel-based Mac: We consistently achieve a throughput of ~2500 MB/s. On modern M-series Macs (from M1 to M4): The throughput is consistently capped at ~1500 MB/s. This performance difference of nearly 40% is significant and is present across the entire Apple Silicon product line. Our Hypothesis: A Shift in Architectural Design Philosophy Since the KEXT and external hardware are identical in both tests, we believe this performance difference is not a bug but a fundamental platform architecture distinction. Our hypothesis is as follows: 1. The Intel Mac Era ("Dedicated Throughput") The Intel-based Macs we tested use a dedicated, discrete Intel Thunderbolt controller chip. This chip has its own dedicated PCIe lanes and resources, and its design appears to be singularly focused on maximizing raw, sustained data throughput for external peripherals. 2. The Apple Silicon Era ("Integrated Efficiency") In contrast, M-series Macs use a deeply integrated I/O controller inside the SoC. This controller must share resources, such as the total unified memory bandwidth and the chip's overall power budget, with all other functional units (CPU, GPU, etc.). We speculate that the design priority for this integrated I/O controller has shifted from "maximizing single-task raw throughput" to "maximizing overall system efficiency, multi-task responsiveness, and low latency." As a result, in a pure, single-task storage benchmark, its performance ceiling may be lower than that of the older, dedicated-chip architecture. Our Question to the Community: Is our understanding correct? Have other developers of high-performance storage drivers or peripherals also observed a similar performance ceiling for external storage on Apple Silicon Macs, when compared to high-end Intel Macs? We believe that understanding this as a deliberate architectural trade-off is crucial for setting realistic performance targets for our DEXT. Our current goal has been adjusted to have our DEXT match the KEXT's ~1500 MB/s on the M-series platform. Any insights, confirmations, or corrections from the community or Apple engineers would be greatly appreciated. Thank you very much! Charles
Replies
1
Boosts
0
Views
596
Activity
Nov ’25
DriverKit IOUserSCSIPeripheralDeviceType00: kernel panic when setPowerState exceeds 20 seconds
We have an IOUserSCSIPeripheralDeviceType00 class DEXT supporting USB attached devices. With some high-capacity drives, the default setPowerState can exceed 20s to complete. This triggers a kernel panic, although this drive behavior is not unexpected. With a kernel extension implementing similar functionality we see no such problem as it appears from reading of Apple open source the timeout was 100s. What changes will allow setPowerState to complete without the kernel panic? kernel panic report excerpt attached. panic-full-2025-09-04-063127.0003.txt
Replies
3
Boosts
0
Views
491
Activity
Oct ’25
Keyboard freezing on comment section
So when you are on tik tok if i press the comment function the phone freezes there you cant press back or go back to a video you have to restart the application
Replies
1
Boosts
0
Views
423
Activity
Jul ’25
Implementing Hardware Interrupt Handling with InterruptOccurred in DriverKit
Hello everyone, I’m working on implementing hardware interrupt handling in DriverKit and came across the InterruptOccurred method in IOInterruptDispatchSource. I noticed that its declaration ends with a TYPE macro: virtual void InterruptOccurred(OSAction* action, uint64_t count, uint64_t time) TYPE(IOInterruptDispatchSource::InterruptOccurred); This structure seems similar to how Timer Events are set up, where an event is linked to a callback and triggered by a timer. I’m attempting to use a similar approach, but for hardware-triggered interrupts rather than timer events. I’m currently in the trial-and-error phase of the implementation, but if anyone has a working example or reference on how to properly implement and register InterruptOccurred, it would be greatly appreciated! Best regards, Charles
Replies
3
Boosts
0
Views
584
Activity
May ’25
macOS Hang After Implementing UserMapHBAData()
Hi everyone, I was following the Video Modernize PCI and SCSI drivers with DriverKit and the Document to implement UserMapHBAData(), and here’s my current implementation: // kern_return_t DRV_MAIN_CLASS_NAME::UserMapHBAData_Impl(uint32_t *uniqueTaskID) kern_return_t IMPL(DRV_MAIN_CLASS_NAME, UserMapHBAData) { Log("UserMapHBAData() - Start"); // Define the vm_page_size explicitly const uint32_t vm_page_size = 4096; kern_return_t ret; IOBufferMemoryDescriptor *buffer = nullptr; IOMemoryMap *memMap = nullptr; void *taskData = nullptr; // Create a buffer for HBA-specific task data ret = IOBufferMemoryDescriptor::Create(kIOMemoryDirectionOutIn, ivars->fTaskDataSize, vm_page_size, &buffer); __Require((kIOReturnSuccess == ret), Exit); // Map memory to the driver extension's memory space ret = buffer->CreateMapping(0, 0, 0, 0, 0, &memMap); __Require((kIOReturnSuccess == ret), Exit); // Retrieve mapped memory address taskData = reinterpret_cast<void *>(memMap->GetAddress()); __Require(taskData, Exit); // WARNING: Potential leak of an object stored into 'buffer' // WARNING: Potential leak of an object stored into 'memMap' // Assign a unique task ID ivars->fTaskID++; // ERROR: No member named 'fTaskID' in 'DriverKitAcxxx_IVars' ivars->fTaskArray[ivars->fTaskID] = taskData; *uniqueTaskID = ivars->fTaskID; Log("UserMapHBAData() - End"); return kIOReturnSuccess; Exit: // Cleanup in case of failure if (memMap) { memMap->free(); // Correct method for releasing memory maps } if (buffer) { buffer->free(); // Correct method for releasing buffer memory } LogErr("ret = 0x%0x", ret); Log("UserMapHBAData() - End"); return ret; } For reference, in KEXT, memory allocation is typically done using: IOBufferMemoryDescriptor *buffer = IOBufferMemoryDescriptor::inTaskWithOptions( kernel_task, // Task in which memory is allocated kIODirectionOutIn, // Direction (read/write) 1024, // Size of the buffer in bytes 4); // Alignment requirements However, after installing the dext, macOS hangs, and I have to do a hardware reset. After rebooting, the sysctl list output shows: % sectl list 1 extension(s) --- com.apple.system_extension.driver_extension enabled active teamID bundleID (version) name [state] * - com.accusys.DriverKitAcxxx (5.0/11) com.accusys.DriverKitAcxxx [activated waiting for user] Questions: What could be causing macOS to halt? How should I approach debugging and resolving this issue? Looking forward to your insights, any suggestions would be greatly appreciated! Best regards, Charles
Replies
7
Boosts
0
Views
914
Activity
May ’25
How to setup DriverKit Timer Event with OSAction Callback Binding
Hello Everyone, I'm encountering an issue while setting up a timer event in DriverKit and would appreciate any guidance. Here's my current implementation: void DRV_MAIN_CLASS_NAME::SetupEventTimer() { // 1. Create dispatch queue kern_return_t ret = IODispatchQueue::Create("TimerQueue", 0, 0, &ivars->dispatchQueue); if (ret != kIOReturnSuccess) { LogErr("Failed to create dispatch queue: 0x%x", ret); return; } // 2. Create timer source ret = IOTimerDispatchSource::Create(ivars->dispatchQueue, &ivars->dispatchSource); if (ret != kIOReturnSuccess) { LogErr("Failed to create timer: 0x%x", ret); OSSafeReleaseNULL(ivars->dispatchQueue); return; } /*! * @brief Create an instance of OSAction. * @discussion Methods to allocate an OSAction instance are generated for each method defined in a class with * a TYPE attribute, so there should not be any need to directly call OSAction::Create(). * @param target OSObject to receive the callback. This object will be retained until the OSAction is * canceled or freed. * @param targetmsgid Generated message ID for the target method. * @param msgid Generated message ID for the method invoked by the receiver of the OSAction * to generate the callback. * @param referenceSize Size of additional state structure available to the creator of the OSAction * with GetReference. * @param action Created OSAction with +1 retain count to be released by the caller. * @return kIOReturnSuccess on success. See IOReturn.h for error codes. */ // 3: Create an OSAction for the TimerOccurred method // THIS IS WHERE I NEED HELP OSAction* timerAction = nullptr; ret = OSAction::Create(this, 0, 0, 0, &timerAction); if (ret != kIOReturnSuccess) { LogErr("Failed to create OSAction: 0x%x", ret); goto cleanup; } // 4. Set handler ret = ivars->dispatchSource->SetHandler(timerAction); if (ret != kIOReturnSuccess) { LogErr("Failed to set handler: 0x%x", ret); goto cleanup; } // 5. Schedule timer (1 second) uint64_t deadline = mach_absolute_time() + NSEC_PER_SEC; ivars->dispatchSource->WakeAtTime(0, deadline, 0); cleanup: if (ret != kIOReturnSuccess) { OSSafeReleaseNULL(timerAction); OSSafeReleaseNULL(ivars->dispatchSource); OSSafeReleaseNULL(ivars->dispatchQueue); } } Problem: The code runs but the OSAction callback binding seems incorrect (Step 3). According to the OSAction documentation, I need to use the TYPE macro to properly bind the callback method. But I try to use TYPE(DRV_MAIN_CLASS_NAME::TimerOccurred) kern_return_t TimerOccurred() LOCALONLY; TYPE(TimerOccurred) kern_return_t TimerOccurred() LOCALONLY; kern_return_t TimerOccurred() TYPE(DRV_MAIN_CLASS_NAME::TimerOccurred) LOCALONLY; All results in Out-of-line definition of 'TimerOccurred' does not match any declaration in 'DRV_MAIN_CLASS_NAME' Questions: What is the correct way to declare a timer callback method using TYPE? How to get the values targetmsgid & msgid generated by Xcode? Any help would be greatly appreciated! Best Regards, Charles
Replies
6
Boosts
0
Views
624
Activity
Apr ’25
Why UserInitializeTargetForID() not be invoked after UserCreateTargetForID() successfully?
Hello Everyone, I am trying to create a Fake SCSI target based on SCSIControllerDriverKit.framework and inherent from IOUserSCSIParallelInterfaceController, here is the code kern_return_t IMPL(DRV_MAIN_CLASS_NAME, Start) { ... // Programmatically create a null SCSI Target SCSIDeviceIdentifier nullTargetID = 0; // Example target ID, adjust as needed ret = UserCreateTargetForID(nullTargetID, nullptr); if (ret != kIOReturnSuccess) { Log("Failed to create Null SCSI Target for ID %llu", nullTargetID); return ret; } ... } According the document UserCreateTargetForID, after creating a TargetID successfully, the framework will call the UserInitializeTargetForID() The document said: As part of the UserCreateTargetForID call, the kernel calls several APIs like UserInitializeTargetForID which run on the default dispatch queue of the dext. But after UserCreateTargetForID created, why the UserInitializeTargetForID() not be invoked automatically? Here is the part of log show init() - Start init() - End Start() - Start Start() - try 1 times UserCreateTargetForID() - Start Allocating resources for Target ID 0 UserCreateTargetForID() - End Start() - Finished. UserInitializeController() - Start - PCI vendorID: 0x14d6, deviceID: 0x626f. - BAR0: 0x1, BAR1: 0x200004. - GetBARInfo() - BAR1 - MemoryIndex: 0, Size: 262144, Type: 0. UserInitializeController() - End UserStartController() - Start - msiInterruptIndex : 0x00000000 - interruptType info is 0x00010000 - PCI Dext interrupt final value, return status info is 0x00000000 UserStartController() - End Any assistance would be greatly appreciated! Thank you in advance for your support. Best regards, Charles
Replies
1
Boosts
0
Views
644
Activity
Mar ’25
The Map() of IOBufferMemoryDescriptor failure and cause the DriverKit Start() repeat
Hello Everyone, I am trying to develop a DriverKit for RAID system, using PCIDriverKit & SCSIControllerDriverKit framework. The driver can detect the Vendor ID and Device ID. But before communicating to the RAID system, I would like to simulate a virtual Volume using a memory block to talk with macOS. In the UserInitializeController(), I allocated a 512K memory for a IOBufferMemoryDescriptor* volumeBuffer, but fail to use Map() to map memory for volumeBuffer. result = ivars->volumeBuffer->Map( 0, // Options: Use default 0, // Offset: Start of the buffer ivars->volumeSize, // Length: Must not exceed buffer size 0, // Flags: Use default nullptr, // Address space: Default address space &mappedAddress // Output parameter ); Log("Memory mapped completed at address: 0x%llx", mappedAddress); // this line never run The Log for Map completed never run, just restart to run the Start() and makes this Driver re-run again and again, in the end, the driver eat out macOS's memory and system halt. Are the parameters for Map() error? or I should not put this code in UserInitializeController()? Any help is appreciated! Thanks in advance. Charles
Replies
0
Boosts
0
Views
522
Activity
Mar ’25
DriverKit CppUserClient Searching for dext service but Failed opening service with error: 0xe00002c7
Hi Everybody, Follow Communicating between a DriverKit extension and a client app to migrate our kext to dext. The dext might have been loaded successfully by using the command systemextensionsctl list, the dext is loaded and enabled. % sectl list 1 extension(s) --- com.apple.system_extension.driver_extension enabled active teamID bundleID (version) name [state] * * K3TDMD9Y6B com.accusys.scsidriver (1.0/1) com.accusys.scsidriver [activated enabled] We try to use the CppUserClient.cpp to communicate with the dext, but can not get the dext service. The debug message as below: Failed opening service with error: 0xe00002c7. Here is the part of CppUserClient.cpp static const char* dextIdentifier = "com.accusys.scsidriver"; kern_return_t ret = kIOReturnSuccess; io_iterator_t iterator = IO_OBJECT_NULL; io_service_t service = IO_OBJECT_NULL; ret = IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching("IOUserServer"), &iterator); printf("dextIdentifier = %s\n", dextIdentifier); printf("IOServiceNameMatching return = %d\n", ret); if (ret != kIOReturnSuccess) { printf("Unable to find service for identifier with error: 0x%08x.\n", ret); PrintErrorDetails(ret); } printf("Searching for dext service...\n"); while ((service = IOIteratorNext(iterator)) != IO_OBJECT_NULL) { // Open a connection to this user client as a server to that client, and store the instance in "service" ret = IOServiceOpen(service, mach_task_self_, kIOHIDServerConnectType, &connection); if (ret == kIOReturnSuccess) { printf("\tOpened service.\n"); break; } else { printf("\tFailed opening service with error: 0x%08x.\n", ret); } IOObjectRelease(service); } IOObjectRelease(iterator); if (service == IO_OBJECT_NULL) { printf("Failed to match to device.\n"); return EXIT_FAILURE; } The console output message is dextIdentifier = com.accusys.scsidriver IOServiceNameMatching return = 0 Searching for dext service... Failed opening service with error: 0xe00002c7. Failed opening service with error: 0xe00002c7. Failed opening service with error: 0xe00002c7. Failed opening service with error: 0xe00002c7. Failed to match to device. Here is the log show message fredapp start UserInitializeController pcitest: fredapp pci vendorID: 14d6 deviceID: 626f fredapp nnnnnew configuaration read32 0x10 info: 1 fredapp nnnnnew configuaration read32 0x14 info: 80100004 fredapp new 128 before enable busmaster ReqMSGport_info 0x00000040 : fffff pcitest: fredapp 131 pci ConfigurationRead16 busmaster value 0 pcitest: fredapp 134 Enable BusMaster and IO space done...... locate 139 fredapp MemoryWrite32 function done...... fredapp new 143 after enable busmaster ReqMSGport_info 0x00000040 : 0 fredapp newwww before GetBARInfo memoryIndex1 info is: 5 fredapp GetBARInfo 1 kernel return status is: 0 fredapp GetBARInfo memoryIndex1 info is: 0 fredapp GetBARInfo barSize1 info is: 262144 fredapp GetBARInfo barType1 info is: 0 fredapp GetBARInfo result0 info is: 3758097136 fredapp GetBARInfo memoryIndex0 info is: 0 fredapp GetBARInfo barSize0 info is: 0 fredapp GetBARInfo barType0 info is: 0 pcitest: newwww fredapp againnnn test ReqMSGport info: 8 fredapp Start MPIO_Init_Prepare fredapp end MPIO_Init_Prepare. fredapp call 741 Total_memory_size: 1bb900 fredapp Start MemoryAllocationForAME_Module. fredapp IOBufferMemoryDescriptor create return status info is kIOReturnSuc fredapp IOBufferMemoryDescriptor virtualAddressSegment address info: 0x1 fredapp virtualAddressSegment length info: 0x00080000 fredapp end IOBufferMemoryDescriptor Create. fredapp dmaSpecification maxAddressBits: 0x00000000 fredapp dmaSpecification maxAddressBits: 0x00000027 fredapp IODMACommand create return status info is kIOReturnSuccess fredapp end IODMACommand Create. fredapp PrepareForDMA return status info is kIOReturnSuccess fredapp PrepareForDMA return status info is 0x00000000 fredapp Allocate memory PrepareforDMA return flags info: 0x00000003 fredapp Allocate memory PrepareforDMA return segmentsCount info: 0x00000 fredapp Allocate memory PrepareforDMA return physicalAddressSegment info: fredapp IOBufferMemoryDescriptor virtualAddressSegment address info-2: 0 fredapp verify data success init() - Finished. fredapp start UserGetDMASpecification fredapp end UserGetDMASpecification fredapp start UserMapHBAData fredapp end UserMapHBAData fredapp start UserStartController fredapp interruptType info is 0x00010000 fredapp PCI Dext interrupt final value return status info is 0x00000000 Any suggestions? Best Regards, Charles
Replies
6
Boosts
0
Views
1k
Activity
Jan ’25
SCSIPeripheralsDriverKit/IOUserSCSIPeripheralDeviceType00 Error:kIOReturnUnsupported (0xe00002c7)
I am using SCSIPeripheralsDriverKit/IOUserSCSIPeripheralDeviceType00 to develop a Dext driver, which has only two classes: MyUserSCSIPeripheralDeviceType00 and MyUserClient, MyUserClient is responsible for receiving APP commands and passing them to MyUserSCSIPeripheralDeviceType00->UserSendCDB(), After the device is connected to the computer, the driver can match the device and start, calling MyUserSCSIPeripheralDeviceType00-->init(), MyUserSCSIPeripheralDeviceType00-->Start(), Any command sent by the APP to MyUserSCSIPeripheralDeviceType00 will return a failure: kIOReturnUnsupported (0xe00002c7), including UserSendCDB(), UserReportMediumBlockSize(), <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>IOKitPersonalities</key> <dict> <key>MySCSIDriver</key> <dict> <key>CFBundleIdentifier</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>CFBundleIdentifierKernel</key> <string>com.apple.kpi.iokit</string> <key>IOClass</key> <string>IOUserService</string> <key>IOMatchCategory</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>IOProviderClass</key> <string>IOSCSIPeripheralDeviceNub</string> <key>IOResourceMatch</key> <string>IOKit</string> <key>IOUserClass</key> <string>MyUserSCSIPeripheralDeviceType00</string> <key>IOUserServerName</key> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <key>UserClientProperties</key> <dict> <key>IOClass</key> <string>IOUserUserClient</string> <key>IOUserClass</key> <string>MyUserClient</string> </dict> <key>bConfigurationValue</key> <integer>1</integer> <key>bInterfaceNumber</key> <integer>0</integer> <key>bcdDevice</key> <integer>1</integer> <key>idProduct</key> <string>*</string> <key>idVendor</key> <integer>12345</integer> <key>Peripheral Device Type</key> <integer>0</integer> <key>IOKitDebug</key> <integer>65535</integer> </dict> </dict> </dict> </plist> This is the method that receives client calls kern_return_t MyUserSCSIPeripheralDeviceType00::HandleExternalStruct(IOUserClientMethodArguments* arguments) { kern_return_t ret = kIOReturnSuccess; SCSIType00OutParameters command; SCSIType00InParameters response; SCSI_Sense_Data sense; UInt64 fSenseAddr = (intptr_t)&sense; bzero((void *)&command, sizeof(SCSIType00OutParameters)); bzero((void *)&response, sizeof(SCSIType00InParameters)); bool test = TEST_UNIT_READY(&command, &response, fSenseAddr); // test is true ret = this->UserSendCDB(command, &response); // ret is kIOReturnUnsupported (0xe00002c7) UInt64 blockSize; kern_return_t sizeRet = this->UserReportMediumBlockSize(&blockSize); // sizeRet is kIOReturnUnsupported (0xe00002c7) }; // Not called. As per the documentation, this should be called during enumeration. kern_return_t IMPL(I4UserSCSIPeripheralDeviceType00, UserDetermineDeviceCharacteristics) { // *result = true; return kIOReturnSuccess; }
Replies
0
Boosts
0
Views
881
Activity
Apr ’24
Need an assistance to fetch the PCI devices information using PCIDrivers
I'm currently working on developing a PCI driver using PCIDriverKit, but I'm encountering challenges, particularly with the driver's extension. I need some insights on the APIs and methods to follow the best practices in generating PCI drivers for retrieving PCI devices information and running NVMe commands on the devices.
Replies
3
Boosts
0
Views
1.5k
Activity
Feb ’24
Need a assistance in getting USB information using DriverKit Extension
I want to get the information of USB like, USB name, size, VID, PID, etc using DriverKit Extension but I'm facing difficulty finding such references or Sample code for the same. Please help me with the Sample code to get USB info with the help of Dext. Thanks
Replies
4
Boosts
0
Views
1.3k
Activity
Dec ’23
Is SCSIPeripheralsDriverKit on board?
I've try to develop a dext to send SCSI commands to some storage products, but when I try to implements SCSIPeripheralsDriverKit/IOUserSCSIPeripheralDeviceType00 interface, I... just don't know how to do it, I tried to convert kext way to Driverkit way, but I always block by error warnings. After I google a lots of solutions, I was wondering is this feature working? or Is there any samples or guideline?
Replies
0
Boosts
0
Views
707
Activity
Jun ’23
How to access dmaaddress (Physical Address) in DriverKit?
I am trying to use IOUserBlockStorageDevice in DriverKit to simulate a fake device (Implementing a Ram Disk). Currently I'm confused on how to use the dmaaddress in the following interface virtual kern_return_t DoAsyncReadWrite (bool isRead, uint32_t requestID, uint64_t dmaAddr, uint64_t size, uint64_t lba, uint64_t numOfBlocks, IOUserStorageOptions options) = 0; According to https://github.com/briancabbott/macOS-system-projects/blob/19310aa5c7b7507408261a22a2e8f46f9d478a88/Resources/Code/apple-oss-distributions/IOStorageFamily/IOUserBlockStorageDevice_kext.cpp Before calling "DoAsyncReadWrite", kernel allocate a segment of physical memory by using "IODMAcommand::genIOVMSegments". This segment's physical address is pass to DoAsyncReadWrite as parameter "dmaAddr". To implement a correct ram disk, we need to "transform" this physical address to virtual so that we can "Read" or "Write" on this physical address. I tried to use "IOMemoryDescriptor" to access this dmaAddr. In IOKit, I belive I can use interface such as "withPhysicalAddress" to access the memory. However, such interface is not exist while using driverkit, all interface that I can use in DriverKit IOMemoryDescriptor is : -kern_return_t GetLength(uint64_t * returnLength) LOCALONLY; // apparently not this one -virtual kern_return_t CreateMapping( uint64_t options, uint64_t address, uint64_t offset, uint64_t length, uint64_t alignment, IOMemoryMap ** map); // Maybe this one with kIOMemoryFixedAddress option? // But I get Segment Fault while calling this with CreateMapping( kIOMemoryFixedAddress , dmaaddr, 0, size, 0, &map); // Or getting error return while calling CreateMapping with same paramters after IOBufferMemoryDescriptor::Create // Also, output iomemorymap is not used here, which is quiet strange. static kern_return_t CreateSubMemoryDescriptor(uint64_t memoryDescriptorCreateOptions, uint64_t offset, uint64_t length, IOMemoryDescriptor * ofDescriptor, IOMemoryDescriptor ** memory) attribute((availability(driverkit,introduced=20.0))); // Seems not this, it create “sub“ memory descriptor static kern_return_t CreateWithMemoryDescriptors(uint64_t memoryDescriptorCreateOptions, uint32_t withDescriptorsCount, IOMemoryDescriptor * const withDescriptors[32], IOMemoryDescriptor ** memory) attribute((availability(driverkit,introduced=20.0))); // Seems not this, it don’t take any dmaaddr as parameter. and a private function kern_return_t Map( uint64_t options, uint64_t address, uint64_t length, uint64_t alignment, uint64_t * returnAddress, uint64_t * returnLength) LOCALONLY; // Maybe this one? But the header file don’t show any description on this function and we are not sure what parameters should we pass. // Currently I've test Map( kIOMemoryFixedAddress , dmaaddr, size, 0, &returnAddress, &returnLength) but get error return. It seems that I've made some mistake on using IOMemoryDescriptor? How to correct access a dmaaddress? I've also tried class "IODMACommand", but also get unexpected behavior. Another question is how to read / write buffer after I create correct mapping. While implementing kext, IOMemoryDescriptor can use "readBytes" or "writeBytes" to read or write memory that IOMemoryDescriptor maps to. However, DriverKit don’t have interface of "readBytes" or "writeBytes". Maybe I can directly access buffer by casting the IOMemoryDescriptor::Map "returnAddress" to void? (I haven't tried it yet cause "Map" always failed now QQ) Thanks for everyone's help.
Replies
2
Boosts
1
Views
2.5k
Activity
Feb ’23
Can Xcode DriverKit library include kern/clock.h?
My user space driver need to call a function: clock_get_calendar_microtime(&currentTime_sec,&currentTime_usec); I hope Xcode DriverKit library can include "kern/clock.h"
Replies
1
Boosts
0
Views
1.7k
Activity
Dec ’22
Sending SCSI commands to USB mass storage device
Our device is USB Mass stroage device. We want to send a specific SCSI command to a USB drive in Mac OS X. Have any demo app that uses IOUserSCSIPeripheralDeviceType00 in SCSIPeripheralsDriverKit? We want to use below SCSI command, but have no demo program. https://developer.apple.com/documentation/scsiperipheralsdriverkit/3946437-inquiry https://developer.apple.com/documentation/scsiperipheralsdriverkit/iouserscsiperipheraldevicetype00/3946461-usersendcdb
Replies
0
Boosts
2
Views
933
Activity
Nov ’22
SCSIControllerDriverKit: Process gets stuck on UserCreateTargetForID.
Context: We are working on migration of the driver, which is currently represented as a kernel extension, to the DriverKit framework. The driver works with Thunderbolt RAID storage devices. When connected through the Thunderbolt interface to the host, the device itself presents in the OS as a PCI device. The main function of our driver (.kext) is to create a "virtual" SCSI device in the OS for each virtual RAID array. So that the OS can work with these SCSI drives as usual disk storage.  We use https://developer.apple.com/documentation/scsicontrollerdriverkit to migrate this functionality in the dext version of the driver. Current issue: When a device is connected - the dext driver cannot create a SCSI drive in the OS. Technically our dext tries to create a SCSI drive using the UserCreateTargetForID method. On this step the OS sends the first SCSI command “Test Unit Ready ''to the device to check if it is a SCSI device. We process this command in an additional thread  separated from the main process of the dext (as it is recommended in the DriverKit documentation). We can see in the logs that the device receives this command and responses but when our dext sends this response to the OS the process is stuck in the waiting mode. How can we understand why it happens and fix it? More details: We are migrating functionality of an already existing “.kext” driver. We checked logs of the kext driver of this step: 15:06:17.902539+0700 Target device try to create for idx:0 15:06:17.902704+0700 Send command 0 for target 0 len 0 15:06:18.161777+0700 Complete command: 0 for target: 0 Len: 0 status: 0 flags: 0 15:06:18.161884+0700 Send command 18 for target 0 len 6 15:06:18.161956+0700 Complete command: 18 for target: 0 Len: 6 status: 0 flags: 0 15:06:18.162010+0700 Send command 18 for target 0 len 44 15:06:18.172972+0700 Complete command: 18 for target: 0 Len: 44 status: 0 flags: 0 15:06:18.275501+0700 Send command 18 for target 0 len 36 15:06:18.275584+0700 Complete command: 18 for target: 0 Len: 36 status: 0 flags: 0 15:06:18.276257+0700 Target device created for idx:0 We can see a successful message “Target device created for idx:0” In the the dext logs of the same step: We do not see the “Send command 18 for target 0 len 6” as we have in the kext logs  no log of the successful result “Target device created for idx:0” 15:54:10.903466+0700 Try to create target for 0 UUID 432421434863538456 15:54:10.903633+0700 UserDoesHBAPerformAutoSense 15:54:10.903763+0700 UserInitializeTargetForID 15:54:10.903876+0700 UserDoesHBASupportMultiPathing 15:54:10.904200+0700 UserProcessParallelTask start. 15:54:10.904298+0700 Sent command : 0 len 0 for target 0 15:54:11.163003+0700 Disable interrupts. 15:54:11.163077+0700 Complete cmd : 0 for target: 0 len: 0  status: 0 flags: 0 15:54:11.163085+0700 Enable interrupts. Will appreciate any help
Replies
3
Boosts
1
Views
1.4k
Activity
Nov ’22
Where is SCSIControllerDriverKit now?
Hi there! There was a presentation of the SCSI support in DriverKit on 2020 WWDC: https://developer.apple.com/videos/play/wwdc2020/10210/ Currently, the Xcode 12.4 (latest) has nothing regarding SCSI in DriverKit folders. Documentation says it is still in beta: https://developer.apple.com/documentation/scsicontrollerdriverkit So I've downloaded xcode 12.5 beta, where the driverkit 20.4 beta resides (according to https://developer.apple.com/support/xcode/) And what we have there? Just Kernel.framework/Versions/A/Headers/DriverKit/IOReturn.h 65:#define sub_iokit_scsi err_sub(16) And nothing more! So, the question is: do we have any way to use SCSI devices now on BigSur? Could I develop something for it with DriverKit, or should I use kext-approach for now, and wait for SCSI DriverKit support to be released indeed?
Replies
4
Boosts
0
Views
2.5k
Activity
Oct ’22