Understand the role of drivers in bridging the gap between software and hardware, ensuring smooth hardware functionality.

Drivers Documentation

Posts under Drivers subtopic

Post

Replies

Boosts

Views

Activity

External Accessory
Hi, we are listed for the MFI program as a licensed manufacturer. We have now started with the IAP3 sample code and the IAP chips to build up a USB communication between our accessory and an iOS device. We are looking for a sample project for the iOS part. Is there some available? The only official I can find is this: https://developer.apple.com/library/archive/samplecode/EADemo/Introduction/Intro.html#//apple_ref/doc/uid/DTS40010079 This app is somehow outdated and from 2016. Is there something else available as a starting point? And how does this relate to IOKit since it is available for serial communication on iOS16 as well? Kind regards,
3
0
116
Jul ’25
USBSendSetLineCoding failing in DeviceRequest with error code 0xe0005000
Hi, This is the code snippet in my driver for an usb uart device. I am trying to call standard cdc-acm command to set the Line Coding in the device, but fails with this error: "USBSendSetLineCoding - Failed : 0xe0005000, bytes transferred: 0" I guess the USB device is returning this error due to incorrect buffer or format. There is no proper documentation on how to use IOMemoryDescriptor when the data has to be passed down in a buffer to the usb stack. (IOUSBHostInterface->DeviceRequest()) Can anyone please point out what is wrong with this code and suggest a right method? void MyDriver::USBSendSetLineCoding(uint32_t BaudRate, uint8_t StopBits, uint8_t TX_Parity, uint8_t CharLength) { kern_return_t ret = kIOReturnSuccess; LineCoding *lineParms; uint16_t lcLen = sizeof(LineCoding)-1; lineParms = (LineCoding *)IOMalloc(lcLen); if (!lineParms) { MyDebugLog("USBSendSetLineCoding - allocate lineParms failed"); return; } bzero(lineParms, lcLen); lineParms->bCharFormat = StopBits - 2; lineParms->bParityType = TX_Parity - 1; lineParms->bDataBits = CharLength; OSSwapBigToHostInt32(BaudRate); lineParms->dwDTERate = BaudRate; IOBufferMemoryDescriptor* bufferDescriptor = nullptr; _controlInterface->CreateIOBuffer(kIOMemoryDirectionOut, lcLen, &bufferDescriptor); IOMemoryMap *map = nullptr; bufferDescriptor->CreateMapping(kIOMemoryMapReadOnly, 0, 0, 0, 0, &map); if(map == nullptr) { MyDebugLog("USBSendSetLineCoding - Failed to map memory in CreateMapping\n"); IOFree(lineParms, lcLen); bufferDescriptor->release(); return; } uint64_t ptr = map->GetAddress(); if(!ptr) { MyDebugLog("USBSendSetLineCoding - Failed to get Memory Address\n"); IOFree(lineParms, lcLen); bufferDescriptor->release(); map->release(); return; } memcpy(&ptr, lineParms, lcLen); uint8_t bmRequestType = kIOUSBDeviceRequestDirectionOut | kIOUSBDeviceRequestTypeClass | kIOUSBDeviceRequestRecipientInterface; uint16_t wValue = 0; uint16_t wIndex = _bControlInterfaceNumber; uint16_t bytesTransferred = 0; ret = _controlInterface->DeviceRequest(bmRequestType, kUSBSET_LINE_CODING, wValue, wIndex, lcLen, bufferDescriptor, &bytesTransferred, 1000); IOFree(lineParms, lcLen); map->release(); bufferDescriptor->release(); if (ret != kIOReturnSuccess) { MyDebugLog("USBSendSetLineCoding - Failed : 0x%x, bytes transferred: %d\n", ret, bytesTransferred); return; } return; } I am able to call DeviceRequest() successfully on the same interface for any other setting that requires no data buffer, such as, "ret = _controlInterface->DeviceRequest(bmRequestType, kUSBSEND_BREAK, wValue, wIndex, 0, NULL, &bytesTransferred, 1000);" So I think the "bufferDescriptor" is not properly created or the data is not copied correctly in this function for the failure. "ret = _controlInterface->DeviceRequest(bmRequestType, kUSBSET_LINE_CODING, wValue, wIndex, lcLen, bufferDescriptor, &bytesTransferred, 1000);" Any help is very much appreciated. Thanks in advance.
3
0
109
Aug ’25
Using alternate DriverKit SDKs in Xcode
After some experimentation with copying multiple DriverKit SDKs into /Applications/Xcode.app/Contents/Developer/Platforms/DriverKit.platform/Developer/SDKs/DriverKit, it's become clear that Xcode only supports the DriverKit version that ships with it. There is no way to configure an alternative SDK within a project and changing to a different one results in strange build warnings and errors. This begs the question - how are developers supposed to develop and support dexts? Here's one example scenario: SCSIDriverKit introduced a breaking change in DriverKit 24.4 (macOS 15.4 and Xcode 16.3) due to a new feature. Once a dext is built against that kit, it will not function on macOS 15.0-15.3 whether that feature is implemented or not. We found a similar thing with NetworkingDriverKit as well. So, over the course of maintaining a Sequoia product while working in Sequoia itself, simply updating Xcode breaks the product. Not to mention trying to maintain a Sequoia product in Tahoe when it is released. How is this a good developer experience? Are developers resigned to having a myriad of Xcode versions which may require booting into multiple macOS versions to use? That would in turn produce a myriad of product versions that would need to be deciphered by the user or an installer? Shouldn't developers be able to use the latest tooling while still being able to produce products for OSes that are just a year or two old? Or should DriverKit files be conditionalized so configuring a deployment version in Xcode actually builds the right thing even with the latest SDK? I just don't get it. Help me understand. Replacing kexts with dexts seems like a development nightmare.
1
0
98
Aug ’25
driverkit.transport.usb
I’m creating my first DriverKit extension and I ran into an entitlement issue when trying to load my driver. Error 0x0 8397 7 taskgated-helper: (ConfigurationProfiles) [com.apple.ManagedClient:ProvisioningProfiles] App.Dext: Unsatisfied entitlements: com.apple.developer.driverkit.transport.usb I have already registered the entitlement com.apple.developer.driverkit.transport.usb with my vendor ID in the Apple Developer portal. However, when I download the provisioning profile, it doesn’t include the idVendor value. Screenshot from the developer portal (provisioning profile without idVendor) ? <key>com.apple.developer.driverkit.transport.usb</key> <array> <dict> <key>idVendor</key> <integer>1356</integer> </dict> </array> -Is this error caused by me registering the vendor ID incorrectly? -Or is there an issue with how the entitlement is reflected in the provisioning profile? Any guidance would be appreciated.
1
0
123
Aug ’25
driverkit.transport.usb
I’m creating my first DriverKit extension and I ran into an entitlement issue when trying to load my driver. Error 0x0 8397 7 taskgated-helper: (ConfigurationProfiles) [com.apple.ManagedClient:ProvisioningProfiles] App.Dext: Unsatisfied entitlements: com.apple.developer.driverkit.transport.usb I have already registered the entitlement com.apple.developer.driverkit.transport.usb with my vendor ID in the Apple Developer portal. However, when I download the provisioning profile, it doesn’t include the idVendor value. Screenshot from the developer portal (provisioning profile without idVendor) ? <key>com.apple.developer.driverkit.transport.usb</key> <array> <dict> <key>idVendor</key> <integer>1356</integer> <!-- Sony --> <!-- Có thể bổ sung: <key>idProduct</key> <integer>XXXXX</integer> --> </dict> </array>
1
0
123
Aug ’25
Trouble with OSDeclareDefaultStructors.
Hi guys! OK, reaching out for some help here. I am having all kinds of trouble with OSDeclareDefaultStructors. I have seriously been at this for nearly a week now and have come to the conclusion that I need to reach out for help from people that are more experience using Xcode. I believe entirely that my issue is just that I can't for whatever reason see how to set up includes and libraries and things like that. I have this line: OSDeclareDefaultStructors(NukeVirtualGamepad) No matter what I do, Xcode will not recognize OSDeclareDefaultStructors. The project builds a DriverKit &gt; Driver extension. I have literally tried absolutely everything with this. I am at a loss for words. I even set up a new blank project and it still will not recognize OSDeclareDefaultStructors. I did a lot of research and it looks like expo needs OSDeclareDefaultStructors in order for the extension to build with a binary in it instead of being just a codeless extension. Here is the code with the issue: #pragma once #include &lt;DriverKit/OSMetaClass.h&gt; #include &lt;HIDDriverKit/IOUserHIDDevice.h&gt; #include &lt;DriverKit/OSData.h&gt; class NukeVirtualGamepad : public IOUserHIDDevice { OSDeclareDefaultStructors(NukeVirtualGamepad) // The problem is right here! This line! public: // Keep it minimal; no 'override' keywords since the .h types may not mark them virtual bool init(); void free(); kern_return_t Start(IOService* provider); void Stop (IOService* provider); OSData* newReportDescriptor(); // (Optional) helper you’ll use later to inject input matching your report kern_return_t PostInput(uint16_t buttons, int8_t x, int8_t y); }; I do have to mention to everyone that I am still very new with Xcode. So there is a ton that I don't know yet or might be misunderstanding. Has anyone seen this before? Thank you in advance.
4
0
182
Aug ’25
Blocking USB Devices on macOS – DriverKit or Other Recommended Approach
Hi Apple, We are working on a general USB device management solution on macOS for enterprise security. Our goal is to enforce policy-based restrictions on USB devices, such as: For USB storage devices: block mount, read, or write access. For other peripherals (e.g., USB headsets or microphones, raspberry pi, etc): block usage entirely. We know in past, kernel extension would be the way to go, but as kext has been deprecated. And DriverKit is the new advertised framework. At first, DriverKit looked like the right direction. However, after reviewing the documentation more closely, we noticed that using DriverKit for USB requires specific entitlements: DriverKit USB Transport – VendorID DriverKit USB Transport – VendorID and ProductID This raises a challenge: if our solution is meant to cover all types of USB devices, we would theoretically need entitlements for every VendorID/ProductID in existence. My questions are: Is DriverKit actually the right framework for this kind of general-purpose USB device control? If not, what framework or mechanism should we be looking at for enforcing these kinds of policies? We also developed an Endpoint Security product, but so far we haven’t found a relevant Endpoint Security event type that would allow us to achieve this. Any guidance on the correct technical approach would be much appreciated. Thanks in advance for your help.
6
0
168
Sep ’25
External PCIe based storage device is not getting relinked with SCSI passthrough command
We have a management application which manages security enable and disable for an external PCIe based storage device using Kernel Extension(SCSI Architecture Model Family for External USB Mass Storage devices which deals with IOSCSIBlockCommandsDevice, IOSCSIPeripheralDeviceType00 and IOBlockStorageService) Now the issue we are facing is when we try to unlock the device using security code (already being set) , we will relink the device using VU command (RelinkBridge). Even-though both the commands are successful , the device is not getting relinked due to which we are not able to use the device for storage. If someone have faced similar issue or any pointer on how to resolve this issue , it would be helpful. Thanks in advance.
1
0
67
Oct ’25
Should UserSendCBD work on UAS interfaces?
The device I am trying to develop a firmware updater for is an NVMe drive with a USB4 interface. It can connect in USB4 mode (tunneled NVMe), in USB 3 mode or in USB 2 mode. In USB 2 and USB 3 mode, the device descriptor shows one interface with two alternates. Alternate 0 uses the bulk-only protocol, with one IN and one OUT pipe. Alternate 1 uses the UAS protocol, with two IN and two OUT pipes. I use identical code in my driver to send custom CDBs. I can see using IORegistryExplorer that in USB 2 mode, macOS chooses alternate 0, the bulk-only protocol. My custom CDBs and their accompanying data pay loads are put on the bus, more or less as expected. In USB 3 mode, macOS chooses alternate 1, the UAS protocol. My custom CDB is put on the bus, but no payload data is transferred. Is this expected behavior? If so, is there a way to force the OS to choose alternate 0 even when on USB 3, perhaps with another dext? I'll file a bug about this when Feedback Assistant lets me.
8
0
287
Oct ’25
Custom USB Network Device Driver on iPhone
Hi, We are using the AX88772C as a USB->Ethernet bridge in a product we are developing. Due to the chip not following the NCM protocol, it is not supported by the default networking drivers on the iPhone. Initially, we intended on using DriverKit to develop a userspace driver for this device. However, we have been informed DriverKit is only available on iPad OS, not iOS. As such is the case, we have found two possible alternatives. First being IOkit, and the second being External Accessory Session (EASession). What are the limitations of each of these options? We need the ability to send and receive USB packets to Control and Bulk endpoints. Is this possible with either of the options defined above? Would either of these options require the device to be MFi certified? We have read that some APIs within IOkit require the apple device to be jailbroken. Is there a list of features that can be used without a jailbroken device? Documentation on these 2 options is limited, so any official documentation would be great. Thanks!
5
0
177
Oct ’25
DriverKit. Data Integrity issue.
Dear Apple engineers and DriverKit developers, We have developed a DriverKit (DEXT) driver for an HBA RAID controller. The RAID controller is connected to hosts through Thunderbolt (PCIe port of the Thunderbolt controller). We use an IO script to verify the developed driver. The test fails after a few (10-12) hours of running with an error: “BUG IN CLIENT OF LIBDISPATCH: dispatch_sync called on queue already owned by current thread”. We inspected the stack trace of the crash report. This error happens in the interrupt handler. Thread 5 Crashed: 0 libdispatch.dylib 0x19671aa8c __DISPATCH_WAIT_FOR_QUEUE__ + 484 1 libdispatch.dylib 0x19671a5d0 _dispatch_sync_f_slow + 152 2 DriverKit 0x195d3fc1c IODispatchQueue::DispatchSync_f(void*, void (*)(void*)) + 296 3 DriverKit 0x195d40860 IOInterruptDispatchSourceThread(void*) + 380 4 libsystem_pthread.dylib 0x1968a3738 _pthread_start + 140 5 libsystem_pthread.dylib 0x1968ac6c8 thread_start + 8 On our side we created 5 DispatchQueue(s) for the interrupt processing and configured 5 interrupt handlers using ConfigureInterrupts(kIOInterruptTypePCIMessagedX, 1, 5). It gives 5 interrupts, as requested and it is not clear what is the reason for the issue. Our code samples are below uint32_t configureInterrupts(uint32_t requested, uint32_t required)  {      const kern_return_t ret = ioPCIdevice->ConfigureInterrupts(kIOInterruptTypePCIMessagedX, required, requested);      if (ret != kIOReturnSuccess)          return 0;      uint64_t interruptType = 0;      uint32_t interruptsCount = 0;      uint32_t interruptIndex = 0;        for ( ;; ++interruptIndex) {          if (IOInterruptDispatchSource::GetInterruptType(ioPCIdevice, interruptIndex, &interruptType) != kIOReturnSuccess)              break;          if ((interruptType & kIOInterruptTypePCIMessagedX) == 0)              continue;          ++interruptsCount;      }      return interruptsCount;  }  ..... // Create DQs     for(int i = 0; i < maxInterrupts; ++i) {          ret = IODispatchQueue::Create(INTERRUPT_DQ_NAME, 0, 0, &ivars->interruptQueue[i]);          if (kIOReturnSuccess != ret || nullptr == ivars->interruptQueue[i]) {              GH_PRINT_ERR("Interrupts queue %d creation failed with error %d", i, ret);              return false;          }      } ..... // Link DQ with interrupt   for(int index = 0; index < maxInterrupts; ++ index) {      kern_return_t ret = CreateActionHandleInterruptRequest(size, &ivars->interruptActions[index]);      if (kIOReturnSuccess != ret) {          GH_PRINT_ERR("Create action for interrupt handler %u failed.", index);          return ;      }      ret = IOInterruptDispatchSource::Create(ivars->PCI_io.dev, index, ivars->interruptQueue[index], &ivars->interruptSources[index]);      if (kIOReturnSuccess != ret || nullptr == ivars->interruptSources[index]) {          GH_PRINT_ERR("Creating interrupt source %u failed for interrupt index %u.", index, index);          return ;      }      ret = ivars->interruptSources[index]->SetHandler(ivars->interruptActions[index]);      if (kIOReturnSuccess != ret) {          GH_PRINT_ERR("Setting the handler for interrupt source %u failed.", index);          return ;      }      ivars->contexts[index] = ivars->interruptActions[index]->GetReference();      }  ..... // definition for interrupt handler void    HandleInterruptRequest ( OSAction *action, uint64_t count, uint64_t time) TYPE (IOInterruptDispatchSource::InterruptOccurred);  Do you have any clue how we can fix this error? Or directions and ways for investigation? Please let us know if you need more details.
7
0
224
Oct ’25
Xcode Signing Fails: Provisioning Profile "doesn't match" com.apple.developer.driverkit.userclient-access entitlement
Hello everyone, I am migrating a legacy KEXT to a DriverKit (DEXT) architecture. While the DEXT itself is working correctly, I am completely blocked by a code signing issue when trying to establish the UserClient connection from our SwiftUI management app. Project Goal & Status: Our DEXT (com.accusys.Acxxx.driver) activates successfully (systemextensionsctl list confirms [activated enabled]). The core functionality is working (diskutil list shows the corresponding disk device node). The Core Problem: The userclient-access Signing Error To allow the app to connect to the DEXT, the com.apple.developer.driverkit.userclient-access entitlement is required in the app's .entitlements file. However, as soon as this entitlement is added, the build fails. Both automatic and manual signing fail with the same error: `Provisioning profile ... doesn't match the entitlements file's value for the ... userclient-access entitlement.` This build failure prevents the generation of an .app bundle, making it impossible to inspect the final entitlements with codesign. What We've Confirmed: The necessary capabilities (like DriverKit Communicates with Drivers) are visible and enabled for our App ID on the developer portal. The issue persists on a clean system state and on the latest macOS Sequoia 15.7.1. Our Research and Hypothesis: We have reviewed the official documentation "Diagnosing issues with entitlements" (TN3125). According to the documentation, a "doesn't match" error implies a discrepancy between the entitlements file and the provisioning profile. Given that we have tried both automatic and manual profiles (after enabling the capability online), our hypothesis is that the provisioning profile generation process on Apple's backend is not correctly including the approved userclient-access entitlement into the profile file itself. The build fails because Xcode correctly detects this discrepancy. Our Questions: Did we misunderstand a step in the process, or is the issue not with the entitlement request at all? Alternatively, are there any other modifications we can make to successfully connect our App to the DEXT and trigger NewUserClient? Thank you for any guidance.
11
0
342
3w
FTDI USB-serial driver on iPadOS
Hello, We have developed a hardware product that embeds an FTDI USB-serial converter, and an application on MacOS that communicates with this device. We would like to port our application to iPadOS. I can see that when I plug the device into the iPad, it is recognized as a serial port, based on its console logs. When I attempt to enumerate serial ports on iPadOS using IOKit, I can see matching IOSerialBSDClient services, but the properties are sandboxed, including the IOCalloutDevice property, for example: 0 error 16:36:10.922450-0700 kernel Sandbox: ***(662) deny(1) iokit-get-properties iokit-class:IOUserSerial property:IOTTYSuffix Is there an entitlement that can be applied that allows access to the serial port properties of an attached USB device? Or do I need to implement my own USBDriverKit driver for this device, as seems to be implied in these forum threads: https://developer.apple.com/forums/thread/795202 https://developer.apple.com/forums/thread/655527
1
0
107
Oct ’25
DriverKit. Plug/unplug test leads to MacOS panic
Dear Apple engineers, We have developed a DriverKit (DEXT) driver for an HBA RAID controller. The RAID controller is connected to hosts through Thunderbolt (PCIe port of the Thunderbolt controller). We do plug/unplug tests to verify the developed driver. The test always fails in about 100 cycles with a MacOS crash (panic). The panic contains “LLC Bus error (Unavailable) from cpu0: FAR=0xa40100008 LLC_ERR_STS/ADR/INF=0x80/0x300480a40100008/0x1400000005 addr=0xa40100008 cmd=0x18(ACC_CIFL2C_CMD_RD_LD: request for load miss in E or S state)” At first we assumed that the issue is with hardware. But we did this test on different hosts (MacMini M3 and M4) with different units of our device. The error points to the same physical address FAR=0xa40100008 even if the hosts are different. The 2 full panic logs are attached (one for M4, another one for M3 host). Could you share your understanding of the crash and give any hints on how we can fix it? Please let us know if you need any additional data. Thank you M3 panic: https://drive.google.com/file/d/1GJXd3tTW6ajdrHpFsJxO_tWWYKYIgcMc/view?usp=share_link M4 panic: https://drive.google.com/file/d/1SU-3aBSdhLsyhhxsLknzw9wGvBQ9TbJC/view?usp=share_link
2
0
177
Oct ’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
115
Oct ’25
How to allocate contiguous memory in DriverKit?
We want to allocate a block of contiguous memory (≤1M) for audio ring DMA usage, but we haven't found any explicit method in the DriverKit documentation for allocating contiguous memory. I'm aware that IOBufferMemoryDescriptor::Create can be used in DriverKit to allocate memory and share it with user space. However, is the allocated memory physically contiguous? Can it guarantee that when I subsequently call PrepareForDMA in IODMACommand, there will be only one segment? Could you please help review this? Thank you!
2
0
111
Oct ’25
DriverKit DEXT Logs Only Once, Subsequent Logs Are Lost Despite Normal Functionality
Hello everyone, I've encountered a very strange and persistent logging issue with my DriverKit DEXT and would appreciate any insights from the community. [Problem Summary] My DriverKit DEXT, along with its companion Swift app, is functionally working perfectly. I can repeatedly call methods in the DEXT from the app (e.g., a Ping-Pong test and a StaticProcessInbandTask call) and receive the correct response every time. However, the os_log messages within my IOUserClient subclass are only successfully recorded for the very first set of interactions. After that, all subsequent logs are completely missing. What's even stranger is that all successfully recorded logs are attributed to the kernel: process, even for purely user-space methods like ExternalMethod. [Development Environment] macOS: 15.7.1 Xcode: 16.4 Hardware: MacBook Pro M1 DEXT Logging Macro (Log.h): #include <os/log.h> #define Log(fmt, ...) \ do { \ os_log(OS_LOG_DEFAULT, "[%{public}s] " fmt, __FUNCTION__, ##__VA_ARGS__); \ } while (0) [Steps to Reproduce & Observed Behavior] The DEXT is successfully loaded via the companion app. I click the "Ping-Pong" button, then the "Process InBand" button in the app. The app's UI log correctly shows that the request was sent and a successful response was received from the DEXT. I repeat step 2 multiple times. Each interaction works flawlessly from the app's perspective. I then use the log show command to export the logs from this period, for example: log show --last 5m | grep "com.accusys.Acxxx.driver" > dext_logs.txt Observed Result (Log Content): In the dext_logs.txt file, I can only see the logs from the very first Ping-Pong and the very first Process InBand call. All subsequent, successful operations leave no trace in the logs. kernel: (com.accusys.Acxxx.driver.dext) [ExternalMethod] // { --- kernel: (com.accusys.Acxxx.driver.dext) [ExternalMethod] // --- } kernel: (com.accusys.Acxxx.driver.dext) [StaticPingPong] // { --- kernel: (com.accusys.Acxxx.driver.dext) [StaticPingPong] // --- } kernel: (com.accusys.Acxxx.driver.dext) [ExternalMethod] // { --- kernel: (com.accusys.Acxxx.driver.dext) [ExternalMethod] // --- } kernel: (com.accusys.Acxxx.driver.dext) [StaticProcessInbandTask] // { --- kernel: (com.accusys.Acxxx.driver.dext) [StaticProcessInbandTask] // --- } <--- END OF FILE (No new logs appear after this point) ---> [Core Questions] Why are logs in IOUserClient subclass only recorded once? Given the DEXT is clearly still running and processing requests, why would os_log calls only succeed in writing to the system log database on the first interaction? Why are all logs attributed to the kernel? Why would logs from 100% user-space code like ExternalMethod and StaticPingPong be attributed to the kernel process? [Solutions Attempted That Did Not Work] I have verified with ps aux that the DEXT process (com.accusys.Acxxx.driver) is running continuously in the background and has not crashed. Attempted to force-restart the logging service with sudo killall logd, but the issue persists. Performed the most thorough reset possible using systemextensionsctl reset followed by a full reboot, then reinstalled the DEXT. The issue remains exactly the same. Thank you for any possible help or suggestions Best, Charles
3
0
149
Oct ’25
DEXT receives zero-filled buffer from DMA, despite firmware confirming data write
Hello everyone, I am migrating a KEXT for a SCSI PCI RAID controller (LSI 3108 RoC) to DriverKit (DEXT). While the DEXT loads successfully, I'm facing a DMA issue: an INQUIRY command results in a 0-byte disk because the data buffer received by the DEXT is all zeros, despite our firmware logs confirming that the correct data was prepared and sent. We have gathered detailed forensic evidence and would appreciate any insights from the community. Detailed Trace of a Failing INQUIRY Command: 1, DEXT Dispatches the Command: Our UserProcessParallelTask implementation correctly receives the INQUIRY task. Logs show the requested transfer size is 6 bytes, and the DEXT obtains the IOVA (0x801c0000) to pass to the hardware. DEXT Log: [UserProcessParallelTask_Impl] --- FORENSIC ANALYSIS --- [UserProcessParallelTask_Impl] fBufferIOVMAddr = 0x801c0000 [UserProcessParallelTask_Impl] fRequestedTransferCount = 6 2, Firmware Receives IOVA and Prepares Correct Data: A probe in our firmware confirms that the hardware successfully received the correct IOVA and the 6-byte length requirement. The firmware then prepares the correct 6-byte INQUIRY response in its internal staging buffer. Firmware Logs: -- [FIRMWARE PROBE: INCOMING DMA DUMP] -- Host IOVA (High:Low) = 0x00000000801c0000 DataLength in Header = 6 (0x6) --- [Firmware Outgoing Data Dump from go_inquiry] --- Source Address: 0x228BB800, Length: 6 bytes 0x0000: 00 00 05 12 1F 00 3, Hardware Reports a Successful Transfer, but Data is Lost: After the firmware initiates the DMA write to the Host IOVA, the hardware reports a successful transfer of 6 bytes back to our DEXT. DEXT Completion Log: [AME_Host_Normal_Handler_SCSI_Request] [TaskID: 200] COMPLETING... [AME_Host_Normal_Handler_SCSI_Request] Hardware Transferred = 6 bytes [AME_Host_Normal_Handler_SCSI_Request] - ReplyStatus = SUCCESS (0x0) [AME_Host_Normal_Handler_SCSI_Request] - SCSIStatus = SUCCESS (0x0) The Core Contradiction: Despite the firmware preparing the correct data and the hardware reporting a successful DMA transfer, the fDataBuffer in our DEXT remains filled with zeros. The 6 bytes of data are lost somewhere between the PCIe bus and host memory. This "data-in-firmware, zeros-in-DEXT" phenomenon leads us to believe the issue lies in memory address translation or a system security policy, as our legacy KEXT works perfectly on the same hardware. Compared to a KEXT, are there any known, stricter IOMMU/security policies for a DEXT that could cause this kind of "silent write failure" (even with a correct IOVA)? Alternatively, what is the correct and complete expected workflow in DriverKit for preparing an IOMemoryDescriptor* fDataBuffer (received in UserProcessParallelTask) for a PCI hardware device to use as a DMA write target? Any official documentation, examples, or advice on the IOMemoryDescriptor to PCI Bus Address workflow would be immensely helpful. Thank you. Charles
5
0
197
Oct ’25
[DEXT Migration Issue] IOUserSCSIParallelInterfaceController fails to handle low-level I/O from `diskutil`
Hello everyone, We are migrating our KEXT for a Thunderbolt storage device to a DEXT based on IOUserSCSIParallelInterfaceController. We've run into a fundamental issue where the driver's behavior splits based on the I/O source: high-level I/O from the file system (e.g., Finder, cp) is mostly functional (with a minor ls -al sorting issue for Traditional Chinese filenames), while low-level I/O directly to the block device (e.g., diskutil) fails or acts unreliably. Basic read/write with dd appears to be mostly functional. We suspect that our DEXT is failing to correctly register its full device "personality" with the I/O Kit framework, unlike its KEXT counterpart. As a result, low-level I/O requests with special attributes (like cache synchronization) sent by diskutil are not being handled correctly by the IOUserSCSIParallelInterfaceController framework of our DEXT. Actions Performed & Relevant Logs 1. Discrepancy: diskutil info Shows Different Device Identities for DEXT vs. KEXT For the exact same hardware, the KEXT and DEXT are identified by the system as two different protocols. KEXT Environment: Device Identifier: disk5 Protocol: Fibre Channel Interface ... Disk Size: 66.0 TB Device Block Size: 512 Bytes DEXT Environment: Device Identifier: disk5 Protocol: SCSI SCSI Domain ID: 2 SCSI Target ID: 0 ... Disk Size: 66.0 TB Device Block Size: 512 Bytes 2. Divergent I/O Behavior: Partial Success with Finder/cp vs. Failure with diskutil High-Level I/O (Partially Successful): In the DEXT environment, if we operate on an existing volume (e.g., /Volumes/MyVolume), file copy operations using Finder or cp succeed. Furthermore, the logs we've placed in our single I/O entry point, UserProcessParallelTask_Impl, are triggered. Side Effect: However, running ls -al on such a volume shows an incorrect sorting order for files with Traditional Chinese names (they appear before . and ..). Low-Level I/O (Contradictory Behavior): In the DEXT environment, when we operate directly on the raw block device (/dev/disk5): diskutil partitionDisk ... -> Fails 100% of the time with the error: Error: -69825: Wiping volume data to prevent future accidental probing failed. dd command -> Basic read/write operations appear to work correctly (a write can be immediately followed by a read within the same DEXT session, and the data is correct). 3. Evidence of Cache Synchronization Failure (Non-deterministic Behavior) The success of the dd command is not deterministic. Cross-environment tests prove that its write operations are unreliable: First Test: In the DEXT environment, write a file with random data to /dev/disk5 using dd. Reboot into the KEXT environment. Read the data back from /dev/disk5 using dd. The result is a file filled with all zeros. Conclusion: The write operation only went to the hardware cache, and the data was lost upon reboot. Second Test: In the DEXT environment, write the same random file to /dev/disk5 using dd. Key Variable: Immediately after, still within the DEXT environment, read the data back once for verification. The content is correct! Reboot into the KEXT environment. Read the data back from /dev/disk5. This time, the content is correct! Conclusion: The additional read operation in the second test unintentionally triggered a hardware cache flush. This proves that the dd (in our DEXT) write operation by itself does not guarantee synchronization, making its behavior unreliable. Our Problem Based on the observations above, we have the conclusion: High-Level Path (triggered by Finder/cp): When an I/O request originates from the high-level file system, the framework seems to enter a fully-featured mode. In this mode, all SCSI commands, including READ/WRITE, INQUIRY, and SYNCHRONIZE CACHE, are correctly packaged and dispatched to our UserProcessParallelTask_Impl entry point. Therefore, Finder operations are mostly functional. Low-Level Path (triggered by dd/diskutil): When an I/O request originates from the low-level raw block device layer: The most basic READ/WRITE commands can be dispatched (which is why dd appears to work). However, critical management commands, such as INQUIRY and SYNCHRONIZE CACHE, are not being correctly dispatched or handled. This leads to the incorrect device identification in diskutil info and the failure of diskutil partitionDisk due to its inability to confirm cache synchronization. We would greatly appreciate any guidance, suggestions, or insights on how to resolve this discrepancy. Specifically, what is the recommended approach within DriverKit to ensure that a DEXT based on IOUserSCSIParallelInterfaceController can properly declare its capabilities and handle both high-level and low-level I/O requests uniformly? Thank you. Charles
12
0
393
4w
Problem with DriverKitUserClientSample
First time working with DEXT, so I'm trying to make "Communicating between a DriverKit extension and a client app" sample project to work and I'm having trouble. I'm following the steps for "Automatically manage signing". It seems that the step “Sign to Run Locally” is wrong now, so I let it to Apple Developer. Now I have a Provisioning Profile error that says it doesn't include the com.apple.developer.driverkit.allow-any-userclient-access entitlement. If I go to Certificates, Identifiers and Profiles for this AppID and go to Capability Requests and select DriverKit Allow Any UserClient Access, this bring me to a page where I select DriverKit Entitlement but Any UserClient Access is not a choice. I tried asking for UserClient Access but the request has been denied saying that the engineering team does not think these entitlements are necessary for testing locally. So I removed com.apple.developer.driverkit.allow-any-userclient-access from NullDriver.entitlements. I can now install the DEXT but when I try "Communicate with Dext" button, I received the error: Failed opening connection to dext with error: 0xe00002e2. Looking in the console, I see this error message: DK: NullDriverUserClient-0x10000ad6a:UC failed userclient-access check, needed bundle ID com.example.apple-samplecode.dext-to-user-client-2-TEST.driver I tried many things, but I can't seem to be able to pass through the check to allow the application to communicate with the dext. What am I missing? Note that I'm focusing only on macOS, not iOS. Thanks.
7
0
92
3w