kfs.py (4946B)
1 #!/usr/bin/env python3 2 """Access Eris 2010 filesystem""" 3 4 import os 5 import argparse 6 import sys 7 8 blocks_per_app = 2**16 9 number_of_apps = 10 10 11 class KFS: 12 def __init__(self, device, command): 13 self.dev = None 14 self.check_device_file(device) 15 self.dev = os.open(device, os.O_RDWR) 16 if command != 'format': 17 # Unless command is format, we only 18 # operate on formatted devices 19 if (self.read_block(block=0))[:2] != b'\x15\xe2': 20 sys.stderr.write("ERROR: Card not formatted for KFS!\n") 21 sys.exit(-1) 22 if (self.read_block(block=0))[2] != 0: 23 sys.stderr.write("ERROR: Wrong file system version!\n") 24 sys.exit(-1) 25 26 27 def __del__(self): 28 if self.dev != None: 29 os.close(self.dev) 30 31 def check_device_file(self, device): 32 # Find device 33 # 34 # Security check: Only small SD cards of 1 GB, 2GB, 4 GB, or 8 GB are accepted. 35 known_devices = [['Generic-', 'SD_MMC', '512', '968.8M'], 36 ['Generic', 'STORAGE_DEVICE', '512', '968.8M'], 37 ['Generic', 'STORAGE_DEVICE', '512', '1.9G'], 38 ['Generic', 'STORAGE_DEVICE', '512', '7.2G'], 39 ['Generic', 'STORAGE_DEVICE', '512', '7.3G'], 40 ['Generic', 'STORAGE_DEVICE', '512', '3.8G']] 41 cmd = os.popen('lsblk --list -o name,vendor,model,phy-sec,size ' + 42 device) 43 cmd.readline() 44 l = cmd.readline().split() 45 if not l[1:] in known_devices: 46 raise IOError("No suitable SD card found") 47 48 def read_block(self, block): 49 return(os.pread(self.dev, 512, 512*block)) 50 51 def write_blocks(self, block, data): 52 return(os.pwrite(self.dev, data, 512*block)) 53 54 55 def format(self): 56 """Format SD card for KFS""" 57 self.write_blocks(block=0, data=b'\x15\xe2\x00\xff') 58 for a in range(number_of_apps): 59 self.write_blocks(block=a*blocks_per_app+1, data=b'\x00') 60 61 def ls(self): 62 """Return list of files on card.""" 63 for a in range(number_of_apps): 64 b = self.read_block(block=a*blocks_per_app+1) 65 number_of_blocks = int(b[0]) 66 if number_of_blocks > 0: 67 end = b[1:].find(b'\x00') 68 filename = b[1:end+1] 69 print("{filenumber}: {filename} ({blocks} blocks)". 70 format(filenumber=a, filename=filename.decode('utf-8'), 71 blocks=number_of_blocks)) 72 print("Autostart: {}".format(self.read_block(0)[3])) 73 74 75 def store(self, app_number, app_name, app_img): 76 with open(app_img, 'rb') as f: 77 img = f.read() 78 number_of_blocks = (len(img) // 512) 79 if (len(img) % 512) != 0: 80 number_of_blocks += 1 81 header = (bytes([number_of_blocks]) + app_name.encode('utf-8') + b'\x00') 82 self.write_blocks(block=app_number*blocks_per_app+1, 83 data=header) 84 self.write_blocks(block=app_number*blocks_per_app+2, 85 data=img) 86 87 88 def autostart(self, app_number): 89 b = list(self.read_block(block=0)) 90 b[3] = app_number 91 self.write_blocks(block=0, data=bytes(b)) 92 93 94 if __name__ == '__main__' or True: 95 list_of_commands = """\ 96 The following commands are available: 97 format : Format card for use with KFS 98 ls : Print list of apps on card. 99 autostart <nr> : Number of program to start on boot (255 to disable autostart). 100 store <nr> <name> <img> : Store image file <img> as application <nr> 101 with name <name>. 102 """ 103 104 parser = argparse.ArgumentParser(description='Access KFS on SD Card.', 105 formatter_class=argparse.RawDescriptionHelpFormatter, 106 epilog=list_of_commands) 107 parser.add_argument('device', metavar='DEV', 108 help='Device') 109 parser.add_argument('command', metavar='CMD', 110 help='Command') 111 parser.add_argument('args', nargs='*', metavar='ARGS', default=[], 112 help='Arguments for command') 113 args = parser.parse_args() 114 fs = KFS(args.device, args.command) 115 if args.command == 'format': 116 fs.format() 117 elif args.command == 'ls': 118 fs.ls() 119 elif ((args.command == 'autostart') and (len(args.args) == 1)): 120 fs.autostart(int(args.args[0])) 121 elif ((args.command == 'store') and (len(args.args) == 3)): 122 fs.store(int(args.args[0]), args.args[1], args.args[2]) 123 else: 124 parser.print_help() 125 if False: 126 b = fs.read_block(0) 127 for c in b: 128 print("{:02x}".format(c), end=" ") 129 print() 130 fs.format() 131 fs.ls()