IPC to boot in-mem PPC ELF, with some test code.

This commit is contained in:
dhewg 2009-04-08 16:30:32 +02:00 committed by bushing
parent 05efa74484
commit b409c9694e
8 changed files with 97 additions and 9 deletions

View File

@ -1,8 +1,10 @@
#ifndef __BOOT2_H__
#define __BOOT2_H__
void boot2_ipc(volatile ipc_request *req);
#include "ipc.h"
int boot2_run(u32 tid_hi, u32 tid_lo);
void boot2_init();
void boot2_ipc(volatile ipc_request *req);
#endif

4
ipc.c
View File

@ -10,6 +10,7 @@
#include "sdhc.h"
#include "crypto.h"
#include "boot2.h"
#include "powerpc.h"
#include "panic.h"
static volatile ipc_request in_queue[IPC_IN_SIZE] ALIGNED(32) MEM2_BSS;
@ -136,6 +137,9 @@ static int process_slow(volatile ipc_request *req)
boot2_ipc(req);
return 0;
break;
case IPC_DEV_PPC:
powerpc_ipc(req);
break;
default:
gecko_printf("IPC: unknown SLOW request %02x-%04x\n", req->device, req->req);
}

3
ipc.h
View File

@ -12,6 +12,7 @@
#define IPC_DEV_KEYS 0x03
#define IPC_DEV_AES 0x04
#define IPC_DEV_BOOT2 0x05
#define IPC_DEV_PPC 0x06
#define IPC_SYS_PING 0x0000
#define IPC_SYS_JUMP 0x0001
@ -56,6 +57,8 @@
#define IPC_BOOT2_RUN 0x0000
#define IPC_PPC_BOOT 0x0000
#define IPC_CODE (f,d,r) (((f)<<24)|((d)<<16)|(r))
#define IPC_IN_SIZE 32

2
main.c
View File

@ -222,7 +222,7 @@ void *_main(void *base)
gecko_printf("Trying to boot:" PPC_BOOT_FILE "\n");
res = powerpc_load_file(PPC_BOOT_FILE);
res = powerpc_boot_file(PPC_BOOT_FILE);
if(res < 0) {
gecko_printf("Failed to boot PPC: %d\n", res);
gecko_printf("Continuing anyway\n");

View File

@ -20,7 +20,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "types.h"
#include "memory.h"
#include "powerpc.h"
#include "powerpc_elf.h"
#include "hollywood.h"
#include "utils.h"
#include "start.h"
@ -73,3 +75,18 @@ void powerpc_reset()
udelay(100000);
set32(HW_EXICTRL, EXICTRL_ENABLE_EXI);
}
void powerpc_ipc(volatile ipc_request *req)
{
switch (req->req) {
case IPC_PPC_BOOT:
dc_invalidaterange((void *) req->args[0], (u32) req->args[1]);
int res = powerpc_boot_mem((u8 *) req->args[0], (u32) req->args[1]);
if (res)
ipc_post(req->code, req->tag, 1, res);
break;
default:
gecko_printf("IPC: unknown SLOW PPC request %04X\n", req->req);
}
}

View File

@ -1,9 +1,12 @@
#ifndef __POWERPC_H__
#define __POWERPC_H__ 1
void ppc_boot_code();
#include "ipc.h"
void powerpc_upload_stub(u32 entry);
void powerpc_hang();
void powerpc_reset();
void powerpc_ipc(volatile ipc_request *req);
#endif

View File

@ -16,7 +16,7 @@ static Elf32_Ehdr elfhdr;
static Elf32_Phdr phdrs[PHDR_MAX];
static FIL fd;
int powerpc_load_file(const char *path)
int powerpc_boot_file(const char *path)
{
u32 read;
FRESULT fres;
@ -49,7 +49,7 @@ int powerpc_load_file(const char *path)
fres = f_lseek(&fd, elfhdr.e_phoff);
if(fres != FR_OK)
return -fres;
fres = f_read(&fd, phdrs, sizeof(phdrs[0])*elfhdr.e_phnum, &read);
if(fres != FR_OK)
return -fres;
@ -67,7 +67,7 @@ int powerpc_load_file(const char *path)
gecko_printf("Skipping PHDR of type %d\n",phdr->p_type);
} else {
void *dst = phdr->p_paddr;
gecko_printf("LOAD 0x%x -> %p [0x%x]\n", phdr->p_offset, phdr->p_paddr, phdr->p_filesz);
fres = f_lseek(&fd, phdr->p_offset);
if(fres != FR_OK)
@ -90,3 +90,61 @@ int powerpc_load_file(const char *path)
return 0;
}
int powerpc_boot_mem(const u8 *addr, u32 len)
{
if (len < sizeof(Elf32_Ehdr))
return -100;
Elf32_Ehdr *ehdr = (Elf32_Ehdr *) addr;
if (memcmp("\x7F" "ELF\x01\x02\x01\x00\x00", ehdr->e_ident, 9)) {
gecko_printf("Invalid ELF header! 0x%02x 0x%02x 0x%02x 0x%02x\n",
ehdr->e_ident[0], ehdr->e_ident[1],
ehdr->e_ident[2], ehdr->e_ident[3]);
return -101;
}
if (ehdr->e_phoff == 0 || ehdr->e_phnum == 0) {
gecko_printf("ELF has no program headers!\n");
return -102;
}
if (ehdr->e_phnum > PHDR_MAX) {
gecko_printf("ELF has too many (%d) program headers!\n",
elfhdr.e_phnum);
return -102;
}
int count = ehdr->e_phnum;
if (len < ehdr->e_phoff + count * sizeof(Elf32_Phdr))
return -103;
Elf32_Phdr *phdr = (Elf32_Phdr *) &addr[ehdr->e_phoff];
// TODO: add more checks here
// - phdrs out of bounds?
// - loaded ELF overwrites itself?
powerpc_hang();
while (count--) {
if (phdr->p_type != PT_LOAD) {
gecko_printf("Skipping PHDR of type %d\n", phdr->p_type);
} else {
gecko_printf("LOAD 0x%x -> %p [0x%x]\n", phdr->p_offset, phdr->p_paddr, phdr->p_filesz);
memcpy((void *) phdr->p_paddr, &addr[phdr->p_offset],
phdr->p_filesz);
}
phdr++;
}
dc_flushall();
gecko_printf("ELF load done, booting PPC...\n");
powerpc_upload_stub(ehdr->e_entry);
powerpc_reset();
gecko_printf("PPC booted!\n");
return 0;
}

View File

@ -1,6 +1,7 @@
#ifndef __POWERPC_H__
#define __POWERPC_H__ 1
#ifndef __POWERPC_ELF_H__
#define __POWERPC_ELF_H__ 1
int powerpc_load_file(const char *path);
int powerpc_boot_file(const char *path);
int powerpc_boot_mem(const u8 *addr, u32 len);
#endif