def recursion(root, outf): "Recursive directory walk" for item in listdir_items(root): if item.is_file: dentry = xstruct.create(DENTRY_FILE % len(item.name)) dentry.kind = TMPFS_FILE dentry.fname_len = len(item.name) dentry.fname = item.name.encode("ascii") dentry.flen = item.size outf.write(dentry.pack()) for data in chunks(item, 4096): outf.write(data) elif item.is_dir: dentry = xstruct.create(DENTRY_DIRECTORY % len(item.name)) dentry.kind = TMPFS_DIRECTORY dentry.fname_len = len(item.name) dentry.fname = item.name.encode("ascii") outf.write(dentry.pack()) recursion(item.path, outf) dentry = xstruct.create(DENTRY_NONE) dentry.kind = TMPFS_NONE dentry.fname_len = 0 outf.write(dentry.pack())
def main(): if (len(sys.argv) < 3): usage(sys.argv[0]) return path = os.path.abspath(sys.argv[1]) if (not os.path.isdir(path)): print("<PATH> must be a directory") return outf = open(sys.argv[2], "wb") header = xstruct.create(HEADER) header.tag = b"TMPFS" outf.write(header.pack()) recursion(path, outf) dentry = xstruct.create(DENTRY_NONE) dentry.kind = TMPFS_NONE dentry.fname_len = 0 outf.write(dentry.pack()) outf.close()
def recursion(root, outf): "Recursive directory walk" for item in listdir_items(root): if item.is_file: dentry = xstruct.create(DENTRY_FILE % len(item.name)) dentry.kind = TMPFS_FILE dentry.fname_len = len(item.name) dentry.fname = item.name.encode('ascii') dentry.flen = item.size outf.write(dentry.pack()) for data in chunks(item, 4096): outf.write(data) elif item.is_dir: dentry = xstruct.create(DENTRY_DIRECTORY % len(item.name)) dentry.kind = TMPFS_DIRECTORY dentry.fname_len = len(item.name) dentry.fname = item.name.encode('ascii') outf.write(dentry.pack()) recursion(item.path, outf) dentry = xstruct.create(DENTRY_NONE) dentry.kind = TMPFS_NONE dentry.fname_len = 0 outf.write(dentry.pack())
def main(): if len(sys.argv) < 3: usage(sys.argv[0]) return path = os.path.abspath(sys.argv[1]) if not os.path.isdir(path): print("<PATH> must be a directory") return outf = open(sys.argv[2], "wb") header = xstruct.create(HEADER) header.tag = b"TMPFS" outf.write(header.pack()) recursion(path, outf) dentry = xstruct.create(DENTRY_NONE) dentry.kind = TMPFS_NONE dentry.fname_len = 0 outf.write(dentry.pack()) outf.close()
def init_gdt(self): "Initialize block group descriptor table" self.superblock_positions = [] self.gdt = [] consumed_blocks_per_group = (1 + self.gdt_blocks + self.inode_bitmap_blocks_per_group + self.block_bitmap_blocks_per_group + self.inode_table_blocks_per_group) initial_free_blocks = self.blocks_per_group - consumed_blocks_per_group for bg in range(self.block_groups): base = bg * self.blocks_per_group if (bg == 0): base = self.superblock_at_block self.superblock_positions.append(1024) else: self.superblock_positions.append(base * self.block_size) self.block_allocator.mark_used_all(range(base, base+consumed_blocks_per_group)) pos = base + 1 + self.gdt_blocks gde = xstruct.create(STRUCT_BLOCK_GROUP_DESCRIPTOR) gde.block_bitmap_block = pos pos += self.block_bitmap_blocks_per_group gde.inode_bitmap_block = pos pos += self.inode_bitmap_blocks_per_group gde.inode_table_first_block = pos gde.free_block_count = initial_free_blocks gde.free_inode_count = self.inodes_per_group gde.directory_inode_count = 0 self.gdt.append(gde)
def init_gdt(self): "Initialize block group descriptor table" self.superblock_positions = [] self.gdt = [] consumed_blocks_per_group = (1 + self.gdt_blocks + self.inode_bitmap_blocks_per_group + self.block_bitmap_blocks_per_group + self.inode_table_blocks_per_group) initial_free_blocks = self.blocks_per_group - consumed_blocks_per_group for bg in range(self.block_groups): base = bg * self.blocks_per_group if (bg == 0): base = self.superblock_at_block self.superblock_positions.append(1024) else: self.superblock_positions.append(base * self.block_size) self.block_allocator.mark_used_all( range(base, base + consumed_blocks_per_group)) pos = base + 1 + self.gdt_blocks gde = xstruct.create(STRUCT_BLOCK_GROUP_DESCRIPTOR) gde.block_bitmap_block = pos pos += self.block_bitmap_blocks_per_group gde.inode_bitmap_block = pos pos += self.inode_bitmap_blocks_per_group gde.inode_table_first_block = pos gde.free_block_count = initial_free_blocks gde.free_inode_count = self.inodes_per_group gde.directory_inode_count = 0 self.gdt.append(gde)
def pack(self): "Pack the inode structure and return the result" data = xstruct.create(STRUCT_INODE) data.mode = (Inode.TYPE2MODE[self.type] << 12) data.mode |= 0x1ff # ugo+rwx data.user_id = 0 data.size = self.size & 0xFFFFFFFF data.group_id = 0 curtime = int(time.time()) data.access_time = curtime data.modification_time = curtime data.creation_time = curtime data.deletion_time = 0 data.usage_count = self.refcount data.reserved_512_blocks = self.blocks * (self.fs.block_size // 512) data.flags = 0 blockconv = lambda x: 0 if x == None else x data.direct_blocks = list(map(blockconv, self.direct)) data.indirect_blocks = list(map(blockconv, self.indirect)) data.version = 0 data.file_acl = 0 if self.type == Inode.TYPE_FILE: data.size_high = (self.size >> 32) else: # size_high represents dir_acl in this case data.size_high = 0 data.mode_high = 0 data.user_id_high = 0 data.group_id_high = 0 return data.pack()
def write(self, inode): "Write the directory entry into the inode" head = xstruct.create(STRUCT_DIR_ENTRY_HEAD) head.inode = self.inode head.skip = self.skip head.name_length = len(self.name) head.inode_type = self.type inode.write(head.pack()) inode.write(self.name+'\0'.encode()) inode.align_pos(4)
def write(self, inode): "Write the directory entry into the inode" head = xstruct.create(STRUCT_DIR_ENTRY_HEAD) head.inode = self.inode head.skip = self.skip head.name_length = len(self.name) head.inode_type = self.type inode.write(head.pack()) inode.write(self.name + '\0'.encode()) inode.align_pos(4)
def get_or_add_block_indirect(self, block): "Get or add a real block to the file (indirect blocks)" # Determine the indirection level for the desired block level = None for i in range(4): if block < self.fs.indirect_limits[i]: level = i break assert level != None # Compute offsets for the topmost level block_offset_in_level = block - self.fs.indirect_limits[level - 1] if self.indirect[level - 1] == None: self.indirect[level - 1] = self.new_block(data=False) current_block = xstruct.create(STRUCT_BLOCK_REFERENCE) current_block.block_id = self.indirect[level - 1] offset_in_block = block_offset_in_level // self.fs.indirect_blocks_per_level[ level - 1] # Navigate through other levels while level > 0: assert offset_in_block < self.fs.block_ids_per_block level -= 1 self.fs.seek_to_block(current_block.block_id, offset_in_block * 4) current_block.unpack(self.fs.outf.read(4)) if current_block.block_id == 0: # The block does not exist, so alloc one and write it there self.fs.outf.seek(-4, os.SEEK_CUR) current_block.block_id = self.new_block(data=(level == 0)) self.fs.outf.write(current_block.pack()) # If we are on the last level, break here as # there is no next level to visit if level == 0: break # Visit the next level block_offset_in_level %= self.fs.indirect_blocks_per_level[level] offset_in_block = block_offset_in_level // self.fs.indirect_blocks_per_level[ level - 1] return current_block.block_id
def get_or_add_block_indirect(self, block): "Get or add a real block to the file (indirect blocks)" # Determine the indirection level for the desired block level = None for i in range(4): if block < self.fs.indirect_limits[i]: level = i break assert level != None # Compute offsets for the topmost level block_offset_in_level = block - self.fs.indirect_limits[level-1]; if self.indirect[level-1] == None: self.indirect[level-1] = self.new_block(data = False) current_block = xstruct.create(STRUCT_BLOCK_REFERENCE) current_block.block_id = self.indirect[level-1] offset_in_block = block_offset_in_level // self.fs.indirect_blocks_per_level[level-1] # Navigate through other levels while level > 0: assert offset_in_block < self.fs.block_ids_per_block level -= 1 self.fs.seek_to_block(current_block.block_id, offset_in_block*4) current_block.unpack(self.fs.outf.read(4)) if current_block.block_id == 0: # The block does not exist, so alloc one and write it there self.fs.outf.seek(-4, os.SEEK_CUR) current_block.block_id = self.new_block(data=(level==0)) self.fs.outf.write(current_block.pack()) # If we are on the last level, break here as # there is no next level to visit if level == 0: break # Visit the next level block_offset_in_level %= self.fs.indirect_blocks_per_level[level]; offset_in_block = block_offset_in_level // self.fs.indirect_blocks_per_level[level-1] return current_block.block_id
def create_dotdot_dirent(parent_cluster): dir_entry = xstruct.create(DOTDOT_DIR_ENTRY) dir_entry.signature = [0x2E, 0x2E] dir_entry.name = b" " dir_entry.ext = b" " dir_entry.attr = 0x10 dir_entry.ctime_fine = 0 # FIXME dir_entry.ctime = 0 # FIXME dir_entry.cdate = 0 # FIXME dir_entry.adate = 0 # FIXME dir_entry.mtime = 0 # FIXME dir_entry.mdate = 0 # FIXME dir_entry.cluster = parent_cluster dir_entry.size = 0 return dir_entry
def create_dot_dirent(empty_cluster): dir_entry = xstruct.create(DOT_DIR_ENTRY) dir_entry.signature = 0x2e dir_entry.name = b' ' dir_entry.ext = b' ' dir_entry.attr = 0x10 dir_entry.ctime_fine = 0 # FIXME dir_entry.ctime = 0 # FIXME dir_entry.cdate = 0 # FIXME dir_entry.adate = 0 # FIXME dir_entry.mtime = 0 # FIXME dir_entry.mdate = 0 # FIXME dir_entry.cluster = empty_cluster dir_entry.size = 0 return dir_entry
def create_dotdot_dirent(parent_cluster): dir_entry = xstruct.create(DOTDOT_DIR_ENTRY) dir_entry.signature = [0x2e, 0x2e] dir_entry.name = b' ' dir_entry.ext = b' ' dir_entry.attr = 0x10 dir_entry.ctime_fine = 0 # FIXME dir_entry.ctime = 0 # FIXME dir_entry.cdate = 0 # FIXME dir_entry.adate = 0 # FIXME dir_entry.mtime = 0 # FIXME dir_entry.mdate = 0 # FIXME dir_entry.cluster = parent_cluster dir_entry.size = 0 return dir_entry
def create_dirent(name, name83_list, directory, cluster, size): short_name, short_ext, lfn = fat_name83(name, name83_list) dir_entry = xstruct.create(DIR_ENTRY) dir_entry.name = short_name dir_entry.ext = short_ext if directory: dir_entry.attr = 0x30 else: dir_entry.attr = 0x20 dir_entry.lcase = 0x18 dir_entry.ctime_fine = 0 # FIXME dir_entry.ctime = 0 # FIXME dir_entry.cdate = 0 # FIXME dir_entry.adate = 0 # FIXME dir_entry.mtime = 0 # FIXME dir_entry.mdate = 0 # FIXME dir_entry.cluster = cluster if directory: dir_entry.size = 0 else: dir_entry.size = size if not lfn: return [dir_entry] long_name = name.encode("utf_16_le") entries = [dir_entry] seq = 1 checksum = lfn_checksum(dir_entry.name + dir_entry.ext) while len(long_name) > 0: long_entry, long_name = create_lfn_dirent(long_name, seq, checksum) entries.append(long_entry) seq += 1 entries.reverse() return entries
def create_dirent(name, name83_list, directory, cluster, size): short_name, short_ext, lfn = fat_name83(name, name83_list) dir_entry = xstruct.create(DIR_ENTRY) dir_entry.name = short_name dir_entry.ext = short_ext if (directory): dir_entry.attr = 0x30 else: dir_entry.attr = 0x20 dir_entry.lcase = 0x18 dir_entry.ctime_fine = 0 # FIXME dir_entry.ctime = 0 # FIXME dir_entry.cdate = 0 # FIXME dir_entry.adate = 0 # FIXME dir_entry.mtime = 0 # FIXME dir_entry.mdate = 0 # FIXME dir_entry.cluster = cluster if (directory): dir_entry.size = 0 else: dir_entry.size = size if not lfn: return [dir_entry] long_name = name.encode('utf_16_le') entries = [dir_entry] seq = 1 checksum = lfn_checksum(dir_entry.name + dir_entry.ext) while len(long_name) > 0: long_entry, long_name = create_lfn_dirent(long_name, seq, checksum) entries.append(long_entry) seq += 1 entries.reverse() return entries
def mkuimage(inf_name, outf_name, image_name, load_addr, start_addr, os_type): inf = open(inf_name, 'rb') outf = open(outf_name, 'wb') header = xstruct.create(UIMAGE_HEADER) header_size = header.size() # # Write data # outf.seek(header_size, os.SEEK_SET) data = inf.read() data_size = inf.tell() data_crc = calc_crc32(data) data_tstamp = (int)(os.path.getmtime(inf_name)) outf.write(data) data = '' # # Write header # outf.seek(0, os.SEEK_SET) header.magic = 0x27051956 # uImage magic header.header_crc = 0 header.c_tstamp = data_tstamp header.data_size = data_size header.load_addr = load_addr # Address where to load image header.start_addr = start_addr # Address of entry point header.data_crc = data_crc header.os = os_type header.arch = 2 # ARM header.img_type = 2 # Kernel header.compression = 0 # None header.img_name = image_name.encode('ascii') header_crc = calc_crc32(header.pack()) header.header_crc = header_crc outf.write(header.pack()) outf.close()
def create_lfn_dirent(name, seq, checksum): "Create LFN directory entry" entry = xstruct.create(LFN_DIR_ENTRY) name_rest = name[26:] if len(name_rest) > 0: entry.seq = seq else: entry.seq = seq | 0x40 entry.name1 = name[0:10] entry.name2 = name[10:22] entry.name3 = name[22:26] entry.attr = 0x0F entry.rec_type = 0 entry.checksum = checksum entry.cluster = 0 return (entry, name_rest)
def write_superblock(self, block_group): "Write superblock at the current position" sb = xstruct.create(STRUCT_SUPERBLOCK) sb.total_inode_count = self.total_inode_count sb.total_block_count = self.total_block_count sb.reserved_block_count = 0 sb.free_block_count = self.block_allocator.free sb.free_inode_count = self.inode_allocator.free sb.first_block = self.superblock_at_block sb.block_size_log2 = num_of_trailing_bin_zeros(self.block_size) - 10 sb.fragment_size_log2 = sb.block_size_log2 sb.blocks_per_group = self.blocks_per_group sb.fragments_per_group = self.blocks_per_group sb.inodes_per_group = self.inodes_per_group curtime = int(time.time()) sb.mount_time = curtime sb.write_time = curtime sb.mount_count = 0 sb.max_mount_count = 21 sb.magic = 0xEF53 sb.state = 5 # clean sb.error_behavior = 1 # continue on errors sb.rev_minor = 0 sb.last_check_time = curtime sb.max_check_interval = 15552000 # 6 months sb.os = 0 # Linux sb.rev_major = 1 sb.first_inode = self.reserved_inode_count + 1 sb.inode_size = self.inode_size sb.block_group_number = block_group sb.features_compatible = 0 sb.features_incompatible = 2 # filetype sb.features_read_only = 0 sb.uuid = self.uuid.bytes_le sb.volume_name = 'Einherjar rdimage\0' self.outf.write(bytes(sb.pack()))
def write_superblock(self, block_group): "Write superblock at the current position" sb = xstruct.create(STRUCT_SUPERBLOCK) sb.total_inode_count = self.total_inode_count sb.total_block_count = self.total_block_count sb.reserved_block_count = 0 sb.free_block_count = self.block_allocator.free sb.free_inode_count = self.inode_allocator.free sb.first_block = self.superblock_at_block sb.block_size_log2 = num_of_trailing_bin_zeros(self.block_size) - 10 sb.fragment_size_log2 = sb.block_size_log2 sb.blocks_per_group = self.blocks_per_group sb.fragments_per_group = self.blocks_per_group sb.inodes_per_group = self.inodes_per_group curtime = int(time.time()) sb.mount_time = curtime sb.write_time = curtime sb.mount_count = 0 sb.max_mount_count = 21 sb.magic = 0xEF53 sb.state = 5 # clean sb.error_behavior = 1 # continue on errors sb.rev_minor = 0 sb.last_check_time = curtime sb.max_check_interval = 15552000 # 6 months sb.os = 0 # Linux sb.rev_major = 1 sb.first_inode = self.reserved_inode_count + 1 sb.inode_size = self.inode_size sb.block_group_number = block_group sb.features_compatible = 0 sb.features_incompatible = 2 # filetype sb.features_read_only = 0 sb.uuid = self.uuid.bytes_le sb.volume_name = 'HelenOS-rd\0\0\0\0\0\0' self.outf.write(bytes(sb.pack()))
def main(): if (len(sys.argv) < 4): usage(sys.argv[0]) return if (not sys.argv[1].isdigit()): print("<EXTRA_BYTES> must be a number") return extra_bytes = int(sys.argv[1]) path = os.path.abspath(sys.argv[2]) if (not os.path.isdir(path)): print("<PATH> must be a directory") return fat16_clusters = 4096 sector_size = 512 cluster_size = 4096 dirent_size = 32 fatent_size = 2 fat_count = 2 reserved_clusters = 2 # Make sure the filesystem is large enough for FAT16 size = subtree_size( path, cluster_size, dirent_size) + reserved_clusters * cluster_size + extra_bytes while (size // cluster_size < fat16_clusters): if (cluster_size > sector_size): cluster_size = cluster_size // 2 size = subtree_size( path, cluster_size, dirent_size) + reserved_clusters * cluster_size + extra_bytes else: size = fat16_clusters * cluster_size + reserved_clusters * cluster_size root_size = align_up(root_entries(path) * dirent_size, cluster_size) fat_size = align_up( align_up(size, cluster_size) // cluster_size * fatent_size, sector_size) sectors = (cluster_size + fat_count * fat_size + root_size + size) // sector_size root_start = cluster_size + fat_count * fat_size data_start = root_start + root_size outf = open(sys.argv[3], "wb") boot_sector = xstruct.create(BOOT_SECTOR) boot_sector.jmp = [0xEB, 0x3C, 0x90] boot_sector.oem = b'MSDOS5.0' boot_sector.sector = sector_size boot_sector.cluster = cluster_size // sector_size boot_sector.reserved = cluster_size // sector_size boot_sector.fats = fat_count boot_sector.rootdir = root_size // dirent_size if (sectors <= 65535): boot_sector.sectors = sectors else: boot_sector.sectors = 0 boot_sector.descriptor = 0xF8 boot_sector.fat_sectors = fat_size // sector_size boot_sector.track_sectors = 63 boot_sector.heads = 6 boot_sector.hidden = 0 if (sectors > 65535): boot_sector.sectors_big = sectors else: boot_sector.sectors_big = 0 boot_sector.drive = 0x80 boot_sector.extboot_signature = 0x29 boot_sector.serial = random.randint(0, 0x7fffffff) boot_sector.label = b'HELENOS' boot_sector.fstype = b'FAT16 ' boot_sector.boot_signature = [0x55, 0xAA] outf.write(boot_sector.pack()) empty_sector = xstruct.create(EMPTY_SECTOR) # Reserved sectors for i in range(1, cluster_size // sector_size): outf.write(empty_sector.pack()) # FAT tables for i in range(0, fat_count): for j in range(0, fat_size // sector_size): outf.write(empty_sector.pack()) # Root directory for i in range(0, root_size // sector_size): outf.write(empty_sector.pack()) # Data for i in range(0, size // sector_size): outf.write(empty_sector.pack()) fat = array.array('L', [0] * (fat_size // fatent_size)) fat[0] = 0xfff8 fat[1] = 0xffff recursion(True, path, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, 0) # Store FAT fat_entry = xstruct.create(FAT_ENTRY) for i in range(0, fat_count): outf.seek(cluster_size + i * fat_size) for j in range(0, fat_size // fatent_size): fat_entry.next = fat[j] outf.write(fat_entry.pack()) outf.close()
def main(): usage = """ %prog [--extra <extra_bytes>] [--size <size>] <source-path> <output-image>""" parser = OptionParser(usage=usage) parser.add_option("-e", "--extra", action="store", dest="extra_bytes", default=0, type="int", help="Extra bytes to pad filesystem") parser.add_option("-s", "--size", action="store", dest="size", default="0", help="Device size (in bytes)") (options, args) = parser.parse_args() if (len(args) != 2): print "Must specify both source-path and output-image" return extra_bytes = options.extra_bytes m = re.search("^(\d+)([kM])?$", options.size) fs_size = int(m.group(1)) if (m.group(2) == "k"): fs_size = fs_size * 1024 elif (m.group(2) == "M"): fs_size = fs_size * 1024 * 1024 path = os.path.abspath(args[0]) if (not os.path.isdir(path)): print("<PATH> must be a directory") return fat16_clusters = 4096 sector_size = 4096 cluster_size = 4096 dirent_size = 32 fatent_size = 2 fat_count = 1 reserved_clusters = 2 # Make sure the filesystem is large enough for FAT16 size = subtree_size( path, cluster_size, dirent_size) + reserved_clusters * cluster_size + extra_bytes if (fs_size > 0 and size > fs_size): # can't fit on the device print "Directory has size (%dkB) which is larger than device size (%dkB)" % ( size // 1024, fs_size // 1024) return if (fs_size > size): size = fs_size - reserved_clusters * cluster_size #while (size // cluster_size < fat16_clusters): # if (cluster_size > sector_size): # cluster_size = cluster_size // 2 # size = subtree_size(path, cluster_size, dirent_size) + reserved_clusters * cluster_size + extra_bytes # else: # size = fat16_clusters * cluster_size + reserved_clusters * cluster_size root_size = align_up(root_entries(path) * dirent_size, cluster_size) fat_size = align_up( align_up(size, cluster_size) // cluster_size * fatent_size, sector_size) sectors = (cluster_size + fat_count * fat_size + root_size + size) // sector_size root_start = cluster_size + fat_count * fat_size data_start = root_start + root_size outf = open(args[1], "wb") boot_sector = xstruct.create(BOOT_SECTOR) boot_sector.jmp = [0xEB, 0x3C, 0x90] boot_sector.oem = b'MSDOS5.0' boot_sector.sector = sector_size boot_sector.cluster = cluster_size // sector_size boot_sector.reserved = cluster_size // sector_size boot_sector.fats = fat_count boot_sector.rootdir = root_size // dirent_size if (sectors * cluster_size // sector_size < fat16_clusters): boot_sector.sectors = fat16_clusters * sector_size // cluster_size elif (sectors <= 65535): boot_sector.sectors = sectors else: boot_sector.sectors = 0 boot_sector.descriptor = 0xF8 boot_sector.fat_sectors = fat_size // sector_size boot_sector.track_sectors = 63 boot_sector.heads = 6 boot_sector.hidden = 0 if (sectors > 65535): boot_sector.sectors_big = sectors else: boot_sector.sectors_big = 0 boot_sector.drive = 0x80 boot_sector.extboot_signature = 0x29 boot_sector.serial = random.randint(0, 0x7fffffff) boot_sector.label = b'HELENOS' boot_sector.fstype = b'FAT16 ' boot_sector.boot_signature = [0x55, 0xAA] outf.write(boot_sector.pack()) empty_sector = xstruct.create(EMPTY_SECTOR) # Reserved sectors for i in range(1, cluster_size // sector_size): outf.write(empty_sector.pack()) # FAT tables for i in range(0, fat_count): for j in range(0, fat_size // sector_size): outf.write(empty_sector.pack()) # Root directory for i in range(0, root_size // sector_size): outf.write(empty_sector.pack()) # Data for i in range(0, size // sector_size): outf.write(empty_sector.pack()) fat = array.array('L', [0] * (fat_size // fatent_size)) fat[0] = 0xfff8 fat[1] = 0xffff recursion(True, path, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, 0) # Store FAT fat_entry = xstruct.create(FAT_ENTRY) for i in range(0, fat_count): outf.seek(cluster_size + i * fat_size) for j in range(0, fat_size // fatent_size): fat_entry.next = fat[j] outf.write(fat_entry.pack()) outf.close()
def main(): if (len(sys.argv) < 4): usage(sys.argv[0]) return if (not sys.argv[1].isdigit()): print("<EXTRA_BYTES> must be a number") return extra_bytes = int(sys.argv[1]) path = os.path.abspath(sys.argv[2]) if (not os.path.isdir(path)): print("<PATH> must be a directory") return fat16_clusters = 4096 sector_size = 512 cluster_size = 4096 dirent_size = 32 fatent_size = 2 fat_count = 2 reserved_clusters = 2 # Make sure the filesystem is large enough for FAT16 size = subtree_size(path, cluster_size, dirent_size) + reserved_clusters * cluster_size + extra_bytes while (size // cluster_size < fat16_clusters): if (cluster_size > sector_size): cluster_size = cluster_size // 2 size = subtree_size(path, cluster_size, dirent_size) + reserved_clusters * cluster_size + extra_bytes else: size = fat16_clusters * cluster_size + reserved_clusters * cluster_size root_size = align_up(root_entries(path) * dirent_size, cluster_size) fat_size = align_up(align_up(size, cluster_size) // cluster_size * fatent_size, sector_size) sectors = (cluster_size + fat_count * fat_size + root_size + size) // sector_size root_start = cluster_size + fat_count * fat_size data_start = root_start + root_size outf = open(sys.argv[3], "wb") boot_sector = xstruct.create(BOOT_SECTOR) boot_sector.jmp = [0xEB, 0x3C, 0x90] boot_sector.oem = b'MSDOS5.0' boot_sector.sector = sector_size boot_sector.cluster = cluster_size // sector_size boot_sector.reserved = cluster_size // sector_size boot_sector.fats = fat_count boot_sector.rootdir = root_size // dirent_size if (sectors <= 65535): boot_sector.sectors = sectors else: boot_sector.sectors = 0 boot_sector.descriptor = 0xF8 boot_sector.fat_sectors = fat_size // sector_size boot_sector.track_sectors = 63 boot_sector.heads = 6 boot_sector.hidden = 0 if (sectors > 65535): boot_sector.sectors_big = sectors else: boot_sector.sectors_big = 0 boot_sector.drive = 0x80 boot_sector.extboot_signature = 0x29 boot_sector.serial = random.randint(0, 0x7fffffff) boot_sector.label = b'EINHERJAR' boot_sector.fstype = b'FAT16 ' boot_sector.boot_signature = [0x55, 0xAA] outf.write(boot_sector.pack()) empty_sector = xstruct.create(EMPTY_SECTOR) # Reserved sectors for i in range(1, cluster_size // sector_size): outf.write(empty_sector.pack()) # FAT tables for i in range(0, fat_count): for j in range(0, fat_size // sector_size): outf.write(empty_sector.pack()) # Root directory for i in range(0, root_size // sector_size): outf.write(empty_sector.pack()) # Data for i in range(0, size // sector_size): outf.write(empty_sector.pack()) fat = array.array('L', [0] * (fat_size // fatent_size)) fat[0] = 0xfff8 fat[1] = 0xffff recursion(True, path, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, 0) # Store FAT fat_entry = xstruct.create(FAT_ENTRY) for i in range(0, fat_count): outf.seek(cluster_size + i * fat_size) for j in range(0, fat_size // fatent_size): fat_entry.next = fat[j] outf.write(fat_entry.pack()) outf.close()
def main(): usage = """ %prog [--extra <extra_bytes>] [--size <size>] <source-path> <output-image>""" parser = OptionParser(usage=usage) parser.add_option( "-e", "--extra", action="store", dest="extra_bytes", default=0, type="int", help="Extra bytes to pad filesystem" ) parser.add_option("-s", "--size", action="store", dest="size", default="0", help="Device size (in bytes)") (options, args) = parser.parse_args() if len(args) != 2: print "Must specify both source-path and output-image" return extra_bytes = options.extra_bytes m = re.search("^(\d+)([kM])?$", options.size) fs_size = int(m.group(1)) if m.group(2) == "k": fs_size = fs_size * 1024 elif m.group(2) == "M": fs_size = fs_size * 1024 * 1024 path = os.path.abspath(args[0]) if not os.path.isdir(path): print ("<PATH> must be a directory") return fat16_clusters = 4096 sector_size = 4096 cluster_size = 4096 dirent_size = 32 fatent_size = 2 fat_count = 1 reserved_clusters = 2 # Make sure the filesystem is large enough for FAT16 size = subtree_size(path, cluster_size, dirent_size) + reserved_clusters * cluster_size + extra_bytes if fs_size > 0 and size > fs_size: # can't fit on the device print "Directory has size (%dkB) which is larger than device size (%dkB)" % (size // 1024, fs_size // 1024) return if fs_size > size: size = fs_size - reserved_clusters * cluster_size # while (size // cluster_size < fat16_clusters): # if (cluster_size > sector_size): # cluster_size = cluster_size // 2 # size = subtree_size(path, cluster_size, dirent_size) + reserved_clusters * cluster_size + extra_bytes # else: # size = fat16_clusters * cluster_size + reserved_clusters * cluster_size root_size = align_up(root_entries(path) * dirent_size, cluster_size) fat_size = align_up(align_up(size, cluster_size) // cluster_size * fatent_size, sector_size) sectors = (cluster_size + fat_count * fat_size + root_size + size) // sector_size root_start = cluster_size + fat_count * fat_size data_start = root_start + root_size outf = open(args[1], "wb") boot_sector = xstruct.create(BOOT_SECTOR) boot_sector.jmp = [0xEB, 0x3C, 0x90] boot_sector.oem = b"MSDOS5.0" boot_sector.sector = sector_size boot_sector.cluster = cluster_size // sector_size boot_sector.reserved = cluster_size // sector_size boot_sector.fats = fat_count boot_sector.rootdir = root_size // dirent_size if sectors * cluster_size // sector_size < fat16_clusters: boot_sector.sectors = fat16_clusters * sector_size // cluster_size elif sectors <= 65535: boot_sector.sectors = sectors else: boot_sector.sectors = 0 boot_sector.descriptor = 0xF8 boot_sector.fat_sectors = fat_size // sector_size boot_sector.track_sectors = 63 boot_sector.heads = 6 boot_sector.hidden = 0 if sectors > 65535: boot_sector.sectors_big = sectors else: boot_sector.sectors_big = 0 boot_sector.drive = 0x80 boot_sector.extboot_signature = 0x29 boot_sector.serial = random.randint(0, 0x7FFFFFFF) boot_sector.label = b"HELENOS" boot_sector.fstype = b"FAT16 " boot_sector.boot_signature = [0x55, 0xAA] outf.write(boot_sector.pack()) empty_sector = xstruct.create(EMPTY_SECTOR) # Reserved sectors for i in range(1, cluster_size // sector_size): outf.write(empty_sector.pack()) # FAT tables for i in range(0, fat_count): for j in range(0, fat_size // sector_size): outf.write(empty_sector.pack()) # Root directory for i in range(0, root_size // sector_size): outf.write(empty_sector.pack()) # Data for i in range(0, size // sector_size): outf.write(empty_sector.pack()) fat = array.array("L", [0] * (fat_size // fatent_size)) fat[0] = 0xFFF8 fat[1] = 0xFFFF recursion(True, path, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, 0) # Store FAT fat_entry = xstruct.create(FAT_ENTRY) for i in range(0, fat_count): outf.seek(cluster_size + i * fat_size) for j in range(0, fat_size // fatent_size): fat_entry.next = fat[j] outf.write(fat_entry.pack()) outf.close()