Inital version of a ARM side geckoloader.

This commit is contained in:
dhewg 2009-04-10 11:25:10 +02:00 committed by bushing
parent 1c137199ac
commit 1f9aa5b566
5 changed files with 141 additions and 8 deletions

119
gecko.c
View File

@ -1,9 +1,12 @@
#include "types.h" #include "types.h"
#include "irq.h"
#include "start.h" #include "start.h"
#include "vsprintf.h" #include "vsprintf.h"
#include "string.h" #include "string.h"
#include "utils.h" #include "utils.h"
#include "hollywood.h" #include "hollywood.h"
#include "powerpc.h"
#include "powerpc_elf.h"
#include "gecko.h" #include "gecko.h"
static u8 gecko_console_enabled = 0; static u8 gecko_console_enabled = 0;
@ -34,7 +37,7 @@ static u32 _gecko_command(u32 command)
return i; return i;
} }
static u32 _gecko_sendbyte(char sendbyte) static u32 _gecko_sendbyte(u8 sendbyte)
{ {
u32 i = 0; u32 i = 0;
i = _gecko_command(0xB0000000 | (sendbyte<<20)); i = _gecko_command(0xB0000000 | (sendbyte<<20));
@ -43,8 +46,7 @@ static u32 _gecko_sendbyte(char sendbyte)
return 0; return 0;
} }
#if 0 static u32 _gecko_recvbyte(u8 *recvbyte)
static u32 _gecko_recvbyte(char *recvbyte)
{ {
u32 i = 0; u32 i = 0;
*recvbyte = 0; *recvbyte = 0;
@ -57,6 +59,7 @@ static u32 _gecko_recvbyte(char *recvbyte)
return 0; return 0;
} }
#if 0
static u32 _gecko_checksend(void) static u32 _gecko_checksend(void)
{ {
u32 i = 0; u32 i = 0;
@ -65,6 +68,7 @@ static u32 _gecko_checksend(void)
return 1; // Return 1 if safe to send return 1; // Return 1 if safe to send
return 0; return 0;
} }
#endif
static u32 _gecko_checkrecv(void) static u32 _gecko_checkrecv(void)
{ {
@ -74,7 +78,6 @@ static u32 _gecko_checkrecv(void)
return 1; // Return 1 if safe to recv return 1; // Return 1 if safe to recv
return 0; return 0;
} }
#endif
static int gecko_isalive(void) static int gecko_isalive(void)
{ {
@ -207,3 +210,111 @@ int gecko_printf(const char *fmt, ...)
return gecko_sendbuffer(buffer, i); return gecko_sendbuffer(buffer, i);
} }
// irq context
#define GECKO_STATE_NONE 0
#define GECKO_STATE_RECEIVE_ELF_SIZE 1
#define GECKO_STATE_RECEIVE_ELF 2
static u32 _gecko_cmd = 0;
static u32 _gecko_cmd_start_time = 0;
static u32 _gecko_state = GECKO_STATE_NONE;
static u32 _gecko_receive_left = 0;
static u32 _gecko_receive_len = 0;
static u8 *_gecko_receive_buffer = NULL;
void gecko_timer_initialize(void)
{
if (!gecko_isalive())
return;
irq_set_alarm(100, 1);
}
void gecko_timer(void) {
u8 b;
if (_gecko_cmd_start_time && read32(HW_TIMER) >
(_gecko_cmd_start_time + IRQ_ALARM_MS2REG(5000))) {
// time's over, bitch
irq_set_alarm(100, 0);
_gecko_cmd = 0;
_gecko_cmd_start_time = 0;
_gecko_state = GECKO_STATE_NONE;
return;
}
switch (_gecko_state) {
case GECKO_STATE_NONE:
if (!_gecko_checkrecv() || !_gecko_recvbyte(&b))
return;
_gecko_cmd <<= 8;
_gecko_cmd |= b;
switch (_gecko_cmd) {
// upload powerpc ELF
case 0x43524150:
_gecko_state = GECKO_STATE_RECEIVE_ELF_SIZE;
_gecko_receive_len = 0;
_gecko_receive_left = 4;
irq_set_alarm(1, 0);
_gecko_cmd_start_time = read32(HW_TIMER);
gecko_console_enabled = 0;
break;
}
return;
case GECKO_STATE_RECEIVE_ELF_SIZE:
if (!_gecko_checkrecv() || !_gecko_recvbyte(&b))
return;
_gecko_receive_len <<= 8;
_gecko_receive_len |= b;
_gecko_receive_left--;
if (!_gecko_receive_left) {
_gecko_state = GECKO_STATE_RECEIVE_ELF;
_gecko_receive_buffer = (u8 *) 0x10100000;
_gecko_receive_left = _gecko_receive_len;
powerpc_hang();
}
return;
case GECKO_STATE_RECEIVE_ELF:
while (_gecko_receive_left) {
if (!_gecko_checkrecv() || !_gecko_recvbyte(_gecko_receive_buffer))
return;
_gecko_receive_buffer++;
_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");
}
return;
default:
gecko_printf("GECKOTIMER: statelolwtf?\n");
break;
}
}

