From 702bb601fb5712e2ae962a34b89204c646fe98f5 Mon Sep 17 00:00:00 2001 From: lameguy64 Date: Sat, 4 May 2024 18:55:05 +0800 Subject: Included PSn00bDBG-mk2 monitor and test utility --- indev/psn00bdbg-mk2/testutil/exec.c | 413 ++++++++++++++++++++++++++++++++++++ 1 file changed, 413 insertions(+) create mode 100644 indev/psn00bdbg-mk2/testutil/exec.c (limited to 'indev/psn00bdbg-mk2/testutil/exec.c') diff --git a/indev/psn00bdbg-mk2/testutil/exec.c b/indev/psn00bdbg-mk2/testutil/exec.c new file mode 100644 index 0000000..bcd91ef --- /dev/null +++ b/indev/psn00bdbg-mk2/testutil/exec.c @@ -0,0 +1,413 @@ +#include +#include +#include +#include "exec.h" + +#define MAX_prg_entry_count 128 + +#pragma pack(push, 1) + +typedef struct _ELF_HEADER { + + 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 _PRG_HEADER { + 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 _PSEXE { + char header[8]; + char pad[8]; + EXEC params; + char license[64]; + char pad2[1908]; +} PSEXE; + +typedef struct _EXEPARAM { + EXEC params; + unsigned int crc32; + unsigned int flags; +} EXEPARAM; + +typedef struct _BINPARAM { + int size; + unsigned int addr; + unsigned int crc32; +} BINPARAM; + + +void* loadELF(FILE* fp, EXEC* param) +{ + int i; + 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; + size_t read_n; + + fseek(fp, 0, SEEK_SET); + read_n = fread(&head, 1, sizeof(head), fp); + + // Check header + if( head.magic != 0x464c457f ) { + + printf("File is neither a PS-EXE, CPE or ELF binary.\n"); + return NULL; + + } + + if( head.type != 2 ) { + + printf("Only executable ELF files are supported.\n"); + return NULL; + + } + + if( head.instr_set != 8 ) { + + printf("ELF file is not a MIPS binary.\n"); + return NULL; + + } + + if( head.word_size != 1 ) { + + printf("Only 32-bit ELF files are supported.\n"); + return NULL; + + } + + if( head.endianness != 1 ) { + + printf("Only little endian ELF files are supported.\n"); + return NULL; + + } + + + // 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; + + + // 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; ipc0 = head.prg_entry_addr; + param->t_addr = exe_taddr; + param->t_size = exe_tsize; + + return binary; + +} + +void* loadCPE(FILE* fp, EXEC* param) { + + int i, val, exe_size = 0; + unsigned int uv, exe_entry = 0; + unsigned int *addr_list = NULL; + int addr_list_len = 0; + char* exe_buff; + unsigned int addr_upper=0; + unsigned int addr_lower=0; + size_t read_n; + + // Check CPE magic word + fseek(fp, 0, SEEK_SET); + read_n = fread(&val, 1, 4, fp); + + if( val != 0x01455043 ) + { + return NULL; + } + + // Clear EXEC parameters + memset(param, 0x0, sizeof(EXEC)); + + // Begin parsing CPE data + val = 0; + read_n = fread(&val, 1, 1, fp); + + while( val ) + { + switch( val ) + { + case 0x1: // Binary chunk + + read_n = fread(&uv, 1, 4, fp); + read_n = fread(&val, 1, 4, fp); + + addr_list_len++; + addr_list = (unsigned int*)realloc(addr_list, + sizeof(unsigned int)*addr_list_len); + + addr_list[addr_list_len-1] = uv; + exe_size += val; + + fseek(fp, val, SEEK_CUR); + break; + + case 0x3: // Set register, ignored + + val = 0; + read_n = fread(&val, 1, 2, fp); + + if( val != 0x90 ) + { + printf("Warning: Unknown SETREG code: %d\n", val); + } + + read_n = fread(&exe_entry, 1, 4, fp); + break; + + case 0x8: // Select unit, ignored + + val = 0; + read_n = fread(&val, 1, 1, fp); + break; + + default: + + printf("Unknown chunk found: %d\n", val); + free(addr_list); + return NULL; + + } + + // Read next code + val = 0; + read_n = fread(&val, 1, 1, fp); + + } + + // Begin loading the executable data + + // Find the highest chunk address + for(i=0; i addr_upper ) { + + addr_upper = addr_list[i]; + + } + + } + + // Find the lowest chunk address + addr_lower = addr_upper; + + for(i=0; ipc0 = exe_entry; + param->t_addr = addr_lower; + param->t_size = exe_size; + + return exe_buff; + +} + +void *loadExecutable(const char* exefile, EXEC *param) { + + PSEXE exe; + unsigned char* buffer; + + FILE* fp = fopen(exefile, "rb"); + + if( fp == NULL ) + { + printf("File not found.\n"); + return(NULL); + } + + // Load PS-EXE header + if( fread(&exe, 1, sizeof(PSEXE), fp) != sizeof(PSEXE) ) + { + printf("Read error or invalid file.\n"); + fclose(fp); + return(NULL); + } + + // Check file ID + if( strcmp(exe.header, "PS-X EXE") ) { + + // If not PS-EXE, try loading it as CPE + buffer = (unsigned char*)loadCPE(fp, param); + + if( buffer == NULL ) { + + // If not CPE, try loading it as ELF + buffer = (unsigned char*)loadELF(fp, param); + + if( buffer == NULL ) { + + fclose(fp); + return(NULL); + + } + + } + + } else { + + // Load PS-EXE body, simple + buffer = (unsigned char*)malloc(param->t_size); + + if( fread(buffer, 1, param->t_size, fp) != param->t_size ) { + + printf("Incomplete file or read error.\n"); + free(buffer); + fclose(fp); + + return(NULL); + + } + + memcpy(param, &exe.params, sizeof(EXEC)); + + } + + // Done with the file + fclose(fp); + + return(buffer); +} -- cgit v1.2.3