void ControlInfo::Load(const fs::file& f) { type = Read32(f); size = Read32(f); next = Read64(f); if (type == 1) { control_flags.ctrl_flag1 = Read32(f); control_flags.unknown1 = Read32(f); control_flags.unknown2 = Read32(f); control_flags.unknown3 = Read32(f); control_flags.unknown4 = Read32(f); control_flags.unknown5 = Read32(f); control_flags.unknown6 = Read32(f); control_flags.unknown7 = Read32(f); } else if (type == 2) { if (size == 0x30) { f.read(file_digest_30.digest, 20); file_digest_30.unknown = Read64(f); } else if (size == 0x40) { f.read(file_digest_40.digest1, 20); f.read(file_digest_40.digest2, 20); file_digest_40.unknown = Read64(f); } } else if (type == 3) { npdrm.magic = Read32(f); npdrm.unknown1 = Read32(f); npdrm.license = Read32(f); npdrm.type = Read32(f); f.read(npdrm.content_id, 48); f.read(npdrm.digest, 16); f.read(npdrm.invdigest, 16); f.read(npdrm.xordigest, 16); npdrm.unknown2 = Read64(f); npdrm.unknown3 = Read64(f); } }
static bool IsSelfElf32(const fs::file& f) { if (!f) return false; f.seek(0); SceHeader hdr; SelfHeader sh; hdr.Load(f); sh.Load(f); // Locate the class byte and check it. u8 elf_class[0x8]; f.seek(sh.se_elfoff); f.read(elf_class, 0x8); return (elf_class[4] == 1); }
static bool CheckDebugSelf(fs::file& s) { if (s.size() < 0x18) { return false; } // Get the key version. s.seek(0x08); const u16 key_version = s.read<le_t<u16>>(); // Check for DEBUG version. if (key_version == 0x80 || key_version == 0xc0) { LOG_WARNING(LOADER, "Debug SELF detected! Removing fake header..."); // Get the real elf offset. s.seek(0x10); // Start at the real elf offset. s.seek(key_version == 0x80 ? +s.read<be_t<u64>>() : +s.read<le_t<u64>>()); // Write the real ELF file back. fs::file e = fs::make_stream<std::vector<u8>>(); // Copy the data. char buf[2048]; while (u64 size = s.read(buf, 2048)) { e.write(buf, size); } s = std::move(e); return true; } // Leave the file untouched. return false; }
void Elf32_Phdr::LoadLE(const fs::file& f) { f.read(this, sizeof(*this)); }
inline u64 Read64LE(const fs::file& f) { u64 ret; f.read(&ret, sizeof(ret)); return ret; }
void Signature::Load(const fs::file& f) { f.read(r, 21); f.read(s, 21); f.read(padding, 6); }
void SectionHash::Load(const fs::file& f) { f.read(sha1, 20); f.read(padding, 12); f.read(hmac_key, 64); }
inline u32 Read32LE(const fs::file& f) { u32 ret; f.read(&ret, sizeof(ret)); return ret; }
inline u16 Read16LE(const fs::file& f) { u16 ret; f.read(&ret, sizeof(ret)); return ret; }
inline u64 Read64(const fs::file& f) { be_t<u64> ret; f.read(&ret, sizeof(ret)); return ret; }
inline u32 Read32(const fs::file& f) { be_t<u32> ret; f.read(&ret, sizeof(ret)); return ret; }
inline u16 Read16(const fs::file& f) { be_t<u16> ret; f.read(&ret, sizeof(ret)); return ret; }
inline u8 Read8(const fs::file& f) { u8 ret; f.read(&ret, sizeof(ret)); return ret; }
registry load_object(const fs::file& stream) { registry result; // Hack for empty input (TODO) if (!stream) { return result; } // Get header header_t header; verify(HERE), stream.read(header); // Check magic and version verify(HERE), header.magic == "\0PSF"_u32, header.version == 0x101, sizeof(header_t) + header.entries_num * sizeof(def_table_t) <= header.off_key_table, header.off_key_table <= header.off_data_table, header.off_data_table <= stream.size(); // Get indices std::vector<def_table_t> indices; verify(HERE), stream.read(indices, header.entries_num); // Get keys std::string keys; verify(HERE), stream.seek(header.off_key_table) == header.off_key_table; verify(HERE), stream.read(keys, header.off_data_table - header.off_key_table); // Load entries for (u32 i = 0; i < header.entries_num; ++i) { verify(HERE), indices[i].key_off < header.off_data_table - header.off_key_table; // Get key name (null-terminated string) std::string key(keys.data() + indices[i].key_off); // Check entry verify(HERE), result.count(key) == 0, indices[i].param_len <= indices[i].param_max, indices[i].data_off < stream.size() - header.off_data_table, indices[i].param_max < stream.size() - indices[i].data_off; // Seek data pointer stream.seek(header.off_data_table + indices[i].data_off); if (indices[i].param_fmt == format::integer && indices[i].param_max == sizeof(u32) && indices[i].param_len == sizeof(u32)) { // Integer data le_t<u32> value; verify(HERE), stream.read(value); result.emplace(std::piecewise_construct, std::forward_as_tuple(std::move(key)), std::forward_as_tuple(value)); } else if (indices[i].param_fmt == format::string || indices[i].param_fmt == format::array) { // String/array data std::string value; verify(HERE), stream.read(value, indices[i].param_len); if (indices[i].param_fmt == format::string) { // Find null terminator value.resize(std::strlen(value.c_str())); } result.emplace(std::piecewise_construct, std::forward_as_tuple(std::move(key)), std::forward_as_tuple(indices[i].param_fmt, indices[i].param_max, std::move(value))); } else { // Possibly unsupported format, entry ignored LOG_ERROR(LOADER, "Unknown entry format (key='%s', fmt=0x%x, len=0x%x, max=0x%x)", key, indices[i].param_fmt, indices[i].param_len, indices[i].param_max); } } return result; }