Skip to content

Commit

Permalink
Implement basic async WUP install
Browse files Browse the repository at this point in the history
  • Loading branch information
GaryOderNichts committed Mar 3, 2024
1 parent 9ec6108 commit 4a8dbff
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 10 deletions.
58 changes: 58 additions & 0 deletions ios_mcp/source/imports.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <stdint.h>
#include <stdio.h>
#include <assert.h>

#define LOCAL_PROCESS_HEAP_ID 0xcafe
#define CROSS_PROCESS_HEAP_ID 0xcaff
Expand All @@ -12,6 +13,63 @@ typedef struct {
uint32_t paddr;
} IOSVec_t;

typedef struct __attribute__((__packed__)) {
uint32_t command;
int32_t result;
int32_t handle;
uint32_t flags;
uint32_t cpuId;
uint32_t processId;
uint64_t titleId;
uint32_t groupId;

union {
uint32_t args[5];

struct __attribute__((__packed__)) {
const char* device;
uint32_t nameLen;
uint32_t mode;
uint64_t caps;
} open;

struct {
uint32_t unknown;
} close;

struct {
void* data;
uint32_t length;
} read;

struct {
const void* data;
uint32_t length;
} write;

struct {
uint32_t offset;
uint32_t origin;
} seek;

struct {
uint32_t request;
const void* inputData;
uint32_t inputLength;
void* outputData;
uint32_t outputLength;
} ioctl;

struct {
uint32_t request;
uint32_t numVecIn;
uint32_t numVecOut;
IOSVec_t* vecs;
} ioctlv;
};
} IOSIpcRequest_t;
static_assert(sizeof(IOSIpcRequest_t) == 0x38);

enum {
UC_DATA_TYPE_U8 = 1,
UC_DATA_TYPE_U16 = 2,
Expand Down
14 changes: 9 additions & 5 deletions ios_mcp/source/mcp_install.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,20 +82,24 @@ int MCP_InstallTitle(int handle, const char* path)
return res;
}

int MCP_InstallTitleAsync(int handle, const char* path, int callbackQueue, void* msg)
int MCP_InstallTitleAsync(int handle, const char* path, int callbackQueue)
{
uint8_t* buf = allocIoBuf(0x27f + sizeof(IOSVec_t));
uint8_t* buf = allocIoBuf(0x27f + sizeof(IOSVec_t) + sizeof(MCPAsyncReply));

char* path_buf = (char*) buf + sizeof(IOSVec_t);
char* path_buf = (char*) buf + sizeof(IOSVec_t) + sizeof(MCPAsyncReply);
strncpy(path_buf, path, 0x27f);

IOSVec_t* vecs = (IOSVec_t*) buf;
vecs[0].ptr = path_buf;
vecs[0].len = 0x27f;

int res = IOS_IoctlvAsync(handle, 0x81, 1, 0, vecs, callbackQueue, msg);
MCPAsyncReply* reply = (MCPAsyncReply*) (buf + sizeof(IOSVec_t));
reply->ioBuf = buf;

freeIoBuf(buf);
int res = IOS_IoctlvAsync(handle, 0x81, 1, 0, vecs, callbackQueue, &reply->reply);
if (res < 0) {
freeIoBuf(buf);
}

return res;
}
Expand Down
8 changes: 7 additions & 1 deletion ios_mcp/source/mcp_install.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "imports.h"
#include <stdint.h>

