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 $@"
@$(MAKEBIN) $(ELFLOADER) $< $@
upload: $(TARGET_BIN)
@$(WIIDEV)/bin/bootmii -a $<
clean: myclean
myclean:

28
boot2.c
View File

@ -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;
}

View File

@ -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

62
gecko.c
View File

@ -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");
break;
}
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;
}

39
ipc.c
View File

@ -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) {
u32 vector = 0;
while (!vector) {
while (slow_queue_head != slow_queue_tail) {
if(!process_slow(&slow_queue[slow_queue_head]))
return;
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;
}

3
ipc.h
View File

@ -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

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 "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;
}