os: support fx-CG OS structures
This change adds OS parsing for fx-CG OSes; this includes the information available in [fxos info] but also makes it possible to disassemble syscalls using [fxos disasm]. Symbols and addresses, including syscall names, are still shared with legacy FX versions, which is definitely a no-no.
This commit is contained in:
parent
772a67e35e
commit
a572f20d4d
|
@ -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++)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<std::string> bootcode_timestamp;
|
||||
Addressable<uint32_t> 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;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <fxos/memory.h>
|
||||
#include <stdexcept>
|
||||
#include <array>
|
||||
|
||||
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);
|
||||
|
|
42
lib/os.cpp
42
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue