IQ.Pilot Release Commit @ bec7652

This commit is contained in:
IQ.Lvbs history cleanup
2026-08-22 23:42:41 -05:00
commit 58039e647c
4603 changed files with 1236178 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
Software/
fw.zip

View File

@@ -0,0 +1,102 @@
#!/usr/bin/env python3
import sys
import time
from argparse import ArgumentParser
from pyftdi.ftdi import Ftdi
from pyftdi.eeprom import FtdiEeprom
from pyftdi.misc import hexdump
class USBGPUDebug:
CBUS_RESET = (1 << 2)
CBUS_BOOTLOADER = (1 << 1)
def __init__(self, device_url: str = 'ftdi://ftdi:230x/1'):
self.device_url = device_url
self.ftdi = None
self.eeprom = None
self.provisioned = False
def __enter__(self):
self.open()
return self
def __exit__(self, exc_type, exc_value, traceback):
self.close()
def open(self):
self.ftdi = Ftdi()
self.ftdi.open_from_url(self.device_url)
self.ftdi.set_baudrate(921600)
self.ftdi.set_line_property(8, 1, 'N')
self.eeprom = FtdiEeprom()
self.eeprom.connect(self.ftdi)
self.provisioned = (self.eeprom.cbus_func_1 == "GPIO" and self.eeprom.cbus_func_2 == "GPIO")
if not self.provisioned:
print("Warning: Device not provisioned for usbgpu debugging. Use --provision to provision it.")
return
# setup gpio for reset control
self.ftdi.set_cbus_direction(self.CBUS_RESET | self.CBUS_BOOTLOADER, self.CBUS_RESET | self.CBUS_BOOTLOADER)
self.ftdi.set_cbus_gpio(0x00)
def close(self):
self.ftdi.close()
def provision(self):
print("Provisioning FTDI device for usbgpu debugging...")
self.eeprom.set_property('cbus_func_1', 'GPIO')
self.eeprom.set_property('cbus_func_2', 'GPIO')
if self.eeprom.commit(dry_run=False):
self.eeprom.reset_device()
self.ftdi.reset()
self.provisioned = True
print("Provisioning complete.")
def reset(self, bootloader=False):
if not self.provisioned:
raise RuntimeError("Device not provisioned for usbgpu debugging. Use --provision to provision it.")
self.ftdi.set_cbus_gpio(self.CBUS_RESET | (self.CBUS_BOOTLOADER if bootloader else 0))
time.sleep(0.5)
self.ftdi.set_cbus_gpio(self.CBUS_BOOTLOADER if bootloader else 0)
if bootloader:
time.sleep(1)
self.ftdi.set_cbus_gpio(0)
print("Device reset complete.")
def read(self) -> bytes:
return self.ftdi.read_data(256).decode('utf-8', errors='replace')
if __name__ == "__main__":
args = ArgumentParser()
args.add_argument('--device', '-d', type=str, default='ftdi://ftdi:230x/1', help="FTDI device URL")
args.add_argument('--provision', '-p', action='store_true', default=False, help="Provision the connected FTDI for usbgpu debugging")
args.add_argument('--reset', '-r', action='store_true', default=False, help="Reset the device")
args.add_argument('--bootloader', '-b', action='store_true', default=False, help="Reset to bootloader")
args.add_argument('--no-read', '-n', action='store_true', default=False, help="Do not read debug output")
args = args.parse_args()
with USBGPUDebug(args.device) as dbg:
if args.provision:
dbg.provision()
if args.reset:
dbg.reset(bootloader=False)
if args.bootloader:
dbg.reset(bootloader=True)
if not args.no_read:
print("Starting debug output. Press Ctrl-C to exit.\n------")
while True:
sys.stdout.write(dbg.read())
sys.stdout.flush()
time.sleep(0.001)

View File

@@ -0,0 +1,23 @@
import array, time, ctypes, struct, random
from hexdump import hexdump
from tinygrad.runtime.support.usb import ASM24Controller, WriteOp, ScsiWriteOp
from tinygrad.runtime.autogen import pci
from tinygrad.helpers import Timing
from tinygrad import Device
usb = ASM24Controller()
def real_scsi_write():
self.exec_ops([ScsiWriteOp(buf, lba)])
for i in range(256):
xxx = (ctypes.c_uint8 * 4096)()
dfg = random.randint(0, 255)
for i in range(len(xxx)): xxx[i] = dfg
# print(dfg, usb.read(0xf000, 0x10))
st = time.perf_counter_ns()
usb.scsi_write(bytes(xxx), lba=0x1000 + i)
en = time.perf_counter_ns()
print("mb/s is ", (0x1000) / (en - st) * 1e9 / 1024 / 1024)
exit(0)

View File

@@ -0,0 +1,88 @@
#!/usr/bin/env python3
import sys
import zlib
def patch(input_filepath, output_filepath, patches):
with open(input_filepath, 'rb') as infile: data = bytearray(infile.read())
for offset, expected_bytes, new_bytes in patches:
if len(expected_bytes) != len(new_bytes):
print(len(expected_bytes), len(new_bytes))
raise ValueError("Expected bytes and new bytes must be the same length")
if offset + len(new_bytes) > len(data): return False
current_bytes = data[offset:offset + len(expected_bytes)]
assert bytes(current_bytes) == expected_bytes, f"Expected {expected_bytes} at offset {offset:x}, but got {current_bytes}"
data[offset:offset + len(new_bytes)] = new_bytes
checksum = sum(data[4:-6]) & 0xff
crc32 = zlib.crc32(data[4:-6]).to_bytes(4, 'little')
data[-5] = checksum
data[-4] = crc32[0]
data[-3] = crc32[1]
data[-2] = crc32[2]
data[-1] = crc32[3]
with open(output_filepath, 'wb') as outfile:
outfile.write(data)
return True
patches = [
# (0x3903 + 1 + 4, b'\x8a', b'\x8b'),
# (0x3cf9 + 1 + 4, b'\x8a', b'\x8b'), # this is the one which triggered...
(0x2a0d + 1 + 4, b'\x0a', b'\x05'), # write handle exit with code 5 (?)
# (0x40e1 + 4, b'\x90\x06\xe6\x04\xf0\x78\x0d\xe6\xfe\x24\x71\x12\x1b\x0b\x60\x0b\x74\x08', b'\x7f\x00\x12\x53\x21\x12\x1c\xfc\x74\x01\xf6\x90\x90\x94\x74\x10\xf0\x22')
# (0x29ad + 1 + 4, b'\x09', b'\x05'), # write handle exit with code 5 (?)
# (0x40ef + 0 + 4, b'\x60', b'\x70'), # jz -> jnz
# (0x40e1 + 0 + 4, b'\x90', b'\x22'), # jmp -> ret
# (0x40fa + 0 + 4, b'\x80', b'\x22'),
# (0x40e1 + 0 + 4, b'\x90\x06\xe6\x04\xf0', b'\x7f\x00\x02\x41\x7c'), # jmp -> ret
]
next_traphandler = 0
def add_traphandler(addr, sec):
global next_traphandler, patches
trap_addr = 0x6000 + next_traphandler * 0x20
return_addr = addr + len(sec)
cntr_addr = 0x3000 + next_traphandler
patches += [
(addr + 4, sec, b'\x02' + trap_addr.to_bytes(2, 'big') + b'\x22'*(len(sec)-3)),
(trap_addr + 4, b'\x00' * (21 + len(sec)),
b'\xc0\xe0\xc0\x82\xc0\x83\x90' + cntr_addr.to_bytes(2, 'big') + b'\xe0\x04\xf0\xd0\x83\xd0\x82\xd0\xe0' + sec + b'\x02' + return_addr.to_bytes(2, 'big')),
]
next_traphandler += 1
# add_traphandler(0x0206, b'\xed\x54\x06') # fill_scsi_resp
# add_traphandler(0x40d9, b'\x78\x6a\xe6') # fill_scsi_to_usb_transport
# add_traphandler(0x4d44, b'\x78\x6a\xe6') # FUN_CODE_4d44
# add_traphandler(0x4784, b'\x78\x6a\xe6') # FUN_CODE_4784
# add_traphandler(0x3e81, b'\x90\xc5\x16') # FUN_CODE_3e81
# add_traphandler(0x32a5, b'\x78\x6a\xe6') # FUN_CODE_32a5
# add_traphandler(0x2a10, b'\x90\xc4\x51') # FUN_CODE_2a10
# add_traphandler(0x2608, b'\x12\x16\x87') # FUN_CODE_2608
# add_traphandler(0x0e78, b'\x90\xc8\x02') # main usb entry
# add_traphandler(0x102f, b'\x12\x18\x0d') # possible scsi entry parser
# add_traphandler(0x1198, b'\x12\x18\x0d') # close_to_scsi_parse_1_and_set_c47a_to_0xff caller to scsi
# add_traphandler(0x180d, b'\x90\x0a\x7d') # close_to_scsi_parse
# add_traphandler(0x1114, b'\x75\x37\x00') # entry into if ((DAT_EXTMEM_c802 >> 2 & 1) != 0) { in main usb entry
# add_traphandler(0x113a, b'\x90\x90\x00') # exit from scsi parse loop
# add_traphandler(0x117b, b'\xd0\x07\xd0\x06') # exit from main usb entry
# add_traphandler(0x2f81, b'\x90\x0a\x59') # main loop? 8
# add_traphandler(0xc7a7, b'\x90\x09\xfa') # call smth in write path 9
# add_traphandler(0x2fcb, b'\x90\x0a\x59') # if ((DAT_EXTMEM_0ae2 != 0) && (DAT_EXTMEM_0ae2 != 0x10)) {
# add_traphandler(0x2fc0, b'\x90\x0a\xe2') # submain loop 11
# add_traphandler(0x30be, b'\x90\x0a\x5a') # aft sub loop 12
# add_traphandler(0x3076, b'\x12\x03\x59') # call to call_wait_for_nvme??(); 13
# add_traphandler(0x30ad, b'\x12\x04\xe4') # call to call_wait_for_nvme??(); 14
# add_traphandler(0x2608, b'\x12\x16\x87') # FUN_CODE_2608
# add_traphandler(0x10ee, b'\x90\x04\x64') # iniside trap handler
# add_traphandler(0x10e0, b'\x90\xc8\x06') # iniside trap handler
# add_traphandler(0x4977, b'\x90\x0a\xa8') # waiter for nvme???
assert patch(sys.argv[1], sys.argv[2], patches) is True

View File

@@ -0,0 +1,22 @@
import array, time, ctypes, struct, random
from hexdump import hexdump
from tinygrad.runtime.support.usb import ASMController, WriteOp
from tinygrad.runtime.autogen import pci
from tinygrad.helpers import Timing
from tinygrad import Device
usb = ASMController()
xxx = (ctypes.c_uint8 * 4096)()
dfg = random.randint(0, 255)
for i in range(len(xxx)): xxx[i] = dfg
print(dfg, usb.read(0xf000, 0x10))
with Timing():
for i in range(64): usb.scsi_write(xxx)
with Timing():
for i in range(64): usb.read(0xf000, 0x1000)
exit(0)

View File

