def gen(self): from math import log2 lvl = b'' lvl += pk_u64(self.offset) lvl += pk_u64(self.size) lvl += pk_u32(int(log2(self.block_size))) lvl += 0x4 * b'\0' return lvl
def _gen_header(self): dir_hash_table_offset = ROMFS_FILEPARTITION_OFS + self.data_size dir_hash_table_length = 4 * self.dir_hash_table_entry_count dir_table_offset = dir_hash_table_offset + dir_hash_table_length dir_table_length = len(self.dir_table) file_hash_table_offset = dir_table_offset + len(self.dir_table) file_hash_table_length = 4 * self.file_hash_table_entry_count file_table_offset = file_hash_table_offset + file_hash_table_length file_table_length = len(self.file_table) header = b'' header += pk_u64(ROMFS_HEADER_LENGTH) header += pk_u64(dir_hash_table_offset) header += pk_u64(dir_hash_table_length) header += pk_u64(dir_table_offset) header += pk_u64(dir_table_length) header += pk_u64(file_hash_table_offset) header += pk_u64(file_hash_table_length) header += pk_u64(file_table_offset) header += pk_u64(file_table_length) header += pk_u64(ROMFS_FILEPARTITION_OFS) header = pad_to(header, length=ROMFS_FILEPARTITION_OFS) return header
def add(self, entry): assert isinstance(entry, self.entry_type), 'Invalid entry type' if (len(self.data) <= self.entry_nb) and (self.entry_type is DirEntry): self.data.append({ 'Parent': pk_u32(entry.offsets['Parent']), 'Sibling': pk_u32(entry.offsets['Sibling']), 'Child': pk_u32(entry.offsets['Child']), 'File': pk_u32(entry.offsets['File']), 'PreviousHash': pk_u32(ROMFS_ENTRY_EMPTY), 'NameLength': pk_u32(len(entry.name)), 'Name': pad_to(entry.name.encode(), multiple=4) }) elif len(self.data) <= self.entry_nb: self.data.append({ 'Parent': pk_u32(entry.offsets['Parent']), 'Sibling': pk_u32(entry.offsets['Sibling']), 'DataOffset': pk_u64(entry.offsets['Data']), 'Size': pk_u64(entry.offsets['Size']), 'PreviousHash': pk_u32(ROMFS_ENTRY_EMPTY), 'NameLength': pk_u32(len(entry.name)), 'Name': pad_to(entry.name.encode(), multiple=4) }) else: raise ValueError('Table is already filled up')
def __init__(self, nca3, section_header, verify=False, ifo=0, buffer=65536): self.nca = nca3 self.section_header = section_header self.key = self.nca.body_key self.nonce = pk_u64(self.section_header.section_ctr, endianness='>') self.section_offset = self.section_header.offset self.section_size = self.section_header.size self.fs_type = self.section_header.fs_type self.crypto = self.section_header.crypto_type self.ifo = ifo self.buffer = buffer if self.crypto in ('BTKR', 'XTS'): raise NotImplementedError('BTKR/XTS not implemented') super(NCA3.SectionInNCA3, self).__init__(self.nca.f, self.section_offset, self.section_size) self.is_exefs = False if self.fs_type == 'PFS0': self.cont_offset = self.section_header.superblock.offset self.cont_size = self.section_header.superblock.size self.fs = HashTableWrappedPFS0(self.section_header.superblock, self, verify=verify) if 'main.npdm' in self.fs.files: self.is_exefs = True elif self.fs_type == 'RomFS': self.cont_offset = self.section_header.superblock.lvls[ IVFCSuperblock.IVFC_MAX_LEVEL - 1].offset self.cont_size = self.section_header.superblock.lvls[ IVFCSuperblock.IVFC_MAX_LEVEL - 1].size self.fs = HashTreeWrappedRomFS(self.section_header.superblock, self, verify=verify)