eris2010

Documentation: http://frombelow.net/projects/eris2010/
Clone: git clone https://git.frombelow.net/eris2010.git
Log | Files | Refs | README | LICENSE

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()