//----------------------------------------------------------------------- static void show_extdefs(linput_t *li, uint32 offset, uint32 length) { if ( offset == 0 || length == 0 ) return; qlseek(li, offset); inf.specsegs = 1; int segsize = 4 * h.num_externals; sel_t sel = h.num_segs+1; set_selector(sel, 0); xea = freechunk(inf.maxEA, segsize, -15); add_segm(sel, xea, xea+segsize, "XTRN", "XTRN"); set_segm_addressing(getseg(xea), true); int n = 0; for ( int i=0; i < length; n++ ) { extdef p; const int size = offsetof(extdef, allocate_len); lread(li, &p, size); p.allocate_len.len_4 = 0; if ( p.allocate ) { ask_for_feedback("extdef.allocate\n"); lread(li, &p.allocate_len.len_4, sizeof(p.allocate_len.len_4)); } int nlen = read_pstring(li, p.sym_name, sizeof(p.sym_name)); i += size + 1 + nlen; ea_t a = xea + 4*n; set_name(a, p.sym_name); if ( p.allocate ) put_long(a, p.allocate_len.len_4); } }
void create_load_seg(linput_t *li, ea_t start, ea_t end, int type, const char *name) { add_segm(0, start, end, name, ""); switch (type) { case 1: for (ea_t i = 0; i < end-start; i+=4) { uint32 data; qlread(li, &data, 4); put_long(start+i, data); } break; case 2: // Word Swap for (ea_t i = 0; i < end-start; i+=4) { uint16 data, data2; qlread(li, &data, 2); qlread(li, &data2, 2); put_long(start+i, (data << 16) | data2); } break; case 3: // Reverse order for (ea_t i = 0; i < end-start; i+=4) { uint32 data; qlread(li, &data, 4); data = swap32(data); put_long(end-i-1, data); } break; default: break; } }
//-------------------------------------------------------------------------- static void load_subspaces(linput_t *li, header &h, long fpos, int n) { if ( !n ) return; char buf[MAXSTR]; for ( int i=0; i < n; i++ ) { subspace_dictionary_record sr; qlseek(li, fpos + i*sizeof(sr)); lread(li, &sr, sizeof(sr)); sr.swap(); if ( !sr.is_loadable() || !sr.subspace_length ) continue; if ( sr.fixup_request_quantity ) complain_fixup(); ea_t start = sr.subspace_start; ea_t end = start + sr.initialization_length; file2base(li, sr.file_loc_init_value, start, end, FILEREG_PATCHABLE); end = start + sr.subspace_length; char *name = get_space_name(li, h, sr.name.n_strx, buf, sizeof(buf)); set_selector(i, 0); const char *sclass = strstr(name, "CODE") ? CLASS_CODE : CLASS_DATA; add_segm(i, start, end, name, sclass); if ( i == first_text_subspace_idx ) first_text_subspace_fpos = sr.file_loc_init_value; // sr.alignment, } }
//----------------------------------------------------------------------- static void show_segdefs(linput_t *li, uint32 offset, uint32 length) { if ( offset == 0 || length == 0 ) return; qlseek(li, offset); int n = 0; for ( int i=0; i < length; ) { segdef s; const int size = offsetof(segdef, combine_name); lread(li, &s, size); int nlen = read_pstring(li, s.combine_name, sizeof(s.combine_name)); i += size + 1 + nlen; n++; const char *sname = s.combine_name; const char *sclas = sname; if ( strnicmp(sname, "CODE", 4) == 0 ) sclas = "CODE"; if ( strnicmp(sname, "DATA", 4) == 0 ) sclas = "DATA"; if ( strnicmp(sname, "CONST", 5) == 0 ) sclas = "CONST"; if ( stricmp(sname, "STACK") == 0 ) sclas = "STACK"; if ( strchr(sname, ':') != NULL ) continue; int segsize = s.slimit + 1; if ( strcmp(sname, "DATA") == 0 ) dsel = n; set_selector(n, 0); ea_t ea = freechunk(inf.maxEA, segsize, -(1<<s.align)); add_segm(n, ea, ea+segsize, sname, sclas); set_segm_addressing(getseg(ea), true); if ( strcmp(sclas, "STACK") == 0 ) doByte(ea, segsize); } }
//---------------------------------------------------------------------- // // creates an SRAM segment, if available on cartridge // static void create_sram_segment( void ) { bool success = add_segm( 0, SRAM_START_ADDRESS, SRAM_START_ADDRESS + SRAM_SIZE, "SRAM", NULL ) == 1; msg("creating SRAM segment..%s", success ? "ok!\n" : "failure!\n"); if(!success) return; set_segm_addressing( getseg( SRAM_START_ADDRESS ), 0 ); }
//---------------------------------------------------------------------- // // creates an EXPANSION ROM segment, I don't know when it is used // static void create_exprom_segment( void ) { bool success = add_segm( 0, EXPROM_START_ADDRESS, EXPROM_START_ADDRESS + EXPROM_SIZE, "EXP_ROM", NULL ) == 1; msg("creating EXP_ROM segment..%s", success ? "ok!\n" : "failure!\n"); if(!success) return; set_segm_addressing( getseg( EXPROM_START_ADDRESS ), 0 ); }
//---------------------------------------------------------------------- // // creates a ROM segment where all the code is being loaded to // static void create_rom_segment( void ) { bool success = add_segm( 0, ROM_START_ADDRESS, ROM_START_ADDRESS + ROM_SIZE, "ROM", CLASS_CODE ) == 1; msg("creating ROM segment..%s", success ? "ok!\n" : "failure!\n"); if(!success) return; set_segm_addressing( getseg( ROM_START_ADDRESS ), 0 ); }
//-------------------------------------------------------------------------- // Create a section. static void create_section(ushort sel, ea_t startEA, ea_t endEA, const char *name, const char *classname) { set_selector(sel, 0); if( !add_segm(sel, startEA, endEA, name, classname) ) loader_failure(); segment_t *s = getseg(startEA); set_arm_segm_flags(startEA, 2 << 10); // alignment s->update(); }
//---------------------------------------------------------------------- // // loads a 512 byte trainer (located at file offset INES_HDR_SIZE) // to TRAINER_START_ADDRESS // static void load_trainer( linput_t *li ) { if( !INES_MASK_SRAM( hdr.rom_control_byte_0 ) ) { bool success = add_segm( 0, TRAINER_START_ADDRESS, TRAINER_START_ADDRESS + TRAINER_SIZE, "TRAINER", CLASS_CODE ) == 1; msg("creating TRAINER segment..%s", success ? "ok!\n" : "failure!\n"); set_segm_addressing( getseg( TRAINER_START_ADDRESS ), 0 ); } file2base(li, INES_HDR_SIZE, TRAINER_START_ADDRESS, TRAINER_START_ADDRESS + TRAINER_SIZE, FILEREG_PATCHABLE); }
//---------------------------------------------------------------------- // // creates a RAM segment // static void create_ram_segment( void ) { bool success = add_segm( 0, RAM_START_ADDRESS, RAM_START_ADDRESS + RAM_SIZE, "RAM", NULL ) == 1; msg("creating RAM segment..%s", success ? "ok!\n" : "failure!\n"); if(!success) return; set_segm_addressing( getseg( RAM_START_ADDRESS ), 0 ); // how do I properly initialize a segment ? //for( unsigned int ea = SRAM_START_ADDRESS; ea<= SRAM_START_ADDRESS + SRAM_SIZE; ea++ ) // put_byte( ea, 0 ); }
//---------------------------------------------------------------------- // // creates an I/O registers segment and names all io registers // static void create_ioreg_segment( void ) { bool success = add_segm( 0, IOREGS_START_ADDRESS, IOREGS_START_ADDRESS + IOREGS_SIZE, "IO_REGS", NULL ) == 1; msg("creating IO_REGS segment..%s", success ? "ok!\n" : "failure!\n"); if(!success) return; set_segm_addressing( getseg( IOREGS_START_ADDRESS ), 0 ); define_item( PPU_CR_1_ADDRESS, PPU_CR_1_SIZE, PPU_CR_1_SHORT_DESCRIPTION, PPU_CR_1_COMMENT ); define_item( PPU_CR_2_ADDRESS, PPU_CR_2_SIZE, PPU_CR_2_SHORT_DESCRIPTION, PPU_CR_2_COMMENT ); define_item( PPU_SR_ADDRESS, PPU_SR_SIZE, PPU_SR_SHORT_DESCRIPTION, PPU_SR_COMMENT ); define_item( SPR_RAM_AR_ADDRESS, SPR_RAM_AR_SIZE, SPR_RAM_AR_SHORT_DESCRIPTION, SPR_RAM_AR_COMMENT ); define_item( SPR_RAM_IOR_ADDRESS, SPR_RAM_IOR_SIZE, SPR_RAM_IOR_SHORT_DESCRIPTION, SPR_RAM_IOR_COMMENT ); define_item( VRAM_AR_1_ADDRESS, VRAM_AR_1_SIZE, VRAM_AR_1_SHORT_DESCRIPTION, VRAM_AR_1_COMMENT ); define_item( VRAM_AR_2_ADDRESS, VRAM_AR_2_SIZE, VRAM_AR_2_SHORT_DESCRIPTION, VRAM_AR_2_COMMENT ); define_item( VRAM_IOR_ADDRESS, VRAM_IOR_SIZE, VRAM_IOR_SHORT_DESCRIPTION, VRAM_IOR_COMMENT ); define_item( PAPU_PULSE_1_CR_ADDRESS, PAPU_PULSE_1_CR_SIZE, PAPU_PULSE_1_CR_SHORT_DESCRIPTION, PAPU_PULSE_1_CR_COMMENT ); define_item( PAPU_PULSE_1_RCR_ADDRESS, PAPU_PULSE_1_RCR_SIZE, PAPU_PULSE_1_RCR_SHORT_DESCRIPTION, PAPU_PULSE_1_RCR_COMMENT ); define_item( PAPU_PULSE_1_FTR_ADDRESS, PAPU_PULSE_1_FTR_SIZE, PAPU_PULSE_1_FTR_SHORT_DESCRIPTION, PAPU_PULSE_1_FTR_COMMENT ); define_item( PAPU_PULSE_1_CTR_ADDRESS, PAPU_PULSE_1_CTR_SIZE, PAPU_PULSE_1_CTR_SHORT_DESCRIPTION, PAPU_PULSE_1_CTR_COMMENT ); define_item( PAPU_PULSE_2_CR_ADDRESS, PAPU_PULSE_2_CR_SIZE, PAPU_PULSE_2_CR_SHORT_DESCRIPTION, PAPU_PULSE_2_CR_COMMENT ); define_item( PAPU_PULSE_2_RCR_ADDRESS, PAPU_PULSE_2_RCR_SIZE, PAPU_PULSE_2_RCR_SHORT_DESCRIPTION, PAPU_PULSE_2_RCR_COMMENT ); define_item( PAPU_PULSE_2_FTR_ADDRESS, PAPU_PULSE_2_FTR_SIZE, PAPU_PULSE_2_FTR_SHORT_DESCRIPTION, PAPU_PULSE_2_FTR_COMMENT ); define_item( PAPU_PULSE_2_CTR_ADDRESS, PAPU_PULSE_2_CTR_SIZE, PAPU_PULSE_2_CTR_SHORT_DESCRIPTION, PAPU_PULSE_2_CTR_COMMENT ); define_item( PAPU_TRIANGLE_CR_1_ADDRESS, PAPU_TRIANGLE_CR_1_SIZE, PAPU_TRIANGLE_CR_1_SHORT_DESCRIPTION, PAPU_TRIANGLE_CR_1_COMMENT ); define_item( PAPU_TRIANGLE_CR_2_ADDRESS, PAPU_TRIANGLE_CR_2_SIZE, PAPU_TRIANGLE_CR_2_SHORT_DESCRIPTION, PAPU_TRIANGLE_CR_2_COMMENT ); define_item( PAPU_TRIANGLE_FR_1_ADDRESS, PAPU_TRIANGLE_FR_1_SIZE, PAPU_TRIANGLE_FR_1_SHORT_DESCRIPTION, PAPU_TRIANGLE_FR_1_COMMENT ); define_item( PAPU_TRIANGLE_FR_2_ADDRESS, PAPU_TRIANGLE_FR_2_SIZE, PAPU_TRIANGLE_FR_2_SHORT_DESCRIPTION, PAPU_TRIANGLE_FR_2_COMMENT ); define_item( PAPU_NOISE_CR_1_ADDRESS, PAPU_NOISE_CR_1_SIZE, PAPU_NOISE_CR_1_SHORT_DESCRIPTION, PAPU_NOISE_CR_1_COMMENT ); define_item( PAPU_NOISE_CR_2_ADDRESS, PAPU_NOISE_CR_2_SIZE, PAPU_NOISE_CR_2_SHORT_DESCRIPTION, PAPU_NOISE_CR_2_COMMENT ); define_item( PAPU_NOISE_FR_1_ADDRESS, PAPU_NOISE_FR_1_SIZE, PAPU_NOISE_FR_1_SHORT_DESCRIPTION, PAPU_NOISE_FR_1_COMMENT ); define_item( PAPU_NOISE_FR_2_ADDRESS, PAPU_NOISE_FR_2_SIZE, PAPU_NOISE_FR_2_SHORT_DESCRIPTION, PAPU_NOISE_FR_2_COMMENT ); define_item( PAPU_DM_CR_ADDRESS, PAPU_DM_CR_SIZE, PAPU_DM_CR_SHORT_DESCRIPTION, PAPU_DM_CR_COMMENT ); define_item( PAPU_DM_DAR_ADDRESS, PAPU_DM_DAR_SIZE, PAPU_DM_DAR_SHORT_DESCRIPTION, PAPU_DM_DAR_COMMENT ); define_item( PAPU_DM_AR_ADDRESS, PAPU_DM_AR_SIZE, PAPU_DM_AR_SHORT_DESCRIPTION, PAPU_DM_AR_COMMENT ); define_item( PAPU_DM_DLR_ADDRESS, PAPU_DM_DLR_SIZE, PAPU_DM_DLR_SHORT_DESCRIPTION, PAPU_DM_DLR_COMMENT ); define_item( PAPU_SV_CSR_ADDRESS, PAPU_SV_CSR_SIZE, PAPU_SV_CSR_SHORT_DESCRIPTION, PAPU_SV_CSR_COMMENT ); define_item( SPRITE_DMAR_ADDRESS, SPRITE_DMAR_SIZE, SPRITE_DMAR_SHORT_DESCRIPTION, SPRITE_DMAR_COMMENT ); define_item( JOYPAD_1_ADDRESS, JOYPAD_1_SIZE, JOYPAD_1_SHORT_DESCRIPTION, JOYPAD_1_COMMENT ); define_item( JOYPAD_2_ADDRESS, JOYPAD_2_SIZE, JOYPAD_2_SHORT_DESCRIPTION, JOYPAD_2_COMMENT ); }
//---------------------------------------------------------------------- static void process_loader(char *ptr, pef_section_t *sec, int nsec) { int i; pef_loader_t &pl = *(pef_loader_t *)ptr; pef_library_t *pil = (pef_library_t *)(&pl + 1); swap_pef_loader(pl); uint32 *impsym = (uint32 *)(pil + pl.importLibraryCount); pef_reloc_header_t *prh = (pef_reloc_header_t *)(impsym + pl.totalImportedSymbolCount); uint16 *relptr = (uint16 *)(ptr + pl.relocInstrOffset); uint32 *hash = (uint32 *)(ptr + pl.exportHashOffset); uint32 hashsize = (1 << pl.exportHashTablePower); uint32 *keytable = hash + hashsize; pef_export_t *pe = (pef_export_t *)(keytable + pl.exportedSymbolCount); #if !__MF__ for ( i=0; i < pl.importLibraryCount; i++ ) swap_pef_library(pil[i]); for ( i=0; i < pl.relocSectionCount; i++ ) swap_pef_reloc_header(prh[i]); for ( i=0; i < pl.exportedSymbolCount; i++ ) swap_pef_export(pe[i]); #endif char *stable = ptr + pl.loaderStringsOffset; if ( pl.totalImportedSymbolCount != 0 ) { uint32 size = pl.totalImportedSymbolCount*4; ea_t undef = freechunk(inf.maxEA, size, -0xF); ea_t end = undef + size; set_selector(nsec+1, 0); if(!add_segm(nsec+1, undef, end, "IMPORT", "XTRN")) loader_failure(); for ( i=0; i < pl.importLibraryCount; i++ ) { ea_t ea = undef + 4*pil[i].firstImportedSymbol; add_long_cmt(ea, 1, "Imports from library %s", stable+pil[i].nameOffset); if ( pil[i].options & PEF_LIB_WEAK ) add_long_cmt(ea, 1, "Library is weak"); } inf.specsegs = 1; for ( i=0; i < pl.totalImportedSymbolCount; i++ ) { uint32 sym = mflong(impsym[i]); uchar sclass = uchar(sym >> 24); ea_t ea = undef+4*i; set_name(ea, get_impsym_name(stable,impsym,i)); if ( (sclass & kPEFWeak) != 0 ) make_name_weak(ea); doDwrd(ea,4); put_long(ea, 0); impsym[i] = (uint32)ea; } }
void ScuLoadState (linput_t *li, ea_t *pc, int size) { scuregs_struct Scu; scudspregs_struct ScuDsp; qlread(li, (void *)&Scu, sizeof(Scu)); qlread(li, (void *)&ScuDsp, sizeof(ScuDsp)); if (pc) { *pc = ScuDsp.PC; ea_t start=0, end=0x100; add_segm(0, start, end, "RAM", ""); for (ea_t i = 0; i < end-start; i++) put_long(start+i, ScuDsp.ProgramRam[i]); } }
//------------------------------------------------------------------ static const char *idaapi parse_area_line(const char *line, char *buf, size_t bufsize) { char word[MAXSTR]; char aclass[MAXSTR]; ea_t ea1, ea2; if ( sscanf(line, "area %s %s %" FMT_EA "i:%" FMT_EA "i", aclass, word, &ea1, &ea2) == 4 ) { int ram = 0; int rom = 0; int eprom = 0; int eeprom = 0; static const char format[] = "RAM=%d ROM=%d EPROM=%d " CUSTOM1 "=%d"; sscanf(buf, format, &ram, &rom, &eprom, &eeprom); int size = ea2 - ea1; if ( stristr(word, "RAM") != NULL ) ram += size; else if ( stristr(word, CUSTOM1) != NULL ) eeprom += size; else if ( stristr(word, "EPROM") != NULL ) eprom += size; else if ( stristr(word, "ROM") != NULL ) rom += size; if ( ram || rom || eeprom || eeprom ) qsnprintf(buf, bufsize, format, ram, rom, eprom, eeprom); else buf[0] = '\0'; if ( (respect_info & IORESP_AREA) != 0 && get_segm_qty() != 0 ) { #ifdef I8051 if ( ( stristr(word, "FSR") != NULL ) ||( stristr(word, "RAM") != NULL )) { AdditionalSegment( ea2-ea1, ea1, word ); } else #endif { sel_t sel = allocate_selector(0); add_segm(sel, ea1, ea2, word, aclass); } if ( ea2-ea1 > 0xFFFF ) set_segm_addressing(getseg(ea1), true); } return NULL; } return "syntax error"; }
//---------------------------------------------------------------------------- static bool map_psram(linput_t *li, uint32 psram_start_in_file) { bool succeeded = false; segment_t s; s.startEA = 0x00000; s.endEA = 0x10000; s.sel = allocate_selector(s.startEA >> 4); if ( !file2base(li, psram_start_in_file, s.startEA, s.endEA, FILEREG_PATCHABLE) ) loader_failure("Failed mapping 0x%x -> [0x%a, 0x%a)\n", psram_start_in_file, s.startEA, s.endEA); succeeded = add_segm(s.sel, s.startEA, s.endEA, "RAM", NULL); if ( succeeded ) succeeded = true; else loader_failure("Failed adding RAM segment\n"); return succeeded; }
static void copy(ea_t &ea, ea_t &top) { if ( sea == BADADDR ) { if ( neflag & NEF_SEGS ) { const char *sname = iscode ? "CODE" : "DATA"; sel = setup_selector(0); add_segm(sel, ea, top, sname, sname); } sea = ea; eea = top; } else { if ( eea < top ) { eea = top; set_segm_end(sea, eea, SEGMOD_KILL); } } mem2base(bytes, ea, top, -1); }
/* * this is where we finally load the file and create segments and other processing */ void idaapi load_file(linput_t *li, ushort neflags, const char *fileformatname) { /* reset file position to 0 - accept_file changed it? */ qlseek(li, 0); /* add header structures */ add_types(); create_filename_cmt(); /* process header and create its own segment */ EFI_IMAGE_TE_HEADER teHeader = {0}; if (qlread(li, &teHeader, sizeof(EFI_IMAGE_TE_HEADER)) != sizeof(EFI_IMAGE_TE_HEADER)) { warning("Failed to read TE header\n"); return; } /* read the data to the database */ /* header starts at 0 */ ea_t delta = teHeader.StrippedSize - sizeof(EFI_IMAGE_TE_HEADER); ea_t header_start = teHeader.ImageBase - delta; /* header total size is the TE header plus all sections that follow */ ea_t header_end = teHeader.ImageBase - delta + sizeof(EFI_IMAGE_TE_HEADER) + teHeader.NumberOfSections * sizeof(EFI_IMAGE_SECTION_HEADER); #if 1 msg("Header start: 0x%llx\n", header_start); msg("Header end: 0x%llx\n", header_end); msg("Delta: 0x%llx\n", delta); #endif file2base(li, 0, header_start, header_end, 1); /* create the HEADER segment */ add_segm(0, header_start, header_end, "HEADER", "DATA"); /* set header structures */ doStruct(teHeader.ImageBase - delta, sizeof(EFI_IMAGE_TE_HEADER), efi_image_te_header_struct); for (uint8_t i = 0; i < teHeader.NumberOfSections; i++) { doStruct(teHeader.ImageBase - delta + sizeof(EFI_IMAGE_TE_HEADER) + i * sizeof(EFI_IMAGE_SECTION_HEADER), sizeof(EFI_IMAGE_SECTION_HEADER), efi_image_section_header_struct); } int headerPosition = sizeof(EFI_IMAGE_TE_HEADER); /* read sections */ for (uint8_t i = 0; i < teHeader.NumberOfSections; i++) { qlseek(li, headerPosition); EFI_IMAGE_SECTION_HEADER sectionHeader = {0}; qlread(li, §ionHeader, sizeof(EFI_IMAGE_SECTION_HEADER)); msg("Section name: %s\n", sectionHeader.Name); /* ok */ uint32_t position = sectionHeader.PointerToRawData - delta; msg("Position %x\n", position); qlseek(li, position); ea_t section_start = sectionHeader.VirtualAddress + teHeader.ImageBase - delta; ea_t section_end = 0; if (sectionHeader.Misc.VirtualSize > sectionHeader.SizeOfRawData) { section_end = sectionHeader.VirtualAddress + teHeader.ImageBase - delta + sectionHeader.Misc.VirtualSize; } else { section_end = sectionHeader.VirtualAddress + teHeader.ImageBase - delta + sectionHeader.SizeOfRawData; } msg("Section start: 0x%llx\n", section_start); msg("Section end: 0x%llx\n", section_end); file2base(li, position, section_start, section_end, 1); int bitness = -1; switch (teHeader.Machine) { case IMAGE_FILE_MACHINE_I386: bitness = 1; break; case IMAGE_FILE_MACHINE_X64: bitness = 2; break; default: bitness = 0; } const char *classType; if (qstrcmp((const char*)sectionHeader.Name, ".text") == 0) { classType = "CODE"; } else { classType = "DATA"; } add_segm(0, section_start, section_end, (const char*)sectionHeader.Name, classType); set_segm_addressing(get_segm_by_name((const char *)sectionHeader.Name), bitness); /* try to find the GUIDs in data section */ if (qstrcmp((const char *)sectionHeader.Name, ".data") == 0) { find_guids(section_start, section_end); } /* advance to next section */ headerPosition += sizeof(EFI_IMAGE_SECTION_HEADER); } /* configure the entrypoint address */ add_entry(teHeader.AddressOfEntryPoint + teHeader.ImageBase - delta, teHeader.AddressOfEntryPoint + teHeader.ImageBase - delta, "_start", 1); /* all done */ }
//-------------------------------------------------------------------------- void idaapi load_file(linput_t *li, ushort neflag, const char * /*fileformatname*/) { char line[BUFFSIZE], bigaddr = 0; ea_t addr, startEA = toEA(inf.baseaddr, 0), endEA = 0, seg_start = 0; char rstart = (inf.filetype == f_SREC) ? 'S' : ((inf.filetype == f_HEX) ? ':' : ';'); register char *p; memset(&lc, 0, sizeof(local_data)); inf.startIP = BADADDR; // f_SREC without start record bool iscode = (neflag & NEF_CODE) != 0; int nb = iscode ? ph.cnbits : ph.dnbits; // number of bits in a byte int bs = (nb + 7) / 8; // number of bytes sel_t sel = setup_selector(startEA >> 4); bool segment_created = false; bool cvt_to_bytes = false; if ( ph.id == PLFM_PIC ) { // pic12xx and pic16xx use 12-bit and 14-bit words in program memory // pic18xx uses 16-bit opcodes but byte addressing if ( strncmp(inf.procName, "PIC18", 5) != 0 ) { static const char form[] = // "PIC HEX file addressing mode\n" // "\n" "There are two flavors of HEX files for PIC: with word addressing\n" "and with byte addressing. It is not possible to recognize the\n" "flavor automatically. Please specify what addressing mode should\n" "be used to load the input file. If you don't know, try both and\n" "choose the one which produces the more meaningful result\n"; int code = askbuttons_c("~B~yte addressing", "~W~ord addressing", "~C~ancel", 1, form); switch ( code ) { case 1: break; case 0: cvt_to_bytes = true; break; default: loader_failure(NULL); } } } ea_t subs_addr = 0; for(lc.ln = 1; qlgets(p = line, BUFFSIZE, li); lc.ln++) { while ( *p == ' ' ) ++p; if ( *p == '\n' || *p == '\r' ) continue; if ( *p++ != rstart) errfmt( ); int sz = 2; int mode = (inf.filetype == f_SREC) ? (uchar)*p++ : 0x100; lc.ptr = p; hexdata(0); if ( mode == 0x100 ) { if ( !lc.len ) break; lc.len += 2; if ( inf.filetype == f_HEX ) ++lc.len; } else { switch ( mode ) { default: errfmt(); case '0': case '5': continue; case '3': case '7': ++sz; case '2': case '8': ++sz; case '1': case '9': if ( mode > '3' ) mode = 0; --lc.len; break; } } addr = hexdata(sz) / bs; if ( !mode ) { inf.startIP = addr; continue; } if ( inf.filetype == f_HEX ) { int type = hexdata(1); // record type switch ( type ) { case 0xFF: // mitsubishi hex format case 4: // Extended linear address record subs_addr = hexdata(2) << 16; break; case 2: // Extended segment address record subs_addr = hexdata(2) << 4; break; } if ( type != 0 ) { if ( type == 1 ) break; // end of file record continue; // not a data record } } addr += subs_addr / bs; if ( lc.len ) { ea_t top = addr + lc.len / bs; p = line; while ( lc.len ) { *p++ = (uchar)hexdata(1); if ( cvt_to_bytes ) // pic *p++ = '\0'; } if ( top >= 0x10000l ) bigaddr = 1; addr += startEA; showAddr(addr); if ( (top += startEA) > endEA || !segment_created ) { endEA = top; if ( neflag & NEF_SEGS ) { if ( !segment_created ) { if ( !add_segm(sel, addr, endEA, NULL, iscode ? CLASS_CODE : CLASS_DATA)) loader_failure(NULL ); segment_created = true; seg_start = addr; } else set_segm_end(get_first_seg()->startEA, endEA, SEGMOD_KILL); } } if ( seg_start > addr ) { set_segm_start(get_first_seg()->startEA, addr, SEGMOD_KILL); seg_start = addr; } mem2base(line, addr, top, -1); } { ushort chi; // checksum ++lc.len; switch ( inf.filetype ) { case f_SREC: chi = (uchar)(~lc.sum); chi ^= (uchar)hexdata(1); break; case f_HEX: hexdata(1); chi = (uchar)lc.sum; break; default: //MEX ++lc.len; chi = lc.sum; chi -= (ushort)hexdata(2); break; } if ( chi ) { static char first = 0; if ( !first ) { ++first; warning("Bad hex input file checksum, line %u. Ignore?", lc.ln); } } } } if ( (neflag & NEF_SEGS) != 0 ) { if ( bigaddr ) { set_segm_addressing(get_first_seg(), 1); if ( ph.id == PLFM_386 ) inf.lflags |= LFLG_PC_FLAT; } set_default_dataseg(sel); inf.start_cs = sel; } else { enable_flags(startEA, endEA, STT_CUR); } inf.af &= ~AF_FINAL; // behave as a binary file create_filename_cmt(); }
//----------------------------------------------------------------------------- // process a file record according to its "record_type". // return true if there is no more records to process. static bool process_record(linput_t *li, const uchar record_type, bool load) { bool finished = false; switch (record_type) { // A record with a header byte of $81 is a record that may contain code or // data from arbitrary segments. // // header : 1 byte // segment : 1 byte // gran : 1 byte // start_addr : 4 bytes (entry point) // length : 2 bytes // data : length bytes case 0x81: { mas_header_t header; memset(&header, 0, sizeof header); // read the header if (qlread(li, &header, sizeof header) != sizeof header) mas_error("unable to read header (%d bytes)", sizeof header); // granularities that differ from 1 are rare and mostly appear // in DSP CPU's that are not designed for byte processing. if (header.gran != 1) mas_error("unsupported granularity (%d)", header.gran); // set processor if (!mas_set_cpu(header.header)) mas_error("processor type '0x%X' is currently unsupported", header.header); if (!load) // we have the processor, nothing else to do { finished = true; break; } // get segment name const char *segname = mas_get_segname(header.segment); if (segname == NULL) mas_error("invalid segment '0x%X'", header.segment); #if defined(DEBUG) msg("MAS: ready to read %d bytes (0x%X -> 0x%X)\n", header.length, header.start_addr, header.start_addr + header.length); #endif // send code in the database file2base(li, qltell(li), header.start_addr, header.start_addr + header.length, FILEREG_PATCHABLE); // set selector sel_t selector = allocate_selector(0); // create segment add_segm(selector, header.start_addr, header.start_addr + header.length, segname, segname); } break; // The last record in a file bears the Header $00 and has only a string as // data field. This string does not have an explicit length specification; // its end is equal to the file's end. // // The string contains only the name of the program that created the file // and has no further meaning. // // creator : x bytes case 0x00: { ulong length = qlsize(li) - qltell(li); #if defined(DEBUG) msg("MAS: creator length : %ld bytes\n", length); #endif if (length >= sizeof creator) mas_error("creator length is too large (%ld >= %ld", length, sizeof creator); int tmp; if ((tmp = qlread(li, creator, length)) != length) mas_error("unable to read creator string (i read %d)", tmp); creator[tmp] = '\0'; } finished = true; break; // entry_point : 4 bytes case 0x80: { if (qlread(li, &entry_point, 4) != 4) mas_error("unable to read entry_point"); if (load) { #if defined(DEBUG) msg("MAS: detected entry point : 0x%X\n", entry_point); #endif inf.startIP = entry_point; // entry point segment_t *s = getseg(entry_point); inf.start_cs = s ? s->sel : 0; // selector of code } } break; default: // start_addr : 4 bytes // length : 2 bytes // data : length bytes if (record_type >= 0x01 && record_type <= 0x7F) { struct header { int start_addr; short length; } header; memset(&header, 0, sizeof header); // read the header if (qlread(li, &header, sizeof header) != sizeof header) mas_error("unable to read header (%d bytes)", sizeof header); if (load) { // send code in the database file2base(li, qltell(li), header.start_addr, header.start_addr + header.length, FILEREG_PATCHABLE); #if defined(DEBUG) msg("MAS: i've read %d DATA bytes (0x%X -> 0x%X)\n", header.length, header.start_addr, header.start_addr + header.length); #endif // set selector sel_t selector = allocate_selector(0); // create data segment add_segm(selector, header.start_addr, header.start_addr + header.length, "DATA", "DATA"); } else qlseek(li, qltell(li)+header.length); } else mas_error("invalid record type '0x%X'\n", record_type); } return finished; }