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__ #ifndef __BOOT2_H__
#define __BOOT2_H__ #define __BOOT2_H__
void boot2_ipc(volatile ipc_request *req); #include "ipc.h"
int boot2_run(u32 tid_hi, u32 tid_lo); int boot2_run(u32 tid_hi, u32 tid_lo);
void boot2_init(); void boot2_init();
void boot2_ipc(volatile ipc_request *req);
#endif #endif

4
ipc.c
View File

@ -10,6 +10,7 @@
#include "sdhc.h" #include "sdhc.h"
#include "crypto.h" #include "crypto.h"
#include "boot2.h" #include "boot2.h"
#include "powerpc.h"
#include "panic.h" #include "panic.h"
static volatile ipc_request in_queue[IPC_IN_SIZE] ALIGNED(32) MEM2_BSS; 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); boot2_ipc(req);
return 0; return 0;
break; break;
case IPC_DEV_PPC:
powerpc_ipc(req);
break;
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);
} }

3
ipc.h
View File

@ -12,6 +12,7 @@
#define IPC_DEV_KEYS 0x03 #define IPC_DEV_KEYS 0x03
#define IPC_DEV_AES 0x04 #define IPC_DEV_AES 0x04
#define IPC_DEV_BOOT2 0x05 #define IPC_DEV_BOOT2 0x05
#define IPC_DEV_PPC 0x06
#define IPC_SYS_PING 0x0000 #define IPC_SYS_PING 0x0000
#define IPC_SYS_JUMP 0x0001 #define IPC_SYS_JUMP 0x0001
@ -56,6 +57,8 @@
#define IPC_BOOT2_RUN 0x0000 #define IPC_BOOT2_RUN 0x0000
#define IPC_PPC_BOOT 0x0000
#define IPC_CODE (f,d,r) (((f)<<24)|((d)<<16)|(r)) #define IPC_CODE (f,d,r) (((f)<<24)|((d)<<16)|(r))
#define IPC_IN_SIZE 32 #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"); 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) { if(res < 0) {
gecko_printf("Failed to boot PPC: %d\n", res); gecko_printf("Failed to boot PPC: %d\n", res);
gecko_printf("Continuing anyway\n"); 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 "types.h"
#include "memory.h"
#include "powerpc.h" #include "powerpc.h"
#include "powerpc_elf.h"
#include "hollywood.h" #include "hollywood.h"
#include "utils.h" #include "utils.h"
#include "start.h" #include "start.h"
@ -73,3 +75,18 @@ void powerpc_reset()
udelay(100000); udelay(100000);
set32(HW_EXICTRL, EXICTRL_ENABLE_EXI); 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__ #ifndef __POWERPC_H__
#define __POWERPC_H__ 1 #define __POWERPC_H__ 1
void ppc_boot_code(); #include "ipc.h"
void powerpc_upload_stub(u32 entry); void powerpc_upload_stub(u32 entry);
void powerpc_hang(); void powerpc_hang();
void powerpc_reset(); void powerpc_reset();
void powerpc_ipc(volatile ipc_request *req);
#endif #endif

View File

@ -16,7 +16,7 @@ static Elf32_Ehdr elfhdr;
static Elf32_Phdr phdrs[PHDR_MAX]; static Elf32_Phdr phdrs[PHDR_MAX];
static FIL fd; static FIL fd;
int powerpc_load_file(const char *path) int powerpc_boot_file(const char *path)
{ {
u32 read; u32 read;
FRESULT fres; FRESULT fres;
@ -49,7 +49,7 @@ int powerpc_load_file(const char *path)
fres = f_lseek(&fd, elfhdr.e_phoff); fres = f_lseek(&fd, elfhdr.e_phoff);
if(fres != FR_OK) if(fres != FR_OK)
return -fres; return -fres;
fres = f_read(&fd, phdrs, sizeof(phdrs[0])*elfhdr.e_phnum, &read); fres = f_read(&fd, phdrs, sizeof(phdrs[0])*elfhdr.e_phnum, &read);
if(fres != FR_OK) if(fres != FR_OK)
return -fres; return -fres;
@ -67,7 +67,7 @@ int powerpc_load_file(const char *path)
gecko_printf("Skipping PHDR of type %d\n",phdr->p_type); gecko_printf("Skipping PHDR of type %d\n",phdr->p_type);
} else { } else {
void *dst = phdr->p_paddr; void *dst = phdr->p_paddr;
gecko_printf("LOAD 0x%x -> %p [0x%x]\n", phdr->p_offset, phdr->p_paddr, phdr->p_filesz); 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); fres = f_lseek(&fd, phdr->p_offset);
if(fres != FR_OK) if(fres != FR_OK)
@ -90,3 +90,61 @@ int powerpc_load_file(const char *path)
return 0; 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__ #ifndef __POWERPC_ELF_H__
#define __POWERPC_H__ 1 #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 #endif