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.
This commit is contained in:
dhewg 2009-04-10 17:25:13 +02:00 committed by bushing
parent a5c87a6127
commit 68397f67cd
7 changed files with 100 additions and 48 deletions

View File

@ -24,6 +24,9 @@ $(TARGET_BIN): $(TARGET) $(ELFLOADER)
@echo "MAKEBIN $@" @echo "MAKEBIN $@"
@$(MAKEBIN) $(ELFLOADER) $< $@ @$(MAKEBIN) $(ELFLOADER) $< $@
upload: $(TARGET_BIN)
@$(WIIDEV)/bin/bootmii -a $<
clean: myclean clean: myclean
myclean: myclean:

28
boot2.c
View File

@ -38,7 +38,6 @@ static u8 boot2_initialized = 0;
static u8 boot2_copy; static u8 boot2_copy;
static u8 pages_read; static u8 pages_read;
static u8 *page_ptr; static u8 *page_ptr;
extern void *vector;
typedef struct { typedef struct {
u32 len; u32 len;
@ -332,7 +331,7 @@ static u32 patch[] = {
0x48415858, 0x48415858,
}; };
void boot2_run(u32 tid_hi, u32 tid_lo) { u32 boot2_run(u32 tid_hi, u32 tid_lo) {
u8 *ptr; u8 *ptr;
int i; int i;
ioshdr *hdr; ioshdr *hdr;
@ -356,37 +355,40 @@ void boot2_run(u32 tid_hi, u32 tid_lo) {
} }
hdr->argument = 0x42; hdr->argument = 0x42;
vector = (u8 *)0x11000000 + hdr->hdrsize;
gecko_printf("boot2 is at %p\n", vector); u32 vector = 0x11000000 + hdr->hdrsize;
return; 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) { switch (req->req) {
case IPC_BOOT2_RUN: case IPC_BOOT2_RUN:
if(boot2_initialized) { if(boot2_initialized) {
// post first so that the memory protection doesn't kill IPC for the PowerPC // post first so that the memory protection doesn't kill IPC for the PowerPC
ipc_post(req->code, req->tag, 1, boot2_copy); ipc_post(req->code, req->tag, 1, boot2_copy);
ipc_flush(); ipc_flush();
boot2_run((u32)req->args[0], (u32)req->args[1]); vector = boot2_run((u32)req->args[0], (u32)req->args[1]);
} else { } else {
ipc_post(req->code, req->tag, 1, -1); ipc_post(req->code, req->tag, 1, -1);
} }
return 0;
break; break;
case IPC_BOOT2_TMD: case IPC_BOOT2_TMD:
if (boot2_initialized) { if (boot2_initialized)
ipc_post(req->code, req->tag, 1, &boot2_tmd); ipc_post(req->code, req->tag, 1, &boot2_tmd);
} else { else
ipc_post(req->code, req->tag, 1, -1); ipc_post(req->code, req->tag, 1, -1);
}
return 1;
break; break;
default: default:
gecko_printf("IPC: unknown SLOW BOOT2 request %04X\n", req->req); gecko_printf("IPC: unknown SLOW BOOT2 request %04X\n", req->req);
} }
return 1;
return vector;
} }

View File

@ -3,8 +3,8 @@
#include "ipc.h" #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_init();
void boot2_ipc(volatile ipc_request *req); u32 boot2_ipc(volatile ipc_request *req);
#endif #endif

58
gecko.c
View File

