From 68397f67cdd8ef4c8c76ff7ceff4c072250501de Mon Sep 17 00:00:00 2001 From: dhewg Date: Fri, 10 Apr 2009 17:25:13 +0200 Subject: [PATCH] Reworked vectoring for mini's _main() ipc_process_slow() and friends return a vector where bootmii branches to upon exit. Implemented IPC_SYS_JUMP via ipc_queue_slow_jump(). Ability to upload armboot.bin with the bootmii client. --- Makefile | 3 +++ boot2.c | 28 ++++++++++++++------------- boot2.h | 4 ++-- gecko.c | 58 +++++++++++++++++++++++++++++++++++++------------------- ipc.c | 41 ++++++++++++++++++++++++++++++++------- ipc.h | 3 ++- main.c | 11 +++++------ 7 files changed, 100 insertions(+), 48 deletions(-) diff --git a/Makefile b/Makefile index 4228b22..da0f7de 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,9 @@ $(TARGET_BIN): $(TARGET) $(ELFLOADER) @echo "MAKEBIN $@" @$(MAKEBIN) $(ELFLOADER) $< $@ +upload: $(TARGET_BIN) + @$(WIIDEV)/bin/bootmii -a $< + clean: myclean myclean: diff --git a/boot2.c b/boot2.c index ed6be54..32b6a71 100644 --- a/boot2.c +++ b/boot2.c @@ -38,7 +38,6 @@ static u8 boot2_initialized = 0; static u8 boot2_copy; static u8 pages_read; static u8 *page_ptr; -extern void *vector; typedef struct { u32 len; @@ -332,7 +331,7 @@ static u32 patch[] = { 0x48415858, }; -void boot2_run(u32 tid_hi, u32 tid_lo) { +u32 boot2_run(u32 tid_hi, u32 tid_lo) { u8 *ptr; int i; ioshdr *hdr; @@ -356,37 +355,40 @@ void boot2_run(u32 tid_hi, u32 tid_lo) { } hdr->argument = 0x42; - vector = (u8 *)0x11000000 + hdr->hdrsize; - gecko_printf("boot2 is at %p\n", vector); - return; + + u32 vector = 0x11000000 + hdr->hdrsize; + gecko_printf("boot2 is at 0x%08x\n", vector); + return vector; } -int boot2_ipc(volatile ipc_request *req) +u32 boot2_ipc(volatile ipc_request *req) { + u32 vector = 0; + switch (req->req) { case IPC_BOOT2_RUN: if(boot2_initialized) { // post first so that the memory protection doesn't kill IPC for the PowerPC ipc_post(req->code, req->tag, 1, boot2_copy); ipc_flush(); - boot2_run((u32)req->args[0], (u32)req->args[1]); + vector = boot2_run((u32)req->args[0], (u32)req->args[1]); } else { ipc_post(req->code, req->tag, 1, -1); } - return 0; + break; case IPC_BOOT2_TMD: - if (boot2_initialized) { + if (boot2_initialized) ipc_post(req->code, req->tag, 1, &boot2_tmd); - } else { + else ipc_post(req->code, req->tag, 1, -1); - } - return 1; + break; default: gecko_printf("IPC: unknown SLOW BOOT2 request %04X\n", req->req); } - return 1; + + return vector; } diff --git a/boot2.h b/boot2.h index 3742335..586a185 100644 --- a/boot2.h +++ b/boot2.h @@ -3,8 +3,8 @@ #include "ipc.h" -int boot2_run(u32 tid_hi, u32 tid_lo); +u32 boot2_run(u32 tid_hi, u32 tid_lo); void boot2_init(); -void boot2_ipc(volatile ipc_request *req); +u32 boot2_ipc(volatile ipc_request *req); #endif diff --git a/gecko.c b/gecko.c index ef268cf..be68c56 100644 --- a/gecko.c +++ b/gecko.c @@ -214,8 +214,8 @@ int gecko_printf(const char *fmt, ...) // irq context #define GECKO_STATE_NONE 0 -#define GECKO_STATE_RECEIVE_ELF_SIZE 1 -#define GECKO_STATE_RECEIVE_ELF 2 +#define GECKO_STATE_RECEIVE_BUFFER_SIZE 1 +#define GECKO_STATE_RECEIVE_BUFFER 2 static u32 _gecko_cmd = 0; static u32 _gecko_cmd_start_time = 0; @@ -257,21 +257,32 @@ void gecko_timer(void) { switch (_gecko_cmd) { // upload powerpc ELF case 0x43524150: - _gecko_state = GECKO_STATE_RECEIVE_ELF_SIZE; + _gecko_state = GECKO_STATE_RECEIVE_BUFFER_SIZE; _gecko_receive_len = 0; _gecko_receive_left = 4; + _gecko_receive_buffer = (u8 *) 0x10100000; irq_set_alarm(1, 0); _gecko_cmd_start_time = read32(HW_TIMER); - gecko_console_enabled = 0; + break; + + // upload ARM ELF + case 0x5a4f4d47: + _gecko_state = GECKO_STATE_RECEIVE_BUFFER_SIZE; + _gecko_receive_len = 0; + _gecko_receive_left = 4; + _gecko_receive_buffer = (u8 *) 0x0; // yarly + + irq_set_alarm(1, 0); + _gecko_cmd_start_time = read32(HW_TIMER); break; } return; - case GECKO_STATE_RECEIVE_ELF_SIZE: + case GECKO_STATE_RECEIVE_BUFFER_SIZE: if (!_gecko_checkrecv() || !_gecko_recvbyte(&b)) return; @@ -280,8 +291,7 @@ void gecko_timer(void) { _gecko_receive_left--; if (!_gecko_receive_left) { - _gecko_state = GECKO_STATE_RECEIVE_ELF; - _gecko_receive_buffer = (u8 *) 0x10100000; + _gecko_state = GECKO_STATE_RECEIVE_BUFFER; _gecko_receive_left = _gecko_receive_len; powerpc_hang(); @@ -289,7 +299,7 @@ void gecko_timer(void) { return; - case GECKO_STATE_RECEIVE_ELF: + case GECKO_STATE_RECEIVE_BUFFER: while (_gecko_receive_left) { if (!_gecko_checkrecv() || !_gecko_recvbyte(_gecko_receive_buffer)) return; @@ -298,23 +308,33 @@ void gecko_timer(void) { _gecko_receive_left--; } - if (!_gecko_receive_left) { - irq_set_alarm(100, 0); - _gecko_cmd = 0; - _gecko_cmd_start_time = 0; - _gecko_state = GECKO_STATE_NONE; - - gecko_console_enabled = 1; - - if (powerpc_boot_mem((u8 *) 0x10100000, _gecko_receive_len)) - gecko_printf("GECKOTIMER: elflolwtf?\n"); - } + if (!_gecko_receive_left) + break; return; default: gecko_printf("GECKOTIMER: statelolwtf?\n"); + return; + } + + // done receiving, handle the command + switch (_gecko_cmd) { + case 0x43524150: + if (powerpc_boot_mem((u8 *) 0x10100000, _gecko_receive_len)) + gecko_printf("GECKOTIMER: elflolwtf?\n"); + break; + + case 0x5a4f4d47: + // skip headerlen, which is stored at u32[0] + ipc_queue_slow_jump(((u32 *) 0x0)[0]); break; } + + irq_set_alarm(100, 0); + + _gecko_cmd = 0; + _gecko_cmd_start_time = 0; + _gecko_state = GECKO_STATE_NONE; } diff --git a/ipc.c b/ipc.c index 49c8a2d..8ecc4ef 100644 --- a/ipc.c +++ b/ipc.c @@ -104,7 +104,7 @@ void ipc_flush(void) while(peek_outhead() != out_tail); } -static int process_slow(volatile ipc_request *req) +static u32 process_slow(volatile ipc_request *req) { //gecko_printf("IPC: process slow_queue @ %p\n",req); @@ -117,6 +117,8 @@ static int process_slow(volatile ipc_request *req) case IPC_SYS_PING: //PING can be both slow and fast for testing purposes ipc_post(req->code, req->tag, 0); break; + case IPC_SYS_JUMP: + return req->args[0]; default: gecko_printf("IPC: unknown SLOW SYS request %04x\n", req->req); } @@ -142,7 +144,8 @@ static int process_slow(volatile ipc_request *req) default: gecko_printf("IPC: unknown SLOW request %02x-%04x\n", req->device, req->req); } - return 1; + + return 0; } static void process_in(void) @@ -244,6 +247,26 @@ void ipc_irq(void) gecko_printf("IPC: IRQ but no bell!\n"); } +void ipc_queue_slow_jump(u32 addr) +{ + volatile ipc_request *req = &in_queue[in_head]; + + if(slow_queue_head == ((slow_queue_tail + 1)&(IPC_SLOW_SIZE-1))) { + gecko_printf("IPC: Slowqueue overrun\n"); + panic2(0, PANIC_IPCOVF); + } + + req->flags = IPC_SLOW; + req->device = IPC_DEV_SYS; + req->req = IPC_SYS_JUMP; + + req->tag = 0; + req->args[0] = addr; + + slow_queue[slow_queue_tail] = *req; + slow_queue_tail = (slow_queue_tail+1)&(IPC_SLOW_SIZE-1); +} + void ipc_initialize(void) { write32(HW_IPC_ARMMSG, 0); @@ -269,18 +292,22 @@ void ipc_shutdown(void) irq_disable(IRQ_IPC); } -void ipc_process_slow(void) +u32 ipc_process_slow(void) { - while(1) { - while(slow_queue_head != slow_queue_tail) { - if(!process_slow(&slow_queue[slow_queue_head])) - return; + u32 vector = 0; + + while (!vector) { + while (slow_queue_head != slow_queue_tail) { + vector = process_slow(&slow_queue[slow_queue_head]); slow_queue_head = (slow_queue_head+1)&(IPC_SLOW_SIZE-1); } + u32 cookie = irq_kill(); if(slow_queue_head == slow_queue_tail) irq_wait(); irq_restore(cookie); } + + return vector; } diff --git a/ipc.h b/ipc.h index 89bf215..97cb38f 100644 --- a/ipc.h +++ b/ipc.h @@ -89,11 +89,12 @@ typedef const struct { } ipc_infohdr; void ipc_irq(void); +void ipc_queue_slow_jump(u32 addr); // only call this from irq context void ipc_initialize(void); void ipc_shutdown(void); void ipc_post(u32 code, u32 tag, u32 num_args, ...); void ipc_flush(void); -void ipc_process_slow(void); +u32 ipc_process_slow(void); #endif diff --git a/main.c b/main.c index 4f45ce3..c474ab1 100644 --- a/main.c +++ b/main.c @@ -38,8 +38,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "nand.h" #include "boot2.h" -void *vector; - typedef struct { u32 hdrsize; u32 loadersize; @@ -167,10 +165,11 @@ void *patch_boot2(void *base, u64 titleID) return (void*)(((u32)parhdr) + parhdr->hdrsize); } -void *_main(void *base) +u32 _main(void *base) { FRESULT fres; int res; + u32 vector; gecko_init(); gecko_printf("mini v0.2 loading\n"); @@ -212,7 +211,7 @@ void *_main(void *base) if (read32(0x0d800190) & 2) { gecko_printf("GameCube compatibility mode detected...\n"); - boot2_run(1, 0x101); + vector = boot2_run(1, 0x101); goto shutdown; } @@ -230,7 +229,7 @@ void *_main(void *base) } gecko_printf("Going into IPC mainloop...\n"); - ipc_process_slow(); + vector = ipc_process_slow(); gecko_printf("IPC mainloop done!\n"); gecko_printf("Shutting down IPC...\n"); ipc_shutdown(); @@ -241,6 +240,6 @@ shutdown: gecko_printf("Shutting down caches and MMU...\n"); mem_shutdown(); - gecko_printf("Vectoring to %p...\n",vector); + gecko_printf("Vectoring to 0x%08x...\n", vector); return vector; }