Add Developer Disk Image Mounting

This commit is contained in:
Stossy11 2025-03-29 14:16:19 +11:00
parent b605e9d7cc
commit b0738cd349
7 changed files with 808 additions and 28 deletions

View file

@ -34,7 +34,7 @@ StikJIT **does not collect or store any user data.**
- [X] Integrate [`em_proxy`](https://github.com/SideStore/em_proxy)
- [X] Compile [`idevice`](https://github.com/jkcoxson/idevice)
- [X] Implement heartbeat
- [ ] Mount the developer image
- [X] Mount the developer image
- [X] Retrieve and filter installed apps by `get-task-allow`
- [X] Enable JIT for selected apps
- [X] Design and implement a user-friendly UI *(Done for now)*

View file

@ -15,6 +15,21 @@ struct HeartbeatApp: App {
@State private var isPairing = false
@State private var heartBeat = false
@State private var error: Int32? = nil
@StateObject private var mount = MountingProgress.shared
let urls: [String] = [
"https://github.com/doronz88/DeveloperDiskImage/raw/refs/heads/main/PersonalizedImages/Xcode_iOS_DDI_Personalized/BuildManifest.plist",
"https://github.com/doronz88/DeveloperDiskImage/raw/refs/heads/main/PersonalizedImages/Xcode_iOS_DDI_Personalized/Image.dmg",
"https://github.com/doronz88/DeveloperDiskImage/raw/refs/heads/main/PersonalizedImages/Xcode_iOS_DDI_Personalized/Image.dmg.trustcache"
]
let outputDir: String = "DDI"
let outputFiles: [String] = [
"DDI/BuildManifest.plist",
"DDI/Image.dmg",
"DDI/Image.dmg.trustcache"
]
init() {
let fixMethod = class_getInstanceMethod(UIDocumentPickerViewController.self, #selector(UIDocumentPickerViewController.fix_init(forOpeningContentTypes:asCopy:)))!
@ -30,7 +45,7 @@ struct HeartbeatApp: App {
startProxy()
if FileManager.default.fileExists(atPath: URL.documentsDirectory.appendingPathComponent("pairingFile.plist").path) {
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { timer in
if heartBeat {
if pubHeartBeat {
isLoading = false
timer.invalidate()
} else {
@ -82,6 +97,17 @@ struct HeartbeatApp: App {
}
} else {
MainTabView()
.onAppear() {
let fileManager = FileManager.default
for (index, urlString) in urls.enumerated() {
let destinationURL = URL.documentsDirectory.appendingPathComponent(outputFiles[index])
if !fileManager.fileExists(atPath: destinationURL.path) {
downloadFile(from: urlString, to: destinationURL)
}
}
mount.pubMount()
}
}
}
}
@ -103,41 +129,86 @@ struct HeartbeatApp: App {
}
}
}
func startHeartbeatInBackground() {
let heartBeat = Thread {
let completionHandler: @convention(block) (Int32, String?) -> Void = { result, message in
}
if result == 0 {
print("Heartbeat started successfully: \(message ?? "")")
self.heartBeat = true
var pubHeartBeat = false
actor FunctionGuard<T> {
private var runningTask: Task<T, Never>?
func execute(_ work: @escaping @Sendable () -> T) async -> T {
if let task = runningTask {
return await task.value // If already running, wait for the existing result
}
let task = Task.detached { work() } // Run in the background
runningTask = task
let result = await task.value
runningTask = nil
return result
}
}
class MountingProgress: ObservableObject {
static var shared = MountingProgress()
@Published var mountProgress: Double = 0.0
@Published var mountingThread: Thread?
@Published var coolisMounted: Bool = false
func checkforMounted() {
DispatchQueue.main.async {
self.coolisMounted = isMounted()
}
}
func pubMount() { mount() }
private func mount() {
self.coolisMounted = isMounted()
let fileManager = FileManager.default
let pairingpath = URL.documentsDirectory.appendingPathComponent("pairingFile.plist").path
if pubHeartBeat, fileManager.fileExists(atPath: pairingpath), !isMounted() {
if let mountingThread {
mountingThread.cancel()
self.mountingThread = nil
}
mountingThread = Thread {
let mount = mountPersonalDDI(imagePath: URL.documentsDirectory.appendingPathComponent("DDI/Image.dmg").path, trustcachePath: URL.documentsDirectory.appendingPathComponent("DDI/Image.dmg.trustcache").path, manifestPath: URL.documentsDirectory.appendingPathComponent("DDI/BuildManifest.plist").path, pairingFilePath: pairingpath)
if !mount {
showAlert(title: "Error", message: "An Error Occured when Mounting the DDI", showOk: true, showTryAgain: true) { cool in
if cool {
self.mount()
}
}
} else {
print("Error: \(result == InvalidHostID.rawValue ? "Invalid host ID, Please Selecr New Pairing File" : message ?? "") (Code: \(result))")
showAlert(title: "HeartBeat Error", message: "\(message ?? "") (\(result))", showOk: true) { _ in
self.error = result
DispatchQueue.main.async {
self.coolisMounted = isMounted()
}
}
}
JITEnableContext.shared().startHeartbeat(completionHandler: completionHandler, logger: nil)
mountingThread!.qualityOfService = .background
mountingThread!.name = "mounting"
mountingThread!.start()
}
heartBeat.qualityOfService = .background
heartBeat.name = "HeartBeat"
heartBeat.start()
}
}
func startHeartbeatInBackground() {
let heartBeat = Thread {
let completionHandler: @convention(block) (Int32, String?) -> Void = { result, message in
if result == 0 {
print("Heartbeat started successfully: \(message ?? "")")
pubHeartBeat = true
} else {
print("Error: \(message ?? "") (Code: \(result))")
@ -199,22 +270,65 @@ struct LoadingView: View {
}
}
public func showAlert(title: String, message: String, showOk: Bool, completion: @escaping (Bool) -> Void) {
public func showAlert(title: String, message: String, showOk: Bool, showTryAgain: Bool = false, completion: @escaping (Bool) -> Void) {
DispatchQueue.main.async {
if let mainWindow = UIApplication.shared.windows.last {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
if showOk {
if showOk, !showTryAgain {
let okAction = UIAlertAction(title: "OK", style: .default) { _ in
completion(true)
}
alert.addAction(okAction)
} else {
} else if !showTryAgain {
completion(false)
}
if showTryAgain {
let tryAgainAction = UIAlertAction(title: "Try Again", style: .default) { _ in
completion(true)
}
alert.addAction(tryAgainAction)
let okAction = UIAlertAction(title: "OK", style: .cancel) { _ in
completion(false)
}
alert.addAction(okAction)
}
mainWindow.rootViewController?.present(alert, animated: true, completion: nil)
}
}
}
func downloadFile(from urlString: String, to destinationURL: URL) {
let fileManager = FileManager.default
let documentsDirectory = URL.documentsDirectory
guard let url = URL(string: urlString) else {
print("Invalid URL: \(urlString)")
return
}
let task = URLSession.shared.downloadTask(with: url) { (tempLocalUrl, response, error) in
guard let tempLocalUrl = tempLocalUrl, error == nil else {
print("Error downloading file from \(urlString): \(String(describing: error))")
return
}
do {
// Move the downloaded file to the destination
try fileManager.createDirectory(at: destinationURL.deletingLastPathComponent(), withIntermediateDirectories: true, attributes: nil)
try fileManager.moveItem(at: tempLocalUrl, to: destinationURL)
print("Downloaded \(urlString) to \(destinationURL.path)")
} catch {
print("Error saving file: \(error)")
}
}
task.resume()
}

View file

@ -0,0 +1,225 @@
//
// mountDDI.swift
// StikJIT
//
// Created by Stossy11 on 29/03/2025.
//
import Foundation
typealias IdevicePairingFile = OpaquePointer
typealias TcpProviderHandle = OpaquePointer
typealias CoreDeviceProxyHandle = OpaquePointer
typealias AdapterHandle = OpaquePointer
typealias ImageMounterHandle = OpaquePointer
typealias LockdowndClientHandle = OpaquePointer
func progressCallback(progress: size_t, total: size_t, context: UnsafeMutableRawPointer?) {
let percentage = Double(progress) / Double(total) * 100.0
print("Mounting progress: \(percentage)%")
MountingProgress.shared.mountProgress = percentage
}
func readFile(path: String) -> Data? {
guard let file = fopen(path, "rb") else {
perror("Failed to open file")
return nil
}
fseek(file, 0, SEEK_END)
let fileSize = ftell(file)
fseek(file, 0, SEEK_SET)
guard fileSize > 0 else {
fclose(file)
return nil
}
var buffer = Data(count: fileSize)
buffer.withUnsafeMutableBytes { ptr in
fread(ptr.baseAddress, 1, fileSize, file)
}
fclose(file)
return buffer
}
func htons(_ value: UInt16) -> UInt16 {
return CFSwapInt16HostToBig(value)
}
func isMounted() -> Bool {
var addr = sockaddr_in()
memset(&addr, 0, MemoryLayout<sockaddr_in>.size)
addr.sin_family = sa_family_t(AF_INET)
addr.sin_port = htons(UInt16(LOCKDOWN_PORT))
let sockaddrPointer = UnsafeRawPointer(&addr).bindMemory(to: sockaddr.self, capacity: 1)
let pairingFilePath = URL.documentsDirectory.appendingPathComponent("pairingFile.plist").path
guard inet_pton(AF_INET, "10.7.0.1", &addr.sin_addr) == 1 else {
print("Invalid IP address")
return false
}
// Read pairing file
var pairingFile: IdevicePairingFile?
let err = idevice_pairing_file_read(pairingFilePath, &pairingFile)
if err != IdeviceSuccess {
print("Failed to read pairing file: \(err)")
return false
}
// Create TCP provider
var provider: TcpProviderHandle?
let providerError = idevice_tcp_provider_new(sockaddrPointer, pairingFile, "ImageMounterTest", &provider)
if providerError != IdeviceSuccess {
print("Failed to create TCP provider: \(providerError)")
return false
}
// Connect to image mounter
var client: ImageMounterHandle?
let connectError = image_mounter_connect_tcp(provider, &client)
if connectError != IdeviceSuccess {
print("Failed to connect to image mounter: \(connectError)")
return false
}
tcp_provider_free(provider)
print("wow")
var devices: UnsafeMutableRawPointer?
var devicesLen: size_t = 0
let listError = image_mounter_copy_devices(client, &devices, &devicesLen)
if listError == IdeviceSuccess {
let deviceList = devices?.assumingMemoryBound(to: plist_t.self)
var devices: [String] = []
for i in 0..<devicesLen {
let device = deviceList?[i]
var xmlData: UnsafeMutablePointer<CChar>?
var xmlLength: Int32 = 0
// Use libplist function to convert to XML
plist_to_xml(device, &xmlData, &xmlLength)
if let xml = xmlData {
devices.append("\(xml)")
}
plist_mem_free(xmlData)
plist_free(device)
}
image_mounter_free(client)
return devices.count != 0
} else {
print("Failed to get device list: \(listError)")
return false
}
}
func mountPersonalDDI(deviceIP: String = "10.7.0.1", imagePath: String, trustcachePath: String, manifestPath: String, pairingFilePath: String) -> Bool {
idevice_init_logger(Debug, Disabled, nil)
print("Mounting \(imagePath) \(trustcachePath) \(manifestPath)")
guard let image = readFile(path: imagePath),
let trustcache = readFile(path: trustcachePath),
let buildManifest = readFile(path: manifestPath) else {
print("Failed to read one or more files")
return false
}
var addr = sockaddr_in()
memset(&addr, 0, MemoryLayout<sockaddr_in>.size)
addr.sin_family = sa_family_t(AF_INET)
addr.sin_port = htons(UInt16(LOCKDOWN_PORT))
let sockaddrPointer = UnsafeRawPointer(&addr).bindMemory(to: sockaddr.self, capacity: 1)
guard inet_pton(AF_INET, deviceIP, &addr.sin_addr) == 1 else {
print("Invalid IP address")
return false
}
var pairingFile: IdevicePairingFile?
let err = idevice_pairing_file_read(pairingFilePath.cString(using: .utf8), &pairingFile)
if err != IdeviceSuccess {
print("Failed to read pairing file: \(err)")
return false
}
var provider: TcpProviderHandle?
let providerError = idevice_tcp_provider_new(sockaddrPointer, pairingFile, "ImageMounterTest".cString(using: .utf8), &provider)
if providerError != IdeviceSuccess {
print("Failed to create TCP provider: \(providerError)")
return false
}
var pairingFile2: IdevicePairingFile?
let P2err = idevice_pairing_file_read(pairingFilePath.cString(using: .utf8), &pairingFile2)
if P2err != IdeviceSuccess {
print("Failed to read pairing file: \(err)")
return false
}
var lockdownClient: LockdowndClientHandle?
guard lockdownd_connect_tcp(provider, &lockdownClient) == IdeviceSuccess else {
print("Failed to connect to lockdownd")
return false
}
guard lockdownd_start_session(lockdownClient, pairingFile2) == IdeviceSuccess else {
print("Failed to start session")
return false
}
var uniqueChipIDPlist: plist_t?
guard lockdownd_get_value(lockdownClient, "UniqueChipID".cString(using: .utf8), &uniqueChipIDPlist) == IdeviceSuccess else {
print("Failed to get UniqueChipID")
return false
}
var uniqueChipID: UInt64 = 0
plist_get_uint_val(uniqueChipIDPlist, &uniqueChipID)
plist_free(uniqueChipIDPlist)
print(uniqueChipID)
var mounterClient: ImageMounterHandle?
guard image_mounter_connect_tcp(provider, &mounterClient) == IdeviceSuccess else {
print("Failed to connect to image mounter")
return false
}
let result = image.withUnsafeBytes { imagePtr in
trustcache.withUnsafeBytes { trustcachePtr in
buildManifest.withUnsafeBytes { manifestPtr in
image_mounter_mount_personalized_tcp_with_callback(
mounterClient,
provider,
imagePtr.baseAddress?.assumingMemoryBound(to: UInt8.self),
image.count,
trustcachePtr.baseAddress?.assumingMemoryBound(to: UInt8.self),
trustcache.count,
manifestPtr.baseAddress?.assumingMemoryBound(to: UInt8.self),
buildManifest.count,
nil,
uniqueChipID,
progressCallback,
nil
)
}
}
}
if result != IdeviceSuccess {
print(result)
print("Failed to mount personalized image")
return false
} else {
print("Successfully mounted personalized image!")
return true
}
}

View file

@ -52,6 +52,14 @@ struct HomeView: View {
// Main action button - changes based on whether we have a pairing file
Button(action: {
if !isMounted() {
showAlert(title: "Device Not Mounted", message: "The Developer Disk Image has not been mounted yet. Check in settings for more information.", showOk: true) { cool in
// No Need
}
}
if pairingFileExists {
// Got a pairing file, show apps
isShowingInstalledApps = true

View file

@ -19,6 +19,8 @@ struct SettingsView: View {
@State private var isImportingFile = false
@State private var importProgress: Float = 0.0
@StateObject private var mountProg = MountingProgress.shared
// Developer profile image URLs
private let developerProfiles: [String: String] = [
"Blu": "https://github.com/0-Blu.png",
@ -169,6 +171,61 @@ struct SettingsView: View {
.padding(.horizontal, 16)
}
SettingsCard {
VStack(alignment: .leading, spacing: 20) {
Text("Developer Disk Image")
.font(.headline)
.foregroundColor(.primary)
.padding(.bottom, 4)
if mountProg.coolisMounted {
HStack {
Spacer()
Text("✓ Developer Disk Image Mounted Sucessfully!")
.font(.system(.callout, design: .rounded))
.foregroundColor(.green)
.padding(.vertical, 10)
.padding(.horizontal, 18)
.background(Color.green.opacity(0.1))
.cornerRadius(10)
Spacer()
}
.padding(.top, 6)
} else {
HStack {
Text("Mounting Developer Disk Image...")
.font(.system(.caption, design: .rounded))
.foregroundColor(.secondary)
Spacer()
Text("\(Int(MountingProgress.shared.mountProgress))%")
.font(.system(.caption, design: .rounded))
.foregroundColor(.secondary)
}
GeometryReader { geometry in
ZStack(alignment: .leading) {
RoundedRectangle(cornerRadius: 6)
.fill(Color(UIColor.tertiarySystemFill))
.frame(height: 10)
RoundedRectangle(cornerRadius: 6)
.fill(Color.green)
.frame(width: geometry.size.width * CGFloat(MountingProgress.shared.mountProgress), height: 10)
.animation(.linear(duration: 0.3), value: MountingProgress.shared.mountProgress)
}
}
.frame(height: 10)
}
}
.padding(.vertical, 20)
.padding(.horizontal, 16)
.onAppear() {
mountProg.checkforMounted()
}
}
// About section
SettingsCard {
VStack(alignment: .leading, spacing: 20) {

View file

@ -1,6 +1,10 @@
// Jackson Coxson
// Bindings to idevice - https://github.com/jkcoxson/idevice
#ifndef IDEVICE_H
#define IDEVICE_H
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
@ -8,11 +12,9 @@
#include <sys/socket.h>
#include "plist.h"
#ifndef IDEVICE_H
#define IDEVICE_H
#define LOCKDOWN_PORT 62078
typedef enum IdeviceErrorCode {
IdeviceSuccess = 0,
Socket = -1,
@ -102,6 +104,8 @@ typedef struct ImageMounterHandle ImageMounterHandle;
typedef struct InstallationProxyClientHandle InstallationProxyClientHandle;
typedef struct LockdowndClientHandle LockdowndClientHandle;
/**
* Opaque handle to a ProcessControlClient
*/
@ -915,6 +919,145 @@ enum IdeviceErrorCode installation_proxy_get_apps(struct InstallationProxyClient
*/
void installation_proxy_client_free(struct InstallationProxyClientHandle *handle);
/**
* Connects to lockdownd service using TCP provider
*
* # Arguments
* * [`provider`] - A TcpProvider
* * [`client`] - On success, will be set to point to a newly allocated LockdowndClient handle
*
* # Returns
* An error code indicating success or failure
*
* # Safety
* `provider` must be a valid pointer to a handle allocated by this library
* `client` must be a valid, non-null pointer to a location where the handle will be stored
*/
enum IdeviceErrorCode lockdownd_connect_tcp(struct TcpProviderHandle *provider,
struct LockdowndClientHandle **client);
/**
* Connects to lockdownd service using Usbmuxd provider
*
* # Arguments
* * [`provider`] - A UsbmuxdProvider
* * [`client`] - On success, will be set to point to a newly allocated LockdowndClient handle
*
* # Returns
* An error code indicating success or failure
*
* # Safety
* `provider` must be a valid pointer to a handle allocated by this library
* `client` must be a valid, non-null pointer to a location where the handle will be stored
*/
enum IdeviceErrorCode lockdownd_connect_usbmuxd(struct UsbmuxdProviderHandle *provider,
struct LockdowndClientHandle **client);
/**
* Creates a new LockdowndClient from an existing Idevice connection
*
* # Arguments
* * [`socket`] - An IdeviceSocket handle
* * [`client`] - On success, will be set to point to a newly allocated LockdowndClient handle
*
* # Returns
* An error code indicating success or failure
*
* # Safety
* `socket` must be a valid pointer to a handle allocated by this library
* `client` must be a valid, non-null pointer to a location where the handle will be stored
*/
enum IdeviceErrorCode lockdownd_new(struct IdeviceHandle *socket,
struct LockdowndClientHandle **client);
/**
* Starts a session with lockdownd
*
* # Arguments
* * `client` - A valid LockdowndClient handle
* * `pairing_file` - An IdevicePairingFile alocated by this library
*
* # Returns
* An error code indicating success or failure
*
* # Safety
* `client` must be a valid pointer to a handle allocated by this library
* `pairing_file` must be a valid plist_t containing a pairing file
*/
enum IdeviceErrorCode lockdownd_start_session(struct LockdowndClientHandle *client,
struct IdevicePairingFile *pairing_file);
/**
* Starts a service through lockdownd
*
* # Arguments
* * `client` - A valid LockdowndClient handle
* * `identifier` - The service identifier to start (null-terminated string)
* * `port` - Pointer to store the returned port number
* * `ssl` - Pointer to store whether SSL should be enabled
*
* # Returns
* An error code indicating success or failure
*
* # Safety
* `client` must be a valid pointer to a handle allocated by this library
* `identifier` must be a valid null-terminated string
* `port` and `ssl` must be valid pointers
*/
enum IdeviceErrorCode lockdownd_start_service(struct LockdowndClientHandle *client,
const char *identifier,
uint16_t *port,
bool *ssl);
/**
* Gets a value from lockdownd
*
* # Arguments
* * `client` - A valid LockdowndClient handle
* * `value` - The value to get (null-terminated string)
* * `out_plist` - Pointer to store the returned plist value
*
* # Returns
* An error code indicating success or failure
*
* # Safety
* `client` must be a valid pointer to a handle allocated by this library
* `value` must be a valid null-terminated string
* `out_plist` must be a valid pointer to store the plist
*/
enum IdeviceErrorCode lockdownd_get_value(struct LockdowndClientHandle *client,
const char *value,
void **out_plist);
/**
* Gets all values from lockdownd
*
* # Arguments
* * `client` - A valid LockdowndClient handle
* * `out_plist` - Pointer to store the returned plist dictionary
*
* # Returns
* An error code indicating success or failure
*
* # Safety
* `client` must be a valid pointer to a handle allocated by this library
* `out_plist` must be a valid pointer to store the plist
*/
enum IdeviceErrorCode lockdownd_get_all_values(struct LockdowndClientHandle *client,
void **out_plist);
/**
* Frees a LockdowndClient handle
*
* # Arguments
* * [`handle`] - The handle to free
*
* # Safety
* `handle` must be a valid pointer to the handle that was allocated by this library,
* or NULL (in which case this function does nothing)
*/
void lockdownd_client_free(struct LockdowndClientHandle *handle);
/**
* Initializes the logger
*
@ -1153,6 +1296,239 @@ enum IdeviceErrorCode image_mounter_mount_developer(struct ImageMounterHandle *c
const uint8_t *signature,
size_t signature_len);
/**
* Queries the personalization manifest from the device
*
* # Arguments
* * [`client`] - A valid ImageMounter handle
* * [`image_type`] - The type of image to query
* * [`signature`] - Pointer to the signature data
* * [`signature_len`] - Length of the signature data
* * [`manifest`] - Will be set to point to the manifest data on success
* * [`manifest_len`] - Will be set to the length of the manifest data
*
* # Returns
* An error code indicating success or failure
*
* # Safety
* All pointers must be valid and non-null
* `image_type` must be a valid null-terminated C string
*/
enum IdeviceErrorCode image_mounter_query_personalization_manifest(struct ImageMounterHandle *client,
const char *image_type,
const uint8_t *signature,
size_t signature_len,
uint8_t **manifest,
size_t *manifest_len);
/**
* Queries the nonce from the device
*
* # Arguments
* * [`client`] - A valid ImageMounter handle
* * [`personalized_image_type`] - The type of image to query (optional)
* * [`nonce`] - Will be set to point to the nonce data on success
* * [`nonce_len`] - Will be set to the length of the nonce data
*
* # Returns
* An error code indicating success or failure
*
* # Safety
* `client`, `nonce`, and `nonce_len` must be valid pointers
* `personalized_image_type` can be NULL
*/
enum IdeviceErrorCode image_mounter_query_nonce(struct ImageMounterHandle *client,
const char *personalized_image_type,
uint8_t **nonce,
size_t *nonce_len);
/**
* Queries personalization identifiers from the device
*
* # Arguments
* * [`client`] - A valid ImageMounter handle
* * [`image_type`] - The type of image to query (optional)
* * [`identifiers`] - Will be set to point to the identifiers plist on success
*
* # Returns
* An error code indicating success or failure
*
* # Safety
* `client` and `identifiers` must be valid pointers
* `image_type` can be NULL
*/
enum IdeviceErrorCode image_mounter_query_personalization_identifiers(struct ImageMounterHandle *client,
const char *image_type,
void **identifiers);
/**
* Rolls the personalization nonce
*
* # Arguments
* * [`client`] - A valid ImageMounter handle
*
* # Returns
* An error code indicating success or failure
*
* # Safety
* `client` must be a valid pointer to a handle allocated by this library
*/
enum IdeviceErrorCode image_mounter_roll_personalization_nonce(struct ImageMounterHandle *client);
/**
* Rolls the cryptex nonce
*
* # Arguments
* * [`client`] - A valid ImageMounter handle
*
* # Returns
* An error code indicating success or failure
*
* # Safety
* `client` must be a valid pointer to a handle allocated by this library
*/
enum IdeviceErrorCode image_mounter_roll_cryptex_nonce(struct ImageMounterHandle *client);
/**
* Mounts a personalized developer image
*
* # Arguments
* * [`client`] - A valid ImageMounter handle
* * [`provider`] - A valid provider 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 error code indicating success or failure
*
* # Safety
* All pointers must be valid (except optional ones which can be null)
*/
enum IdeviceErrorCode image_mounter_mount_personalized_usbmuxd(struct ImageMounterHandle *client,
struct UsbmuxdProviderHandle *provider,
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
*
* # Arguments
* * [`client`] - A valid ImageMounter handle
* * [`provider`] - A valid provider 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 error code indicating success or failure
*
* # Safety
* All pointers must be valid (except optional ones which can be null)
*/
enum IdeviceErrorCode image_mounter_mount_personalized_tcp(struct ImageMounterHandle *client,
struct TcpProviderHandle *provider,
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 with progress callback
*
* # Arguments
* * [`client`] - A valid ImageMounter handle
* * [`provider`] - A valid provider 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 error code indicating success or failure
*
* # Safety
* All pointers must be valid (except optional ones which can be null)
*/
enum IdeviceErrorCode image_mounter_mount_personalized_usbmuxd_with_callback(struct ImageMounterHandle *client,
struct UsbmuxdProviderHandle *provider,
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
*
* # Arguments
* * [`client`] - A valid ImageMounter handle
* * [`provider`] - A valid provider 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 error code indicating success or failure
*
* # Safety
* All pointers must be valid (except optional ones which can be null)
*/
enum IdeviceErrorCode image_mounter_mount_personalized_tcp_with_callback(struct ImageMounterHandle *client,
struct TcpProviderHandle *provider,
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);
/**
* Reads a pairing file from the specified path
*
@ -1633,4 +2009,4 @@ enum IdeviceErrorCode idevice_usbmuxd_unix_addr_new(const char *addr,
*/
void idevice_usbmuxd_addr_free(struct UsbmuxdAddrHandle *usbmuxd_addr);
#endif /* IDEVICE_H */
#endif

Binary file not shown.