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:
Lephenixnoir 2020-06-13 09:59:01 +02:00
parent 772a67e35e
commit a572f20d4d
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
5 changed files with 54 additions and 18 deletions

View File

@ -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++)

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;
}