aboutsummaryrefslogtreecommitdiff
path: root/tools/util/elf2cpe.c
diff options
context:
space:
mode:
authorJohn Wilbert M. Villamor <lameguy64@gmail.com>2021-02-18 13:31:17 +0800
committerJohn Wilbert M. Villamor <lameguy64@gmail.com>2021-02-18 13:31:17 +0800
commit63419d9cc07c56234d0f61a80f32105b192aec8e (patch)
tree827cf4d134cf3b4618d0167cc912f3efd47c3aac /tools/util/elf2cpe.c
parent1625072293c40ba3cb819f8f48aeb4b64e93b133 (diff)
downloadpsn00bsdk-63419d9cc07c56234d0f61a80f32105b192aec8e.tar.gz
Lots of makefile corrections, improved build and toolchain instructions, added elf2cpe converter, fixed typo in plasma_tbl.h of n00bdemo example
Diffstat (limited to 'tools/util/elf2cpe.c')
-rw-r--r--tools/util/elf2cpe.c251
1 files changed, 251 insertions, 0 deletions
diff --git a/tools/util/elf2cpe.c b/tools/util/elf2cpe.c
new file mode 100644
index 0000000..4379f4a
--- /dev/null
+++ b/tools/util/elf2cpe.c
@@ -0,0 +1,251 @@
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+#include "elf.h"
+
+#define MAX_prg_entry_count 128
+
+#ifndef false
+#define false 0
+#endif
+
+#ifndef true
+#define true 1
+#endif
+
+char *in_file = NULL;
+char *out_file = NULL;
+
+int quiet;
+
+int copydata( FILE *in, FILE *out, int len )
+{
+ char buff[8192];
+ int i,readlen;
+
+ while( len > 0 )
+ {
+ readlen = len;
+ if( readlen > 8192 )
+ {
+ readlen = 8192;
+ }
+
+ i = fread( buff, 1, readlen, in );
+ fwrite( buff, 1, i, out );
+
+ if( i < readlen )
+ {
+ break;
+ }
+ len -= readlen;
+ }
+
+ return( 0 );
+
+} /* copydata */
+
+int convertELF( void )
+{
+ ELF_HEADER head;
+ PRG_HEADER prg_heads[MAX_prg_entry_count];
+
+ int i;
+ char *output_name;
+
+ FILE *in_fp;
+ FILE *out_fp;
+
+ /* Generate output filename if no output is specified */
+ if( out_file )
+ {
+ output_name = out_file;
+ }
+ else
+ {
+ char *ptr;
+
+ output_name = strdup( in_file );
+
+ ptr = &output_name[strlen(output_name)];
+ while (ptr != output_name)
+ {
+ if (*ptr == '.')
+ break;
+ else
+ ptr--;
+ }
+
+ if( ptr != output_name )
+ {
+ strcpy( ptr, ".cpe" );
+ }
+ else
+ {
+ strcat( ptr, ".cpe" );
+ }
+ }
+
+ if( !out_file )
+ {
+ free( output_name );
+ }
+
+ if( !( in_fp = fopen( in_file, "rb" ) ) )
+ {
+ printf( "Cannot open input file.\n" );
+ return( -1 );
+ }
+
+ /* read ELF header */
+ fread( &head, 1, sizeof(head), in_fp );
+
+ /* test header to make sure it is valid */
+ if( head.magic != 0x464c457f )
+ {
+ printf( "File is not an ELF file.\n" );
+ fclose( in_fp );
+ return( -1 );
+ }
+
+ if( head.type != 2 )
+ {
+ printf( "Only executable ELF files are supported.\n" );
+ fclose( in_fp );
+ return( -1 );
+ }
+
+ if( head.instr_set != 8 )
+ {
+ printf( "ELF file is not a MIPS binary.\n" );
+ fclose( in_fp );
+ return( -1 );
+ }
+
+ if( head.word_size != 1 )
+ {
+ printf( "Only 32-bit ELF files are supported.\n" );
+ fclose( in_fp );
+ return( -1 );
+ }
+
+ if( head.endianness != 1 )
+ {
+ printf( "Only little endian ELF files are supported.\n" );
+ fclose( in_fp );
+ return( -1 );
+ }
+
+ /* read program headers */
+ fseek( in_fp, head.prg_head_pos, SEEK_SET );
+ fread( prg_heads, sizeof( PRG_HEADER ), head.prg_entry_count, in_fp );
+
+ if( !quiet )
+ {
+ printf( "pc:%08x\n", head.prg_entry_addr );
+ }
+
+ /* create the CPE file */
+ printf( "%s\n", output_name );
+ if( !( out_fp = fopen( output_name, "wb" ) ) )
+ {
+ printf( "Cannot create output file.\n" );
+ return( -1 );
+ }
+
+ /* create file header */
+ fputs( "CPE", out_fp );
+ fputc( 0x01, out_fp );
+
+ /* select unit 0 */
+ fputc( 0x08, out_fp ); /* chunk ID */
+ fputc( 0x00, out_fp ); /* unit number */
+
+ /* set entrypoint */
+ fputc( 0x03, out_fp ); /* chunk ID */
+ fputc( 0x90, out_fp ); /* entry point type */
+ fputc( 0x00, out_fp );
+ fwrite( &head.prg_entry_addr, 1, 4, out_fp );
+
+ /* copy the program chunks */
+ for( i=0; i<head.prg_entry_count; i++ )
+ {
+ if( prg_heads[i].flags == 4 )
+ {
+ continue;
+ }
+
+ /* seek to location of program chunk */
+ fseek( in_fp, prg_heads[i].p_offset, SEEK_SET );
+
+ /* create load chunk */
+ fputc( 0x01, out_fp ); /* chunk ID */
+ fwrite( &prg_heads[i].p_vaddr, 1, 4, out_fp ); /* load address */
+ fwrite( &prg_heads[i].p_filesz, 1, 4, out_fp ); /* load length */
+
+ /* copy the chunk data */
+ copydata( in_fp, out_fp, prg_heads[i].p_filesz );
+ }
+
+ /* end of file chunk */
+ fputc( 0x00, out_fp );
+
+ /* close files */
+ fclose( in_fp );
+ fclose( out_fp );
+
+ return( 0 );
+
+} /* convertELF */
+
+int main( int argc, char *argv[] )
+{
+ int i;
+
+ quiet = false;
+
+ /* parse program arguments */
+ for( i=1; i<argc; i++ )
+ {
+ if( strcasecmp( "-q", argv[i] ) == 0 )
+ {
+ quiet = true;
+ }
+ else
+ {
+ if( in_file == NULL )
+ {
+ in_file = argv[i];
+ }
+ else if( out_file == NULL )
+ {
+ out_file = argv[i];
+ }
+ }
+ }
+
+ /* print banner if not in quiet mode */
+ if( !quiet )
+ {
+ printf( "PSn00bSDK elf2cpe - Experimental ELF to CPE executable "
+ "converter\n" );
+ printf( "2021 Meido-Tek Productions\n\n" );
+ }
+
+ /* print usage parameters if no arguments specified */
+ if( argc == 1 )
+ {
+ printf( "Usage:\n" );
+ printf( " elf2cpe [-q] <elf_file> [cpe_file]\n" );
+ return( 0 );
+ }
+
+ if( !in_file )
+ {
+ printf( "No input file specified.\n" );
+ return( 0 );
+ }
+
+ return( convertELF() );
+
+} /* main */ \ No newline at end of file