mirror of
https://github.com/fail0verflow/mini.git
synced 2024-11-30 23:24:19 +01:00
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:
parent
a5c87a6127
commit
68397f67cd
3
Makefile
3
Makefile
@ -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
28
boot2.c
@ -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;
|
||||||
}
|
}
|
||||||
|
4
boot2.h
4
boot2.h
@ -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
|
||||||
|
62
gecko.c
62
gecko.c
@ -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");
|
||||||
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
39
ipc.c
@ -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 (!vector) {
|
||||||
while (slow_queue_head != slow_queue_tail) {
|
while (slow_queue_head != slow_queue_tail) {
|
||||||
if(!process_slow(&slow_queue[slow_queue_head]))
|
vector = process_slow(&slow_queue[slow_queue_head]);
|
||||||
return;
|
|
||||||
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
3
ipc.h
@ -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
11
main.c
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user