add OS checksum computations
This commit is contained in:
parent
4e76ff3a24
commit
2394725074
|
@ -34,6 +34,11 @@ public:
|
|||
Addressable<std::string> timestamp;
|
||||
Addressable<uint32_t> checksum;
|
||||
|
||||
/* Separated version components */
|
||||
int version_major, version_minor, version_patch;
|
||||
/* Recomputed checksum */
|
||||
uint32_t computed_checksum;
|
||||
|
||||
/* Get number of syscalls */
|
||||
int syscall_count() const noexcept;
|
||||
/* Get a syscall entry */
|
||||
|
@ -43,6 +48,12 @@ public:
|
|||
/* Get address of syscall table */
|
||||
uint32_t syscall_table_address() const noexcept;
|
||||
|
||||
/* Tests against the OS version */
|
||||
bool version_lt(int major, int minor, int patch) const noexcept;
|
||||
bool version_le(int major, int minor, int patch) const noexcept;
|
||||
bool version_gt(int major, int minor, int patch) const noexcept;
|
||||
bool version_ge(int major, int minor, int patch) const noexcept;
|
||||
|
||||
/* Footer address, or -1 if not found */
|
||||
uint32_t footer;
|
||||
/* Number of langdata entries */
|
||||
|
@ -64,6 +75,9 @@ private:
|
|||
/* Locate and parse the footer. */
|
||||
void parse_footer();
|
||||
|
||||
/* Compute OS checkum .*/
|
||||
uint32_t compute_checksum() const;
|
||||
|
||||
//---
|
||||
// OS information
|
||||
//---
|
||||
|
|
|
@ -26,10 +26,14 @@ public:
|
|||
/* Check if a full region is simulated */
|
||||
virtual bool covers(MemoryRegion const ®ion) const noexcept;
|
||||
|
||||
/* Returns the data located at the provided virtual address. Throws
|
||||
std::out_of_range if the interval is not entirely simulated */
|
||||
/* Returns the data located at the provided virtual address, nullptr if it
|
||||
is not entirely covered. */
|
||||
virtual char const *translate(uint32_t addr, int size=1) const = 0;
|
||||
|
||||
/* Returns the data located at the provided virtual address, and indicates
|
||||
how much is available in *size. */
|
||||
virtual char const *translate_dynamic(uint32_t addr, int *size) const = 0;
|
||||
|
||||
/* Read data from the memory. The following methods read data of
|
||||
various types. (Not a template because of the restriction about
|
||||
template specialization in non-namespaces scopes still in g++.)
|
||||
|
@ -77,16 +81,12 @@ struct Binding: public AbstractMemory
|
|||
/* Underlying buffer (copy of the original one) */
|
||||
Buffer buffer;
|
||||
|
||||
/* Checks if an address is covered by the binding */
|
||||
bool covers(uint32_t addr, int size=1) const noexcept override;
|
||||
/* Check if a region is covered by the binding */
|
||||
bool covers(MemoryRegion const ®ion) const noexcept override;
|
||||
|
||||
/* Returns this process' address (in [data]) corresponding to the
|
||||
provided virtual address */
|
||||
char const *translate(uint32_t addr, int size=1) const override;
|
||||
char const *translate_dynamic(uint32_t addr, int *size) const override;
|
||||
|
||||
/* Search a pattern */
|
||||
uint32_t search(uint32_t start, uint32_t end, void const *pattern,
|
||||
int size) const override;
|
||||
};
|
||||
|
@ -140,15 +140,12 @@ public:
|
|||
bound. */
|
||||
void bind_region(MemoryRegion const ®ion, Buffer const &buffer);
|
||||
|
||||
/* Check if an address is bound */
|
||||
bool covers(uint32_t addr, int size=1) const noexcept override;
|
||||
/* Check if a full region is bound */
|
||||
bool covers(MemoryRegion const ®ion) const noexcept override;
|
||||
|
||||
/* Returns the data at the provided virtual address */
|
||||
char const *translate(uint32_t addr, int size=1) const override;
|
||||
char const *translate_dynamic(uint32_t addr, int *size) const override;
|
||||
|
||||
/* Search a pattern */
|
||||
uint32_t search(uint32_t start, uint32_t end, void const *pattern,
|
||||
int size) const override;
|
||||
|
||||
|
|
87
lib/os.cpp
87
lib/os.cpp
|
@ -47,6 +47,47 @@ void OS::parse_header()
|
|||
this->version = s.read_str(0x80020020, 10);
|
||||
this->serial_number = s.read_str(0x8001ffd0, 8);
|
||||
}
|
||||
|
||||
/* Version has format MM.mm.pppp */
|
||||
version_major = std::stoi(this->version.value.substr(0, 2));
|
||||
version_minor = std::stoi(this->version.value.substr(3, 2));
|
||||
version_patch = std::stoi(this->version.value.substr(6, 4));
|
||||
}
|
||||
|
||||
bool OS::version_lt(int major, int minor, int patch) const noexcept
|
||||
{
|
||||
if(this->version_major < major) return true;
|
||||
if(this->version_major > major) return false;
|
||||
if(this->version_minor < minor) return true;
|
||||
if(this->version_minor > minor) return false;
|
||||
return (this->version_patch < patch);
|
||||
}
|
||||
|
||||
bool OS::version_le(int major, int minor, int patch) const noexcept
|
||||
{
|
||||
if(this->version_major < major) return true;
|
||||
if(this->version_major > major) return false;
|
||||
if(this->version_minor < minor) return true;
|
||||
if(this->version_minor > minor) return false;
|
||||
return (this->version_patch <= patch);
|
||||
}
|
||||
|
||||
bool OS::version_gt(int major, int minor, int patch) const noexcept
|
||||
{
|
||||
if(this->version_major < major) return false;
|
||||
if(this->version_major > major) return true;
|
||||
if(this->version_minor < minor) return false;
|
||||
if(this->version_minor > minor) return true;
|
||||
return (this->version_patch > patch);
|
||||
}
|
||||
|
||||
bool OS::version_ge(int major, int minor, int patch) const noexcept
|
||||
{
|
||||
if(this->version_major < major) return false;
|
||||
if(this->version_major > major) return true;
|
||||
if(this->version_minor < minor) return false;
|
||||
if(this->version_minor > minor) return true;
|
||||
return (this->version_patch >= patch);
|
||||
}
|
||||
|
||||
//---
|
||||
|
@ -117,6 +158,7 @@ void OS::parse_footer()
|
|||
this->footer = -1;
|
||||
this->timestamp = std::string("");
|
||||
this->langdata = 0;
|
||||
this->computed_checksum = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -131,6 +173,51 @@ void OS::parse_footer()
|
|||
|
||||
this->timestamp = s.read_str(addr, 14);
|
||||
this->checksum = s.read_u32(addr + 0x18);
|
||||
this->computed_checksum = this->compute_checksum();
|
||||
}
|
||||
|
||||
//---
|
||||
// Checksum
|
||||
//---
|
||||
|
||||
static uint32_t accumulate_range(VirtualSpace const &m_space,
|
||||
uint32_t start, uint32_t end)
|
||||
{
|
||||
uint32_t sum = 0;
|
||||
|
||||
/* Read from dynamically-sized bindings; read_u8() would be too slow */
|
||||
while(start < end) {
|
||||
int size;
|
||||
uint8_t *buf = (uint8_t *)m_space.translate_dynamic(start, &size);
|
||||
|
||||
if(start + size > end)
|
||||
size = end - start;
|
||||
|
||||
for(int i = 0; i < size; i++)
|
||||
sum += buf[i];
|
||||
|
||||
start += size;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
uint32_t OS::compute_checksum() const
|
||||
{
|
||||
if(this->type == FX) {
|
||||
return accumulate_range(m_space, 0x80010000, &this->checksum);
|
||||
}
|
||||
else if(this->type == CG) {
|
||||
if(this->version_lt(2, 2, 0)) {
|
||||
return accumulate_range(m_space, 0x80020000, 0x80b5feb0)
|
||||
+ accumulate_range(m_space,0x80b5fef0, 0x80b5fff8);
|
||||
}
|
||||
else {
|
||||
return accumulate_range(m_space, 0x80020000, 0x80b20000)
|
||||
+ accumulate_range(m_space, this->footer+8, &this->checksum);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
} /* namespace FxOS */
|
||||
|
|
|
@ -90,6 +90,13 @@ char const *Binding::translate(uint32_t addr, int size) const
|
|||
return buffer.data.get() + (addr - region.start);
|
||||
}
|
||||
|
||||
char const *Binding::translate_dynamic(uint32_t addr, int *size) const
|
||||
{
|
||||
if(!covers(addr, 1)) return nullptr;
|
||||
*size = region.end - addr;
|
||||
return buffer.data.get() + (addr - region.start);
|
||||
}
|
||||
|
||||
uint32_t Binding::search(uint32_t start, uint32_t end, void const *pattern,
|
||||
int size) const
|
||||
{
|
||||
|
@ -169,6 +176,17 @@ char const *VirtualSpace::translate(uint32_t addr, int size) const
|
|||
throw AddressError(addr, size);
|
||||
}
|
||||
|
||||
char const *VirtualSpace::translate_dynamic(uint32_t addr, int *size) const
|
||||
{
|
||||
for(auto it = m_bindings.crbegin(); it != m_bindings.crend(); it++)
|
||||
{
|
||||
char const *ptr = it->translate_dynamic(addr, size);
|
||||
if(ptr) return ptr;
|
||||
}
|
||||
|
||||
throw AddressError(addr, 1);
|
||||
}
|
||||
|
||||
uint32_t VirtualSpace::search(uint32_t start, uint32_t end,void const *pattern,
|
||||
int size) const
|
||||
{
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
//---
|
||||
|
||||
static char const *info_str =
|
||||
"OS type: %s\n"
|
||||
"OS: type %s version %02d.%02d.%04d\n"
|
||||
"\n"
|
||||
"Header information:\n"
|
||||
" Bootcode timestamp (DateA) (0x%000008x) : %s\n"
|
||||
|
@ -25,7 +25,8 @@ static char const *footer_str =
|
|||
" Detected footer address : 0x%08x\n"
|
||||
" Langdata entries found : %d\n"
|
||||
" OS date (DateO) (0x%000008x) : %s\n"
|
||||
" OS checksum (0x%000008x) : 0x%08x\n";
|
||||
" OS checksum (0x%000008x) : 0x%08x\n"
|
||||
" Computed OS checksum : 0x%08x\n";
|
||||
|
||||
static char const *syscall_str =
|
||||
"\nSyscall information:\n"
|
||||
|
@ -56,6 +57,7 @@ void _io(Session &session, std::string name)
|
|||
if(!os) throw CommandError("os analysis on '{}' failed", name);
|
||||
|
||||
printf(info_str, (os->type == OS::FX ? "FX" : "CG"),
|
||||
os->version_major, os->version_minor, os->version_patch,
|
||||
&os->bootcode_timestamp, os->bootcode_timestamp.value.c_str(),
|
||||
&os->bootcode_checksum, os->bootcode_checksum,
|
||||
&os->serial_number, os->serial_number.value.c_str(),
|
||||
|
@ -69,7 +71,7 @@ void _io(Session &session, std::string name)
|
|||
{
|
||||
printf(footer_str, os->footer, os->langdata,
|
||||
&os->timestamp, os->timestamp.value.c_str(),
|
||||
&os->checksum, os->checksum);
|
||||
&os->checksum, os->checksum, os->computed_checksum);
|
||||
}
|
||||
|
||||
uint32_t syscall_table = os->syscall_table_address();
|
||||
|
|
Loading…
Reference in New Issue