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;
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.