@ -214,8 +214,8 @@ int gecko_printf(const char *fmt, ...)
// irq context // irq context
#define GECKO_STATE_NONE 0 #define GECKO_STATE_NONE 0
#define GECKO_STATE_RECEIVE_ELF_SIZE 1 #define GECKO_STATE_RECEIVE_BUFFER_SIZE 1
#define GECKO_STATE_RECEIVE_ELF 2 #define GECKO_STATE_RECEIVE_BUFFER 2
static u32 _gecko_cmd = 0; static u32 _gecko_cmd = 0;
static u32 _gecko_cmd_start_time = 0; static u32 _gecko_cmd_start_time = 0;
@ -257,21 +257,32 @@ void gecko_timer(void) {
switch (_gecko_cmd) { switch (_gecko_cmd) {
// upload powerpc ELF // upload powerpc ELF
case 0x43524150: case 0x43524150:
_gecko_state = GECKO_STATE_RECEIVE_ELF_SIZE; _gecko_state = GECKO_STATE_RECEIVE_BUFFER_SIZE;
_gecko_receive_len = 0; _gecko_receive_len = 0;
_gecko_receive_left = 4; _gecko_receive_left = 4;
_gecko_receive_buffer = (u8 *) 0x10100000;
irq_set_alarm(1, 0); irq_set_alarm(1, 0);
_gecko_cmd_start_time = read32(HW_TIMER); _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; break;
} }
return; return;
case GECKO_STATE_RECEIVE_ELF_SIZE: case GECKO_STATE_RECEIVE_BUFFER_SIZE:
if (!_gecko_checkrecv() || !_gecko_recvbyte(&b)) if (!_gecko_checkrecv() || !_gecko_recvbyte(&b))
return; return;
@ -280,8 +291,7 @@ void gecko_timer(void) {
_gecko_receive_left--; _gecko_receive_left--;
if (!_gecko_receive_left) { if (!_gecko_receive_left) {
_gecko_state = GECKO_STATE_RECEIVE_ELF; _gecko_state = GECKO_STATE_RECEIVE_BUFFER;
_gecko_receive_buffer = (u8 *) 0x10100000;
_gecko_receive_left = _gecko_receive_len; _gecko_receive_left = _gecko_receive_len;
powerpc_hang(); powerpc_hang();
@ -289,7 +299,7 @@ void gecko_timer(void) {
return; return;
case GECKO_STATE_RECEIVE_ELF: case GECKO_STATE_RECEIVE_BUFFER:
while (_gecko_receive_left) { while (_gecko_receive_left) {
if (!_gecko_checkrecv() || !_gecko_recvbyte(_gecko_receive_buffer)) if (!_gecko_checkrecv() || !_gecko_recvbyte(_gecko_receive_buffer))
return; return;
@ -298,23 +308,33 @@ void gecko_timer(void) {
_gecko_receive_left--; _gecko_receive_left--;
} }
if (!_gecko_receive_left) { if (!_gecko_receive_left)
irq_set_alarm(100, 0); break;
_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");
}
return; return;
default: default:
gecko_printf("GECKOTIMER: statelolwtf?\n"); 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; break;
} }
irq_set_alarm(100, 0);
_gecko_cmd = 0;
_gecko_cmd_start_time = 0;
_gecko_state = GECKO_STATE_NONE;
} }

41
ipc.c
View File

@ -104,7 +104,7 @@ void ipc_flush(void)
while(peek_outhead() != out_tail); 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); //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 case IPC_SYS_PING: //PING can be both slow and fast for testing purposes
ipc_post(req->code, req->tag, 0); ipc_post(req->code, req->tag, 0);
break; break;
case IPC_SYS_JUMP:
return req->args[0];
default: default:
gecko_printf("IPC: unknown SLOW SYS request %04x\n", req->req); gecko_printf("IPC: unknown SLOW SYS request %04x\n", req->req);
} }
@ -142,7 +144,8 @@ static int process_slow(volatile ipc_request *req)
default: default:
gecko_printf("IPC: unknown SLOW request %02x-%04x\n", req->device, req->req); gecko_printf("IPC: unknown SLOW request %02x-%04x\n", req->device, req->req);
} }
return 1;
return 0;
} }
static void process_in(void) static void process_in(void)
@ -244,6 +247,26 @@ void ipc_irq(void)
gecko_printf("IPC: IRQ but no bell!\n"); 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) void ipc_initialize(void)
{ {
write32(HW_IPC_ARMMSG, 0); write32(HW_IPC_ARMMSG, 0);
@ -269,18 +292,22 @@ void ipc_shutdown(void)
irq_disable(IRQ_IPC); irq_disable(IRQ_IPC);
} }
void ipc_process_slow(void) u32 ipc_process_slow(void)
{ {
while(1) { u32 vector = 0;
while(slow_queue_head != slow_queue_tail) {
if(!process_slow(&slow_queue[slow_queue_head])) while (!vector) {
return; 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); slow_queue_head = (slow_queue_head+1)&(IPC_SLOW_SIZE-1);
} }
u32 cookie = irq_kill(); u32 cookie = irq_kill();
if(slow_queue_head == slow_queue_tail) if(slow_queue_head == slow_queue_tail)
irq_wait(); irq_wait();
irq_restore(cookie); irq_restore(cookie);
} }
return vector;
} }

3
ipc.h
View File

@ -89,11 +89,12 @@ typedef const struct {
} ipc_infohdr; } ipc_infohdr;
void ipc_irq(void); void ipc_irq(void);
void ipc_queue_slow_jump(u32 addr); // only call this from irq context
void ipc_initialize(void); void ipc_initialize(void);
void ipc_shutdown(void); void ipc_shutdown(void);
void ipc_post(u32 code, u32 tag, u32 num_args, ...); void ipc_post(u32 code, u32 tag, u32 num_args, ...);
void ipc_flush(void); void ipc_flush(void);
void ipc_process_slow(void); u32 ipc_process_slow(void);
#endif #endif

11
main.c
View File

@ -38,8 +38,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "nand.h" #include "nand.h"
#include "boot2.h" #include "boot2.h"
void *vector;
typedef struct { typedef struct {
u32 hdrsize; u32 hdrsize;
u32 loadersize; u32 loadersize;
@ -167,10 +165,11 @@ void *patch_boot2(void *base, u64 titleID)
return (void*)(((u32)parhdr) + parhdr->hdrsize); return (void*)(((u32)parhdr) + parhdr->hdrsize);
} }
void *_main(void *base) u32 _main(void *base)
{ {
FRESULT fres; FRESULT fres;
int res; int res;
u32 vector;
gecko_init(); gecko_init();
gecko_printf("mini v0.2 loading\n"); gecko_printf("mini v0.2 loading\n");
@ -212,7 +211,7 @@ void *_main(void *base)
if (read32(0x0d800190) & 2) { if (read32(0x0d800190) & 2) {
gecko_printf("GameCube compatibility mode detected...\n"); gecko_printf("GameCube compatibility mode detected...\n");
boot2_run(1, 0x101); vector = boot2_run(1, 0x101);
goto shutdown; goto shutdown;
} }
@ -230,7 +229,7 @@ void *_main(void *base)
} }
gecko_printf("Going into IPC mainloop...\n"); gecko_printf("Going into IPC mainloop...\n");
ipc_process_slow(); vector = ipc_process_slow();
gecko_printf("IPC mainloop done!\n"); gecko_printf("IPC mainloop done!\n");
gecko_printf("Shutting down IPC...\n"); gecko_printf("Shutting down IPC...\n");
ipc_shutdown(); ipc_shutdown();
@ -241,6 +240,6 @@ shutdown:
gecko_printf("Shutting down caches and MMU...\n"); gecko_printf("Shutting down caches and MMU...\n");
mem_shutdown(); mem_shutdown();
gecko_printf("Vectoring to %p...\n",vector); gecko_printf("Vectoring to 0x%08x...\n", vector);
return vector; return vector;
} }