Raiders of the Lost Array: vibe-coding a macOS driver for my orphaned Drobo
Raiders of the Lost Array: Vibe-Coding a macOS Driver for my Orphaned Drobo
DISCLAIMER: I have no idea if any of this is actually legal.
Furthermore, I possess absolutely no profound expertise in the realm of hardware hacking.
DISCLAIMER 2: While I am sufficiently lazy/inefficient that I'd likely use an LLM to automate my morning coffee (oops!) and I do occasionally use AI to generate code, this specific text was written by a human and barely touched by an LLM for proofreading.
I launched this site back in 2021, but I never actually got around to posting anything. Well, that ends today. Inspired by a submission on Hacker News regarding Claude writing a macOS driver for a Windows-only HP printer, I looked at my Drobo 5D. This RAID array has been a rock-solid servant for 14 years, failing only once in 2019 when a power adapter died.
The problem? Drobo is defunct. With the upcoming "Golden Gate" (macOS 27) release expected to be the final version supporting Rosetta 2, the Drobo software suite will become a brick. Since the software offers too many quality-of-life features to abandon, I decided—while sick and housebound—to let "Claudio" (Claude) handle it.
🛠️ The Mission Objectives
- Analyze existing Drobo 5D firmware and Dashboard software.
- Identify the cause of incompatibility with modern macOS.
- Determine hardware blockers for newer Mac silicon.
- Develop a solution, ranging from a patch to a full rewrite.
📝 Phase 1: The Prompt
The approach was straightforward. I provided the context, the goal, and the raw data.
The Prompt: "The company Drobo has gone out of business. I own a Drobo 5D connected via USB 3 (Thunderbolt 2 is obsolete for my new gear). It currently works on my 2017 iMac (macOS 13), but on newer macOS versions, the Dashboard software fails, and the device only mounts as a basic external drive.
For the sake of ecology, I want to keep this hardware alive without sacrificing my ability to upgrade my Mac. Your task: analyze the firmware and Dashboard software to figure out WHY it fails and HOW to fix it.
I've provided the last five versions of the drivers and Dashboard in
/Users/fetzu/Dev/ReDrobo/ZZ_BUFFER. Use them as needed, but don't try to install them on this machine."
I initially tried Fable 5 on High, but it got flagged and downgraded to Opus 4.8. I pivoted to a fresh session using Opus 5 on Max, and the project officially began.
🗺️ The Strategic Roadmap
Claude proposed a five-stage engineering plan, starting (as all great engineers do) at zero:
- Protect the data first: The absolute priority.
- Validate the protocol: Compare data output between a working setup (2017 iMac/macOS 13) and a non-working setup (MacBook Pro M5 Pro/macOS 26).
- Decode record payloads: Reverse engineer the protocol specification.
- Ship a usable CLI: Create a command-line tool to mirror the Dashboard's info.
- The live driver: Build a full replacement for the Drobo Dashboard.
🔍 Execution: Probing the Hardware
I connected the Drobo to my MacBook Pro. While the volume mounted and was readable/writable, it was "lying" about its capacity and provided zero health data. To investigate, Claude wrote a C utility called droboprobe.
After I provided screenshots of the actual state from the working iMac, we saw a massive discrepancy in reported storage:
| Metric | Dashboard (iMac) | macOS (MBP) |
|---|---|---|
| Total Capacity | 5.42 TB | 17.6 TB |
| Used Space | 4.25 TB | 4.7 TB |
| Free Space | 1.17 TB | 12.9 TB |
The mathematical error in reporting is roughly:
⚠️ The Technical Wall (and the Way Around)
Claude hit a snag: SCSITaskUserClient was a dead end.
IOCreatePlugInInterfaceForService returned kIOReturnUnsupported. The issue is that the Drobo is claimed by IOSCSIPeripheralDeviceType00, meaning it doesn't fall into the category of devices that SCSITaskLib serves (which are typically devices without in-kernel drivers).
However, there was a silver lining. Since the kernel extension (kext) still works on the iMac, we could extract the dispatch table from the binary.
The Extracted Dispatch Table
// Selector | Method | Shape
2 -> sGetESAModePage | 2 scalars in, 1308-byte struct out (READ)
3 -> sSetESAModePage | 3 scalars + 1308-byte struct in (WRITE)
Key Findings:
- Selectors
0–3were verified against the symbol table. - To remain safe, I will only call
selector 2. IOKithandles the validation of argument sizes before thekextever sees the data, providing a layer of safety.