#include #include #include #include namespace FxOS { OS::OS(Target &t): m_target {t} { if(!t.covers(0x80000000)) throw std::runtime_error("OS requires a target with ROM"); /* OS files are all at least 1 MB large */ if(!t.covers(0x80000000, 1000000)) throw std::runtime_error("OS requires target with >1MB ROM"); parse_header(); parse_syscall_table(); parse_footer(); } void OS::parse_header() { Target &t = m_target; /* Bootcode timestamp at 0xffb0 (the very end of the bootcode) */ this->bootcode_timestamp = t.read_str(0x8000ffb0, 14); /* Bootcode checksum at 0xfffc */ this->bootcode_checksum = t.read_u32(0x8000fffc); /* Version string at 0x10020 */ this->version = t.read_str(0x80010020, 10); /* Serial numer at 0xffd0... sometimes? */ this->serial_number = t.read_str(0x8000ffd0, 8); } //--- // Syscall resolution //--- int OS::syscall_count() const noexcept { return m_syscall_table.size(); } uint32_t OS::syscall(int id) const { return m_syscall_table[id]; } int OS::find_syscall(uint32_t entry) const noexcept { try { return m_syscall_addresses.at(entry); } catch(std::out_of_range &e) { return -1; } } void OS::parse_syscall_table() { Target &t = m_target; /* Traverse the syscall table */ uint32_t syscall_table = t.read_u32(0x8001007c); int id = 0; while(1) { uint32_t entry = t.read_u32(syscall_table + 4 * id); MemoryRegion const *r = MemoryRegion::region_for(entry); if(!r) break; m_syscall_table.push_back(entry); m_syscall_addresses[entry] = id; id++; } } //--- // Footer search //--- void OS::parse_footer() { Target &t = m_target; /* Find the footer address (occurrence of "CASIOABSLangdata") */ uint32_t start = MemoryRegion::ROM.start; uint32_t end = MemoryRegion::ROM.end; this->footer = t.search(start, end, "CASIOABSLangdata", 16); if(this->footer == end) { this->footer = -1; this->timestamp = std::string(""); this->bootcode_timestamp = std::string(""); this->langdata = 0; return; } uint32_t addr = this->footer + 8; this->langdata = 0; while(!memcmp(t.translate(addr, 8), "Langdata", 8)) { this->langdata++; addr += 0x30; } this->timestamp = t.read_str(addr, 14); this->checksum = t.read_u32(addr + 0x18); } } /* namespace FxOS */