typedef struct __attribute__((packed)) {
Expand All @@ -16,6 +17,11 @@ typedef struct __attribute__((packed)) {
uint32_t contentsProgress;
} MCPInstallProgress;

typedef struct __attribute__((packed)) {
IOSIpcRequest_t reply;
void* ioBuf;
} MCPAsyncReply;

int MCP_InstallGetInfo(int handle, const char* path, MCPInstallInfo* out_info);

int MCP_InstallSetTargetUsb(int handle, int target);
Expand All @@ -24,6 +30,6 @@ int MCP_InstallSetTargetDevice(int handle, int device);

int MCP_InstallTitle(int handle, const char* path);

int MCP_InstallTitleAsync(int handle, const char* path, int callbackQueue, void* msg);
int MCP_InstallTitleAsync(int handle, const char* path, int callbackQueue);

int MCP_InstallGetProgress(int handle, MCPInstallProgress* progress);
64 changes: 61 additions & 3 deletions ios_mcp/source/options/InstallWUP.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,27 @@
#include "mcp_install.h"
#include "imports.h"
#include "utils.h"
#include <unistd.h>

static int callbackQueue = -1;
static uint8_t callbackThreadStack[0x200] __attribute__((aligned(0x20)));
static int asyncPending = 0;
static int asyncResult = -1;

static int callbackThread(void* arg)
{
MCPAsyncReply* reply = NULL;
int ret = IOS_ReceiveMessage(callbackQueue, (uint32_t*)&reply, IOS_MESSAGE_FLAGS_NONE);
if (ret >= 0 && reply) {
asyncResult = reply->reply.result;
asyncPending = 0;

// Free original request
IOS_HeapFree(CROSS_PROCESS_HEAP_ID, reply->ioBuf);
}

return 0;
}

void option_InstallWUP(void)
{
Expand Down Expand Up @@ -51,18 +72,55 @@ void option_InstallWUP(void)
return;
}

// TODO: async installations
res = MCP_InstallTitle(mcpHandle, "/vol/storage_recovsd/install");
int callbackThreadId = IOS_CreateThread(callbackThread, NULL, callbackThreadStack + sizeof(callbackThreadStack), sizeof(callbackThreadStack), IOS_GetThreadPriority(0), IOS_THREAD_FLAGS_NONE);
if (callbackThreadId < 0) {
IOS_Close(mcpHandle);
printf_error(index, "IOS_CreateThread: %x", res);
return;
}

if (IOS_StartThread(callbackThreadId) < 0) {
IOS_Close(mcpHandle);
printf_error(index, "IOS_StartThread failed");
return;
}

uint32_t messages[5];
callbackQueue = IOS_CreateMessageQueue(messages, sizeof(messages) / sizeof(uint32_t));
if (callbackQueue < 0) {
IOS_Close(mcpHandle);
printf_error(index, "IOS_CreateThread: %x", res);
return;
}

asyncResult = -1;
asyncPending = 1;
res = MCP_InstallTitleAsync(mcpHandle, "/vol/storage_recovsd/install", callbackQueue);
if (res < 0) {
IOS_Close(mcpHandle);
printf_error(index, "Failed to install: %x", res);
return;
}

while (asyncPending) {
MCPInstallProgress progress;
res = MCP_InstallGetProgress(mcpHandle, &progress);
if (res < 0) {
// Uh oh
}

gfx_printf(16, index, GfxPrintFlag_ClearBG, "Installing (%ld)... (%lu KiB / %lu KiB)", progress.inProgress, (uint32_t) (progress.sizeProgress / 1024llu), (uint32_t) (progress.sizeTotal / 1024llu));
usleep(50 * 1000);
}
index += CHAR_SIZE_DRC_Y + 4;

setNotificationLED(NOTIF_LED_PURPLE, 0);
gfx_set_font_color(COLOR_SUCCESS);
gfx_print(16, index, 0, "Done!");
gfx_printf(16, index, 0, "Done (with result %d)!", asyncResult);
waitButtonInput();

IOS_JoinThread(callbackThreadId, NULL);
IOS_DestroyMessageQueue(callbackQueue);

IOS_Close(mcpHandle);
}
2 changes: 1 addition & 1 deletion ios_mcp/source/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ enum {
};

static int asyncThreadHandle = -1;
static uint8_t asyncThreadStack[0x400] __attribute__((aligned(0x20)));
static uint8_t asyncThreadStack[0x200] __attribute__((aligned(0x20)));
static uint32_t asyncMessageQueueBuf[0x20];
static int asyncMessageQueue = -1;
static int ledTimer = -1;
Expand Down

0 comments on commit 4a8dbff

Please sign in to comment.