View File

@ -6,5 +6,7 @@
void gecko_init(void); void gecko_init(void);
u8 gecko_enable_console(const u8 enable); u8 gecko_enable_console(const u8 enable);
int gecko_printf(const char *fmt, ...) __attribute__((format (printf, 1, 2))); int gecko_printf(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
void gecko_timer_initialize(void);
void gecko_timer(void);
#endif #endif

22
irq.c
View File

@ -6,6 +6,8 @@
#include "crypto.h" #include "crypto.h"
#include "nand.h" #include "nand.h"
static u32 _alarm_frequency = 0;
void irq_setup_stack(void); void irq_setup_stack(void);
void irq_initialize(void) void irq_initialize(void)
@ -18,6 +20,8 @@ void irq_initialize(void)
//??? //???
write32(HW_ARMIRQMASK+0x04, 0); write32(HW_ARMIRQMASK+0x04, 0);
write32(HW_ARMIRQMASK+0x20, 0); write32(HW_ARMIRQMASK+0x20, 0);
write32(HW_ALARM, 0);
} }
void irq_shutdown(void) void irq_shutdown(void)
@ -37,10 +41,11 @@ void irq_handler(void)
flags = flags & enabled; flags = flags & enabled;
if(flags & IRQF_TIMER) { if(flags & IRQF_TIMER) {
gecko_printf("IRQ: timer\n"); if (_alarm_frequency) {
gecko_printf("Timer: %08x\n", read32(HW_TIMER)); // currently we use the alarm timer only for lame usbgecko polling
gecko_printf("Alarm: %08x\n", read32(HW_ALARM)); gecko_timer();
write32(HW_ALARM, 0); // shut it up write32(HW_ALARM, read32(HW_TIMER) + _alarm_frequency);
}
write32(HW_ARMIRQFLAG, IRQF_TIMER); write32(HW_ARMIRQFLAG, IRQF_TIMER);
} }
if(flags & IRQF_NAND) { if(flags & IRQF_NAND) {
@ -88,3 +93,12 @@ void irq_disable(u32 irq)
{ {
clear32(HW_ARMIRQMASK, 1<<irq); clear32(HW_ARMIRQMASK, 1<<irq);
} }
void irq_set_alarm(u32 ms, u8 enable)
{
_alarm_frequency = IRQ_ALARM_MS2REG(ms);
if (enable)
write32(HW_ALARM, read32(HW_TIMER) + _alarm_frequency);
}

5
irq.h
View File

@ -33,8 +33,11 @@
#define CPSR_FIQDIS 0x40 #define CPSR_FIQDIS 0x40
#ifndef _LANGUAGE_ASSEMBLY #ifndef _LANGUAGE_ASSEMBLY
#include "types.h" #include "types.h"
#define IRQ_ALARM_MS2REG(x) (1898 * x)
void irq_initialize(void); void irq_initialize(void);
void irq_shutdown(void); void irq_shutdown(void);
@ -50,6 +53,8 @@ static inline void irq_wait(void)
__asm__ volatile ( "mcr\tp15, 0, %0, c7, c0, 4" : : "r" (data) ); __asm__ volatile ( "mcr\tp15, 0, %0, c7, c0, 4" : : "r" (data) );
} }
void irq_set_alarm(u32 ms, u8 enable);
#endif #endif
#endif #endif

1
main.c
View File

@ -190,6 +190,7 @@ void *_main(void *base)
irq_enable(IRQ_GPIO1B); irq_enable(IRQ_GPIO1B);
irq_enable(IRQ_GPIO1); irq_enable(IRQ_GPIO1);
irq_enable(IRQ_RESET); irq_enable(IRQ_RESET);
gecko_timer_initialize();
gecko_printf("Interrupts initialized\n"); gecko_printf("Interrupts initialized\n");
crypto_initialize(); crypto_initialize();