@@ -0,0 +1,98 @@
#!/usr/bin/env python3
import os, zlib, struct, hashlib
from tinygrad.helpers import getenv
from tinygrad.runtime.support.usb import USB3
SUPPORTED_CONTROLLERS = [
(0x174C, 0x2464),
(0x174C, 0x2463),
(0xADD1, 0x0001),
]
if getenv("USBDEV", ""): SUPPORTED_CONTROLLERS.insert(0, (int(x, 16) for x in getenv("USBDEV", "").split(":")))
def patch(input_filepath, file_hash, patches):
with open(input_filepath, 'rb') as infile: data = bytearray(infile.read())
if_hash = hashlib.md5(data).hexdigest()
if if_hash != file_hash:
raise ValueError(f"File hash mismatch: expected {file_hash}, got {if_hash}")
for offset, expected_bytes, new_bytes in patches:
if len(expected_bytes) != len(new_bytes):
raise ValueError("Expected bytes and new bytes must be the same length")
if offset + len(new_bytes) > len(data): return False
current_bytes = data[offset:offset + len(expected_bytes)]
assert bytes(current_bytes) == expected_bytes, f"Expected {expected_bytes} at offset {offset:x}, but got {current_bytes}"
data[offset:offset + len(new_bytes)] = new_bytes
checksum = sum(data[4:-6]) & 0xff
crc32 = zlib.crc32(data[4:-6]).to_bytes(4, 'little')
data[-5] = checksum
data[-4] = crc32[0]
data[-3] = crc32[1]
data[-2] = crc32[2]
data[-1] = crc32[3]
return data
path = os.path.dirname(os.path.abspath(__file__))
file_hash = "5284e618d96ef804c06f47f3b73656b7"
file_path = os.path.join(path, "Software/AS_USB4_240417_85_00_00.bin")
if not os.path.exists(file_path):
url = "https://web.archive.org/web/20250430124720/https://www.station-drivers.com/index.php/en/component/remository/func-download/6341/chk,3ef8b04704a18eb2fc57ff60382379ad/no_html,1/lang,en-gb/"
os.system(f'curl -o "{path}/fw.zip" "{url}"')
os.system(f'unzip -o "{path}/fw.zip" "Software/AS_USB4_240417_85_00_00.bin" -d "{path}"')
patches = [(0x2a0d + 1 + 4, b'\x0a', b'\x05')]
patched_fw = patch(file_path, file_hash, patches)
dev = None
for vendor, device in SUPPORTED_CONTROLLERS:
try:
dev = USB3(vendor, device, 0x81, 0x83, 0x02, 0x04, use_bot=True)
break
except RuntimeError: pass
if dev is None:
raise RuntimeError('Could not open controller. You can set USBDEV environment variable to your device\'s vendor and device ID (e.g., USBDEV="174C:2464")')
config1 = bytes([
0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x42, 0x30, 0x30, 0x36, 0x30,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x74, 0x69, 0x6E, 0x79, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x74, 0x69, 0x6E, 0x79,
0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0x53, 0x42, 0x20, 0x33, 0x2E, 0x32, 0x20, 0x50, 0x43, 0x49, 0x65,
0x20, 0x54, 0x69, 0x6E, 0x79, 0x45, 0x6E, 0x63, 0x6C, 0x6F, 0x73, 0x75, 0x72, 0x65, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0x69, 0x6E, 0x79, 0x45, 0x6E, 0x63, 0x6C, 0x6F, 0x73, 0x75, 0x72,
0x65, 0xFF, 0xFF, 0xFF, 0xD1, 0xAD, 0x01, 0x00, 0x00, 0x01, 0xCF, 0xFF, 0x02, 0xFF, 0x5A, 0x94])
config2 = bytes([
0xFF, 0xFF, 0xFF, 0xFF, 0x47, 0x6F, 0x70, 0x6F, 0x64, 0x20, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x20,
0x4C, 0x69, 0x6D, 0x69, 0x74, 0x65, 0x64, 0x2E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0x53, 0x42, 0x34,
0x20, 0x4E, 0x56, 0x4D, 0x65, 0x20, 0x53, 0x53, 0x44, 0x20, 0x50, 0x72, 0x6F, 0x20, 0x45, 0x6E,
0x63, 0x6C, 0x6F, 0x73, 0x75, 0x72, 0x65, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x8C, 0xBF, 0xFF, 0x97, 0xC1, 0xF3, 0xFF, 0xFF, 0x01, 0x2D, 0x66, 0xD6,
0x66, 0x06, 0x00, 0xC0, 0x87, 0x01, 0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCA, 0x01, 0x66, 0xD6,
0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x00, 0xA5, 0x67])
part1 = patched_fw[:0xff00]
part2 = patched_fw[0xff00:]
# config patch
cdb = struct.pack('>BBB12x', 0xe1, 0x50, 0x0)
dev.send_batch(cdbs=[cdb], odata=[config1])
cdb = struct.pack('>BBB12x', 0xe1, 0x50, 0x1)
dev.send_batch(cdbs=[cdb], odata=[config2])
cdb = struct.pack('>BBI', 0xe3, 0x50, len(part1))
dev.send_batch(cdbs=[cdb], odata=[part1])
cdb = struct.pack('>BBI', 0xe3, 0xd0, len(part2))
dev.send_batch(cdbs=[cdb], odata=[part2])
cdb = struct.pack('>BB13x', 0xe8, 0x51)
dev.send_batch(cdbs=[cdb])
print("done, you can disconnect the controller!")

View File

@@ -0,0 +1,67 @@
import array, time
from hexdump import hexdump
from tinygrad.runtime.support.usb import ASM24Controller
from tinygrad.runtime.autogen import pci
usb = ASM24Controller()
def print_cfg(bus, dev):
cfg = []
for i in range(0, 256, 4):
cfg.append(usb.pcie_cfg_req(i, bus=bus, dev=dev, fn=0, value=None, size=4))
print("bus={}, dev={}".format(bus, dev))
dmp = bytearray(array.array('I', cfg))
hexdump(dmp)
return dmp
def rescan_bus(bus, gpu_bus):
print("set PCI_SUBORDINATE_BUS bus={} to {}".format(bus, gpu_bus))
usb.pcie_cfg_req(pci.PCI_SUBORDINATE_BUS, bus=bus, dev=0, fn=0, value=gpu_bus, size=1)
usb.pcie_cfg_req(pci.PCI_SECONDARY_BUS, bus=bus, dev=0, fn=0, value=bus+1, size=1)
usb.pcie_cfg_req(pci.PCI_PRIMARY_BUS, bus=bus, dev=0, fn=0, value=max(0, bus-1), size=1)
print("rescan bus={}".format(bus))
usb.pcie_cfg_req(pci.PCI_BRIDGE_CONTROL, bus=bus, dev=0, fn=0, value=pci.PCI_BRIDGE_CTL_BUS_RESET, size=1)
time.sleep(0.1)
usb.pcie_cfg_req(pci.PCI_BRIDGE_CONTROL, bus=bus, dev=0, fn=0, value=pci.PCI_BRIDGE_CTL_PARITY|pci.PCI_BRIDGE_CTL_SERR, size=1)
usb.pcie_cfg_req(pci.PCI_MEMORY_BASE, bus=bus, dev=0, fn=0, value=0x1000, size=2)
usb.pcie_cfg_req(pci.PCI_MEMORY_LIMIT, bus=bus, dev=0, fn=0, value=0x2000, size=2)
usb.pcie_cfg_req(pci.PCI_PREF_MEMORY_BASE, bus=bus, dev=0, fn=0, value=0x2000, size=2)
usb.pcie_cfg_req(pci.PCI_PREF_MEMORY_LIMIT, bus=bus, dev=0, fn=0, value=0xffff, size=2)
print_cfg(0, 0)
rescan_bus(0, gpu_bus=4)
print_cfg(1, 0)
rescan_bus(1, gpu_bus=4)
time.sleep(0.1)
print_cfg(2, 0)
def setup_bus(bus, gpu_bus):
print("setup bus={}".format(bus))
usb.pcie_cfg_req(pci.PCI_SUBORDINATE_BUS, bus=bus, dev=0, fn=0, value=gpu_bus, size=1)
usb.pcie_cfg_req(pci.PCI_SECONDARY_BUS, bus=bus, dev=0, fn=0, value=bus+1, size=1)
usb.pcie_cfg_req(pci.PCI_PRIMARY_BUS, bus=bus, dev=0, fn=0, value=max(0, bus-1), size=1)
usb.pcie_cfg_req(pci.PCI_BRIDGE_CONTROL, bus=bus, dev=0, fn=0, value=pci.PCI_BRIDGE_CTL_BUS_RESET, size=1)
usb.pcie_cfg_req(pci.PCI_BRIDGE_CONTROL, bus=bus, dev=0, fn=0, value=pci.PCI_BRIDGE_CTL_PARITY|pci.PCI_BRIDGE_CTL_SERR, size=1)
usb.pcie_cfg_req(pci.PCI_COMMAND, bus=bus, dev=0, fn=0, value=pci.PCI_COMMAND_IO | pci.PCI_COMMAND_MEMORY | pci.PCI_COMMAND_MASTER, size=1)
usb.pcie_cfg_req(pci.PCI_MEMORY_BASE, bus=bus, dev=0, fn=0, value=0x1000, size=2)
usb.pcie_cfg_req(pci.PCI_MEMORY_LIMIT, bus=bus, dev=0, fn=0, value=0x2000, size=2)
usb.pcie_cfg_req(pci.PCI_PREF_MEMORY_BASE, bus=bus, dev=0, fn=0, value=0x2000, size=2)
usb.pcie_cfg_req(pci.PCI_PREF_MEMORY_LIMIT, bus=bus, dev=0, fn=0, value=0xffff, size=2)
setup_bus(2, gpu_bus=4)
print_cfg(3, 0)
setup_bus(3, gpu_bus=4)
dmp = print_cfg(4, 0)
print(dmp[0:4])
assert dmp[0:4] in (b"\x02\x10\x80\x74", b"\x02\x10\x4c\x74", b"\x02\x10\x50\x75"), "GPU NOT FOUND!"
print("GPU FOUND!")

View File

@@ -0,0 +1,22 @@
#!/bin/bash
set -e
APP_PATH="/Applications/TinyGPU.app"
DEXT_ID="org.tinygrad.tinygpu.driver2"
# Install app if not present. TODO: url
if [[ ! -d "$APP_PATH" ]]; then
echo "TinyGPU.app not found in /Applications"
exit 1
fi
# Ask user to install
read -n1 -p "Install TinyGPU driver extension now? [y/N] " answer
echo
if [[ "$answer" =~ ^[Yy]$ ]]; then
"$APP_PATH/Contents/MacOS/TinyGPU" install
else
echo "Skipped."
exit 0
fi

View File

@@ -0,0 +1,13 @@
xcuserdata/
**/*.xcodeproj/project.xcworkspace/*
!**/*.xcodeproj/project.xcworkspace/xcshareddata
**/*.xcodeproj/project.xcworkspace/xcshareddata/*
!**/*.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
**/*.playground/playground.xcworkspace/*
!**/*.playground/playground.xcworkspace/xcshareddata
**/*.playground/playground.xcworkspace/xcshareddata/*
!**/*.playground/playground.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings

