fxos/lib/os.cpp

111 lines
2.0 KiB
C++

#include <fxos/os.h>
#include <fxos/target.h>
#include <fxos/memory.h>
#include <cstring>
namespace FxOS {
OS::OS(File &file): m_target()
{
/* OS files are all at least 1 MB large */
if(file.size() < 1000000)
throw std::runtime_error("OS files cannot be < 1MB");
/* Bind the given file to the internal analysis target */
m_target.bind_region(MemoryRegion::ROM, file);
m_target.bind_region(MemoryRegion::ROM_P2, file);
parse_version();
parse_syscall_table();
// parse_footer();
}
void OS::parse_version()
{
/* Extract the version string at 0x10020 */
Target &t = m_target;
char *version = (char *)t.translate(0x80010020, 10);
m_version = std::string(version, 10);
}
//---
// Syscalle 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
//---
uint32_t OS::footer() const noexcept
{
return m_footer;
}
void OS::parse_footer()
{
/* Find the footer address (last occurrence of "CASIOABSLangdata") */
uint32_t start = MemoryRegion::ROM.start;
uint32_t end = MemoryRegion::ROM.end;
m_target.search(start, end, "CASIOABSLangdata", 16);
#if 0
char const *signature = "CASIOABSLangdata";
void *occ = NULL, *next = memmem(os->data, os->len, signature, 16);
void *end = os->data + os->len;
while(next)
{
occ = next;
next = memmem(next + 1, end - (next + 1), signature, 16);
}
os->footer = (occ) ? (occ - os->data) : (uint32_t)-1;
#endif
}
} /* namespace FxOS */