Skip to content

Commit

Permalink
Merge pull request #129 from fjtrujy/loadELF
Browse files Browse the repository at this point in the history
Create a library to make easier the Loading of ELF files
  • Loading branch information
fjtrujy authored Jun 28, 2020
2 parents 85bc643 + f17192f commit 202279e
Show file tree
Hide file tree
Showing 9 changed files with 372 additions and 1 deletion.
3 changes: 2 additions & 1 deletion ee/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
SUBDIRS = erl kernel kernel-nopatch libc rpc debug \
eedebug sbv dma graph math3d \
packet draw erl-loader mpeg libgs \
libvux font input inputx network iopreboot
libvux font input inputx network iopreboot \
elf-loader

include $(PS2SDKSRC)/Defs.make
include $(PS2SDKSRC)/Rules.make
Expand Down
25 changes: 25 additions & 0 deletions ee/elf-loader/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
#-----------------------------------------------------------------------
# (c) 2020 Francisco Javier Trujillo Mata <[email protected]>
# Licenced under Academic Free License version 2.0
# Review ps2sdk README & LICENSE files for further details.

EE_OBJS = elf.o loader.o

all:: prepareLoader $(EE_LIB)

clean:: cleanLoader

prepareLoader:
$(MAKE) -C src/loader
$(PS2SDKSRC)/tools/bin2c/bin/bin2c src/loader/loader.elf src/loader.c loader_elf

cleanLoader:
$(MAKE) -C src/loader clean

include $(PS2SDKSRC)/Defs.make
include $(PS2SDKSRC)/ee/Rules.lib.make
include $(PS2SDKSRC)/ee/Rules.make
include $(PS2SDKSRC)/ee/Rules.release
30 changes: 30 additions & 0 deletions ee/elf-loader/include/elf-loader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
#-----------------------------------------------------------------------
# (c) 2020 Francisco Javier Trujillo Mata <[email protected]>
# Licenced under Academic Free License version 2.0
# Review ps2sdk README & LICENSE files for further details.
*/

/**
* @file
* ELF Loader functions.
*/

#ifndef __ELFLOADER_H__
#define __ELFLOADER_H__

#ifdef __cplusplus
extern "C" {
#endif

// Before call this method be sure that you have previously called sbv_patch_disable_prefix_check();
int LoadELFFromFile(const char *filename, int argc, char *argv[]);

#ifdef __cplusplus
}
#endif

#endif /* __ELFLOADER_H__ */
2 changes: 2 additions & 0 deletions ee/elf-loader/src/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# c representation of generated loader.elf
loader.c
80 changes: 80 additions & 0 deletions ee/elf-loader/src/elf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
#-----------------------------------------------------------------------
# (c) 2020 Francisco Javier Trujillo Mata <[email protected]>
# Licenced under Academic Free License version 2.0
# Review ps2sdk README & LICENSE files for further details.
*/

#include <string.h>
#include <sifrpc.h>
#include <kernel.h>
#include <sys/stat.h>
#include <stdbool.h>
#include <malloc.h>

#include "elf.h"

// Loader ELF variables
extern u8 loader_elf[];
extern int size_loader_elf;

// ELF-loading stuff
#define ELF_MAGIC 0x464c457f
#define ELF_PT_LOAD 1

static bool file_exists(const char *filename) {
struct stat buffer;
return (stat (filename, &buffer) == 0);
}

