// Originally written in C++ by Lameguy64 // Ported to plain C by Orion #include #include #include #define MAX_prg_entry_count 128 #define true (1) #define false (0) #pragma pack(push, 1) typedef struct { unsigned int magic; // 0-3 unsigned char word_size; // 4 unsigned char endianness; // 5 unsigned char elf_version; // 6 unsigned char os_abi; // 7 unsigned int unused[2]; // 8-15 unsigned short type; // 16-17 unsigned short instr_set; // 18-19 unsigned int elf_version2; // 20-23 unsigned int prg_entry_addr; // 24-27 unsigned int prg_head_pos; // 28-31 unsigned int sec_head_pos; // 32-35 unsigned int flags; // 36-39 unsigned short head_size; // 40-41 unsigned short prg_entry_size; // 42-23 unsigned short prg_entry_count; // 44-45 unsigned short sec_entry_size; // 46-47 unsigned short sec_entry_count; // 48-49 unsigned short sec_names_index; // 50-51 } ELF_HEADER; typedef struct { unsigned int seg_type; unsigned int p_offset; unsigned int p_vaddr; unsigned int undefined; unsigned int p_filesz; unsigned int p_memsz; unsigned int flags; unsigned int alignment; } PRG_HEADER; #pragma pack(pop) typedef struct { unsigned int pc0; unsigned int gp0; unsigned int t_addr; unsigned int t_size; unsigned int d_addr; unsigned int d_size; unsigned int b_addr; unsigned int b_size; unsigned int sp_addr; unsigned int sp_size; unsigned int sp; unsigned int fp; unsigned int gp; unsigned int ret; unsigned int base; } EXEC; typedef struct { char header[8]; char pad[8]; EXEC params; char license[64]; char pad2[1908]; } PSEXE; int main(int argc, char** argv) { char* in_file = NULL; char* out_file = NULL; int quiet = false; int i; FILE* fp; ELF_HEADER head; PRG_HEADER prg_heads[MAX_prg_entry_count]; unsigned int exe_taddr = 0xffffffff; unsigned int exe_haddr = 0; unsigned int exe_tsize = 0; unsigned char* binary; PSEXE exe; char *output_name; for( i=1; i [exe_file]\n" ); return 0; } if( in_file == NULL ) { printf( "No input file specified.\n" ); return EXIT_FAILURE; } fp = fopen( in_file, "rb" ); if( fp == NULL ) { printf( "Cannot open file %s.\n", in_file ); return EXIT_FAILURE; } fread( &head, 1, sizeof(head), fp ); // Check header if( head.magic != 0x464c457f ) { printf( "File is not an ELF file.\n" ); return EXIT_FAILURE; } if( head.type != 2 ) { printf( "Only executable ELF files are supported.\n" ); fclose( fp ); return EXIT_FAILURE; } if( head.instr_set != 8 ) { printf( "ELF file is not a MIPS binary.\n" ); fclose( fp ); return EXIT_FAILURE; } if( head.word_size != 1 ) { printf( "Only 32-bit ELF files are supported.\n" ); fclose( fp ); return EXIT_FAILURE; } if( head.endianness != 1 ) { printf( "Only little endian ELF files are supported.\n" ); fclose( fp ); return EXIT_FAILURE; } // Load program headers and determine binary size and load address fseek( fp, head.prg_head_pos, SEEK_SET ); for( i=0; i exe_haddr ) { exe_haddr = prg_heads[i].p_vaddr; } } exe_tsize = (exe_haddr-exe_taddr); exe_tsize += prg_heads[head.prg_entry_count-1].p_filesz; if( !quiet ) { printf( "pc:%08x t_addr:%08x t_size:%d\n", head.prg_entry_addr, exe_taddr, exe_tsize ); } // Check if load address is appropriate in main RAM locations if( ( ( exe_taddr>>24 ) == 0x0 ) || ( ( exe_taddr>>24 ) == 0x80 ) || ( ( exe_taddr>>24 ) == 0xA0 ) ) { if( ( exe_taddr&0x00ffffff ) < 65536 ) { printf( "Warning: Program text address overlaps kernel area!\n" ); } } // Pad out the size to multiples of 2KB exe_tsize = 2048*((exe_tsize+2047)/2048); // Load the binary data binary = (unsigned char*)malloc( exe_tsize ); memset( binary, 0x0, exe_tsize ); for( i=0; i