diff --git a/fxos/info.cpp b/fxos/info.cpp index 002d7dc..1e3b06e 100644 --- a/fxos/info.cpp +++ b/fxos/info.cpp @@ -7,6 +7,8 @@ using namespace FxOS; static char const *info_str = +"OS type: %s\n" +"\n" "Header information:\n" " Bootcode timestamp (DateA) (0x%000008x) : %s\n" " Bootcode checksum (0x%000008x) : 0x%08x\n" @@ -22,7 +24,7 @@ static char const *footer_str = static char const *syscall_str = "\nSyscall information:\n" -" Syscall table address (0x8001007c) : 0x%08x\n" +" Syscall table address (0x%000008x) : 0x%08x\n" " Entries that point to valid memory : 0x%x\n" " First seemingly invalid entry : 0x%08x\n" " Syscall entries outside ROM:\n"; @@ -36,7 +38,7 @@ void os_info(Target &t) will fail with an exception */ OS os(t); - printf(info_str, + printf(info_str, (os.type == OS::FX ? "FX" : "CG"), &os.bootcode_timestamp, os.bootcode_timestamp.value.c_str(), &os.bootcode_checksum, os.bootcode_checksum, // &os.serial_number, os.serial_number, @@ -53,11 +55,12 @@ void os_info(Target &t) &os.checksum, os.checksum); } - uint32_t syscall_table = t.read_u32(0x8001007c); + uint32_t syscall_table = os.syscall_table_address(); uint32_t first_noncall = t.read_u32(syscall_table + 4 * os.syscall_count()); - printf(syscall_str, syscall_table, os.syscall_count(), first_noncall); + printf(syscall_str, (os.type == OS::FX ? 0x8001007c : 0x8002007c), + syscall_table, os.syscall_count(), first_noncall); int total = 0; for(int i = 0; i < os.syscall_count(); i++) diff --git a/fxos/main.cpp b/fxos/main.cpp index 9bbc3d6..516a773 100644 --- a/fxos/main.cpp +++ b/fxos/main.cpp @@ -249,8 +249,14 @@ int main_info(int argc, char **argv) return 1; } - Target t(lib.targets().at(tname), lib.paths()); - os_info(t); + try { + Target t(lib.targets().at(tname), lib.paths()); + os_info(t); + } + catch(std::exception &e) { + log(ERR "%s", e.what()); + return 1; + } } return 0; diff --git a/include/fxos/os.h b/include/fxos/os.h index fe773ff..8b38069 100644 --- a/include/fxos/os.h +++ b/include/fxos/os.h @@ -20,6 +20,10 @@ public: data loaded in ROM, this raises an exception. */ OS(Target &target); + /* Type of OS, determined at construction */ + enum Type { FX, CG }; + Type type; + /* Bootcode timestamp and checksum */ Addressable bootcode_timestamp; Addressable bootcode_checksum; @@ -36,6 +40,8 @@ public: uint32_t syscall(int id) const; /* Find a syscall entry. Returns -1 if syscall is not found */ int find_syscall(uint32_t entry) const noexcept; + /* Get address of syscall table */ + uint32_t syscall_table_address() const noexcept; /* Footer address, or -1 if not found */ uint32_t footer; diff --git a/lib/memory.cpp b/lib/memory.cpp index 0d6c2cb..a10a24c 100644 --- a/lib/memory.cpp +++ b/lib/memory.cpp @@ -1,4 +1,5 @@ #include +#include #include namespace FxOS { @@ -103,7 +104,7 @@ void MemoryRegion::guess_flags() noexcept using R = MemoryRegion; /* Basic memory regions */ -R const &R::ROM = MemoryRegion("ROM", 0x80000000, 0x807fffff, false); +R const &R::ROM = MemoryRegion("ROM", 0x80000000, 0x81ffffff, false); R const &R::RAM = MemoryRegion("RAM", 0x88000000, 0x88040000, true); R const &R::ROM_P2 = MemoryRegion("ROM_P2", 0xa0000000, 0xa07fffff, false); R const &R::RAM_P2 = MemoryRegion("RAM_P2", 0xa8000000, 0xa8040000, true); diff --git a/lib/os.cpp b/lib/os.cpp index 8a8e1da..fa01a97 100644 --- a/lib/os.cpp +++ b/lib/os.cpp @@ -15,6 +15,14 @@ OS::OS(Target &t): m_target {t} if(!t.covers(0x80000000, 1000000)) throw std::runtime_error("OS requires target with >1MB ROM"); + /* Detect OS type by heuristic */ + if(t.read_str(0x80010000, 8).value == "CASIOWIN") + this->type = FX; + else if(t.read_str(0x80020000, 8).value == "CASIOWIN") + this->type = CG; + else + throw std::runtime_error("Cannot determine OS type (FX/CG)"); + parse_header(); parse_syscall_table(); parse_footer(); @@ -24,15 +32,22 @@ 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); + if(this->type == FX) + { + /* Bootcode timestamp at the very end of the bootcode */ + this->bootcode_timestamp = t.read_str(0x8000ffb0, 14); + this->bootcode_checksum = t.read_u32(0x8000fffc); + this->version = t.read_str(0x80010020, 10); + /* Serial numer at 0xffd0... sometimes? */ + this->serial_number = t.read_str(0x8000ffd0, 8); + } + else if(this->type == CG) + { + this->bootcode_timestamp = t.read_str(0x8001ffb0, 14); + this->bootcode_checksum = t.read_u32(0x8001fffc); + this->version = t.read_str(0x80020020, 10); + this->serial_number = t.read_str(0x8001ffd0, 8); + } } //--- @@ -59,12 +74,18 @@ int OS::find_syscall(uint32_t entry) const noexcept } } +uint32_t OS::syscall_table_address() const noexcept +{ + uint32_t address = (this->type == FX) ? 0x8001007c : 0x8002007c; + return m_target.read_u32(address); +} + void OS::parse_syscall_table() { Target &t = m_target; /* Traverse the syscall table */ - uint32_t syscall_table = t.read_u32(0x8001007c); + uint32_t syscall_table = syscall_table_address(); int id = 0; while(1) @@ -98,7 +119,6 @@ void OS::parse_footer() { this->footer = -1; this->timestamp = std::string(""); - this->bootcode_timestamp = std::string(""); this->langdata = 0; return; }