int LoadELFFromFile(const char *filename, int argc, char *argv[])
{
u8 *boot_elf;
elf_header_t *eh;
elf_pheader_t *eph;
void *pdata;
int i;
int new_argc = argc + 1;

// We need to check that the ELF file before continue
if (!file_exists(filename)) {
return -1; // ELF file doesn't exists
}
// ELF Exists
char *new_argv[new_argc];

new_argv[0] = (char *)filename;
for (i = 0; i < argc; i++) {
new_argv[i + 1] = argv[i];
}

/* NB: LOADER.ELF is embedded */
boot_elf = (u8 *)loader_elf;
eh = (elf_header_t *)boot_elf;
if (_lw((u32)&eh->ident) != ELF_MAGIC)
asm volatile("break\n");

eph = (elf_pheader_t *)(boot_elf + eh->phoff);

/* Scan through the ELF's program headers and copy them into RAM, then zero out any non-loaded regions. */
for (i = 0; i < eh->phnum; i++) {
if (eph[i].type != ELF_PT_LOAD)
continue;

pdata = (void *)(boot_elf + eph[i].offset);
memcpy(eph[i].vaddr, pdata, eph[i].filesz);

if (eph[i].memsz > eph[i].filesz)
memset(eph[i].vaddr + eph[i].filesz, 0, eph[i].memsz - eph[i].filesz);
}

/* Let's go. */
SifExitRpc();
FlushCache(0);
FlushCache(2);

return ExecPS2((void *)eh->entry, NULL, new_argc, new_argv);
}
54 changes: 54 additions & 0 deletions ee/elf-loader/src/elf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
#-----------------------------------------------------------------------
# (c) 2020 Francisco Javier Trujillo Mata <[email protected]>
# Licenced under Academic Free License version 2.0
# Review ps2sdk README & LICENSE files for further details.
*/

#ifndef __ELF_H__
#define __ELF_H__

#include <tamtypes.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct
{
u8 ident[16]; // struct definition for ELF object header
u16 type;
u16 machine;
u32 version;
u32 entry;
u32 phoff;
u32 shoff;
u32 flags;
u16 ehsize;
u16 phentsize;
u16 phnum;
u16 shentsize;
u16 shnum;
u16 shstrndx;
} elf_header_t;

typedef struct
{
u32 type; // struct definition for ELF program section header
u32 offset;
void *vaddr;
u32 paddr;
u32 filesz;
u32 memsz;
u32 flags;
u32 align;
} elf_pheader_t;

#ifdef __cplusplus
}
#endif

#endif /* __ELF_H__ */
40 changes: 40 additions & 0 deletions ee/elf-loader/src/loader/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
#-----------------------------------------------------------------------
# (c) 2020 Francisco Javier Trujillo Mata <[email protected]>
# Licenced under Academic Free License version 2.0
# Review ps2sdk README & LICENSE files for further details.

### Adjust these three, for PS2Link compatibility tests
### Old LaunchELF used LA=0x90000, SA=0xB0000, SS=0x08000
LOADADDR = 0x90000
STACKADDR = 0xA8000
STACKSIZE = 0x04000

ifeq ($(DEBUG),1)
LOADADDR = 0x1700000
STACKADDR = 0x1720000
STACKSIZE = 0x08000
endif

LDPARAMS := -Wl,--defsym -Wl,_stack_size=$(STACKSIZE) -Wl,--defsym -Wl,_stack=$(STACKADDR)

EE_LDFLAGS += -Wl,-Ttext -Wl,$(LOADADDR) -s $(LDPARAMS)

EE_BIN = loader.elf

EE_OBJS = loader.o

EE_LIBS =
ifeq ($(DEBUG),1)
EE_LIBS += -ldebug
endif

all: $(EE_BIN)

clean:
rm -f -r $(EE_OBJS) $(EE_BIN)

include $(PS2SDKSRC)/Defs.make
include Rules.make
66 changes: 66 additions & 0 deletions ee/elf-loader/src/loader/Rules.make
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
#-----------------------------------------------------------------------
# Copyright 2001-2004, ps2dev - http://www.ps2dev.org
# Licenced under Academic Free License version 2.0
# Review ps2sdk README & LICENSE files for further details.

EE_CC_VERSION := $(shell $(EE_CC) -dumpversion)

EE_SRC_DIR ?= src/
EE_INC_DIR ?= include/

# Include directories
EE_INCS := $(EE_INCS) -I$(EE_SRC_DIR) -I$(EE_SRC_DIR)include -I$(EE_INC_DIR) -I$(PS2SDKSRC)/ee/kernel/include -I$(PS2SDKSRC)/common/include -I$(PS2SDKSRC)/ee/libc/include -I$(PS2SDKSRC)/ee/erl/include

# C compiler flags
EE_CFLAGS := -D_EE -O2 -G0 -Wall -Werror $(EE_CFLAGS)

# C++ compiler flags
EE_CXXFLAGS := -D_EE -O2 -G0 -Wall -Werror $(EE_CXXFLAGS)

