Update DDI to mount over RSD

This commit is contained in:
Stephen 2026-04-03 20:31:08 -04:00
parent 8bae535b44
commit de290279f4
3 changed files with 139 additions and 13 deletions

View file

@ -44,6 +44,35 @@ private enum IdeviceBridge {
return makeError(domain: domain, code: code, message: message)
}
static func mappedFileData(atPath path: String, description: String) throws -> Data {
let url = URL(fileURLWithPath: path)
do {
let data = try Data(contentsOf: url, options: .mappedIfSafe)
guard !data.isEmpty else {
throw makeError(message: "\(description) is empty")
}
return data
} catch let error as NSError {
throw makeError(code: error.code, message: "Failed to read \(description): \(error.localizedDescription)")
}
}
static func uint64Value(from plist: plist_t?, fieldName: String) throws -> UInt64 {
guard let plist else {
throw makeError(message: "\(fieldName) was not returned by lockdownd")
}
var value: UInt64 = 0
plist_get_uint_val(plist, &value)
guard value != 0 else {
throw makeError(message: "Failed to decode \(fieldName)")
}
return value
}
static func withTunnelHandles<T>(
for context: JITEnableContext,
_ body: (OpaquePointer, OpaquePointer) throws -> T
@ -263,14 +292,12 @@ extension JITEnableContext {
}
func mountPersonalDDI(withImagePath imagePath: String, trustcachePath: String, manifestPath: String) throws {
guard FileManager.default.fileExists(atPath: imagePath),
FileManager.default.fileExists(atPath: trustcachePath),
FileManager.default.fileExists(atPath: manifestPath) else {
throw IdeviceBridge.makeError(code: 1, message: "Failed to read one or more files")
}
let imageData = try IdeviceBridge.mappedFileData(atPath: imagePath, description: "developer disk image")
let trustcacheData = try IdeviceBridge.mappedFileData(atPath: trustcachePath, description: "developer disk image trust cache")
let manifestData = try IdeviceBridge.mappedFileData(atPath: manifestPath, description: "developer disk image manifest")
try IdeviceBridge.withTunnelHandles(for: self) { adapter, handshake in
try IdeviceBridge.withConnectedClient(
let uniqueChipID = try IdeviceBridge.withConnectedClient(
fallback: "Failed to connect to lockdownd",
missingClientMessage: "Lockdownd client was not created",
connect: { lockdownd_connect_rsd(adapter, handshake, $0) },
@ -281,9 +308,13 @@ extension JITEnableContext {
throw IdeviceBridge.consumeFFIError(ffiError, fallback: "Failed to query UniqueChipID")
}
if let uniqueChipIDPlist {
plist_free(uniqueChipIDPlist)
defer {
if let uniqueChipIDPlist {
plist_free(uniqueChipIDPlist)
}
}
return try IdeviceBridge.uint64Value(from: uniqueChipIDPlist, fieldName: "UniqueChipID")
}
try IdeviceBridge.withConnectedClient(
@ -291,11 +322,32 @@ extension JITEnableContext {
missingClientMessage: "Image mounter client was not created",
connect: { image_mounter_connect_rsd(adapter, handshake, $0) },
cleanup: { image_mounter_free($0) }
) { _ in
throw IdeviceBridge.makeError(
code: 10,
message: "mount_personalized not yet available over RSD tunnels"
)
) { imageMounterClient in
let ffiError = imageData.withUnsafeBytes { imageBuffer -> UnsafeMutablePointer<IdeviceFfiError>? in
trustcacheData.withUnsafeBytes { trustcacheBuffer -> UnsafeMutablePointer<IdeviceFfiError>? in
manifestData.withUnsafeBytes { manifestBuffer -> UnsafeMutablePointer<IdeviceFfiError>? in
image_mounter_mount_personalized_with_callback_rsd(
imageMounterClient,
adapter,
handshake,
imageBuffer.bindMemory(to: UInt8.self).baseAddress,
imageData.count,
trustcacheBuffer.bindMemory(to: UInt8.self).baseAddress,
trustcacheData.count,
manifestBuffer.bindMemory(to: UInt8.self).baseAddress,
manifestData.count,
nil,
uniqueChipID,
progressCallback,
nil
)
}
}
}
if let ffiError {
throw IdeviceBridge.consumeFFIError(ffiError, fallback: "Failed to mount personalized DDI")
}
}
}
}

View file

@ -207,6 +207,7 @@ typedef struct Vec_u64 Vec_u64;
typedef struct IdeviceFfiError {
int32_t code;
int32_t sub_code;
const char *message;
} IdeviceFfiError;
@ -4093,6 +4094,79 @@ struct IdeviceFfiError *image_mounter_mount_personalized(struct ImageMounterHand
const void *info_plist,
uint64_t unique_chip_id);
/**
* Mounts a personalized developer image via RSD
*
* # Arguments
* * [`client`] - A valid ImageMounter handle
* * [`provider`] - An adapter handle
* * [`handshake`] - An RSD handshake handle
* * [`image`] - Pointer to the image data
* * [`image_len`] - Length of the image data
* * [`trust_cache`] - Pointer to the trust cache data
* * [`trust_cache_len`] - Length of the trust cache data
* * [`build_manifest`] - Pointer to the build manifest data
* * [`build_manifest_len`] - Length of the build manifest data
* * [`info_plist`] - Pointer to info plist (optional)
* * [`unique_chip_id`] - The device's unique chip ID
*
* # Returns
* An IdeviceFfiError on error, null on success
*
* All pointers must be valid (except optional ones which can be null)
*/
struct IdeviceFfiError *image_mounter_mount_personalized_rsd(struct ImageMounterHandle *client,
struct AdapterHandle *provider,
struct RsdHandshakeHandle *handshake,
const uint8_t *image,
size_t image_len,
const uint8_t *trust_cache,
size_t trust_cache_len,
const uint8_t *build_manifest,
size_t build_manifest_len,
const void *info_plist,
uint64_t unique_chip_id);
/**
* Mounts a personalized developer image via RSD with progress callback
*
* # Arguments
* * [`client`] - A valid ImageMounter handle
* * [`provider`] - An adapter handle
* * [`handshake`] - An RSD handshake handle
* * [`image`] - Pointer to the image data
* * [`image_len`] - Length of the image data
* * [`trust_cache`] - Pointer to the trust cache data
* * [`trust_cache_len`] - Length of the trust cache data
* * [`build_manifest`] - Pointer to the build manifest data
* * [`build_manifest_len`] - Length of the build manifest data
* * [`info_plist`] - Pointer to info plist (optional)
* * [`unique_chip_id`] - The device's unique chip ID
* * [`callback`] - Progress callback function
* * [`context`] - User context to pass to callback
*
* # Returns
* An IdeviceFfiError on error, null on success
*
* # Safety
* All pointers must be valid (except optional ones which can be null)
*/
struct IdeviceFfiError *image_mounter_mount_personalized_with_callback_rsd(struct ImageMounterHandle *client,
struct AdapterHandle *provider,
struct RsdHandshakeHandle *handshake,
const uint8_t *image,
size_t image_len,
const uint8_t *trust_cache,
size_t trust_cache_len,
const uint8_t *build_manifest,
size_t build_manifest_len,
const void *info_plist,
uint64_t unique_chip_id,
void (*callback)(size_t progress,
size_t total,
void *context),
void *context);
/**
* Mounts a personalized developer image with progress callback
*

Binary file not shown.