View File

@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,148 @@
{
"images" : [
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "16x16"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "16x16"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "32x32"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "32x32"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "128x128"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "128x128"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "256x256"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "256x256"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "512x512"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "512x512"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1 @@
int run_server(const char *sock_path);

View File

@@ -0,0 +1,48 @@
import SwiftUI
private let dextID = "org.tinygrad.tinygpu.driver2"
@main
struct TinyGPUApp: App {
private static var runner: TinyGPUCLIRunner? // prevent dealloc before callback
@State private var text = ""
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
init() {
guard CommandLine.arguments.count > 1 else { return }
Self.runner = TinyGPUCLIRunner(dextID)
Self.runner?.run(args: CommandLine.arguments) { exit($0.rawValue) }
dispatchMain()
}
var body: some Scene {
WindowGroup("TinyGPU") {
ScrollView {
Text(text).font(.custom("Menlo", size: 11)).frame(maxWidth: .infinity, alignment: .leading).padding(8)
}
.frame(width: 500, height: 300).padding()
.onAppear { setup() }
}
.commands { CommandGroup(replacing: .newItem) {} }
}
func setup() {
let bundlePath = Bundle.main.bundlePath
guard bundlePath.hasPrefix("/Applications/") else {
var error: NSDictionary?
NSAppleScript(source: "do shell script \"mv '\(bundlePath)' '/Applications/'\" with administrator privileges")?.executeAndReturnError(&error)
text = error == nil ? "Moved! Please reopen from /Applications/\n" : "Move TinyGPU to /Applications first.\n"
return
}
let state = TinyGPUCLIRunner.queryDextState(dextID)
if state == .unloaded || state == .activating {
Self.runner = TinyGPUCLIRunner(dextID)
Self.runner?.run(args: ["", "install"]) { _ in }
}
text = "TinyGPU - Remote PCI Device Server\n\n" + TinyGPUCLIRunner.statusText(state)
}
}
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { true }
}

View File

@@ -0,0 +1,122 @@
import Foundation
import SystemExtensions
enum TinyGPUCLIExit: Int32 { case ok = 0, usage = 2, failed = 3, needsApproval = 4 }
enum DextState { case unloaded, activating, needsApproval, activated }
final class TinyGPUCLIRunner: NSObject, OSSystemExtensionRequestDelegate {
private let dextID: String
private var done: ((TinyGPUCLIExit) -> Void)?
private var isInstall = true
init(_ dextID: String) { self.dextID = dextID }
static func queryDextState(_ bundleID: String) -> DextState {
let p = Process()
p.executableURL = URL(fileURLWithPath: "/usr/bin/systemextensionsctl")
p.arguments = ["list"]
let pipe = Pipe()
p.standardOutput = pipe
p.standardError = Pipe()
guard (try? p.run()) != nil else { return .unloaded }
p.waitUntilExit()
guard let output = String(data: pipe.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8),
let line = output.split(separator: "\n").first(where: { $0.contains(bundleID) }) else { return .unloaded }
if line.contains("[activated enabled]") { return .activated }
if line.contains("[activated waiting for user]") { return .needsApproval }
return line.contains("terminated waiting to uninstall") ? .unloaded : .activating
}
private static let approvalHelp = """
Please go to System Settings > Privacy & Security and allow the extension.
If previously disabled: System Settings > General > Login Items & Extensions > Driver Extensions > Toggle TinyGPU ON
"""
static func statusText(_ state: DextState) -> String {
switch state {
case .unloaded: return "Driver extension not installed.\n\n"
case .activating: return "Extension is activating...\n\n"
case .needsApproval: return "Extension awaiting approval.\n\n" + approvalHelp
case .activated: return "Extension is ready! Run tinygrad to use your eGPU.\n\n"
}
}
func run(args: [String], done: @escaping (TinyGPUCLIExit) -> Void) {
self.done = done
guard args.count > 1 else { return usage() }
switch args[1] {
case "status":
print(Self.statusText(Self.queryDextState(dextID)))
done(.ok)
case "install":
if Self.queryDextState(dextID) == .needsApproval { print(Self.statusText(.needsApproval)); return done(.needsApproval) }
print("Installing TinyGPU driver extension...\nYou may need to approve in System Settings.\n")
submitRequest(activate: true)
case "uninstall":
guard Self.queryDextState(dextID) != .unloaded else { print("Not installed.\n"); return done(.ok) }
print("Uninstalling TinyGPU driver extension...\n")
isInstall = false
submitRequest(activate: false)
case "server":
guard args.count > 2 else { print("Error: server requires socket path\n"); return usage() }
done(run_server(args[2]) == 0 ? .ok : .failed)
case "help", "-h", "--help":
usage(); done(.ok)
default:
print("Unknown command: \(args[1])\n"); usage()
}
}
private func usage() {
print("""
Usage: TinyGPU <command>
status Show extension status
install Install the driver extension
uninstall Remove the driver extension
server <path> Start server on Unix socket
""")
done?(.usage)
}
private func submitRequest(activate: Bool) {
let req = activate
? OSSystemExtensionRequest.activationRequest(forExtensionWithIdentifier: dextID, queue: .main)
: OSSystemExtensionRequest.deactivationRequest(forExtensionWithIdentifier: dextID, queue: .main)
req.delegate = self
OSSystemExtensionManager.shared.submitRequest(req)
}
// MARK: - OSSystemExtensionRequestDelegate
func requestNeedsUserApproval(_ request: OSSystemExtensionRequest) {
print("\nUser approval required!\n\n\(Self.approvalHelp)After approval, connect the gpu and use it with tinygrad.\n")
done?(.needsApproval)
}
func request(_ request: OSSystemExtensionRequest, didFinishWithResult result: OSSystemExtensionRequest.Result) {
switch result {
case .completed: print("Driver extension \(isInstall ? "installed" : "uninstalled") successfully!\n")
case .willCompleteAfterReboot: print("Will complete after reboot.\n")
@unknown default: print("Completed: \(result)\n")
}
done?(.ok)
}
func request(_ request: OSSystemExtensionRequest, didFailWithError error: Error) {
print("\nError: \(error.localizedDescription)\n")
let code = (error as NSError).code
if code == 4 { print("Missing entitlements. Rebuild with proper signing.\n") }
else if code == 8 { print("Extension not found in app bundle.\n") }
else if code == 9 { print("Extension disabled by user.\n\n\(Self.approvalHelp)") }
done?(.failed)
}
func request(_ request: OSSystemExtensionRequest, actionForReplacingExtension existing: OSSystemExtensionProperties,
withExtension ext: OSSystemExtensionProperties) -> OSSystemExtensionRequest.ReplacementAction {
print("Updating v\(existing.bundleShortVersion) -> v\(ext.bundleShortVersion)...\n")
return .replace
}
}

View File

@@ -0,0 +1,285 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <errno.h>
#include <dispatch/dispatch.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOMessage.h>
#include <mach/mach.h>
// Protocol
enum {
CMD_PROBE = 0, // probe devices, returns count
CMD_MAP_BAR = 1, // map PCI BAR, returns size
CMD_MAP_SYSMEM_FD = 2, // alloc DMA memory, returns fd via SCM_RIGHTS
CMD_CFG_READ = 3, // read PCI config space
CMD_CFG_WRITE = 4, // write PCI config space
CMD_RESET = 5, // reset device
CMD_MMIO_READ = 6, // bulk read from BAR
CMD_MMIO_WRITE = 7, // bulk write to BAR
CMD_MAP_SYSMEM = 8, // map system memory
CMD_SYSMEM_READ = 9, // bulk read from system memory
CMD_SYSMEM_WRITE = 10, // bulk write to system memory
CMD_RESIZE_BAR = 11, // resize bar (noop)
RESP_OK = 0, RESP_ERR = 1,
};
typedef struct { uint8_t cmd; uint32_t dev_id, bar; uint64_t arg0, arg1, arg2; } __attribute__((packed)) request_t;
typedef struct { uint8_t status; uint64_t resp0, resp1; } __attribute__((packed)) response_t;
// Constants and state
#define BULK_BUF_SIZE (64 << 20)
#define MAX_BARS 6
#define MAX_SYSMEM 128
static uint8_t g_bulk_buf[BULK_BUF_SIZE];
static io_connect_t g_conn = IO_OBJECT_NULL;
static int g_client_active = 0;
static struct { mach_vm_address_t addr; mach_vm_size_t size; } g_bars[MAX_BARS];
static struct { mach_vm_address_t addr; mach_vm_size_t size; int shm_fd; char shm_name[32]; } g_sysmem[MAX_SYSMEM];
static int g_sysmem_count = 0;
// Utilities
static void recvall(int fd, void *buf, size_t len) {
for (size_t off = 0; off < len; ) {
ssize_t r = recv(fd, (uint8_t*)buf + off, len - off, 0);
if (r <= 0) break;
off += r;
}
}
// MMIO requires 32-bit aligned volatile accesses
static void mmio_copy(void *dst, void *src, size_t len) {
volatile uint32_t *d = dst, *s = src;
for (size_t i = 0; i < len / 4; i++) d[i] = s[i];
for (size_t i = len & ~3; i < len; i++) ((volatile uint8_t*)dst)[i] = ((volatile uint8_t*)src)[i];
}
static int send_response(int fd, response_t *resp, int send_fd) {
char cmsgbuf[CMSG_SPACE(sizeof(int))];
struct iovec iov = {resp, sizeof(*resp)};
struct msghdr msg = {.msg_iov = &iov, .msg_iovlen = 1};
if (send_fd >= 0) {
msg.msg_control = cmsgbuf;
msg.msg_controllen = sizeof(cmsgbuf);
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
*cmsg = (struct cmsghdr){.cmsg_level = SOL_SOCKET, .cmsg_type = SCM_RIGHTS, .cmsg_len = CMSG_LEN(sizeof(int))};
memcpy(CMSG_DATA(cmsg), &send_fd, sizeof(int));
}
return sendmsg(fd, &msg, 0) > 0 ? 0 : -1;
}
static void send_error(int fd, const char *msg) {
response_t resp = {.status = RESP_ERR, .resp0 = strlen(msg)};
send_response(fd, &resp, -1);
send(fd, msg, strlen(msg), 0);
}
// Driver interface
static void on_disconnect(void *refcon, io_service_t svc, uint32_t msg, void *arg) {
if (msg == kIOMessageServiceIsTerminated) _exit(0);
}
static io_connect_t open_tinygpu(void) {
static io_object_t notif;
io_service_t svc = IOServiceGetMatchingService(kIOMainPortDefault, IOServiceNameMatching("tinygpu"));
if (!svc) return IO_OBJECT_NULL;
if (!notif) {
IONotificationPortRef port = IONotificationPortCreate(kIOMainPortDefault);
IONotificationPortSetDispatchQueue(port, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
IOServiceAddInterestNotification(port, svc, kIOGeneralInterest, on_disconnect, NULL, &notif);
}
io_connect_t conn;
kern_return_t kr = IOServiceOpen(svc, mach_task_self(), 0, &conn);
IOObjectRelease(svc);
return kr == KERN_SUCCESS ? conn : IO_OBJECT_NULL;
}
static int dext_rpc(uint32_t sel, uint64_t *in, uint32_t in_cnt, uint64_t *out_val) {
uint64_t out[2];
uint32_t out_cnt = 2;
if (IOConnectCallMethod(g_conn, sel, in, in_cnt, NULL, 0, out, &out_cnt, NULL, NULL) != KERN_SUCCESS) return -1;
if (out_val) *out_val = out[0];
return 0;
}
static int map_bar(uint32_t bar, response_t *resp) {
if (bar >= MAX_BARS) return -1;
if (!g_bars[bar].addr && IOConnectMapMemory64(g_conn, bar, mach_task_self(), &g_bars[bar].addr, &g_bars[bar].size, kIOMapAnywhere)) return -1;
resp->resp0 = g_bars[bar].addr;
resp->resp1 = g_bars[bar].size;
return 0;
}
static int map_sysmem_fd(uint64_t size, int contiguous, response_t *resp, int *out_fd) {
if (g_sysmem_count >= MAX_SYSMEM) return -1;
int idx = g_sysmem_count;
int fd = -1;
void *ptr = MAP_FAILED;
char shm_name[32];
// page-align, min 16KB for IOMemoryDescriptor
size_t alloc_sz = (size + 0xfff) & ~0xfff;
if (alloc_sz < 0x4000) alloc_sz = 0x4000;
snprintf(shm_name, sizeof(shm_name), "/tinygpu_%d", idx);
shm_unlink(shm_name);
if ((fd = shm_open(shm_name, O_CREAT | O_RDWR, 0600)) < 0) goto fail;
if (ftruncate(fd, alloc_sz) < 0) goto fail;
if ((ptr = mmap(NULL, alloc_sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) goto fail;
// PrepareDMA writes physical addresses to output buffer, copy to shared mem
uint8_t paddr_buf[8192] = {0};
size_t out_sz = sizeof(paddr_buf);
if (IOConnectCallStructMethod(g_conn, 3, ptr, alloc_sz, paddr_buf, &out_sz) != KERN_SUCCESS) goto fail;
memcpy(ptr, paddr_buf, out_sz);
g_sysmem[idx] = (typeof(g_sysmem[idx])){.addr = (mach_vm_address_t)ptr, .size = alloc_sz, .shm_fd = fd};
strncpy(g_sysmem[idx].shm_name, shm_name, sizeof(g_sysmem[idx].shm_name));
g_sysmem_count++;
*resp = (response_t){.resp0 = alloc_sz, .resp1 = idx};
*out_fd = fd;
return 0;
fail:
if (ptr != MAP_FAILED) munmap(ptr, alloc_sz);
if (fd >= 0) close(fd);
shm_unlink(shm_name);
return -1;
}
static int validate_bar(uint8_t bar, uint64_t off, uint64_t sz) {
return (bar < MAX_BARS && g_bars[bar].addr && off + sz <= g_bars[bar].size && sz <= BULK_BUF_SIZE) ? 0 : -1;
}
static void cleanup(void) {
for (int i = 0; i < MAX_BARS; i++)
if (g_bars[i].addr) { IOConnectUnmapMemory64(g_conn, i, mach_task_self(), g_bars[i].addr); g_bars[i].addr = 0; }
for (int i = 0; i < g_sysmem_count; i++) {
munmap((void*)g_sysmem[i].addr, g_sysmem[i].size);
close(g_sysmem[i].shm_fd);
shm_unlink(g_sysmem[i].shm_name);
}
g_sysmem_count = 0;
if (g_conn != IO_OBJECT_NULL) { IOServiceClose(g_conn); g_conn = IO_OBJECT_NULL; }
}
static void handle_client(int fd) {
int bufsize = BULK_BUF_SIZE;
setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
printf("client connected\n");
g_conn = open_tinygpu();
if (g_conn == IO_OBJECT_NULL) {
fprintf(stderr, "failed to connect to tinygpu driver\n");
request_t req; recv(fd, &req, sizeof(req), 0);
send_error(fd, "Driver not available. Check: System Report > PCI for GPU, System Settings > Privacy & Security.");
return;
}
request_t req;
response_t resp;
while (recv(fd, &req, sizeof(req), 0) == sizeof(req)) {
resp = (response_t){0};
switch (req.cmd) {
case CMD_MAP_BAR:
resp.status = map_bar(req.bar, &resp) ? 1 : 0;
break;
case CMD_MAP_SYSMEM_FD: {
int shm_fd = -1;
resp.status = map_sysmem_fd(req.arg0, (int)req.arg1, &resp, &shm_fd) ? 1 : 0;
send_response(fd, &resp, shm_fd);
continue;
}
case CMD_CFG_READ: {
uint64_t in[2] = {req.arg0, req.arg1};
resp.status = dext_rpc(0, in, 2, &resp.resp0) ? 1 : 0;
break;
}
case CMD_CFG_WRITE: {
uint64_t in[3] = {req.arg0, req.arg1, req.arg2};
resp.status = dext_rpc(1, in, 3, NULL) ? 1 : 0;
break;
}
case CMD_RESIZE_BAR:
break;
case CMD_RESET:
resp.status = dext_rpc(2, NULL, 0, NULL) ? 1 : 0;
break;
case CMD_MMIO_READ:
if (validate_bar(req.bar, req.arg0, req.arg1)) { resp.status = 1; break; }
mmio_copy(g_bulk_buf, (void*)(g_bars[req.bar].addr + req.arg0), req.arg1);
resp.resp0 = req.arg1;
send_response(fd, &resp, -1);
send(fd, g_bulk_buf, req.arg1, 0);
continue;
case CMD_MMIO_WRITE:
recvall(fd, g_bulk_buf, req.arg1);
if (!validate_bar(req.bar, req.arg0, req.arg1))
mmio_copy((void*)(g_bars[req.bar].addr + req.arg0), g_bulk_buf, req.arg1);
continue;
default:
resp.status = 1;
}
send_response(fd, &resp, -1);
}
printf("client disconnected\n");
cleanup();
}
int run_server(const char *sock_path) {
int server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (server_fd < 0) { perror("socket"); return 1; }
struct sockaddr_un addr = {.sun_family = AF_UNIX};
strncpy(addr.sun_path, sock_path, sizeof(addr.sun_path) - 1);
unlink(sock_path);
if (bind(server_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { perror("bind"); close(server_fd); return 1; }
if (listen(server_fd, 1) < 0) { perror("listen"); close(server_fd); return 1; }
printf("listening on %s\n", sock_path);
while (1) {
int client_fd = accept(server_fd, NULL, NULL);
if (client_fd < 0) { if (errno == EINTR) continue; perror("accept"); break; }
if (g_client_active) { printf("rejected: client already connected\n"); close(client_fd); continue; }
g_client_active = 1;
handle_client(client_fd);
g_client_active = 0;
close(client_fd);
}
close(server_fd);
unlink(sock_path);
cleanup();
return 0;
}

View File

@@ -0,0 +1,18 @@
<svg viewBox="0 0 130 50" xmlns="http://www.w3.org/2000/svg">
<!-- t -->
<rect x="10" y="0" width="10" height="40" fill="#000000"></rect>
<rect x="0" y="10" width="30" height="10" fill="#000000"></rect>
<rect x="10" y="30" width="20" height="10" fill="#000000"></rect>
<!-- i -->
<rect x="40" y="0" width="10" height="10" fill="#000000"></rect>
<rect x="40" y="20" width="10" height="20" fill="#000000"></rect>
<!-- n -->
<rect x="60" y="10" width="10" height="30" fill="#000000"></rect>
<rect x="60" y="10" width="20" height="10" fill="#000000"></rect>
<rect x="80" y="20" width="10" height="20" fill="#000000"></rect>
<!-- y -->
<rect x="100" y="10" width="10" height="20" fill="#000000"></rect>
<rect x="100" y="20" width="30" height="10" fill="#000000"></rect>
<rect x="120" y="10" width="10" height="30" fill="#000000"></rect>
<rect x="100" y="40" width="20" height="10" fill="#000000"></rect>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,52 @@
{
"fill" : "automatic",
"groups" : [
{
"layers" : [
{
"fill-specializations" : [
{
"value" : "automatic"
},
{
"appearance" : "dark",
"value" : {
"solid" : "display-p3:0.94011,0.96611,0.94301,1.00000"
}
},
{
"appearance" : "tinted",
"value" : {
"solid" : "display-p3:0.79528,0.79528,0.79528,1.00000"
}
}
],
"hidden" : false,
"image-name" : "tiny.svg",
"name" : "tiny_svg",
"position" : {
"scale" : 5,
"translation-in-points" : [
0,
19
]
}
}
],
"shadow" : {
"kind" : "neutral",
"opacity" : 0.5
},
"translucency" : {
"enabled" : true,
"value" : 0.5
}
}
],
"supported-platforms" : {
"circles" : [
"watchOS"
],
"squares" : "shared"
}
}

View File

@@ -0,0 +1,625 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
0A52E8692F18FC6900A816CD /* tiny_icon.icon in Resources */ = {isa = PBXBuildFile; fileRef = 0A52E8682F18FC6900A816CD /* tiny_icon.icon */; };
0A5C11DD2F18E466006DBBCA /* server.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A5C11DC2F18E461006DBBCA /* server.c */; };
0ACB55392E9CB880007029EF /* PCIDriverKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0ACB55382E9CB880007029EF /* PCIDriverKit.framework */; };
0AD7C2E52F18DEBC00562D1A /* TinyGPUCLIRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AD7C2E42F18DEB800562D1A /* TinyGPUCLIRunner.swift */; };
54798269286A3512009785F6 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 54798268286A3512009785F6 /* CoreAudio.framework */; };
549EB123286A1D48009D38AB /* org.tinygrad.tinygpu.driver2.dext in Embed System Extensions */ = {isa = PBXBuildFile; fileRef = C5B7D9BC26128AC50089B4C3 /* org.tinygrad.tinygpu.driver2.dext */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
549EB131286A2B98009D38AB /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 549EB130286A2B98009D38AB /* IOKit.framework */; };
54E42BC8286A1697000E1E9A /* TinyGPUApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54E42BB8286A1696000E1E9A /* TinyGPUApp.swift */; };
54E42BCC286A1697000E1E9A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 54E42BBA286A1697000E1E9A /* Assets.xcassets */; };
C5B7D9C326128AC50089B4C3 /* TinyGPUDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C5B7D9C226128AC50089B4C3 /* TinyGPUDriver.cpp */; };
C5B7D9C526128AC50089B4C3 /* TinyGPUDriver.iig in Sources */ = {isa = PBXBuildFile; fileRef = C5B7D9C426128AC50089B4C3 /* TinyGPUDriver.iig */; };
C5C3BBB32612ACDC003C7BFE /* AudioDriverKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5C3BBB12612ACD3003C7BFE /* AudioDriverKit.framework */; };
C5C3BBB52612ACEF003C7BFE /* DriverKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5C3BBB42612ACEF003C7BFE /* DriverKit.framework */; };
C5D787AC261667FC006047E5 /* TinyGPUDriverUserClient.iig in Sources */ = {isa = PBXBuildFile; fileRef = C5D787AB261667FC006047E5 /* TinyGPUDriverUserClient.iig */; };
C5D787AE26168E59006047E5 /* TinyGPUDriverUserClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C5D787AD26168D1E006047E5 /* TinyGPUDriverUserClient.cpp */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
549EB126286A1D66009D38AB /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = C5B7D9B326128AC50089B4C3 /* Project object */;
proxyType = 1;
remoteGlobalIDString = C5B7D9BB26128AC50089B4C3;
remoteInfo = SimpleAudioDriver;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
0AD7C2DB2F18D7D500562D1A /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 6;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
549EB122286A1D3A009D38AB /* Embed System Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "$(SYSTEM_EXTENSIONS_FOLDER_PATH)";
dstSubfolderSpec = 16;
files = (
549EB123286A1D48009D38AB /* org.tinygrad.tinygpu.driver2.dext in Embed System Extensions */,
);
name = "Embed System Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0A52E8682F18FC6900A816CD /* tiny_icon.icon */ = {isa = PBXFileReference; lastKnownFileType = folder.iconcomposer.icon; path = tiny_icon.icon; sourceTree = "<group>"; };
0A5C11DC2F18E461006DBBCA /* server.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = server.c; sourceTree = "<group>"; };
0A5C11DE2F18E468006DBBCA /* TinyGPU-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TinyGPU-Bridging-Header.h"; sourceTree = "<group>"; };
0ACB55382E9CB880007029EF /* PCIDriverKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PCIDriverKit.framework; path = System/DriverKit/System/Library/Frameworks/PCIDriverKit.framework; sourceTree = SDKROOT; };
0AD7C2D62F18D3DB00562D1A /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.2.sdk/System/Library/Frameworks/IOKit.framework; sourceTree = DEVELOPER_DIR; };
0AD7C2D82F18D3E300562D1A /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.2.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; };
0AD7C2E42F18DEB800562D1A /* TinyGPUCLIRunner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TinyGPUCLIRunner.swift; sourceTree = "<group>"; };
0AFA851D2F1CE486005FDAC2 /* TinyGPUDriver.Release.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = TinyGPUDriver.Release.entitlements; sourceTree = "<group>"; };
54798268286A3512009785F6 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.0.sdk/System/Library/Frameworks/CoreAudio.framework; sourceTree = DEVELOPER_DIR; };
549EB130286A2B98009D38AB /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.0.sdk/System/Library/Frameworks/IOKit.framework; sourceTree = DEVELOPER_DIR; };
549EB132286A2B9D009D38AB /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.0.sdk/System/Library/Frameworks/IOKit.framework; sourceTree = DEVELOPER_DIR; };
54E42BB8286A1696000E1E9A /* TinyGPUApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TinyGPUApp.swift; sourceTree = "<group>"; };
54E42BBA286A1697000E1E9A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
54E42BC4286A1697000E1E9A /* TinyGPU.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TinyGPU.app; sourceTree = BUILT_PRODUCTS_DIR; };
54E42BC6286A1697000E1E9A /* macOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = macOS.entitlements; sourceTree = "<group>"; };
C5B7D9BC26128AC50089B4C3 /* org.tinygrad.tinygpu.driver2.dext */ = {isa = PBXFileReference; explicitFileType = "wrapper.driver-extension"; includeInIndex = 0; path = org.tinygrad.tinygpu.driver2.dext; sourceTree = BUILT_PRODUCTS_DIR; };
C5B7D9BF26128AC50089B4C3 /* DriverKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DriverKit.framework; path = Library/Frameworks/DriverKit.framework; sourceTree = DEVELOPER_DIR; };
C5B7D9C226128AC50089B4C3 /* TinyGPUDriver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TinyGPUDriver.cpp; sourceTree = "<group>"; usesTabs = 1; };
C5B7D9C426128AC50089B4C3 /* TinyGPUDriver.iig */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.iig; path = TinyGPUDriver.iig; sourceTree = "<group>"; };
C5B7D9C626128AC50089B4C3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
C5B7D9CC26128ADA0089B4C3 /* AudioDriverKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioDriverKit.framework; path = System/DriverKit/System/Library/Frameworks/AudioDriverKit.framework; sourceTree = SDKROOT; };
C5B7D9CE26128B150089B4C3 /* TinyGPUDriver.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = TinyGPUDriver.entitlements; sourceTree = "<group>"; };
C5C0063326178F98003345D8 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.0.sdk/System/Library/Frameworks/AppKit.framework; sourceTree = DEVELOPER_DIR; };
C5C006352617ACB8003345D8 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.0.sdk/System/Library/Frameworks/CoreAudio.framework; sourceTree = DEVELOPER_DIR; };
C5C3BBB12612ACD3003C7BFE /* AudioDriverKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioDriverKit.framework; path = Platforms/DriverKit.platform/Developer/SDKs/DriverKit.MacOSX21.0.Internal.sdk/System/DriverKit/System/Library/Frameworks/AudioDriverKit.framework; sourceTree = DEVELOPER_DIR; };
C5C3BBB42612ACEF003C7BFE /* DriverKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DriverKit.framework; path = Platforms/DriverKit.platform/Developer/SDKs/DriverKit.MacOSX21.0.Internal.sdk/System/DriverKit/System/Library/Frameworks/DriverKit.framework; sourceTree = DEVELOPER_DIR; };
C5D787AB261667FC006047E5 /* TinyGPUDriverUserClient.iig */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.iig; path = TinyGPUDriverUserClient.iig; sourceTree = "<group>"; };
C5D787AD26168D1E006047E5 /* TinyGPUDriverUserClient.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TinyGPUDriverUserClient.cpp; sourceTree = "<group>"; };
C5D787B026169723006047E5 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.0.sdk/System/Library/Frameworks/IOKit.framework; sourceTree = DEVELOPER_DIR; };
C5D787B22616973F006047E5 /* SystemExtensions.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemExtensions.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.0.sdk/System/Library/Frameworks/SystemExtensions.framework; sourceTree = DEVELOPER_DIR; };
C5D787B426169747006047E5 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
54E42BC1286A1697000E1E9A /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
54798269286A3512009785F6 /* CoreAudio.framework in Frameworks */,
549EB131286A2B98009D38AB /* IOKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C5B7D9B926128AC50089B4C3 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
C5C3BBB32612ACDC003C7BFE /* AudioDriverKit.framework in Frameworks */,
C5C3BBB52612ACEF003C7BFE /* DriverKit.framework in Frameworks */,
0ACB55392E9CB880007029EF /* PCIDriverKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
54E42BB7286A1696000E1E9A /* Shared */ = {
isa = PBXGroup;
children = (
0A5C11DC2F18E461006DBBCA /* server.c */,
0AD7C2E42F18DEB800562D1A /* TinyGPUCLIRunner.swift */,
54E42BB8286A1696000E1E9A /* TinyGPUApp.swift */,
54E42BBA286A1697000E1E9A /* Assets.xcassets */,
0A52E8682F18FC6900A816CD /* tiny_icon.icon */,
0A5C11DE2F18E468006DBBCA /* TinyGPU-Bridging-Header.h */,
);
path = Shared;
sourceTree = "<group>";
};
54E42BC5286A1697000E1E9A /* macOS */ = {
isa = PBXGroup;
children = (
54E42BC6286A1697000E1E9A /* macOS.entitlements */,
);
path = macOS;
sourceTree = "<group>";
};
C5B7D9B226128AC50089B4C3 = {
isa = PBXGroup;
children = (
C5B7D9C126128AC50089B4C3 /* TinyGPUDriverExtension */,
54E42BB7286A1696000E1E9A /* Shared */,
54E42BC5286A1697000E1E9A /* macOS */,
C5B7D9BE26128AC50089B4C3 /* Frameworks */,
C5B7D9BD26128AC50089B4C3 /* Products */,
);
sourceTree = "<group>";
usesTabs = 1;
};
C5B7D9BD26128AC50089B4C3 /* Products */ = {
isa = PBXGroup;
children = (
C5B7D9BC26128AC50089B4C3 /* org.tinygrad.tinygpu.driver2.dext */,
54E42BC4286A1697000E1E9A /* TinyGPU.app */,
);
name = Products;
sourceTree = "<group>";
};
C5B7D9BE26128AC50089B4C3 /* Frameworks */ = {
isa = PBXGroup;
children = (
0AD7C2D82F18D3E300562D1A /* CoreFoundation.framework */,
0AD7C2D62F18D3DB00562D1A /* IOKit.framework */,
0ACB55382E9CB880007029EF /* PCIDriverKit.framework */,
54798268286A3512009785F6 /* CoreAudio.framework */,
549EB130286A2B98009D38AB /* IOKit.framework */,
549EB132286A2B9D009D38AB /* IOKit.framework */,
C5C006352617ACB8003345D8 /* CoreAudio.framework */,
C5C0063326178F98003345D8 /* AppKit.framework */,
C5D787B426169747006047E5 /* Foundation.framework */,
C5D787B22616973F006047E5 /* SystemExtensions.framework */,
C5D787B026169723006047E5 /* IOKit.framework */,
C5C3BBB42612ACEF003C7BFE /* DriverKit.framework */,
C5B7D9CC26128ADA0089B4C3 /* AudioDriverKit.framework */,
C5C3BBB12612ACD3003C7BFE /* AudioDriverKit.framework */,
C5B7D9BF26128AC50089B4C3 /* DriverKit.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
C5B7D9C126128AC50089B4C3 /* TinyGPUDriverExtension */ = {
isa = PBXGroup;
children = (
C5B7D9C226128AC50089B4C3 /* TinyGPUDriver.cpp */,
C5B7D9C426128AC50089B4C3 /* TinyGPUDriver.iig */,
C5D787AD26168D1E006047E5 /* TinyGPUDriverUserClient.cpp */,
C5D787AB261667FC006047E5 /* TinyGPUDriverUserClient.iig */,
C5B7D9C626128AC50089B4C3 /* Info.plist */,
C5B7D9CE26128B150089B4C3 /* TinyGPUDriver.entitlements */,
0AFA851D2F1CE486005FDAC2 /* TinyGPUDriver.Release.entitlements */,
);
path = TinyGPUDriverExtension;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
C5B7D9B726128AC50089B4C3 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
54E42BC3286A1697000E1E9A /* TinyGPU */ = {
isa = PBXNativeTarget;
buildConfigurationList = 54E42BD2286A1697000E1E9A /* Build configuration list for PBXNativeTarget "TinyGPU" */;
buildPhases = (
54E42BC0286A1697000E1E9A /* Sources */,
54E42BC1286A1697000E1E9A /* Frameworks */,
54E42BC2286A1697000E1E9A /* Resources */,
549EB122286A1D3A009D38AB /* Embed System Extensions */,
0AD7C2DB2F18D7D500562D1A /* CopyFiles */,
);
buildRules = (
);
dependencies = (
549EB127286A1D66009D38AB /* PBXTargetDependency */,
);
name = TinyGPU;
productName = "SimpleAudioDriverExtension2 (macOS)";
productReference = 54E42BC4286A1697000E1E9A /* TinyGPU.app */;
productType = "com.apple.product-type.application";
};
C5B7D9BB26128AC50089B4C3 /* TinyGPUDriver */ = {
isa = PBXNativeTarget;
buildConfigurationList = C5B7D9C926128AC50089B4C3 /* Build configuration list for PBXNativeTarget "TinyGPUDriver" */;
buildPhases = (
C5B7D9B726128AC50089B4C3 /* Headers */,
C5B7D9B826128AC50089B4C3 /* Sources */,
C5B7D9B926128AC50089B4C3 /* Frameworks */,
C5B7D9BA26128AC50089B4C3 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = TinyGPUDriver;
productName = SimpleAudioDriverExtension;
productReference = C5B7D9BC26128AC50089B4C3 /* org.tinygrad.tinygpu.driver2.dext */;
productType = "com.apple.product-type.driver-extension";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
C5B7D9B326128AC50089B4C3 /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = YES;
DefaultBuildSystemTypeForWorkspace = Latest;
LastSwiftUpdateCheck = 1400;
LastUpgradeCheck = 1600;
ORGANIZATIONNAME = Apple;
TargetAttributes = {
54E42BC3286A1697000E1E9A = {
CreatedOnToolsVersion = 14.0;
LastSwiftMigration = 2620;
};
C5B7D9BB26128AC50089B4C3 = {
CreatedOnToolsVersion = 13.0;
};
};
};
buildConfigurationList = C5B7D9B626128AC50089B4C3 /* Build configuration list for PBXProject "TinyGPUDriverExtension" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = C5B7D9B226128AC50089B4C3;
productRefGroup = C5B7D9BD26128AC50089B4C3 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
C5B7D9BB26128AC50089B4C3 /* TinyGPUDriver */,
54E42BC3286A1697000E1E9A /* TinyGPU */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
54E42BC2286A1697000E1E9A /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
54E42BCC286A1697000E1E9A /* Assets.xcassets in Resources */,
0A52E8692F18FC6900A816CD /* tiny_icon.icon in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C5B7D9BA26128AC50089B4C3 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
54E42BC0286A1697000E1E9A /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
54E42BC8286A1697000E1E9A /* TinyGPUApp.swift in Sources */,
0A5C11DD2F18E466006DBBCA /* server.c in Sources */,
0AD7C2E52F18DEBC00562D1A /* TinyGPUCLIRunner.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C5B7D9B826128AC50089B4C3 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C5B7D9C526128AC50089B4C3 /* TinyGPUDriver.iig in Sources */,
C5D787AE26168E59006047E5 /* TinyGPUDriverUserClient.cpp in Sources */,
C5D787AC261667FC006047E5 /* TinyGPUDriverUserClient.iig in Sources */,
C5B7D9C326128AC50089B4C3 /* TinyGPUDriver.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
549EB127286A1D66009D38AB /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = C5B7D9BB26128AC50089B4C3 /* TinyGPUDriver */;
targetProxy = 549EB126286A1D66009D38AB /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
54E42BCF286A1697000E1E9A /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = tiny_icon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = macOS/macOS.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 9YG3G8543N;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = org.tinygrad.tinygpu.installer;
PRODUCT_NAME = TinyGPU;
PROVISIONING_PROFILE_SPECIFIER = "";
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OBJC_BRIDGING_HEADER = "Shared/TinyGPU-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
};
name = Debug;
};
54E42BD0286A1697000E1E9A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = tiny_icon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = macOS/macOS.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 9YG3G8543N;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = org.tinygrad.tinygpu.installer;
PRODUCT_NAME = TinyGPU;
PROVISIONING_PROFILE_SPECIFIER = "";
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OBJC_BRIDGING_HEADER = "Shared/TinyGPU-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
};
name = Release;
};
C5B7D9C726128AC50089B4C3 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
DRIVERKIT_DEPLOYMENT_TARGET = 22.0;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = driverkit;
};
name = Debug;
};
C5B7D9C826128AC50089B4C3 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "Apple Development";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DRIVERKIT_DEPLOYMENT_TARGET = 22.0;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = driverkit;
SWIFT_COMPILATION_MODE = wholemodule;
};
name = Release;
};
C5B7D9CA26128AC50089B4C3 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
AD_HOC_CODE_SIGNING_ALLOWED = YES;
CODE_SIGN_ENTITLEMENTS = TinyGPUDriverExtension/TinyGPUDriver.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = 9YG3G8543N;
DRIVERKIT_DEPLOYMENT_TARGET = 22.0;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
EXCLUDED_ARCHS = "";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(SDKROOT)/System/DriverKit/System/Library/Frameworks",
);
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = TinyGPUDriverExtension/Info.plist;
INFOPLIST_KEY_OSBundleUsageDescription = "TinyGPU Driver";
IPHONEOS_DEPLOYMENT_TARGET = 17.6;
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = org.tinygrad.tinygpu.driver2;
PRODUCT_NAME = "$(inherited)";
PROVISIONING_PROFILE_SPECIFIER = "";
RUN_CLANG_STATIC_ANALYZER = YES;
SDKROOT = driverkit;
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = driverkit;
};
name = Debug;
};
C5B7D9CB26128AC50089B4C3 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
AD_HOC_CODE_SIGNING_ALLOWED = YES;
CODE_SIGN_ENTITLEMENTS = TinyGPUDriverExtension/TinyGPUDriver.Release.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=driverkit*]" = "Apple Development";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=driverkit*]" = 9YG3G8543N;
DRIVERKIT_DEPLOYMENT_TARGET = 22.0;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
EXCLUDED_ARCHS = "";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(SDKROOT)/System/DriverKit/System/Library/Frameworks",
);
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = TinyGPUDriverExtension/Info.plist;
INFOPLIST_KEY_OSBundleUsageDescription = "TinyGPU Driver";
IPHONEOS_DEPLOYMENT_TARGET = 17.6;
MARKETING_VERSION = 1.0.0;
ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.tinygrad.tinygpu.driver2;
PRODUCT_NAME = "$(inherited)";
PROVISIONING_PROFILE_SPECIFIER = "";
RUN_CLANG_STATIC_ANALYZER = YES;
SDKROOT = driverkit;
SKIP_INSTALL = YES;
SUPPORTED_PLATFORMS = driverkit;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
54E42BD2286A1697000E1E9A /* Build configuration list for PBXNativeTarget "TinyGPU" */ = {
isa = XCConfigurationList;
buildConfigurations = (
54E42BCF286A1697000E1E9A /* Debug */,
54E42BD0286A1697000E1E9A /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C5B7D9B626128AC50089B4C3 /* Build configuration list for PBXProject "TinyGPUDriverExtension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C5B7D9C726128AC50089B4C3 /* Debug */,
C5B7D9C826128AC50089B4C3 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C5B7D9C926128AC50089B4C3 /* Build configuration list for PBXNativeTarget "TinyGPUDriver" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C5B7D9CA26128AC50089B4C3 /* Debug */,
C5B7D9CB26128AC50089B4C3 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = C5B7D9B326128AC50089B4C3 /* Project object */;
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildSystemType</key>
<string>Latest</string>
<key>DerivedDataLocationStyle</key>
<string>Default</string>
</dict>
</plist>

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!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>TinyGPUDriver</key>
<dict>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>IOClass</key>
<string>IOUserService</string>
<key>IOMatchCategory</key>
<string>TinyGPUDriver</string>
<key>IOPCIClassMatch</key>
<string>0x03000000</string>
<key>IOPCITunnelCompatible</key>
<true/>
<key>IOProviderClass</key>
<string>IOPCIDevice</string>
<key>IOResourceMatch</key>
<string>IOKit</string>
<key>IOUserClass</key>
<string>TinyGPUDriver</string>
<key>IOUserServerName</key>
<string>org.tinygrad.tinygpu.Driver</string>
<key>TinyGPUDriverUserClientProperties</key>
<dict>
<key>IOClass</key>
<string>IOUserUserClient</string>
<key>IOUserClass</key>
<string>TinyGPUDriverUserClient</string>
</dict>
</dict>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.application-identifier</key>
<string>9YG3G8543N.org.tinygrad.tinygpu.driver2</string>
<key>com.apple.developer.driverkit</key>
<true/>
<key>com.apple.developer.driverkit.transport.pci</key>
<array>
<dict>
<key>IOPCIPrimaryMatch</key>
<string>0x000010de&amp;0x0000FFFF</string>
</dict>
</array>
</dict>
</plist>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.driverkit</key>
<true/>
<key>com.apple.developer.driverkit.transport.pci</key>
<array>
<dict>
<key>IOPCIPrimaryMatch</key>
<string>0xFFFFFFFF&amp;0x00000000</string>
</dict>
</array>
<key>com.apple.developer.driverkit.allow-any-userclient-access</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.application-identifier</key>
<string>9YG3G8543N.org.tinygrad.tinygpu.driver2</string>
<key>com.apple.developer.driverkit</key>
<true/>
<key>com.apple.developer.driverkit.transport.pci</key>
<array>
<dict>
<key>IOPCIPrimaryMatch</key>
<string>0x000010de&amp;0x0000FFFF</string>
</dict>
<dict>
<key>IOPCIPrimaryMatch</key>
<string>0x00001002&amp;0x0000FFFF</string>
</dict>
</array>
</dict>
</plist>

View File

@@ -0,0 +1,198 @@
#include "TinyGPUDriver.h"
#include "TinyGPUDriverUserClient.h"
#include <DriverKit/IOLib.h>
#include <PCIDriverKit/PCIDriverKit.h>
struct TinyGPUDriver_IVars
{
IOPCIDevice *pci = nullptr;
};
bool TinyGPUDriver::init()
{
os_log(OS_LOG_DEFAULT, "tinygpu: init");
auto answer = super::init();
if (!answer) {
return false;
}
ivars = new TinyGPUDriver_IVars();
if (ivars == nullptr) {
return false;
}
return true;
}
void TinyGPUDriver::free()
{
IOSafeDeleteNULL(ivars, TinyGPUDriver_IVars, 1);
super::free();
}
kern_return_t TinyGPUDriver::Start_Impl(IOService* in_provider)
{
IOServiceName service_name;
os_log(OS_LOG_DEFAULT, "tinygpu: on gpu detected");
kern_return_t err = Start(in_provider, SUPERDISPATCH);
if (err) return err;
ivars->pci = OSDynamicCast(IOPCIDevice, in_provider);
if (!ivars->pci) return kIOReturnNoDevice;
err = ivars->pci->Open(this, 0);
if (err) {
os_log(OS_LOG_DEFAULT, "tinygpu: Open() failed 0x%08x", err);
ivars->pci = nullptr;
return err;
}
uint16_t ven = 0, dev = 0;
ivars->pci->ConfigurationRead16(kIOPCIConfigurationOffsetVendorID, &ven);
ivars->pci->ConfigurationRead16(kIOPCIConfigurationOffsetDeviceID, &dev);
os_log(OS_LOG_DEFAULT, "tinygpu: opened device ven=0x%04x dev=0x%04x", ven, dev);
uint16_t commandRegister;
ivars->pci->ConfigurationRead16(kIOPCIConfigurationOffsetCommand, &commandRegister);
commandRegister |= (kIOPCICommandIOSpace | kIOPCICommandBusMaster | kIOPCICommandMemorySpace);
ivars->pci->ConfigurationWrite16(kIOPCIConfigurationOffsetCommand, commandRegister);
memcpy((void*)service_name, (void*)"tinygpu\0", 8);
SetName(service_name);
os_log(OS_LOG_DEFAULT, "tinygpu: will register service %s", service_name);
RegisterService();
os_log(OS_LOG_DEFAULT, "tinygpu: service started %s", service_name);
return 0;
}
kern_return_t TinyGPUDriver::Stop_Impl(IOService* in_provider)
{
ivars->pci->Close(this, 0);
return 0;
}
kern_return_t TinyGPUDriver::NewUserClient_Impl(uint32_t in_type, IOUserClient** out_user_client)
{
kern_return_t err = 0;
IOService* user_client_service = nullptr;
err = Create(this, "TinyGPUDriverUserClientProperties", &user_client_service);
if (err) {
os_log(OS_LOG_DEFAULT, "tinygpu: failed to create NewUserClient");
goto error;
}
*out_user_client = OSDynamicCast(IOUserClient, user_client_service);
os_log(OS_LOG_DEFAULT, "tinygpu: NewUserClient created");
error:
return err;
}
kern_return_t TinyGPUDriver::MapBar(uint32_t bar, IOMemoryDescriptor** memory)
{
uint8_t barMemoryIndex, barMemoryType;
uint64_t barMemorySize;
kern_return_t err = ivars->pci->GetBARInfo(bar, &barMemoryIndex, &barMemorySize, &barMemoryType);
if (err) return err;
os_log(OS_LOG_DEFAULT, "tinygpu: bar mapping %d idx=%d", bar, barMemoryIndex);
return ivars->pci->_CopyDeviceMemoryWithIndex(barMemoryIndex, memory, this);
}
static kern_return_t WriteDMASegments(IOMemoryDescriptor* mem, IOAddressSegment* segments, uint32_t segCount,
uint64_t mapOffset = 0, uint64_t mapSize = 0)
{
// write dma segments to mapped memory as [addr0, len0, addr1, len1, ..., 0, 0]
IOMemoryMap* map = nullptr;
kern_return_t err = mem->CreateMapping(0, 0, 0, mapOffset, mapSize, &map);
if (err || !map) return err ?: kIOReturnError;
uint64_t* out = (uint64_t*)map->GetAddress();
for (uint32_t i = 0; i < segCount; i++) { out[i * 2] = segments[i].address; out[i * 2 + 1] = segments[i].length; }
out[segCount * 2] = 0; out[segCount * 2 + 1] = 0;
map->release();
return 0;
}
kern_return_t TinyGPUDriver::SetupDMA(IOMemoryDescriptor* memory, uint64_t size, IODMACommand** outCmd,
IOAddressSegment* segments, uint32_t* segCount)
{
IODMACommandSpecification dmaSpec = {.options = 0, .maxAddressBits = 40};
IODMACommand* dmaCmd = nullptr;
kern_return_t err = IODMACommand::Create(ivars->pci, kIODMACommandCreateNoOptions, &dmaSpec, &dmaCmd);
if (err) { os_log(OS_LOG_DEFAULT, "tinygpu: DMA create failed err=%d", err); return err; }
uint64_t flags = kIOMemoryDirectionInOut;
err = dmaCmd->PrepareForDMA(kIODMACommandPrepareForDMANoOptions, memory, 0, size, &flags, segCount, segments);
if (err) { os_log(OS_LOG_DEFAULT, "tinygpu: PrepareForDMA failed err=%d", err); dmaCmd->release(); return err; }
*outCmd = dmaCmd;
return 0;
}
kern_return_t TinyGPUDriver::CreateDMA(size_t size, TinyGPUCreateDMAResp* dmaDesc)
{
IOBufferMemoryDescriptor* sharedBuf = nullptr;
kern_return_t err = IOBufferMemoryDescriptor::Create(kIOMemoryDirectionInOut, size, IOVMPageSize, &sharedBuf);
if (err) { os_log(OS_LOG_DEFAULT, "tinygpu: alloc failed err=%d", err); return err; }
IODMACommand* dmaCmd = nullptr;
IOAddressSegment segments[32];
uint32_t segCount = 32;
err = SetupDMA(sharedBuf, size, &dmaCmd, segments, &segCount);
if (err) { sharedBuf->release(); return err; }
err = WriteDMASegments(sharedBuf, segments, segCount, IOVMPageSize, IOVMPageSize);
if (err) { dmaCmd->CompleteDMA(kIODMACommandCompleteDMANoOptions); dmaCmd->release(); sharedBuf->release(); return err; }
dmaDesc->sharedBuf = sharedBuf;
dmaDesc->dmaCmd = dmaCmd;
os_log(OS_LOG_DEFAULT, "tinygpu: CreateDMA size=0x%zx segs=%u", size, segCount);
return 0;
}
kern_return_t TinyGPUDriver::CfgRead(uint32_t off, uint32_t size, uint32_t* outVal)
{
if (!ivars->pci || !outVal) return kIOReturnNotReady;
if (size == 1) {
uint8_t v8 = 0;
ivars->pci->ConfigurationRead8(off, &v8);
*outVal = v8;
} else if (size == 2) {
uint16_t v16 = 0;
ivars->pci->ConfigurationRead16(off, &v16);
*outVal = v16;
} else if (size == 4) {
uint32_t v32 = 0;
ivars->pci->ConfigurationRead32(off, &v32);
*outVal = v32;
}
return 0;
}
kern_return_t TinyGPUDriver::CfgWrite(uint32_t off, uint32_t size, uint32_t val)
{
if (!ivars->pci) return kIOReturnNotReady;
if (size == 1) ivars->pci->ConfigurationWrite8 (off, (uint8_t)val);
else if (size == 2) ivars->pci->ConfigurationWrite16(off, (uint16_t)val);
else if (size == 4) ivars->pci->ConfigurationWrite32(off, (uint32_t)val);
return 0;
}
kern_return_t TinyGPUDriver::ResetDevice()
{
if (!ivars->pci) return kIOReturnNotReady;
kern_return_t ret = ivars->pci->Reset(kIOPCIDeviceResetTypeFunctionReset);
return ret == kIOReturnSuccess ? ret : ivars->pci->Reset(kIOPCIDeviceResetTypeHotReset);
}
IOPCIDevice* TinyGPUDriver::GetPCI()
{
return ivars->pci;
}

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.driverkit</key>
<true/>
<key>com.apple.developer.driverkit.transport.pci</key>
<array>
<dict>
<key>IOPCIPrimaryMatch</key>
<string>0xFFFFFFFF&amp;0x00000000</string>
</dict>
</array>
</dict>
</plist>

View File

@@ -0,0 +1,40 @@
#ifndef TinyGPUDriver_h
#define TinyGPUDriver_h
#include <Availability.h>
#include <DriverKit/IOService.iig>
#include <PCIDriverKit/IOPCIDevice.iig>
#include <DriverKit/IOMemoryMap.iig>
#include <DriverKit/IODMACommand.iig>
struct TinyGPUCreateDMAResp
{
IOBufferMemoryDescriptor* sharedBuf;
IODMACommand* dmaCmd;
};
class TinyGPUDriver: public IOService
{
public:
virtual bool init() override;
virtual void free() override;
virtual kern_return_t Start(IOService * provider) override;
virtual kern_return_t Stop(IOService * provider) override;
virtual kern_return_t NewUserClient(uint32_t in_type, IOUserClient** out_user_client) override;
kern_return_t MapBar(uint32_t bar, IOMemoryDescriptor** memory) LOCALONLY;
kern_return_t CreateDMA(size_t size, TinyGPUCreateDMAResp* dmaDesc) LOCALONLY;
kern_return_t SetupDMA(IOMemoryDescriptor* memory, uint64_t size, IODMACommand** outCmd,
IOAddressSegment* segments, uint32_t* segCount) LOCALONLY;
kern_return_t CfgRead(uint32_t off, uint32_t size, uint32_t* val) LOCALONLY;
kern_return_t CfgWrite(uint32_t off, uint32_t size, uint32_t val) LOCALONLY;
kern_return_t ResetDevice() LOCALONLY;
IOPCIDevice* GetPCI() LOCALONLY;
};
#endif /* TinyGPUDriver_h */

View File

@@ -0,0 +1,191 @@
#include "TinyGPUDriverUserClient.h"
#include "TinyGPUDriver.h"
#include <DriverKit/DriverKit.h>
#include <DriverKit/OSSharedPtr.h>
#include <PCIDriverKit/PCIDriverKit.h>
struct TinyGPUDriverUserClient_IVars
{
OSSharedPtr<TinyGPUDriver> provider = nullptr;
TinyGPUCreateDMAResp *dmas = nullptr;
size_t dmaCount = 0;
size_t dmaCap = 0;
int ensureDMACap(size_t need)
{
// not thread-safe
if (need <= dmaCap) return 0;
size_t newCap = dmaCap ? dmaCap * 2 : 16;
while (newCap < need) newCap *= 2;
auto *newArr = IONewZero(TinyGPUCreateDMAResp, newCap);
if (!newArr) return -kIOReturnNoMemory;
if (dmas && dmaCount) {
memcpy(newArr, dmas, dmaCount * sizeof(TinyGPUCreateDMAResp));
}
IOSafeDeleteNULL(dmas, TinyGPUCreateDMAResp, dmaCap);
dmas = newArr;
dmaCap = newCap;
return 0;
}
};
bool TinyGPUDriverUserClient::init()
{
auto ok = super::init();
if (!ok) return false;
ivars = IONewZero(TinyGPUDriverUserClient_IVars, 1);
if (!ivars) return false;
return true;
}
void TinyGPUDriverUserClient::free()
{
if (ivars) {
IOSafeDeleteNULL(ivars, TinyGPUDriverUserClient_IVars, 1);
}
super::free();
}
kern_return_t TinyGPUDriverUserClient::Start_Impl(IOService* in_provider)
{
kern_return_t err = kIOReturnSuccess;
if (!in_provider) {
os_log(OS_LOG_DEFAULT, "tinygpu: provider is null");
err = kIOReturnBadArgument;
goto error;
}
err = Start(in_provider, SUPERDISPATCH);
if (err) {
os_log(OS_LOG_DEFAULT, "tinygpu: failed to start super (%d)", err);
goto error;
}
ivars->provider = OSSharedPtr(OSDynamicCast(TinyGPUDriver, in_provider), OSRetain);
return 0;
error:
ivars->provider.reset();
return err;
}
kern_return_t TinyGPUDriverUserClient::Stop_Impl(IOService* in_provider)
{
// release all DMA allocations for this client
if (ivars) {
for (size_t i = 0; i < ivars->dmaCount; i++) {
auto &d = ivars->dmas[i];
if (d.dmaCmd) {
d.dmaCmd->CompleteDMA(kIODMACommandCompleteDMANoOptions);
d.dmaCmd->release();
d.dmaCmd = nullptr;
}
}
ivars->dmaCount = 0;
IOSafeDeleteNULL(ivars->dmas, TinyGPUCreateDMAResp, ivars->dmaCap);
ivars->dmas = nullptr;
ivars->provider.reset();
}
return Stop(in_provider, SUPERDISPATCH);
}
kern_return_t TinyGPUDriverUserClient::ExternalMethod(uint64_t selector, IOUserClientMethodArguments* args, const IOUserClientMethodDispatch* in_dispatch, OSObject* in_target, void* in_reference)
{
kern_return_t err = 0;
os_log(OS_LOG_DEFAULT, "tinygpu: rpc (%llu) in:%d, out:%d", selector, args->scalarInputCount, args->scalarOutputCount);
if (selector == TinyGPURPC::ReadCfg) {
if (args->scalarInputCount != 2 or args->scalarOutputCount < 1) return kIOReturnBadArgument;
uint32_t off = uint32_t(args->scalarInput[0]);
uint32_t size = uint32_t(args->scalarInput[1]);
uint32_t val = 0;
err = ivars->provider->CfgRead(off, size, &val);
os_log(OS_LOG_DEFAULT, "tinygpu: read cfg off:%x sz:%d, val:%x", off, size, val);
if (!err) {
args->scalarOutput[0] = val;
args->scalarOutputCount = 1;
}
return err;
} else if (selector == TinyGPURPC::WriteCfg) {
if (args->scalarInputCount != 3) return kIOReturnBadArgument;
uint32_t off = uint32_t(args->scalarInput[0]);
uint32_t size = uint32_t(args->scalarInput[1]);
uint32_t val = uint32_t(args->scalarInput[2]);
os_log(OS_LOG_DEFAULT, "tinygpu: wr cfg off:%x sz:%d, val:%x", off, size, val);
return ivars->provider->CfgWrite(off, size, val);
} else if (selector == TinyGPURPC::Reset) {
os_log(OS_LOG_DEFAULT, "tinygpu: reset");
return ivars->provider->ResetDevice();
} else if (selector == TinyGPURPC::PrepareDMA) {
// both input and output buffers must be >= 4097 bytes for IOMemoryDescriptor
if (!args->structureInputDescriptor || !args->structureOutputDescriptor) {
os_log(OS_LOG_DEFAULT, "tinygpu: PrepareDMA requires buffers >= 4097 bytes");
return kIOReturnBadArgument;
}
if (ivars->ensureDMACap(ivars->dmaCount + 1)) return kIOReturnNoMemory;
uint64_t size = 0;
args->structureInputDescriptor->GetLength(&size);
IODMACommand* dmaCmd = nullptr;
IOAddressSegment segments[32];
uint32_t segCount = 32;
err = ivars->provider->SetupDMA(args->structureInputDescriptor, size, &dmaCmd, segments, &segCount);
if (err) return err;
// write physical addresses to output: [addr0, len0, addr1, len1, ..., 0, 0]
IOMemoryMap* outMap = nullptr;
err = args->structureOutputDescriptor->CreateMapping(0, 0, 0, 0, 0, &outMap);
if (err || !outMap) { os_log(OS_LOG_DEFAULT, "tinygpu: output map failed err=%d", err); dmaCmd->release(); return err; }
uint64_t* out = (uint64_t*)outMap->GetAddress();
for (uint32_t i = 0; i < segCount; i++) { out[i * 2] = segments[i].address; out[i * 2 + 1] = segments[i].length; }
out[segCount * 2] = 0; out[segCount * 2 + 1] = 0;
outMap->release();
os_log(OS_LOG_DEFAULT, "tinygpu: PrepareDMA size=%llu segs=%u", size, segCount);
ivars->dmas[ivars->dmaCount++] = {nullptr, dmaCmd};
return kIOReturnSuccess;
}
return kIOReturnUnsupported;
}
kern_return_t IMPL(TinyGPUDriverUserClient, CopyClientMemoryForType)
{
if (!memory) return kIOReturnBadArgument;
if (!ivars->provider.get()) return kIOReturnNotAttached;
// bar handling, type is bar num
if (type < 6) {
uint32_t bar = (uint32_t)type;
return ivars->provider->MapBar(bar, memory);
}
// dma handling, type is size
if (ivars->ensureDMACap(ivars->dmaCount + 1)) {
os_log(OS_LOG_DEFAULT, "tinygpu: cannot grow dma array");
return kIOReturnNoMemory;
}
TinyGPUCreateDMAResp buf{};
kern_return_t err = ivars->provider->CreateDMA(type, &buf);
if (err) return err;
ivars->dmas[ivars->dmaCount++] = buf;
*memory = buf.sharedBuf;
return 0;
}

View File

@@ -0,0 +1,29 @@
#ifndef TinyGPUDriverUserClient_h
#define TinyGPUDriverUserClient_h
#include <DriverKit/IOUserClient.iig>
enum TinyGPURPC
{
ReadCfg,
WriteCfg,
Reset,
PrepareDMA,
};
class TinyGPUDriverUserClient : public IOUserClient
{
public:
virtual bool init() final;
virtual void free() final;
virtual kern_return_t Start(IOService* in_provider) final;
virtual kern_return_t Stop(IOService* in_provider) final;
virtual kern_return_t ExternalMethod(uint64_t in_selector, IOUserClientMethodArguments* in_arguments, const IOUserClientMethodDispatch* in_dispatch, OSObject* in_target, void* in_reference) final;
virtual kern_return_t CopyClientMemoryForType(
uint64_t type, uint64_t *options, IOMemoryDescriptor **memory) final;
};
#endif /* TinyGPUDriverUserClient_h */

View File

@@ -0,0 +1,33 @@
#!/bin/bash
set -e
xcodebuild clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO -alltargets -configuration Release build
cp "../profiles/driver_release_0431.provisionprofile" "./build/Release/TinyGPU.app/Contents/Library/SystemExtensions/org.tinygrad.tinygpu.driver2.dext/embedded.provisionprofile"
cp "../profiles/installer_release_0431.provisionprofile" "./build/Release/TinyGPU.app/Contents/embedded.provisionprofile"
codesign \
--sign "Developer ID Application: tinygrad, Corp. (9YG3G8543N)" \
--entitlements ./TinyGPUDriverExtension/TinyGPUDriver.Release.entitlements \
--verbose \
--options runtime \
--timestamp \
--force \
./build/Release/TinyGPU.app/Contents/Library/SystemExtensions/org.tinygrad.tinygpu.driver2.dext
codesign \
--sign "Developer ID Application: tinygrad, Corp. (9YG3G8543N)" \
--entitlements ./macOS/macOS.entitlements \
--options runtime \
--verbose \
--timestamp \
--force \
./build/Release/TinyGPU.app
codesign --verify --deep --strict --verbose=4 ./build/Release/TinyGPU.app/Contents/Library/SystemExtensions/org.tinygrad.tinygpu.driver2.dext
codesign --verify --deep --strict --verbose=4 ./build/Release/TinyGPU.app
spctl -a -vv ./build/Release/TinyGPU.app
spctl -a -vv ./build/Release/TinyGPU.app/Contents/Library/SystemExtensions/org.tinygrad.tinygpu.driver2.dext

View File

@@ -0,0 +1,33 @@
#!/bin/bash
set -e
xcodebuild clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO -alltargets -configuration Release build
cp "../profiles/edriver_rel_2.provisionprofile" "./build/Release/TinyGPU.app/Contents/Library/SystemExtensions/org.tinygrad.tinygpu.driver2.dext/embedded.provisionprofile"
cp "../profiles/installer_provisioning.provisionprofile" "./build/Release/TinyGPU.app/Contents/embedded.provisionprofile"
codesign \
--sign "Developer ID Application: tinygrad, Corp. (9YG3G8543N)" \
--entitlements ./TinyGPUDriverExtension/TinyGPUDriver.NV.Release.entitlements \
--verbose \
--options runtime \
--timestamp \
--force \
./build/Release/TinyGPU.app/Contents/Library/SystemExtensions/org.tinygrad.tinygpu.driver2.dext
codesign \
--sign "Developer ID Application: tinygrad, Corp. (9YG3G8543N)" \
--entitlements ./macOS/macOS.entitlements \
--options runtime \
--verbose \
--timestamp \
--force \
./build/Release/TinyGPU.app
codesign --verify --deep --strict --verbose=4 ./build/Release/TinyGPU.app/Contents/Library/SystemExtensions/org.tinygrad.tinygpu.driver2.dext
codesign --verify --deep --strict --verbose=4 ./build/Release/TinyGPU.app
spctl -a -vv ./build/Release/TinyGPU.app
spctl -a -vv ./build/Release/TinyGPU.app/Contents/Library/SystemExtensions/org.tinygrad.tinygpu.driver2.dext

View File

@@ -0,0 +1,52 @@
#!/bin/bash
set -e
# Check SIP status if not building only
if [[ "$1" != "--build" ]]; then
SIP_STATUS=$(csrutil status 2>&1)
if [[ "$SIP_STATUS" == *"enabled"* ]]; then
echo "ERROR: System Integrity Protection (SIP) is enabled."
echo "This dev build requires SIP to be disabled to load unsigned dexts."
echo ""
echo "To disable SIP:"
echo " 1. Restart and hold Power button (M1+) or Cmd+R (Intel)"
echo " 2. Open Terminal from Recovery menu"
echo " 3. Run: csrutil disable"
echo " 4. Restart"
exit 1
fi
fi
echo "SIP is disabled, proceeding with dev build..."
cd "$(dirname "$0")"
# Build without code signing
xcodebuild clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO -alltargets -configuration Debug build
APP_PATH="./build/Debug/TinyGPU.app"
DEXT_PATH="$APP_PATH/Contents/Library/SystemExtensions/org.tinygrad.tinygpu.driver2.dext"
# Ad-hoc sign with dev entitlements (matches any GPU)
codesign --sign - --entitlements ./TinyGPUDriverExtension/TinyGPUDriver.NoSIP.entitlements --force --timestamp --verbose "$DEXT_PATH"
codesign --sign - --entitlements ./macOS/macOS.entitlements --force --timestamp --verbose "$APP_PATH"
echo "Build complete: $APP_PATH"
if [[ "$1" == "--build" ]]; then
exit 0
fi
# Install
echo "Installing to /Applications..."
if [ -d "/Applications/TinyGPU.app" ]; then
echo "Removing existing /Applications/TinyGPU.app..."
rm -rf "/Applications/TinyGPU.app"
fi
cp -r "$APP_PATH" /Applications/
echo "Installed to /Applications/TinyGPU.app"
echo "Activating driver extension..."
/Applications/TinyGPU.app/Contents/MacOS/TinyGPU install

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<false/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>com.apple.developer.system-extension.install</key>
<true/>
<key>com.apple.developer.driverkit.userclient-access</key>
<array>
<string>org.tinygrad.tinygpu.driver2</string>
</array>
</dict>
</plist>

View File

@@ -0,0 +1,9 @@
#!/bin/bash
set -e
ditto -c -k --keepParent ./build/Release/TinyGPU.app ./build/Release/TinyGPU.zip
xcrun notarytool submit ./build/Release/TinyGPU.zip --keychain-profile "hgwJFhdheiIEy82nDN" --wait
rm ./build/Release/TinyGPU.zip
xcrun stapler staple ./build/Release/TinyGPU.app
ditto -c -k --keepParent ./build/Release/TinyGPU.app ./build/Release/TinyGPU.zip

View File

@@ -0,0 +1,2 @@
#!/bin/bash
pkill -f "tinygpu.sock"