# Linker flags
EE_LDFLAGS := -L$(PS2SDKSRC)/ee/kernel/lib -L$(PS2SDKSRC)/ee/libc/lib $(EE_LDFLAGS)

# Assembler flags
EE_ASFLAGS := -G0 $(EE_ASFLAGS)

# Externally defined variables: EE_BIN, EE_OBJS, EE_LIB

# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
#-----------------------------------------------------------------------
# (c) 2020 Francisco Javier Trujillo Mata <[email protected]>
# Licenced under Academic Free License version 2.0
# Review ps2sdk README & LICENSE files for further details.

# These macros can be used to simplify certain build rules.
EE_C_COMPILE = $(EE_CC) $(EE_CFLAGS) $(EE_INCS)
EE_CXX_COMPILE = $(EE_CXX) $(EE_CXXFLAGS) $(EE_INCS)

%.o: %.c
$(EE_CC) $(EE_CFLAGS) $(EE_INCS) -c $< -o $@

%.o: %.cc
$(EE_CXX) $(EE_CXXFLAGS) $(EE_INCS) -c $< -o $@

%.o: %.cpp
$(EE_CXX) $(EE_CXXFLAGS) $(EE_INCS) -c $< -o $@

%.o: %.S
$(EE_CC) $(EE_CFLAGS) $(EE_INCS) -c $< -o $@

%.o: %.s
$(EE_AS) $(EE_ASFLAGS) $< -o $@

$(EE_BIN): $(EE_OBJS)
$(EE_CC) $(EE_CFLAGS) -o $(EE_BIN) $(EE_OBJS) $(EE_LDFLAGS) $(EE_LIBS)

$(EE_ERL): $(EE_OBJS)
$(EE_CC) -o $(EE_ERL) $(EE_OBJS) $(EE_CFLAGS) $(EE_LDFLAGS) -Wl,-r -Wl,-d
$(EE_STRIP) --strip-unneeded -R .mdebug.eabi64 -R .reginfo -R .comment $(EE_ERL)

$(EE_LIB): $(EE_OBJS)
$(EE_AR) cru $(EE_LIB) $(EE_OBJS)
73 changes: 73 additions & 0 deletions ee/elf-loader/src/loader/loader.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
# _____ ___ ____ ___ ____
# ____| | ____| | | |____|
# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
#-----------------------------------------------------------------------
# (c) 2020 Francisco Javier Trujillo Mata <[email protected]>
# Licenced under Academic Free License version 2.0
# Review ps2sdk README & LICENSE files for further details.
*/

#include <kernel.h>
#include <loadfile.h>
#include <sifrpc.h>
#include <errno.h>

//--------------------------------------------------------------
//Start of function code:
//--------------------------------------------------------------
// Clear user memory
// PS2Link (C) 2003 Tord Lindstrom ([email protected])
// (C) 2003 adresd ([email protected])
//--------------------------------------------------------------
static void wipeUserMem(void)
{
int i;
for (i = 0x100000; i < GetMemorySize(); i += 64) {
asm volatile(
"\tsq $0, 0(%0) \n"
"\tsq $0, 16(%0) \n"
"\tsq $0, 32(%0) \n"
"\tsq $0, 48(%0) \n" ::"r"(i));
}
}

//--------------------------------------------------------------
//End of func: void wipeUserMem(void)
//--------------------------------------------------------------
// *** MAIN ***
//--------------------------------------------------------------
int main(int argc, char *argv[])
{
static t_ExecData elfdata;
int ret;

if (argc < 1) { // arg1=path to ELF
return -EINVAL;
}

// Initialize
SifInitRpc(0);
wipeUserMem();

//Writeback data cache before loading ELF.
FlushCache(0);
ret = SifLoadElf(argv[0], &elfdata);
if (ret == 0) {
SifExitRpc();
FlushCache(0);
FlushCache(2);

// Following the standard the first parameter of a argv is the executable itself
return ExecPS2((void *)elfdata.epc, (void *)elfdata.gp, argc, argv);
} else {
SifExitRpc();
return -ENOENT;
}
}

//--------------------------------------------------------------
//End of func: int main(int argc, char *argv[])
//--------------------------------------------------------------
//End of file: loader.c
//--------------------------------------------------------------

0 comments on commit 202279e

Please sign in to comment.