def _parse_dir(self, offset, parent): cur_dir_dict = { 'Parent': read_u32(self.dir_table, offset + 0x0), 'Sibling': read_u32(self.dir_table, offset + 0x4), 'Child': read_u32(self.dir_table, offset + 0x8), 'File': read_u32(self.dir_table, offset + 0xC), 'Name': read_at(self.dir_table, offset + 0x18, read_u32(self.dir_table, offset + 0x14)).decode() } dir_entry = DirEntry(parent, cur_dir_dict['Name']) if cur_dir_dict[ 'Child'] != ROMFS_ENTRY_EMPTY: # if not cur_dir_dict['Child'] + 1 & 1 << 32: child_dict, child_entry = self._parse_dir(cur_dir_dict['Child'], dir_entry) dir_entry.childs.append(child_entry) while child_dict['Sibling'] != ROMFS_ENTRY_EMPTY: child_dict, child_entry = self._parse_dir( child_dict['Sibling'], dir_entry) dir_entry.childs.append(child_entry) if cur_dir_dict['File'] != ROMFS_ENTRY_EMPTY: file_dict, file_entry = self._parse_file(cur_dir_dict['File'], dir_entry) dir_entry.files.append(file_entry) while file_dict['Sibling'] != ROMFS_ENTRY_EMPTY: file_dict, file_entry = self._parse_file( file_dict['Sibling'], dir_entry) dir_entry.files.append(file_entry) return cur_dir_dict, dir_entry
def __init__(self, block): if read_at(block, 0x0, 0x4) != b'IVFC': print('[WARN] Invalid IVFC magic') if read_u32(block, 0x4) != 0x20000: print('[WARN] Invalid 0x20000 IVFC magic') self.master_hash_size = read_u32(block, 0x8) self.nb_lvl = read_u32(block, 0xC) self.lvls = [] for n in range(self.IVFC_MAX_LEVEL): lvl = io.BytesIO(read_at(block, 0x10 + n * 0x18, 0x18)) self.lvls.append(self.IVFClvl(lvl)) self.master_hash = read_at(block, 0xC0, self.master_hash_size)
def _parse(self): self.rsa_sig = read_at(self.f, 0x0, 0x100) self.rsa_pubk = read_at(self.f, 0x100, 0x100) if read_at(self.f, 0x200, 0x4) != b'ACID': raise ValueError('Invalid ACID magic') self.flags = read_u32(self.f, 0x20C) self.tid_min = read_u64(self.f, 0x210) self.tid_max = read_u64(self.f, 0x218) fs_access_control_offset = read_u32(self.f, 0x220) fs_access_control_size = read_u32(self.f, 0x224) service_access_control_offset = read_u32(self.f, 0x228) service_access_control_size = read_u32(self.f, 0x22C) kernel_access_control_offset = read_u32(self.f, 0x230) kernel_access_control_size = read_u32(self.f, 0x234) self.fs_access_control = FsAccessControl( io.BytesIO( read_at(self.f, fs_access_control_offset, fs_access_control_size))) self.service_access_control = ServiceAccessControl( io.BytesIO( read_at(self.f, service_access_control_offset, service_access_control_size))) self.kernel_access_control = KernelAccessControl( io.BytesIO( read_at(self.f, kernel_access_control_offset, kernel_access_control_size)))
def _parse_file(self, offset, parent): file_dict = { 'Parent': read_u32(self.file_table, offset + 0x0), 'Sibling': read_u32(self.file_table, offset + 0x4), 'DataOffset': read_u64(self.file_table, offset + 0x8), 'Size': read_u32(self.file_table, offset + 0x10), 'Name': read_at(self.file_table, offset + 0x20, read_u32(self.file_table, offset + 0x1C)).decode() } file_entry = FileEntry(parent, file_dict['Name'], file_dict['Size']) file_entry.offset_in_romfs_data = file_dict['DataOffset'] file_entry.is_repacked = True return file_dict, file_entry
def _parse(self): if read_at(self.f, 0x0, 0x4) != b'META': raise ValueError('Invalid META magic') self.mmu_flags = read_u8(self.f, 0xC) self.main_thread_priority = read_u8(self.f, 0xE) self.default_cpu_id = read_u8(self.f, 0xF) self.process_category = self.process_categories[read_u32(self.f, 0x18)] self.main_thread_stack_size = read_u32(self.f, 0x1C) self.title_name = read_at(self.f, 0x20, 0x50).strip(b'\0').decode() aci0_offset = read_u32(self.f, 0x70) aci0_size = read_u32(self.f, 0x74) acid_offset = read_u32(self.f, 0x78) acid_size = read_u32(self.f, 0x7C) self.acid = ACID(io.BytesIO(read_at(self.f, acid_offset, acid_size))) self.aci0 = ACI0(io.BytesIO(read_at(self.f, aci0_offset, aci0_size)))
def _parse(self): if read_at(self.f, 0x0, 0x4) != b'ACI0': raise ValueError('Invalid ACI0 magic') self.tid = read_u64(self.f, 0x10) fs_access_control_offset = read_u32(self.f, 0x20) fs_access_control_size = read_u32(self.f, 0x24) service_access_control_offset = read_u32(self.f, 0x28) service_access_control_size = read_u32(self.f, 0x2C) kernel_access_control_offset = read_u32(self.f, 0x30) kernel_access_control_size = read_u32(self.f, 0x34) self.fs_access_control = FsAccessControl(io.BytesIO(read_at(self.f, fs_access_control_offset, fs_access_control_size))) self.service_access_control = ServiceAccessControl(io.BytesIO(read_at(self.f, service_access_control_offset, service_access_control_size))) self.kernel_access_control = KernelAccessControl(io.BytesIO(read_at(self.f, kernel_access_control_offset, kernel_access_control_size)))
def __init__(self, raw_section_table): media_start_offset = read_u32(raw_section_table, 0x0) media_end_offset = read_u32(raw_section_table, 0x4) self.start_offset = media_start_offset * self.MEDIA_SIZE self.end_offset = media_end_offset * self.MEDIA_SIZE
def ret(self): aci0_offset = read_u32(self.f, 0x70) aci0_size = read_u32(self.f, 0x74) acid_offset = read_u32(self.f, 0x78) acid_size = read_u32(self.f, 0x7C) return read_at(self.f, 0x0, acid_offset+acid_size)
def __init__(self, block): self.offset = read_u64(block, 0x0) self.size = read_u64(block, 0x8) self.block_size = 1 << read_u32(block, 0x10) # In log2 in the header