diff --git a/ee/Makefile b/ee/Makefile index e26e9a957ec..8b01a740d3b 100644 --- a/ee/Makefile +++ b/ee/Makefile @@ -6,12 +6,35 @@ # Licenced under Academic Free License version 2.0 # Review ps2sdk README & LICENSE files for further details. -SUBDIRS = startup erl kernel libcglue libpthreadglue libprofglue rpc debug \ - eedebug sbv dma graph math3d \ - packet packet2 draw libgs \ - libvux font input inputx network iopreboot \ +SUBDIRS = \ + startup \ + erl \ + kernel \ + libcglue \ + libpthreadglue \ + libprofglue \ + rpc \ + debug \ + eedebug \ + sbv \ + dma \ + graph \ + math3d \ + packet \ + packet2 \ + draw \ + libgs \ + libvux \ + font \ + input \ + inputx \ + network \ + iopreboot \ + ioprpgen \ mpeg \ - elf-loader elf-loader-nocolour elf-loader2 \ + elf-loader \ + elf-loader-nocolour \ + elf-loader2 include $(PS2SDKSRC)/Defs.make include $(PS2SDKSRC)/Rules.make diff --git a/ee/ioprpgen/Makefile b/ee/ioprpgen/Makefile new file mode 100644 index 00000000000..226eb50465e --- /dev/null +++ b/ee/ioprpgen/Makefile @@ -0,0 +1,14 @@ +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. + +EE_OBJS = ioprpgen.o + +include $(PS2SDKSRC)/Defs.make +include $(PS2SDKSRC)/ee/Rules.lib.make +include $(PS2SDKSRC)/ee/Rules.make +include $(PS2SDKSRC)/ee/Rules.release diff --git a/ee/ioprpgen/README.md b/ee/ioprpgen/README.md new file mode 100644 index 00000000000..eb3a9111e58 --- /dev/null +++ b/ee/ioprpgen/README.md @@ -0,0 +1,7 @@ +# IOPRP image generator + +This library generates IOPRP images at runtime for usage with iopreboot. + +## Usage + +See "ioprpgen" sample for usage example. diff --git a/ee/ioprpgen/include/ioprpgen.h b/ee/ioprpgen/include/ioprpgen.h new file mode 100644 index 00000000000..740df8f75e5 --- /dev/null +++ b/ee/ioprpgen/include/ioprpgen.h @@ -0,0 +1,62 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +/** + * @file + * Definitions for IOPRP generation library. + */ + +#ifndef __IOPRPGEN__ +#define __IOPRPGEN__ + +#include + +struct ioprpgen_ctx; + +typedef int (*ioprpgen_write_cb_t)(void *userdata, const struct ioprpgen_ctx *ctx, const void *buf, u32 size); + +struct ioprpgen_ctx +{ + ioprpgen_write_cb_t m_write_cb; + void *m_write_cb_userdata; +}; + +struct ioprpgen_memwrite_ctx +{ + void *m_write_ptr; + u32 m_write_ptr_size; + u32 m_write_ptr_curpos; +}; + +struct ioprpgen_entry +{ + const char *m_name; + const void *m_data; + u32 m_data_size; +}; + +/** Setup ioprpgen context + * + * @param ctx Pointer to context + * @param memwrite_ctx Pointer to memwrite context (ensure it has the same lifetime as ctx) + * @param buf Output buffer + * @param size Size of the output buffer + * @return 1 on success, 0 on failure. + */ +extern void ioprpgen_setup_membuf(struct ioprpgen_ctx *ctx, struct ioprpgen_memwrite_ctx *memwrite_ctx, void *buf, u32 size); +/** Generate IOPRP image using provided entries + * + * @param ctx Pointer to context prepared by ioprpgen_setup_membuf + * @param entries Pointer to NULL-terminated list of entries + * @return 0 on failure, other value for size + */ +extern u32 ioprpgen_write_ioprp(const struct ioprpgen_ctx *ctx, const struct ioprpgen_entry *entries); + +#endif /* __IOPRPGEN__ */ diff --git a/ee/ioprpgen/samples/Makefile b/ee/ioprpgen/samples/Makefile new file mode 100644 index 00000000000..7ccb1f332a3 --- /dev/null +++ b/ee/ioprpgen/samples/Makefile @@ -0,0 +1,12 @@ +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. + +SAMPLE_DIR = ioprpgen + +include $(PS2SDKSRC)/Defs.make +include $(PS2SDKSRC)/samples/Rules.samples diff --git a/ee/ioprpgen/samples/Makefile.sample b/ee/ioprpgen/samples/Makefile.sample new file mode 100644 index 00000000000..3b11ea215f0 --- /dev/null +++ b/ee/ioprpgen/samples/Makefile.sample @@ -0,0 +1,29 @@ +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. + +EE_BIN = ioprpgen_sample.elf +EE_OBJS = ioprpgen_sample.o sifinit_irx.o threadman_irx.o igreeting_irx.o +EE_LIBS = -lioprpgen -liopreboot -lc -lpatches -ldebug + +all: $(EE_BIN) + $(EE_STRIP) --strip-all $(EE_BIN) + +clean: + rm -f $(EE_BIN) $(EE_OBJS) *_irx.c + +%_irx.c: $(PS2SDK)/iop/irx/%.irx + bin2c $< $@ $(basename $(notdir $@)) + +run: $(EE_BIN) + ps2client execee host:$(EE_BIN) + +reset: + ps2client reset + +include $(PS2SDK)/samples/Makefile.pref +include $(PS2SDK)/samples/Makefile.eeglobal diff --git a/ee/ioprpgen/samples/ioprpgen_sample.c b/ee/ioprpgen/samples/ioprpgen_sample.c new file mode 100644 index 00000000000..1ba8ca93b75 --- /dev/null +++ b/ee/ioprpgen/samples/ioprpgen_sample.c @@ -0,0 +1,88 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern unsigned char igreeting_irx[]; +extern unsigned int size_igreeting_irx; + +extern unsigned char threadman_irx[]; +extern unsigned int size_threadman_irx; + +extern unsigned char sifinit_irx[]; +extern unsigned int size_sifinit_irx; + +int main(int ac, char **av) +{ + struct ioprpgen_ctx ctx; + struct ioprpgen_memwrite_ctx memwrite_ctx; + struct ioprpgen_entry entries[3]; + int sz; + int sz2; + void *buf; + + (void)ac; + (void)av; + + init_scr(); + scr_printf("Preparing IOPRP image\n"); + memset(&entries, 0, sizeof(entries)); + entries[0].m_name = "IGREETING"; + entries[0].m_data = igreeting_irx; + entries[0].m_data_size = size_igreeting_irx; + entries[1].m_name = "SIFINIT"; + entries[1].m_data = sifinit_irx; + entries[1].m_data_size = size_sifinit_irx; + // Ensure the end is NULL terminated + entries[2].m_name = NULL; + entries[2].m_data = NULL; + entries[2].m_data_size = 0; + ioprpgen_setup_membuf(&ctx, &memwrite_ctx, NULL, 0); + sz = ioprpgen_write_ioprp(&ctx, entries); + if ( !sz ) + { + scr_printf("Error getting size of IOPRP image\n"); + SleepThread(); + return 0; + } + buf = memalign(64, sz); + if ( !buf ) + { + scr_printf("Error allocating memory for IOPRP image\n"); + SleepThread(); + return 0; + } + ioprpgen_setup_membuf(&ctx, &memwrite_ctx, buf, sz); + sz2 = ioprpgen_write_ioprp(&ctx, entries); + if ( sz != sz2 ) + { + scr_printf("Error generating IOPRP image\n"); + SleepThread(); + return 0; + } + sceSifInitRpc(0); + SifIopRebootBuffer(buf, sz); + while ( !SifIopSync() ) + ; + free(buf); + sceSifInitRpc(0); + scr_printf("Successfully rebooted IOP with IOPRP image!\n"); + SleepThread(); + return 0; +} diff --git a/ee/ioprpgen/src/ioprpgen.c b/ee/ioprpgen/src/ioprpgen.c new file mode 100644 index 00000000000..91fd3e7c28a --- /dev/null +++ b/ee/ioprpgen/src/ioprpgen.c @@ -0,0 +1,162 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +#include +#include + +static int ioprpgen_dummy_writecb(void *userdata, const struct ioprpgen_ctx *ctx, const void *buf, u32 size) +{ + (void)userdata; + (void)ctx; + (void)buf; + + return size; +} + +static int ioprpgen_membuf_writecb(void *userdata, const struct ioprpgen_ctx *ctx, const void *buf, u32 size) +{ + struct ioprpgen_memwrite_ctx *memwrite_ctx; + + (void)ctx; + memwrite_ctx = (struct ioprpgen_memwrite_ctx *)userdata; + if ( (memwrite_ctx->m_write_ptr_curpos + size) > memwrite_ctx->m_write_ptr_size ) + return 0; + if ( buf ) + memcpy(&((u8 *)(memwrite_ctx->m_write_ptr))[memwrite_ctx->m_write_ptr_curpos], buf, size); + else + memset(&((u8 *)(memwrite_ctx->m_write_ptr))[memwrite_ctx->m_write_ptr_curpos], 0, size); + memwrite_ctx->m_write_ptr_curpos += size; + + return size; +} + +void ioprpgen_setup_membuf(struct ioprpgen_ctx *ctx, struct ioprpgen_memwrite_ctx *memwrite_ctx, void *buf, u32 size) +{ + memset(ctx, 0, sizeof(*ctx)); + if ( !buf || !size ) + { + ctx->m_write_cb = ioprpgen_dummy_writecb; + ctx->m_write_cb_userdata = NULL; + return; + } + memwrite_ctx->m_write_ptr = buf; + memwrite_ctx->m_write_ptr_size = size; + memwrite_ctx->m_write_ptr_curpos = 0; + ctx->m_write_cb = ioprpgen_membuf_writecb; + ctx->m_write_cb_userdata = (void *)memwrite_ctx; +} + +struct ioprp_romdir_entry +{ + char m_name[10]; + u16 m_extinfo_size; + u32 m_data_size; +}; + +struct ioprp_extinfo_entry +{ + u16 m_value; + u8 m_extlen; + u8 m_type; +}; + +static int +ioprpgen_write_romdir_entry(const struct ioprpgen_ctx *ctx, const char *name, u32 extinfo_size, u32 data_size) +{ + struct ioprp_romdir_entry ent; + memset(&ent, 0, sizeof(ent)); + if ( name ) + { + strncpy(ent.m_name, name, sizeof(ent.m_name) - 1); + ent.m_name[sizeof(ent.m_name) - 1] = 0; + } + ent.m_extinfo_size = extinfo_size; + ent.m_data_size = data_size; + return ctx->m_write_cb(ctx->m_write_cb_userdata, ctx, &ent, sizeof(ent)) == sizeof(ent); +} + +u32 ioprpgen_write_ioprp(const struct ioprpgen_ctx *ctx, const struct ioprpgen_entry *entries) +{ + int entry_count; + int i; + u32 romdir_size; + u32 extinfo_size; + u32 total_size; + + entry_count = 0; + for ( i = 0; !!entries[i].m_name; i += 1 ) + { + if ( + !strcmp(entries[i].m_name, "RESET") || !strcmp(entries[i].m_name, "ROMDIR") + || !strcmp(entries[i].m_name, "EXTINFO") ) + return 0; + entry_count += 1; + } + if ( !ioprpgen_write_romdir_entry(ctx, "RESET", 0, 0) ) + return 0; + romdir_size = 16 * (entry_count + 4); + if ( !ioprpgen_write_romdir_entry(ctx, "ROMDIR", 0, romdir_size) ) + return 0; + total_size = romdir_size; + extinfo_size = 4 * entry_count; + if ( !ioprpgen_write_romdir_entry(ctx, "EXTINFO", 0, extinfo_size) ) + return 0; + for ( i = 0; i < entry_count; i += 1 ) + if ( !ioprpgen_write_romdir_entry(ctx, entries[i].m_name, 4, entries[i].m_data_size) ) + return 0; + if ( !ioprpgen_write_romdir_entry(ctx, NULL, 0, 0) ) + return 0; + { + u32 cur_entry_size; + u32 padding_size; + u32 cur_padding_size; + struct ioprp_extinfo_entry extinfo_entry; + + // These values are needed in order for UDNL to select the module + extinfo_entry.m_value = 0xFFFF; + extinfo_entry.m_extlen = 0; + extinfo_entry.m_type = 2; + cur_entry_size = 0; + for ( i = 0; i < entry_count; i += 1 ) + { + u32 cur_value_size; + + cur_value_size = ctx->m_write_cb(ctx->m_write_cb_userdata, ctx, &extinfo_entry, sizeof(extinfo_entry)); + if ( cur_value_size != sizeof(extinfo_entry) ) + return 0; + cur_entry_size += cur_value_size; + } + if ( cur_entry_size != extinfo_size ) + return 0; + total_size += cur_entry_size; + padding_size = ((((cur_entry_size - 1) >> 4) + 1) << 4) - cur_entry_size; + cur_padding_size = ctx->m_write_cb(ctx->m_write_cb_userdata, ctx, NULL, padding_size); + if ( cur_padding_size != padding_size ) + return 0; + total_size += cur_padding_size; + } + for ( i = 0; i < entry_count; i += 1 ) + { + u32 cur_entry_size; + u32 padding_size; + u32 cur_padding_size; + + cur_entry_size = ctx->m_write_cb(ctx->m_write_cb_userdata, ctx, entries[i].m_data, entries[i].m_data_size); + if ( cur_entry_size != entries[i].m_data_size ) + return 0; + total_size += cur_entry_size; + padding_size = ((((cur_entry_size - 1) >> 4) + 1) << 4) - cur_entry_size; + cur_padding_size = ctx->m_write_cb(ctx->m_write_cb_userdata, ctx, NULL, padding_size); + if ( cur_padding_size != padding_size ) + return 0; + total_size += cur_padding_size; + } + return total_size; +}