| Index: embios/trunk/tools/embios.py | 
| — | — | @@ -1,7 +1,7 @@ | 
| 2 | 2 | #!/usr/bin/env python | 
| 3 | 3 | # | 
| 4 | 4 | # | 
| 5 |  | -#    Copyright 2010 TheSeven, benedikt93
 | 
|  | 5 | +#    Copyright 2010 TheSeven, benedikt93, Farthen | 
| 6 | 6 | # | 
| 7 | 7 | # | 
| 8 | 8 | #    This file is part of emBIOS. | 
| — | — | @@ -21,378 +21,595 @@ | 
| 22 | 22 | # | 
| 23 | 23 | # | 
| 24 | 24 |  | 
| 25 |  | -# note: handles commands 1 to 20
 | 
|  | 25 | +import sys | 
|  | 26 | +import os | 
|  | 27 | +import inspect | 
|  | 28 | +import re | 
| 26 | 29 |  | 
| 27 |  | -import sys
 | 
| 28 |  | -import time
 | 
| 29 | 30 | import libembios | 
| 30 |  | -import struct
 | 
|  | 31 | +from libembios import Error | 
|  | 32 | +import libembiosdata | 
| 31 | 33 |  | 
|  | 34 | +class NotImplementedError(Error): | 
|  | 35 | +    pass | 
| 32 | 36 |  | 
| 33 |  | -def usage():
 | 
| 34 |  | -  print ""
 | 
| 35 |  | -  print "Please provide a command and (if needed) parameters as command line arguments"
 | 
| 36 |  | -  print ""
 | 
| 37 |  | -  print "Available commands:"
 | 
| 38 |  | -  print ""
 | 
| 39 |  | -  print "  getinfo <infotype>"
 | 
| 40 |  | -  print "    Get info on the running emBIOS."
 | 
| 41 |  | -  print "    <infotype> may be either off 'version', 'packetsize', 'usermemrange'."
 | 
| 42 |  | -  print ""
 | 
| 43 |  | -  print "  reset <force>"
 | 
| 44 |  | -  print "    Resets the device"
 | 
| 45 |  | -  print "    If <force> is 1, the reset will be forced, otherwise it will be gracefully,"
 | 
| 46 |  | -  print "    which may take some time."
 | 
| 47 |  | -  print ""
 | 
| 48 |  | -  print "  poweroff <force>"
 | 
| 49 |  | -  print "    Powers the device off"
 | 
| 50 |  | -  print "    If <force> is 1, the poweroff will be forced, otherwise it will be gracefully,"
 | 
| 51 |  | -  print "    which may take some time."
 | 
| 52 |  | -  print ""
 | 
| 53 |  | -  print ""
 | 
| 54 |  | -  print "  uploadfile <offset> <file> <usedma> <freezescheduler>"
 | 
| 55 |  | -  print "    Uploads a file to the iPod"
 | 
| 56 |  | -  print "      <offset>: the address to upload the file to"
 | 
| 57 |  | -  print "      <file>: the path to the file"
 | 
| 58 |  | -  print "      <usedma>: if 0, DMA will not be used when uploading the file,"
 | 
| 59 |  | -  print "          otherwise it will be used. It can be omitted, default is then 1"
 | 
| 60 |  | -  print "      <freezescheduler>: if not 0, the scheduler will be frozen during DMA access"
 | 
| 61 |  | -  print "          to prevent non-consistent data after the transfer."
 | 
| 62 |  | -  print "          It can be omitted, default is then 0"
 | 
| 63 |  | -  print ""
 | 
| 64 |  | -  print "  downloadfile <offset> <size> <file> <usedma> <freezescheduler>"
 | 
| 65 |  | -  print "    Uploads a file to the iPod"
 | 
| 66 |  | -  print "      <offset>: the address to upload the file to"
 | 
| 67 |  | -  print "      <size>: the number of bytes to be read"
 | 
| 68 |  | -  print "      <file>: the path to the file"
 | 
| 69 |  | -  print "      <usedma>: if 0, DMA will not be used when downloading the file,"
 | 
| 70 |  | -  print "          otherwise it will be used. It can be omitted, default is then 1"
 | 
| 71 |  | -  print "      <freezescheduler>: if not 0, the scheduler will be frozen during DMA access"
 | 
| 72 |  | -  print "          to prevent non-consistent data after the transfer"
 | 
| 73 |  | -  print "          It can be omitted, default is then 0"
 | 
| 74 |  | -  print ""
 | 
| 75 |  | -  print "  uploadint <offset> <data>"
 | 
| 76 |  | -  print "    Uploads a single integer to the iPod"
 | 
| 77 |  | -  print "      <offset>: the address to upload the integer to"
 | 
| 78 |  | -  print "      <data>: the integer to upload"
 | 
| 79 |  | -  print ""
 | 
| 80 |  | -  print "  downloadint <offset>"
 | 
| 81 |  | -  print "    Downloads a single integer from the iPod and prints it to the console window"
 | 
| 82 |  | -  print "      <offset>: the address to download the integer from"
 | 
| 83 |  | -  print ""
 | 
| 84 |  | -  print ""
 | 
| 85 |  | -  print "  i2crecv <bus> <slave> <addr> <size>"
 | 
| 86 |  | -  print "    Reads data from an I2C device"
 | 
| 87 |  | -  print "      <bus> the bus index"
 | 
| 88 |  | -  print "      <slave> the slave address"
 | 
| 89 |  | -  print "      <addr> the start address on the I2C device"
 | 
| 90 |  | -  print "      <size> the number of bytes to read"
 | 
| 91 |  | -  print ""
 | 
| 92 |  | -  print "  i2csend <bus> <slave> <addr> <db1> <db2> ... <dbN>"
 | 
| 93 |  | -  print "    Writes data to an I2C device"
 | 
| 94 |  | -  print "      <bus> the bus index"
 | 
| 95 |  | -  print "      <slave> the slave address"
 | 
| 96 |  | -  print "      <addr> the start address on the I2C device"
 | 
| 97 |  | -  print "      <db1> ... <dbN> the data in single bytes, seperated by whitespaces,"
 | 
| 98 |  | -  print "                      eg. 0x37 0x56 0x45 0x12"
 | 
| 99 |  | -  print ""
 | 
| 100 |  | -  print ""
 | 
| 101 |  | -  print "  readusbconsole <size> <outtype> <file>"
 | 
| 102 |  | -  print "    Reads data from the USB console."
 | 
| 103 |  | -  print "      <size>: the number of bytes to read"
 | 
| 104 |  | -  print "      <outtype>: defines how to output the result:"
 | 
| 105 |  | -  print "        'file': writes the result to file <file>"
 | 
| 106 |  | -  print "        'printstring': writes the result as string to the console window"
 | 
| 107 |  | -  print "        'printhex': writes the result in hexedit notation to the console window"
 | 
| 108 |  | -  print "      <file>: the file to write the result to, can be omitted"
 | 
| 109 |  | -  print "               if <outtype> is not 'file'"
 | 
| 110 |  | -  print ""
 | 
| 111 |  | -  print "  writeusbconsole file <file> <offset> <length>"
 | 
| 112 |  | -  print "    Writes the file <file> to the USB console."
 | 
| 113 |  | -  print "      Optional params <offset> <length>: specify the range in <file> to write"
 | 
| 114 |  | -  print "  writeusbconsole direct <i1> <i2> ... <iN>"
 | 
| 115 |  | -  print "    Writes the integers <i1> ... <iN> to the USB console."
 | 
| 116 |  | -  print "  writeusbconsole string <str>"
 | 
| 117 |  | -  print "    Writes the string <str> to the USB console."
 | 
| 118 |  | -  print ""
 | 
| 119 |  | -  print "  readdevconsole <bitmask> <size> <outtype> <file>"
 | 
| 120 |  | -  print "    Reads data from one or more of the device's consoles."
 | 
| 121 |  | -  print "      <bitmask>: the bitmask of the consoles to read from"
 | 
| 122 |  | -  print "      <size>: the number of bytes to read"
 | 
| 123 |  | -  print "      <outtype>: defines how to output the result:"
 | 
| 124 |  | -  print "        'file': writes the result to file <file>"
 | 
| 125 |  | -  print "        'printstring': writes the result as string to the console window"
 | 
| 126 |  | -  print "        'printhex': writes the result in hexedit notation to the console window"
 | 
| 127 |  | -  print "      <file>: the file to write the result to, can be omitted"
 | 
| 128 |  | -  print "               if <outtype> is not 'file'"
 | 
| 129 |  | -  print ""
 | 
| 130 |  | -  print "  writedevconsole file <bitmask> <file> <offset> <length>"
 | 
| 131 |  | -  print "    Writes the file <file> to the device consoles specified by <bitmask>"
 | 
| 132 |  | -  print "      Optional params <offset> <length>: specify the range in <file> to write"
 | 
| 133 |  | -  print "  writedevconsole direct <bitmask> <i1> <i2> ... <iN>"
 | 
| 134 |  | -  print "    Writes the integers <i1> ... <iN> to the device consoles specified"
 | 
| 135 |  | -  print "                         by <bitmask>"
 | 
| 136 |  | -  print "  writedevconsole string <bitmask> <str>"
 | 
| 137 |  | -  print "    Writes the string <str> to the device consoles specified by <bitmask>"
 | 
| 138 |  | -  print ""
 | 
| 139 |  | -  print "  flushconsolebuffers <bitmask>"
 | 
| 140 |  | -  print "    flushes one or more of the device consoles' buffers."
 | 
| 141 |  | -  print "      <bitmask>: the bitmask of the consoles to be flushed"
 | 
| 142 |  | -  print ""
 | 
| 143 |  | -  print ""
 | 
| 144 |  | -  print "  getprocessinformation / getprocinfo"
 | 
| 145 |  | -  print "    Fetches data on the currently running processes"
 | 
| 146 |  | -  print "     ATTENTION: this function will be print the information to the console window."
 | 
| 147 |  | -  print "                If several threads are running this might overflow the window,"
 | 
| 148 |  | -  print "                causing not everything to be shown."
 | 
| 149 |  | -  print ""
 | 
| 150 |  | -  print "  lockscheduler"
 | 
| 151 |  | -  print "    Locks (freezes) the scheduler"
 | 
| 152 |  | -  print ""
 | 
| 153 |  | -  print "  unlockscheduler"
 | 
| 154 |  | -  print "    Unlocks the scheduler"
 | 
| 155 |  | -  print ""
 | 
| 156 |  | -  print "  suspendthread <threadid>"
 | 
| 157 |  | -  print "    Suspends/resumes the thread with thread ID <threadid>"
 | 
| 158 |  | -  print ""
 | 
| 159 |  | -  print "  resumethread <threadid>"
 | 
| 160 |  | -  print "    Resumes the thread with thread ID <threadid>"
 | 
| 161 |  | -  print ""
 | 
| 162 |  | -  print "  killthread <threadid>"
 | 
| 163 |  | -  print "    Kills the thread with thread ID <threadid>"
 | 
| 164 |  | -  print ""
 | 
| 165 |  | -  print "  createthread <namepointer> <entrypoint> <stackpointer> <stacksize> <type> <priority> <state>"
 | 
| 166 |  | -  print "    Creates a new thread and returns its thread ID"
 | 
| 167 |  | -  print "      <namepointer> a pointer to the thread's name"
 | 
| 168 |  | -  print "      <entrypoint> a pointer to the entrypoint of the thread"
 | 
| 169 |  | -  print "      <stackpointer> a pointer to the stack of the thread"
 | 
| 170 |  | -  print "      <stacksize> the size of the thread's stack"
 | 
| 171 |  | -  print "      <type> the thread type, vaild are: 0 => user thread, 1 => system thread"
 | 
| 172 |  | -  print "      <priority> the priority of the thread, from 1 to 255"
 | 
| 173 |  | -  print "      <state> the thread's initial state, valid are: 1 => ready, 0 => suspended"
 | 
| 174 |  | -  print ""
 | 
| 175 |  | -  print "  execimage <offset>"
 | 
| 176 |  | -  print "    Executes the emBIOS executable image at <offset>."
 | 
| 177 |  | -  print ""
 | 
| 178 |  | -  print "  execfirmware <offset>"
 | 
| 179 |  | -  print "    Executes the firmware image at the specified address <offset>."
 | 
| 180 |  | -  print ""
 | 
| 181 |  | -  print ""
 | 
| 182 |  | -  print "  readrawbootflash <addr_bootflsh> <addr_mem> <size>"
 | 
| 183 |  | -  print "    Reads <size> bytes from bootflash to memory."
 | 
| 184 |  | -  print "      <addr_bootflsh>: the address in bootflash to read from"
 | 
| 185 |  | -  print "      <addr_mem>: the address in memory to copy the data to"
 | 
| 186 |  | -  print ""
 | 
| 187 |  | -  print "  writerawbootflash <addr_mem> <addr_bootflsh> <size>"
 | 
| 188 |  | -  print "    Writes <size> bytes from memory to bootflash."
 | 
| 189 |  | -  print "    Don't call this unless you really know what you're doing."
 | 
| 190 |  | -  print "      <addr_mem>: the address in memory to copy the data from"
 | 
| 191 |  | -  print "      <addr_bootflsh>: the address in bootflash to write to"
 | 
| 192 |  | -  print ""
 | 
| 193 |  | -  print ""
 | 
| 194 |  | -  print "  flushcaches"
 | 
| 195 |  | -  print "    Flushes the CPUs data and instruction caches."
 | 
| 196 |  | -  print ""
 | 
| 197 |  | -  print "All numbers are hexadecimal!"
 | 
| 198 |  | -  exit(2)
 | 
|  | 37 | +class ArgumentError(Error): | 
|  | 38 | +    pass | 
| 199 | 39 |  | 
|  | 40 | +class ArgumentTypeError(Error): | 
|  | 41 | +    def __init__(self, expected, seen=False): | 
|  | 42 | +        self.expected = expected | 
|  | 43 | +        self.seen = seen | 
|  | 44 | +    def __str__(self): | 
|  | 45 | +        if self.seen: | 
|  | 46 | +            return "Expected " + str(self.expected) + " but saw " + str(self.seen) | 
|  | 47 | +        else: | 
|  | 48 | +            return "Expected " + str(self.expected) + ", but saw something else" | 
| 200 | 49 |  | 
| 201 |  | -def parsecommand(dev, argv):
 | 
| 202 |  | -  if len(argv) < 2: usage()
 | 
| 203 | 50 |  | 
| 204 |  | -  elif argv[1] == "getinfo":
 | 
| 205 |  | -    if len(argv) != 3: usage()
 | 
| 206 |  | -    dev.getinfo(argv[2])
 | 
| 207 |  | -  
 | 
| 208 |  | -  elif argv[1] == "reset":
 | 
| 209 |  | -    if len(argv) != 3: usage()
 | 
| 210 |  | -    dev.reset(int(argv[2]), 16)
 | 
| 211 |  | -  
 | 
| 212 |  | -  elif argv[1] == "poweroff":
 | 
| 213 |  | -    if len(argv) != 3: usage()
 | 
| 214 |  | -    dev.poweroff(int(argv[2]), 16)
 | 
|  | 51 | +def usage(errormsg=None, specific=False): | 
|  | 52 | +    """ | 
|  | 53 | +        Prints the usage information. | 
|  | 54 | +        It is auto generated from various places. | 
|  | 55 | +    """ | 
|  | 56 | +    logger = Logger() | 
|  | 57 | +    cmddict= Commandline.cmddict | 
|  | 58 | +    doc = {} | 
|  | 59 | +    # This sorts the output of various internal functions | 
|  | 60 | +    # and puts everything in easy readable form | 
|  | 61 | +    for function in cmddict: | 
|  | 62 | +        function = cmddict[function].func | 
|  | 63 | +        docinfo = {} | 
|  | 64 | +        name = function.__name__ | 
|  | 65 | +        args = inspect.getargspec(function)[0] | 
|  | 66 | +        docinfo['varargs'] = False | 
|  | 67 | +        if inspect.getargspec(function)[1]: | 
|  | 68 | +            docinfo['varargs'] = True | 
|  | 69 | +        kwargvalues = inspect.getargspec(function)[3] | 
|  | 70 | +        kwargs = {} | 
|  | 71 | +        if args: | 
|  | 72 | +            if kwargvalues: | 
|  | 73 | +                argnum = len(args) - len(kwargvalues) | 
|  | 74 | +                kwargnum = len(kwargvalues) | 
|  | 75 | +                kwargs = dict(zip(args[argnum:], kwargvalues)) | 
|  | 76 | +            else: | 
|  | 77 | +                argnum = len(args) | 
|  | 78 | +        else: | 
|  | 79 | +            argnum = 0 | 
|  | 80 | +        docinfo['args'] = args[1:argnum] | 
|  | 81 | +        docinfo['kwargs'] = kwargs | 
|  | 82 | +        if function.__doc__: | 
|  | 83 | +            # strip unneccessary whitespace | 
|  | 84 | +            docinfo['documentation'] = re.sub(r'\n        ', '\n', function.__doc__) | 
|  | 85 | +        else: | 
|  | 86 | +            docinfo['documentation'] = None | 
|  | 87 | +        doc[name] = docinfo | 
| 215 | 88 |  | 
| 216 |  | -    
 | 
| 217 |  | -  elif argv[1] == "uploadfile":
 | 
| 218 |  | -    if len(argv) < 4 or len(argv) > 6: usage()
 | 
| 219 |  | -    if len(argv) > 4:
 | 
| 220 |  | -      usedma = int(argv[4], 16)
 | 
| 221 |  | -      if len(argv) > 5:
 | 
| 222 |  | -        freezesched = int(argv[5], 16)
 | 
| 223 |  | -      else:
 | 
| 224 |  | -        freezesched = 0
 | 
|  | 89 | +    if not specific: | 
|  | 90 | +        logger.log("Please provide a command and (if needed) parameters as command line arguments\n\n") | 
|  | 91 | +        logger.log("Available commands:\n\n") | 
| 225 | 92 | else: | 
| 226 |  | -      freezesched = 0
 | 
| 227 |  | -      usedma = 1
 | 
| 228 |  | -    dev.uploadfile(int(argv[2], 16), argv[3], usedma, freezesched)
 | 
| 229 |  | -  
 | 
| 230 |  | -  elif argv[1] == "downloadfile":
 | 
| 231 |  | -    if len(argv) < 5 or len(argv) > 7: usage()
 | 
| 232 |  | -    if len(argv) > 5:
 | 
| 233 |  | -      usedma = int(argv[5], 16)
 | 
| 234 |  | -      if len(argv) > 6:
 | 
| 235 |  | -        freezesched = int(argv[6], 16)
 | 
| 236 |  | -      else:
 | 
| 237 |  | -        freezesched = 0
 | 
| 238 |  | -    else:
 | 
| 239 |  | -      freezesched = 0
 | 
| 240 |  | -      usedma = 1
 | 
| 241 |  | -    dev.downloadfile(int(argv[2], 16), int(argv[3], 16), argv[4], usedma, freezesched)
 | 
| 242 |  | -  
 | 
| 243 |  | -  elif argv[1] == "uploadint":
 | 
| 244 |  | -    if len(argv) != 4: usage()
 | 
| 245 |  | -    dev.uploadint(int(argv[2], 16), int(argv[3], 16))
 | 
| 246 |  | -  
 | 
| 247 |  | -  elif argv[1] == "downloadint":
 | 
| 248 |  | -    if len(argv) != 3: usage()
 | 
| 249 |  | -    dev.downloadint(int(argv[2], 16))
 | 
| 250 |  | -  
 | 
| 251 |  | -  
 | 
| 252 |  | -  elif argv[1] == "i2cread":
 | 
| 253 |  | -    if len(argv) != 6: usage()
 | 
| 254 |  | -    dev.i2crecv(int(argv[2], 16), int(argv[3], 16), int(argv[4], 16), int(argv[5], 16))
 | 
|  | 93 | +        logger.log("\n") | 
|  | 94 | +    for function in sorted(doc.items()): | 
|  | 95 | +        function = function[0] | 
|  | 96 | +        if specific == False or specific == function: | 
|  | 97 | +            logger.log("  " + function + " ") | 
|  | 98 | +            for arg in doc[function]['args']: | 
|  | 99 | +                logger.log("<" + arg + "> ") | 
|  | 100 | +            if doc[function]['kwargs']: | 
|  | 101 | +                for kwarg in doc[function]['kwargs']: | 
|  | 102 | +                    logger.log("[" + kwarg + "] ") | 
|  | 103 | +            if doc[function]['varargs']: | 
|  | 104 | +                logger.log("<db1> ... <dbN>") | 
|  | 105 | +            if doc[function]['documentation']: | 
|  | 106 | +                logger.log(doc[function]['documentation']+"\n") | 
| 255 | 107 |  | 
| 256 |  | -  elif argv[1] == "i2csend":
 | 
| 257 |  | -    if len(argv) < 6: usage()
 | 
| 258 |  | -    data = ""
 | 
| 259 |  | -    ptr = 5
 | 
| 260 |  | -    while ptr < len(argv):
 | 
| 261 |  | -      data += struct.pack("<B", int(argv[ptr], 16))
 | 
| 262 |  | -      ptr += 1
 | 
| 263 |  | -    dev.i2csend(int(argv[2], 16), int(argv[3], 16), int(argv[4], 16), data)
 | 
| 264 |  | -  
 | 
| 265 |  | -  
 | 
| 266 |  | -  elif argv[1] == "readusbconsole":
 | 
| 267 |  | -    if len(argv) not in [4, 5]: usage()
 | 
| 268 |  | -    if len(argv) == 4: argv[4] = ""
 | 
| 269 |  | -    dev.readusbcon(int(argv[2], 16), argv[3], argv[4])
 | 
| 270 |  | -  
 | 
| 271 |  | -  elif argv[1] == "writeusbconsole":
 | 
| 272 |  | -    if len(argv) < 4: usage()
 | 
|  | 108 | +    logger.log("\n") | 
|  | 109 | + | 
|  | 110 | +    if errormsg: | 
|  | 111 | +        logger.error(str(errormsg)+"\n") | 
|  | 112 | +    exit(2) | 
|  | 113 | + | 
|  | 114 | + | 
|  | 115 | +class Logger(object): | 
|  | 116 | +    """ | 
|  | 117 | +        Simple stdout logger. | 
|  | 118 | +        Loglevel 4 is most verbose, Loglevel 0 only say something if there is an error. | 
|  | 119 | +    """ | 
|  | 120 | +    def __init__(self): | 
|  | 121 | +        # Possible values: 0 (only errors), 1 (warnings), 2 (info, recommended for production use), 3 and more (debug) | 
|  | 122 | +        self.loglevel = 3 | 
|  | 123 | + | 
|  | 124 | +    def log(self, text): | 
|  | 125 | +        sys.stdout.write(text) | 
| 273 | 126 |  | 
| 274 |  | -    if argv[2] == "file":
 | 
| 275 |  | -      f = open(argv[3], "rb")
 | 
| 276 |  | -      data = f.read()
 | 
| 277 |  | -      
 | 
| 278 |  | -      if len(argv) > 4:
 | 
| 279 |  | -        offset = int(argv[4], 16)
 | 
| 280 |  | -      else:
 | 
| 281 |  | -        offset = 0
 | 
| 282 |  | -      if len(argv) > 5:
 | 
| 283 |  | -        size = int(argv[5], 16)
 | 
| 284 |  | -      else:
 | 
| 285 |  | -        size = len(data)
 | 
| 286 |  | -      if len(argv) > 6: usage()
 | 
| 287 |  | -      
 | 
| 288 |  | -      dev.writeusbcon(data, 0, offset, size)
 | 
| 289 |  | -      
 | 
| 290 |  | -    if argv[2] == "direct":
 | 
| 291 |  | -      data = ""
 | 
| 292 |  | -      ptr = 3
 | 
| 293 |  | -      while ptr < len(argv):
 | 
| 294 |  | -        data += struct.pack("<I", int(argv[ptr], 16))
 | 
| 295 |  | -        ptr += 1
 | 
| 296 |  | -      dev.writeusbcon(data)
 | 
| 297 |  | -      
 | 
| 298 |  | -    if argv[2] == "string":
 | 
| 299 |  | -      if len(argv) > 4: usage()
 | 
| 300 |  | -      dev.writeusbcon(argv[3])
 | 
|  | 127 | +    def debug(self, text): | 
|  | 128 | +        if self.loglevel >= 3: | 
|  | 129 | +            self.log(text) | 
| 301 | 130 |  | 
| 302 |  | -    else: usage()
 | 
| 303 |  | -  
 | 
| 304 |  | -  elif argv[1] == "readdevconsole":
 | 
| 305 |  | -    if len(argv) not in [5, 6]: usage()
 | 
| 306 |  | -    if len(argv) == 5: argv[5] = ""
 | 
| 307 |  | -    dev.readusbcon(int(argv[2], 16), int(argv[3], 16), argv[4], argv[5])
 | 
| 308 |  | -  
 | 
| 309 |  | -  elif argv[1] == "writedevconsole":
 | 
| 310 |  | -    if len(argv) < 5: usage()
 | 
|  | 131 | +    def info(self, text): | 
|  | 132 | +        if self.loglevel >= 2: | 
|  | 133 | +            self.log(text) | 
| 311 | 134 |  | 
| 312 |  | -    if argv[2] == "file":
 | 
| 313 |  | -      f = open(argv[4], "rb")
 | 
| 314 |  | -      data = f.read()
 | 
| 315 |  | -      
 | 
| 316 |  | -      if len(argv) > 5:
 | 
| 317 |  | -        offset = int(argv[5], 16)
 | 
| 318 |  | -      else:
 | 
| 319 |  | -        offset = 0
 | 
| 320 |  | -      if len(argv) > 6:
 | 
| 321 |  | -        size = int(argv[6], 16)
 | 
| 322 |  | -      else:
 | 
| 323 |  | -        size = len(data)
 | 
| 324 |  | -      if len(argv) > 7: usage()
 | 
| 325 |  | -      
 | 
| 326 |  | -      dev.writeusbcon(int(argv[3], 16), data, 0, offset, size)
 | 
| 327 |  | -      
 | 
| 328 |  | -    if argv[2] == "direct":
 | 
| 329 |  | -      data = ""
 | 
| 330 |  | -      ptr = 4
 | 
| 331 |  | -      while ptr < len(argv):
 | 
| 332 |  | -        data += struct.pack("<I", int(argv[ptr], 16))
 | 
| 333 |  | -        ptr += 1
 | 
| 334 |  | -      dev.writeusbcon(int(argv[3], 16), data)
 | 
| 335 |  | -      
 | 
| 336 |  | -    if argv[2] == "string":
 | 
| 337 |  | -      if len(argv) > 5: usage()
 | 
| 338 |  | -      dev.writedevcon(int(argv[3], 16), argv[4])
 | 
|  | 135 | +    def warning(self, text): | 
|  | 136 | +        if self.loglevel >= 1: | 
|  | 137 | +            self.log("WARNING: " + text) | 
| 339 | 138 |  | 
| 340 |  | -    else: usage()
 | 
| 341 |  | -  
 | 
| 342 |  | -  elif argv[1] == "flushconsolebuffers":
 | 
| 343 |  | -    if len(argv) != 3: usage()
 | 
| 344 |  | -    dev.flushconsolebuffers(int(argv[2], 16))
 | 
| 345 |  | -   
 | 
| 346 |  | -   
 | 
| 347 |  | -  elif argv[1] == "getprocessinformation" or argv[1] == "getprocinfo":
 | 
| 348 |  | -    if len(argv) != 2: usage()
 | 
| 349 |  | -    dev.getprocinfo()
 | 
|  | 139 | +    def error(self, text): | 
|  | 140 | +        self.log("ERROR: " + text) | 
|  | 141 | + | 
|  | 142 | + | 
|  | 143 | +def command(func): | 
|  | 144 | +    """ | 
|  | 145 | +        Decorator for all commands. | 
|  | 146 | +        The decorated function is called with (self, all, other, arguments, ...) | 
|  | 147 | +    """ | 
|  | 148 | +    def decorator(args): | 
|  | 149 | +        return func(args[0], *args[1:]) | 
|  | 150 | +    func._command = True | 
|  | 151 | +    decorator.func = func | 
|  | 152 | +    return decorator | 
|  | 153 | + | 
|  | 154 | + | 
|  | 155 | +def commandClass(cls): | 
|  | 156 | +    """ | 
|  | 157 | +        Decorator for the class. Sets the self.cmddict of the class | 
|  | 158 | +        to all functions decorated with @command | 
|  | 159 | +    """ | 
|  | 160 | +    cls.cmddict = {} | 
|  | 161 | +    for attr, value in cls.__dict__.iteritems(): | 
|  | 162 | +        if getattr(value, 'func', False): | 
|  | 163 | +            if getattr(value.func, '_command', False): | 
|  | 164 | +                cls.cmddict[value.func.__name__] = value | 
|  | 165 | +    return cls | 
|  | 166 | + | 
|  | 167 | + | 
|  | 168 | +@commandClass | 
|  | 169 | +class Commandline(object): | 
|  | 170 | +    """ | 
|  | 171 | +        If you want to create a new commandline function you just need to | 
|  | 172 | +        create a function with the name of it in this class and decorate | 
|  | 173 | +        it with the decorator @command. If you don't want to call the desired | 
|  | 174 | +        function (wrong arguments etc) just raise ArgumentError with or | 
|  | 175 | +        without an error message or raise ArgumentCountError | 
|  | 176 | +    """ | 
|  | 177 | +    def __init__(self): | 
|  | 178 | +        self.logger = Logger() | 
|  | 179 | +        try: | 
|  | 180 | +            self.embios = libembios.Embios() | 
|  | 181 | +        except libembios.DeviceNotFoundError: | 
|  | 182 | +            self.logger.error("No emBIOS device found!") | 
|  | 183 | +            end(1) | 
|  | 184 | + | 
|  | 185 | +    def _parsecommand(self, func, args): | 
|  | 186 | +        # adds self to the commandline args. | 
|  | 187 | +        # this is needed because the functions need access to their class. | 
|  | 188 | +        args.insert(0, self) | 
|  | 189 | +        if func in self.cmddict: | 
|  | 190 | +            try: | 
|  | 191 | +                self.cmddict[func](args) | 
|  | 192 | +            except ArgumentError, e: | 
|  | 193 | +                usage(e) | 
|  | 194 | +            except ArgumentError: | 
|  | 195 | +                usage("Syntax Error in function '" + func + "'") | 
|  | 196 | +            except ArgumentTypeError, e: | 
|  | 197 | +                usage(e) | 
|  | 198 | +            except NotImplementedError: | 
|  | 199 | +                self.logger.error("This function is not implemented yet!") | 
|  | 200 | +            except libembios.DeviceError, e: | 
|  | 201 | +                self.logger.error(str(e)) | 
|  | 202 | +            except TypeError, e: | 
|  | 203 | +                if str(e).split(" ", 1)[0] == func + "()": | 
|  | 204 | +                    self.logger.error(usage("Argument Error in '" + func + "': Wrong argument count", specific=func)) | 
|  | 205 | +                else: | 
|  | 206 | +                    raise | 
|  | 207 | +        else: | 
|  | 208 | +            usage("No such command") | 
| 350 | 209 |  | 
| 351 |  | -  elif argv[1] == "lockscheduler":
 | 
| 352 |  | -    if len(argv) != 2: usage()
 | 
| 353 |  | -    dev.freezescheduler(1)
 | 
|  | 210 | +    @staticmethod | 
|  | 211 | +    def _bool(something): | 
|  | 212 | +        """ | 
|  | 213 | +            Converts quite everything into bool. | 
|  | 214 | +        """ | 
|  | 215 | +        if type(something) == bool: | 
|  | 216 | +            return something | 
|  | 217 | +        elif type(something) == int or type(something) == long: | 
|  | 218 | +            return bool(something) | 
|  | 219 | +        elif type(something == str): | 
|  | 220 | +            truelist = ['true', '1', 't', 'y', 'yes'] | 
|  | 221 | +            falselist = ['false', '0', 'f', 'n', 'no'] | 
|  | 222 | +            if something.lower() in truelist: | 
|  | 223 | +                return True | 
|  | 224 | +            elif something.lower() in falselist: | 
|  | 225 | +                return False | 
|  | 226 | +        raise ArgumentTypeError("bool", "'"+str(something)+"'") | 
|  | 227 | + | 
|  | 228 | +    @staticmethod | 
|  | 229 | +    def _hexint(something): | 
|  | 230 | +        """ | 
|  | 231 | +            Converts quite everything to a hexadecimal represented integer. | 
|  | 232 | +            This works for default arguments too, because it returns | 
|  | 233 | +            None when it found that it got a NoneType object. | 
|  | 234 | +        """ | 
|  | 235 | +        if type(something) == int or type(something) == long: | 
|  | 236 | +            return something | 
|  | 237 | +        elif type(something) == str: | 
|  | 238 | +            try: | 
|  | 239 | +                return int(something, 16) | 
|  | 240 | +            except ValueError: | 
|  | 241 | +                raise ArgumentTypeError("hexadecimal coded integer", "'"+str(something)+"'") | 
|  | 242 | +        elif type(something) == NoneType: | 
|  | 243 | +            return None | 
|  | 244 | +        else: | 
|  | 245 | +            raise ArgumentTypeError("hexadecimal coded integer", "'"+str(something)+"'") | 
|  | 246 | + | 
|  | 247 | +    @staticmethod | 
|  | 248 | +    def _strcheck(string, values): | 
|  | 249 | +        if string in values: | 
|  | 250 | +            return string | 
|  | 251 | +        else: | 
|  | 252 | +            expected = "" | 
|  | 253 | +            for item in values: | 
|  | 254 | +                expected += "'" + item + "', " | 
|  | 255 | +            expected = expected[:-2] | 
|  | 256 | +            raise ArgumentTypeError("one out of " + expected, "'" + string + "'") | 
| 354 | 257 |  | 
| 355 |  | -  elif argv[1] == "unlockscheduler":
 | 
| 356 |  | -    if len(argv) != 2: usage()
 | 
| 357 |  | -    dev.freezescheduler(0)
 | 
| 358 | 258 |  | 
| 359 |  | -  elif argv[1] == "suspendthread":
 | 
| 360 |  | -    if len(argv) != 3: usage()
 | 
| 361 |  | -    dev.suspendthread(1, int(argv[2], 16))
 | 
|  | 259 | +    @command | 
|  | 260 | +    def getinfo(self, infotype): | 
|  | 261 | +        """ | 
|  | 262 | +            Get info on the running emBIOS. | 
|  | 263 | +            <infotype> may be either of 'version', 'packetsize', 'usermemrange'. | 
|  | 264 | +        """ | 
|  | 265 | +        if infotype == "version": | 
|  | 266 | +            resp = self.embios.getversioninfo() | 
|  | 267 | +            self.logger.info(libembiosdata.swtypes[resp.swtypeid] + " v" + str(resp.majorv) + "." + str(resp.minorv) + | 
|  | 268 | +                             "." + str(resp.patchv) + " r" + str(resp.revision) + " running on " + libembiosdata.hwtypes[resp.hwtypeid] + "\n") | 
|  | 269 | +        elif infotype == "packetsize": | 
|  | 270 | +            resp = self.embios.getpacketsizeinfo() | 
|  | 271 | +            self.logger.info("Maximum packet sizes: "+str(resp)) | 
|  | 272 | +        elif infotype == "usermemrange": | 
|  | 273 | +            resp = self.embios.getusermemrange() | 
|  | 274 | +            self.logger.info("The user memory range is "+hex(resp.lower)+" - "+hex(resp.upper-1)) | 
|  | 275 | +        else: | 
|  | 276 | +            raise ArgumentTypeError("one out of 'version', 'packetsize', 'usermemrange'", infotype) | 
| 362 | 277 |  | 
| 363 |  | -  elif argv[1] == "resumethread":
 | 
| 364 |  | -    if len(argv) != 3: usage()
 | 
| 365 |  | -    dev.suspendthread(0, int(argv[2], 16))
 | 
|  | 278 | +    @command | 
|  | 279 | +    def reset(self, force=False): | 
|  | 280 | +        """ | 
|  | 281 | +            Resets the device" | 
|  | 282 | +            If <force> is 1, the reset will be forced, otherwise it will be gracefully, | 
|  | 283 | +            which may take some time. | 
|  | 284 | +        """ | 
|  | 285 | +        force = self._bool(force) | 
|  | 286 | +        if force: self.logger.info("Resetting forcefully...\n") | 
|  | 287 | +        else: self.logger.info("Resetting...\n") | 
|  | 288 | +        self.embios.reset(force) | 
| 366 | 289 |  | 
| 367 |  | -  elif argv[1] == "killthread":
 | 
| 368 |  | -    if len(argv) != 3: usage()
 | 
| 369 |  | -    dev.killthread(int(argv[2], 16))
 | 
|  | 290 | +    @command | 
|  | 291 | +    def poweroff(self, force=False): | 
|  | 292 | +        """ | 
|  | 293 | +            Powers the device off | 
|  | 294 | +            If <force> is 1, the poweroff will be forced, otherwise it will be gracefully, | 
|  | 295 | +            which may take some time. | 
|  | 296 | +        """ | 
|  | 297 | +        force = self._bool(force) | 
|  | 298 | +        if force: self.logger.info("Resetting forcefully...\n") | 
|  | 299 | +        else: self.logger.info("Resetting...\n") | 
|  | 300 | +        self.embios.reset(force) | 
| 370 | 301 |  | 
| 371 |  | -  elif argv[1] == "createthread":
 | 
| 372 |  | -    if len(argv) != 9: usage()
 | 
| 373 |  | -    dev.createthread(int(argv[2], 16), int(argv[3], 16), int(argv[4], 16), int(argv[5], 16), int(argv[6], 16), int(argv[7], 16), int(argv[8], 16))
 | 
|  | 302 | +    @command | 
|  | 303 | +    def uploadfile(self, addr, filename): | 
|  | 304 | +        """ | 
|  | 305 | +            Uploads a file to the device | 
|  | 306 | +            <offset>: the address to upload the file to | 
|  | 307 | +            <filename>: the path to the file | 
|  | 308 | +        """ | 
|  | 309 | +        addr = self._hexint(addr) | 
|  | 310 | +        try: | 
|  | 311 | +            f = open(filename, 'rb') | 
|  | 312 | +        except IOError: | 
|  | 313 | +            raise ArgumentError("File not readable. Does it exist?") | 
|  | 314 | +        self.logger.info("Writing file '"+filename+"' to memory at "+hex(addr)+"...") | 
|  | 315 | +        with f: | 
|  | 316 | +            self.embios.write(addr, f.read()) | 
|  | 317 | +        self.logger.info("done\n") | 
|  | 318 | + | 
|  | 319 | + | 
|  | 320 | + | 
|  | 321 | +    @command | 
|  | 322 | +    def downloadfile(self, addr, size, filename): | 
|  | 323 | +        """ | 
|  | 324 | +            Uploads a file to the device | 
|  | 325 | +            <offset>: the address to upload the file to | 
|  | 326 | +            <size>: the number of bytes to be read | 
|  | 327 | +            <filename>: the path to the file | 
|  | 328 | +        """ | 
|  | 329 | +        addr = self._hexint(addr) | 
|  | 330 | +        size = self._hexint(size) | 
|  | 331 | +        try: | 
|  | 332 | +            f = open(filename, 'wb') | 
|  | 333 | +        except IOError: | 
|  | 334 | +            raise ArgumentError("Can not open file for write!") | 
|  | 335 | +        self.logger.info("Reading data from address "+hex(addr)+" with the size "+hex(size)+" to '"+filename+"'...") | 
|  | 336 | +        with f: | 
|  | 337 | +            f.write(self.embios.read(addr, size)) | 
|  | 338 | +        self.logger.info("done\n") | 
|  | 339 | + | 
|  | 340 | +    @command | 
|  | 341 | +    def uploadint(self, addr, integer): | 
|  | 342 | +        """ | 
|  | 343 | +            Uploads a single integer to the device | 
|  | 344 | +            <offset>: the address to upload the integer to | 
|  | 345 | +            <data>: the integer to upload | 
|  | 346 | +        """ | 
|  | 347 | +        addr = self._hexint(addr) | 
|  | 348 | +        integer = self._hexint(integer) | 
|  | 349 | +        if integer > 0xFFFFFFFF: | 
|  | 350 | +            raise ArgumentError("Specified integer too long") | 
|  | 351 | +        data = chr(integer) | 
|  | 352 | +        self.embios.writemem(addr, data) | 
|  | 353 | +        self.logger.info("Integer '"+hex(integer)+"' written successfully to "+hex(addr)) | 
|  | 354 | + | 
|  | 355 | +    @command | 
|  | 356 | +    def downloadint(self, addr): | 
|  | 357 | +        """ | 
|  | 358 | +            Downloads a single integer from the device and prints it to the console window | 
|  | 359 | +            <offset>: the address to download the integer from | 
|  | 360 | +        """ | 
|  | 361 | +        addr = self._hexint(addr) | 
|  | 362 | +        data = self.embios.readmem(addr, 1) | 
|  | 363 | +        integer = ord(data) | 
|  | 364 | +        self.logger.info("Integer '"+hex(integer)+"' read from address "+hex(addr)) | 
|  | 365 | + | 
|  | 366 | +    @command | 
|  | 367 | +    def i2crecv(self, bus, slave, addr, size): | 
|  | 368 | +        """ | 
|  | 369 | +            Reads data from an I2C device | 
|  | 370 | +            <bus> the bus index | 
|  | 371 | +            <slave> the slave address | 
|  | 372 | +            <addr> the start address on the I2C device | 
|  | 373 | +            <size> the number of bytes to read | 
|  | 374 | +        """ | 
|  | 375 | +        bus = self._hexint(bus) | 
|  | 376 | +        slave = self._hexint(slave) | 
|  | 377 | +        addr = self._hexint(addr) | 
|  | 378 | +        size = self._hexint(size) | 
|  | 379 | +        raise NotImplementedError | 
|  | 380 | + | 
|  | 381 | +    @command | 
|  | 382 | +    def i2csend(self, bus, slave, addr, *args): | 
|  | 383 | +        """ | 
|  | 384 | +            Writes data to an I2C device | 
|  | 385 | +            <bus> the bus index | 
|  | 386 | +            <slave> the slave address | 
|  | 387 | +            <addr> the start address on the I2C device | 
|  | 388 | +            <db1> ... <dbN> the data in single bytes, seperated by whitespaces, | 
|  | 389 | +                eg. 0x37 0x56 0x45 0x12 | 
|  | 390 | +        """ | 
|  | 391 | +        bus = self._hexint(bus) | 
|  | 392 | +        slave = self._hexint(slave) | 
|  | 393 | +        addr = self._hexint(addr) | 
|  | 394 | +        data = [] | 
|  | 395 | +        for arg in args: | 
|  | 396 | +            data.append(self._hexint(arg)) | 
|  | 397 | +        raise NotImplementedError | 
|  | 398 | + | 
|  | 399 | +    @command | 
|  | 400 | +    def readusbconsole(self, size, outtype): | 
|  | 401 | +        """ | 
|  | 402 | +            Reads data from the USB console. | 
|  | 403 | +            <size>: the number of bytes to read | 
|  | 404 | +            <outtype>: defines how to output the result: | 
|  | 405 | +                'file': writes the result to file <file> | 
|  | 406 | +                'printstring': writes the result as string to the console window | 
|  | 407 | +                'printhex': writes the result in hexedit notation to the console window | 
|  | 408 | +            <file>: the file to write the result to, can be omitted | 
|  | 409 | +                if <outtype> is not 'file' | 
|  | 410 | +        """ | 
|  | 411 | +        size = self._hexint(size) | 
|  | 412 | +        raise NotImplementedError | 
|  | 413 | + | 
|  | 414 | + | 
|  | 415 | +    @command | 
|  | 416 | +    def writeusbconsole_file(self, file, offset=0, length=None): | 
|  | 417 | +        """ | 
|  | 418 | +            Writes the file <file> to the USB console. | 
|  | 419 | +            Optional params <offset> <length>: specify the range in <file> to write | 
|  | 420 | +        """ | 
|  | 421 | +        # We don't care about file here, this is done when opening it | 
|  | 422 | +        offset = self._hexint(offset) | 
|  | 423 | +        length = self._hexint(length) | 
|  | 424 | +        raise NotImplementedError | 
|  | 425 | + | 
|  | 426 | +    @command | 
|  | 427 | +    def writeusbconsole_direct(self, *args): | 
|  | 428 | +        """ | 
|  | 429 | +            Writes the strings <db1> ... <dbN> to the USB console." | 
|  | 430 | +        """ | 
|  | 431 | +        raise NotImplementedError | 
|  | 432 | + | 
|  | 433 | +    @command | 
|  | 434 | +    def readdevconsole(self, bitmask, size, outtype, file=None): | 
|  | 435 | +        """ | 
|  | 436 | +            Reads data from one or more of the device's consoles. | 
|  | 437 | +            <bitmask>: the bitmask of the consoles to read from | 
|  | 438 | +            <size>: the number of bytes to read | 
|  | 439 | +            <outtype>: defines how to output the result: | 
|  | 440 | +                'file': writes the result to file <file> | 
|  | 441 | +                'printstring': writes the result as string to the console window | 
|  | 442 | +                'printhex': writes the result in hexedit notation to the console window | 
|  | 443 | +            <file>: the file to write the result to, can be omitted | 
|  | 444 | +                if <outtype> is not 'file' | 
|  | 445 | +        """ | 
|  | 446 | +        bitmask = self._hexint(bitmask) | 
|  | 447 | +        size = self._hexint(size) | 
|  | 448 | +        outtype = self._strcheck(['file', 'printstring', 'printhex']) | 
|  | 449 | +        raise NotImplementedError | 
|  | 450 | + | 
|  | 451 | +    @command | 
|  | 452 | +    def writedevconsole_file(self, bitmask, file, offset=0, length=None): | 
|  | 453 | +        """ | 
|  | 454 | +            Writes the file <file> to the device consoles specified by <bitmask> | 
|  | 455 | +            Optional params <offset> <length>: specify the range in <file> to write | 
|  | 456 | +        """ | 
|  | 457 | +        bitmask = self._hexint(bitmask) | 
|  | 458 | +        # We don't care about file here, this is done when opening it | 
|  | 459 | +        offset = self._hexint(offset) | 
|  | 460 | +        length = self._hexint(length) | 
|  | 461 | +        raise NotImplementedError | 
|  | 462 | + | 
|  | 463 | +    @command | 
|  | 464 | +    def writedevconsole_direct(self, bitmask, *args): | 
|  | 465 | +        """ | 
|  | 466 | +            Writes the integers <db1> ... <dbN> to the device consoles specified | 
|  | 467 | +            by <bitmask> | 
|  | 468 | +        """ | 
|  | 469 | +        bitmask = self._hexint(bitmask) | 
|  | 470 | +        data = [] | 
|  | 471 | +        for arg in args: | 
|  | 472 | +            data.append(self._hexint(arg)) | 
|  | 473 | +        raise NotImplementedError | 
|  | 474 | + | 
|  | 475 | +    @command | 
|  | 476 | +    def flushconsolebuffers(self, bitmask): | 
|  | 477 | +        """ | 
|  | 478 | +            flushes one or more of the device consoles' buffers. | 
|  | 479 | +            <bitmask>: the bitmask of the consoles to be flushed | 
|  | 480 | +        """ | 
|  | 481 | +        bitmask = self._hexint(bitmask) | 
|  | 482 | +        raise NotImplementedError | 
|  | 483 | + | 
|  | 484 | +    @command | 
|  | 485 | +    def getprocinfo(self): | 
|  | 486 | +        """ | 
|  | 487 | +            Fetches data on the currently running processes | 
|  | 488 | +            ATTENTION: this function will be print the information to the console window. | 
|  | 489 | +                If several threads are running this might overflow the window, | 
|  | 490 | +                causing not everything to be shown. | 
|  | 491 | +        """ | 
|  | 492 | +        raise NotImplementedError | 
|  | 493 | + | 
|  | 494 | +    @command | 
|  | 495 | +    def lockscheduler(self): | 
|  | 496 | +        """ | 
|  | 497 | +            Locks (freezes) the scheduler | 
|  | 498 | +        """ | 
|  | 499 | +        raise NotImplementedError | 
|  | 500 | + | 
|  | 501 | +    @command | 
|  | 502 | +    def unlockscheduler(self): | 
|  | 503 | +        """ | 
|  | 504 | +            Unlocks (unfreezes) the scheduler | 
|  | 505 | +        """ | 
|  | 506 | +        raise NotImplementedError | 
|  | 507 | + | 
|  | 508 | +    @command | 
|  | 509 | +    def suspendthread(self, threadid): | 
|  | 510 | +        """ | 
|  | 511 | +            Suspends/resumes the thread with thread ID <threadid> | 
|  | 512 | +        """ | 
|  | 513 | +        threadid = self._hexint(threadid) | 
|  | 514 | +        raise NotImplementedError | 
|  | 515 | + | 
|  | 516 | +    @command | 
|  | 517 | +    def resumethread(self, threadid): | 
|  | 518 | +        """ | 
|  | 519 | +            Resumes the thread with thread ID <threadid> | 
|  | 520 | +        """ | 
|  | 521 | +        threadid = self._hexint(threadid) | 
|  | 522 | +        raise NotImplementedError | 
|  | 523 | + | 
|  | 524 | +    @command | 
|  | 525 | +    def killthread(self, threadid): | 
|  | 526 | +        """ | 
|  | 527 | +            Kills the thread with thread ID <threadid> | 
|  | 528 | +        """ | 
|  | 529 | +        threadid = self._hexint(threadid) | 
|  | 530 | +        raise NotImplementedError | 
|  | 531 | + | 
|  | 532 | +    @command | 
|  | 533 | +    def createthread(self, nameptr, entrypoint, stackptr, stacksize, threadtype, priority, state): | 
|  | 534 | +        """ | 
|  | 535 | +            Creates a new thread and returns its thread ID | 
|  | 536 | +            <namepointer> a pointer to the thread's name | 
|  | 537 | +            <entrypoint> a pointer to the entrypoint of the thread | 
|  | 538 | +            <stackpointer> a pointer to the stack of the thread | 
|  | 539 | +            <stacksize> the size of the thread's stack | 
|  | 540 | +            <type> the thread type, vaild are: 0 => user thread, 1 => system thread | 
|  | 541 | +            <priority> the priority of the thread, from 1 to 255 | 
|  | 542 | +            <state> the thread's initial state, valid are: 1 => ready, 0 => suspended | 
|  | 543 | +        """ | 
|  | 544 | +        nameptr = self._hexint(nameptr) | 
|  | 545 | +        entrypoint = self._hexint(entrypoint) | 
|  | 546 | +        stackpointer = self._hexint(stackpointer) | 
|  | 547 | +        stacksize = self._hexint(stacksize) | 
|  | 548 | +        priority = self._hexint(priority) | 
|  | 549 | +        self.embios.createthread(nameptr, entrypoint, stackptr, stacksize, type, priority, state) | 
|  | 550 | + | 
|  | 551 | +    @command | 
|  | 552 | +    def run(self, address): | 
|  | 553 | +        """ | 
|  | 554 | +            Executes the emBIOS application at <address>. | 
|  | 555 | +        """ | 
|  | 556 | +        address = self._hexint(address) | 
|  | 557 | +        raise NotImplementedError | 
|  | 558 | + | 
|  | 559 | +    @command | 
|  | 560 | +    def readrawbootflash(self, addr_flash, addr_mem, size): | 
|  | 561 | +        """ | 
|  | 562 | +            Reads <size> bytes from bootflash to memory. | 
|  | 563 | +            <addr_bootflsh>: the address in bootflash to read from | 
|  | 564 | +            <addr_mem>: the address in memory to copy the data to | 
|  | 565 | +        """ | 
|  | 566 | +        addr_flash = self._hexint(addr_flash) | 
|  | 567 | +        addr_mem = self._hexint(addr_mem) | 
|  | 568 | +        size = self._hexint(size) | 
|  | 569 | +        raise NotImplementedError | 
|  | 570 | + | 
|  | 571 | +    @command | 
|  | 572 | +    def writerawbootflash(self, addr_flash, addr_mem, size): | 
|  | 573 | +        """ | 
|  | 574 | +            Writes <size> bytes from memory to bootflash. | 
|  | 575 | +            ATTENTION: Don't call this unless you really know what you're doing! | 
|  | 576 | +            This may BRICK your device (unless it has a good recovery option) | 
|  | 577 | +            <addr_mem>: the address in memory to copy the data from | 
|  | 578 | +            <addr_bootflsh>: the address in bootflash to write to | 
|  | 579 | +        """ | 
|  | 580 | +        addr_flash = self._hexint(addr_flash) | 
|  | 581 | +        addr_mem = self._hexint(addr_mem) | 
|  | 582 | +        size = self._hexint(size) | 
|  | 583 | +        raise NotImplementedError | 
|  | 584 | + | 
|  | 585 | +    @command | 
|  | 586 | +    def flushcaches(self): | 
|  | 587 | +        """ | 
|  | 588 | +            Flushes the CPUs data and instruction caches. | 
|  | 589 | +        """ | 
|  | 590 | +        raise NotImplementedError | 
| 374 | 591 |  | 
| 375 |  | -  elif argv[1] == "execimage":
 | 
| 376 |  | -    if len(argv) != 3: usage()
 | 
| 377 |  | -    dev.execimage(int(argv[2], 16))
 | 
|  | 592 | +    @command | 
|  | 593 | +    def aesencrypt(self, addr, size, keyindex): | 
|  | 594 | +        """ | 
|  | 595 | +            Encrypt a buffer using a hardware key | 
|  | 596 | +        """ | 
|  | 597 | +        addr = self._hexint(addr) | 
|  | 598 | +        size = self._hexint(size) | 
|  | 599 | +        keyindex = self._hexint(keyindex) | 
|  | 600 | +        self.embios.aesencrypt(addr, size, keyindex) | 
| 378 | 601 |  | 
| 379 |  | -  elif argv[1] == "execfirmware":
 | 
| 380 |  | -    if len(argv) != 3: usage()
 | 
| 381 |  | -    dev.execfirmware(int(argv[2], 16))
 | 
| 382 |  | -    
 | 
| 383 |  | -  elif argv[1] == "readrawbootflash":
 | 
| 384 |  | -    if len(argv) != 5: usage()
 | 
| 385 |  | -    dev.readrawbootflash(int(argv[2], 16), int(argv[3], 16), int(argv[4], 16))
 | 
| 386 |  | -    
 | 
| 387 |  | -  elif argv[1] == "writerawbootflash":
 | 
| 388 |  | -    if len(argv) != 5: usage()
 | 
| 389 |  | -    dev.writerawbootflash(int(argv[2], 16), int(argv[3], 16), int(argv[4], 16))
 | 
| 390 |  | - 
 | 
| 391 |  | - 
 | 
| 392 |  | -  elif argv[1] == "flushcaches":
 | 
| 393 |  | -    if len(argv) != 2: usage()
 | 
| 394 |  | -    dev.flushcaches()
 | 
| 395 |  | -    
 | 
| 396 |  | -  else: usage()
 | 
|  | 602 | +    @command | 
|  | 603 | +    def aesdecrypt(self, addr, size, keyindex): | 
|  | 604 | +        """ | 
|  | 605 | +            Decrypt a buffer using a hardware key | 
|  | 606 | +        """ | 
|  | 607 | +        addr = self._hexint(addr) | 
|  | 608 | +        size = self._hexint(size) | 
|  | 609 | +        keyindex = self._hexint(keyindex) | 
|  | 610 | +        self.embios.aesdecrypt(addr, size, keyindex) | 
| 397 | 611 |  | 
| 398 |  | -dev = libembios.embios()
 | 
| 399 |  | -parsecommand(dev, sys.argv)
 | 
|  | 612 | +if __name__ == "__main__": | 
|  | 613 | +    if len(sys.argv) < 2: | 
|  | 614 | +        usage("No command specified") | 
|  | 615 | +    interface = Commandline() | 
|  | 616 | +    interface._parsecommand(sys.argv[1], sys.argv[2:]) | 
| \ No newline at end of file | 
| Index: embios/trunk/tools/libembiosdata.py | 
| — | — | @@ -0,0 +1,19 @@ | 
|  | 2 | +hwtypes = { | 
|  | 3 | +    0: "invalid", | 
|  | 4 | +    0x47324e49: "iPod nano 2g", | 
|  | 5 | +    0x47334e49: "iPod nano 3g", | 
|  | 6 | +    0x47344e49: "iPod nano 4g", | 
|  | 7 | +    0x4c435049: "iPod classic" | 
|  | 8 | +} | 
|  | 9 | + | 
|  | 10 | +swtypes = { | 
|  | 11 | +    0: "invalid", | 
|  | 12 | +    1: "emBIOS Debugger" | 
|  | 13 | +} | 
|  | 14 | + | 
|  | 15 | +responsecodes = { | 
|  | 16 | +    0: "invalid", | 
|  | 17 | +    1: "ok", | 
|  | 18 | +    2: "unsupported", | 
|  | 19 | +    3: "busy" | 
|  | 20 | +} | 
| \ No newline at end of file | 
| Index: embios/trunk/tools/libembios.py | 
| — | — | @@ -1,7 +1,7 @@ | 
| 2 | 2 | #!/usr/bin/env python | 
| 3 | 3 | # | 
| 4 | 4 | # | 
| 5 |  | -#    Copyright 2010 TheSeven, benedikt93
 | 
|  | 5 | +#    Copyright 2010 TheSeven, benedikt93, Farthen | 
| 6 | 6 | # | 
| 7 | 7 | # | 
| 8 | 8 | #    This file is part of emBIOS. | 
| — | — | @@ -21,996 +21,440 @@ | 
| 22 | 22 | # | 
| 23 | 23 | # | 
| 24 | 24 |  | 
| 25 |  | -# note: handles commands 1 to 21
 | 
| 26 |  | -
 | 
| 27 | 25 | import sys | 
| 28 |  | -import math
 | 
| 29 | 26 | import struct | 
| 30 |  | -import time
 | 
| 31 |  | -import usb
 | 
|  | 27 | +import usb.core | 
|  | 28 | +import libembiosdata | 
| 32 | 29 |  | 
|  | 30 | +class Error(Exception): | 
|  | 31 | +    def __init__(self, value=None): | 
|  | 32 | +        self.value = value | 
|  | 33 | +    def __str__(self): | 
|  | 34 | +        if self.value != None: | 
|  | 35 | +            return repr(self.value) | 
| 33 | 36 |  | 
| 34 |  | -class embios:
 | 
| 35 |  | -  def __init__(self, devtype = 0, type = 0):
 | 
| 36 |  | -    busses = usb.busses()
 | 
| 37 |  | - 
 | 
| 38 |  | -    for bus in busses:
 | 
| 39 |  | -      devices = bus.devices
 | 
| 40 |  | -      for dev in devices:
 | 
| 41 |  | -        if dev.idVendor == 0xffff and dev.idProduct == 0xe000:
 | 
| 42 |  | -          # get endpoints
 | 
| 43 |  | -          self.__coutep = dev.configurations[0].interfaces[0][0].endpoints[0].address
 | 
| 44 |  | -          self.__cinep = dev.configurations[0].interfaces[0][0].endpoints[1].address
 | 
| 45 |  | -          self.__doutep = dev.configurations[0].interfaces[0][0].endpoints[2].address
 | 
| 46 |  | -          self.__dinep = dev.configurations[0].interfaces[0][0].endpoints[3].address
 | 
| 47 |  | -          
 | 
| 48 |  | -          handle = dev.open()
 | 
| 49 |  | -          handle.setConfiguration(1)
 | 
| 50 |  | -          handle.claimInterface(0)
 | 
| 51 |  | -          
 | 
| 52 |  | -          # get version info
 | 
| 53 |  | -          handle.bulkWrite(self.__coutep, struct.pack("<IIII", 1, 0, 0, 0))
 | 
| 54 |  | -          response = self.__getbulk(handle, self.__cinep, 0x10)
 | 
| 55 |  | -          self.__checkstatus(response)
 | 
| 56 |  | -          i = struct.unpack("<IIBBBBI", response)
 | 
| 57 |  | -          
 | 
| 58 |  | -          if devtype in [0, i[6]] and type in [0, i[5]]:
 | 
| 59 |  | -            # correct device
 | 
| 60 |  | -            self.handle = handle
 | 
| 61 |  | -            self.dev = dev
 | 
| 62 |  | -            
 | 
| 63 |  | -            self.svnrev, self.major, self.minor, self.patch, self.type, self.devtype = i[1:]
 | 
| 64 |  | -            self.__myprint("Connected to emBIOS %s v%d.%d.%d (SVN revision: %d) on %s, USB version %s\n" \
 | 
| 65 |  | -                  % (self.type2name(self.type), self.major, self.minor, self.patch, self.svnrev, \
 | 
| 66 |  | -                     self.devtype2name(self.devtype), dev.deviceVersion))
 | 
| 67 |  | -                     
 | 
| 68 |  | -            # get packet size info
 | 
| 69 |  | -            self.getinfo("packetsize", 1)
 | 
| 70 |  | -            
 | 
| 71 |  | -            return
 | 
| 72 |  | -          
 | 
| 73 |  | -          # wrong device
 | 
| 74 |  | -          handle.releaseInterface()
 | 
|  | 37 | +class ArgumentError(Error): | 
|  | 38 | +    pass | 
| 75 | 39 |  | 
| 76 |  | -    raise Exception("Could not find specified device (devtype = %d, type = %d)" % (devtype, type))
 | 
|  | 40 | +class DeviceNotFoundError(Error): | 
|  | 41 | +    pass | 
| 77 | 42 |  | 
|  | 43 | +class DeviceError(Error): | 
|  | 44 | +    pass | 
| 78 | 45 |  | 
| 79 |  | -#=====================================================================================    
 | 
| 80 |  | -    
 | 
| 81 |  | -    
 | 
| 82 |  | -  @staticmethod
 | 
| 83 |  | -  def __myprint(data, silent = 0):
 | 
| 84 |  | -    if not silent:
 | 
| 85 |  | -      sys.stdout.write(data)
 | 
| 86 |  | -      sys.stdout.flush()
 | 
|  | 46 | +class SendError(Error): | 
|  | 47 | +    pass | 
| 87 | 48 |  | 
| 88 |  | -      
 | 
| 89 |  | -  @staticmethod
 | 
| 90 |  | -  def __gethexviewprintout(data, title, showaddr):
 | 
| 91 |  | -    printout_temp = struct.unpack("%dB" % (len(data)), data)
 | 
| 92 |  | -      
 | 
| 93 |  | -    printout = title + ":\n"
 | 
| 94 |  | -    pointer = 0
 | 
| 95 |  | -    pointer2 = 0
 | 
| 96 |  | -    
 | 
| 97 |  | -    while (pointer < len(printout_temp)):
 | 
| 98 |  | -      pointer2 = 0
 | 
| 99 |  | -      if (showaddr): printout += "0x%08x     " % (pointer)
 | 
| 100 |  | -      while (pointer2 < 0x10) and (pointer < len(printout_temp)):
 | 
| 101 |  | -        printout += ("%2x " % (printout_temp[pointer]))
 | 
| 102 |  | -        pointer += 1
 | 
| 103 |  | -        pointer2 += 1
 | 
| 104 |  | -      printout += "\n"
 | 
| 105 |  | -        
 | 
| 106 |  | -    if (pointer2 != 0x10):
 | 
| 107 |  | -      printout += "\n"
 | 
| 108 |  | -      
 | 
| 109 |  | -    return printout
 | 
|  | 49 | +class ReceiveError(Error): | 
|  | 50 | +    pass | 
| 110 | 51 |  | 
| 111 |  | -    
 | 
| 112 |  | -  @staticmethod
 | 
| 113 |  | -  def __getbulk(handle, endpoint, size):
 | 
| 114 |  | -    data = handle.bulkRead(endpoint, size, 1000)
 | 
| 115 |  | -    return struct.pack("%dB" % len(data), *data)
 | 
| 116 | 52 |  | 
| 117 |  | -
 | 
| 118 |  | -  @staticmethod
 | 
| 119 |  | -  def __checkstatus(data):
 | 
| 120 |  | -    errorcode = struct.unpack("<I", data[:4])[0]
 | 
| 121 |  | -    if errorcode == 1:
 | 
| 122 |  | -      # everything went fine
 | 
| 123 |  | -      return
 | 
| 124 |  | -    elif errorcode == 2:
 | 
| 125 |  | -      print("\nError: Device doesn't support this function!")
 | 
| 126 |  | -      raise Exception("emBIOS device doesn't support this function!")
 | 
| 127 |  | -    elif errorcode == 3:
 | 
| 128 |  | -      print("\nError: Device is busy!")
 | 
| 129 |  | -      raise Exception("emBIOS device is busy!")
 | 
| 130 |  | -    else:
 | 
| 131 |  | -      print("\nUnknown error %d" % errorcode)
 | 
| 132 |  | -      raise Exception("Unknown emBIOS error %d" % errorcode)
 | 
| 133 |  | -
 | 
| 134 |  | -
 | 
| 135 |  | -  @staticmethod
 | 
| 136 |  | -  def type2name(type):
 | 
| 137 |  | -    if type == 1: return "Debugger"
 | 
| 138 |  | -    else: return "UNKNOWN (0x%08x)" % type
 | 
| 139 |  | -
 | 
| 140 |  | -
 | 
| 141 |  | -  @staticmethod
 | 
| 142 |  | -  def devtype2name(devtype):
 | 
| 143 |  | -    if devtype == 0x47324e49: return "iPod Nano 2G"
 | 
| 144 |  | -    if devtype == 0x47334e49: return "iPod Nano 3G"
 | 
| 145 |  | -    if devtype == 0x47344e49: return "iPod Nano 4G"
 | 
| 146 |  | -    if devtype == 0x4c435049: return "iPod Classic"
 | 
| 147 |  | -    else: return "UNKNOWN (0x%08x)" % devtype
 | 
| 148 |  | -
 | 
| 149 |  | -
 | 
| 150 |  | -#=====================================================================================
 | 
| 151 |  | -    
 | 
| 152 |  | -    
 | 
| 153 |  | -  def getinfo (self, infotype, silent = 0):
 | 
| 154 |  | -    if (infotype == "version"):
 | 
| 155 |  | -      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 1, 0, 0, 0))
 | 
| 156 |  | -      response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 157 |  | -      self.__checkstatus(response)
 | 
| 158 |  | -      
 | 
| 159 |  | -      i = struct.unpack("<IIBBBBI", response)
 | 
| 160 |  | -      
 | 
| 161 |  | -      self.svnrev, self.major, self.minor, self.patch, self.type, self.devtype = i[1:]
 | 
| 162 |  | -      
 | 
| 163 |  | -      self.__myprint("emBIOS %s v%d.%d.%d (SVN revision: %d) on %s, USB version %s\n" \
 | 
| 164 |  | -              % (self.type2name(self.type), self.major, self.minor, self.patch, self.svnrev, \
 | 
| 165 |  | -                 self.devtype2name(self.devtype), self.dev.deviceVersion)\
 | 
| 166 |  | -            , silent)
 | 
| 167 |  | -      
 | 
| 168 |  | -    elif (infotype == "packetsize"):
 | 
| 169 |  | -      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 1, 1, 0, 0))
 | 
| 170 |  | -      response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 171 |  | -      self.__checkstatus(response)
 | 
| 172 |  | -      
 | 
| 173 |  | -      i = struct.unpack("<IHHII", response)
 | 
| 174 |  | -      
 | 
| 175 |  | -      self.cout_maxsize = i[1]
 | 
| 176 |  | -      self.cin_maxsize = i[2]
 | 
| 177 |  | -      self.dout_maxsize = i[3]
 | 
| 178 |  | -      self.din_maxsize = i[4]
 | 
| 179 |  | -      
 | 
| 180 |  | -      self.__myprint("Maximum packet sizes:\n     Command out: %d bytes\n     Command in: %d bytes\n     Data out: %d bytes\n     Data in: %d bytes\n" \
 | 
| 181 |  | -              % (self.cout_maxsize, self.cin_maxsize, self.dout_maxsize, self.din_maxsize)
 | 
| 182 |  | -            , silent)
 | 
| 183 |  | -    
 | 
| 184 |  | -    elif (infotype == "usermemrange"):
 | 
| 185 |  | -      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 1, 1, 0, 0))
 | 
| 186 |  | -      response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 187 |  | -      self.__checkstatus(response)
 | 
| 188 |  | -      
 | 
| 189 |  | -      i = struct.unpack("<IIII", response)
 | 
| 190 |  | -      
 | 
| 191 |  | -      self.usermem_lower = i[1]
 | 
| 192 |  | -      self.usermem_upper = i[2]
 | 
| 193 |  | -      
 | 
| 194 |  | -      self.__myprint("User memory range:\n     Lower bound (inclusive): %x\n     Upper bound (exclusive) %x\n" \
 | 
| 195 |  | -              % (self.usermem_lower, self.usermem_upper)
 | 
| 196 |  | -            , silent)
 | 
| 197 |  | -      
 | 
| 198 |  | -    else:
 | 
| 199 |  | -      self.__myprint("Unsupported type of info: %d" % (infotype))
 | 
| 200 |  | -    
 | 
| 201 |  | -  
 | 
| 202 |  | -  def reset(self, force, silent = 0):
 | 
| 203 |  | -    """ Resets the device.
 | 
| 204 |  | -      <force>: if 0, the reset will be gracefully, otherwise it will be forced.
 | 
| 205 |  | -      <silent>: if not 0, nothing will be printed to the console window
 | 
|  | 53 | +class Bunch(dict): | 
| 206 | 54 | """ | 
| 207 |  | -    if (force == 0):
 | 
| 208 |  | -      force = 1
 | 
| 209 |  | -    else:
 | 
| 210 |  | -      force = 0
 | 
| 211 |  | -  
 | 
| 212 |  | -    self.__myprint("Resetting device...", silent)
 | 
| 213 |  | -    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 2, force, 0, 0))
 | 
| 214 |  | -    
 | 
| 215 |  | -    if (force == 1):
 | 
| 216 |  | -      # reset not forced
 | 
| 217 |  | -      response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 218 |  | -      self.__checkstatus(response)
 | 
| 219 |  | -    
 | 
| 220 |  | -    self.__myprint(" done\n", silent)  
 | 
| 221 |  | -  
 | 
| 222 |  | -
 | 
| 223 |  | -  def poweroff(self, force, silent = 0):
 | 
| 224 |  | -    """ Powers the device off.
 | 
| 225 |  | -      <force>: if 0, the poweroff will be gracefully, otherwise it will be forced.
 | 
| 226 |  | -      <silent>: if not 0, nothing will be printed to the console window
 | 
|  | 55 | +        This is a dict whose items can also be accessed with | 
|  | 56 | +        bunchinstance.something. | 
| 227 | 57 | """ | 
| 228 |  | -    if (force == 0):
 | 
| 229 |  | -      force = 1
 | 
| 230 |  | -    else:
 | 
| 231 |  | -      force = 0
 | 
| 232 |  | -  
 | 
| 233 |  | -    self.__myprint("Powering device off...", silent)
 | 
| 234 |  | -    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 3, force, 0, 0))
 | 
|  | 58 | +    def __init__(self, **kw): | 
|  | 59 | +        dict.__init__(self, kw) | 
|  | 60 | +        self.__dict__ = self | 
| 235 | 61 |  | 
| 236 |  | -    if (force == 1):
 | 
| 237 |  | -      # shutdown not forced
 | 
| 238 |  | -      response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 239 |  | -      self.__checkstatus(response)
 | 
|  | 62 | +    def __getstate__(self): | 
|  | 63 | +        return self | 
| 240 | 64 |  | 
| 241 |  | -    self.__myprint(" done\n", silent)
 | 
| 242 |  | -  
 | 
| 243 |  | -  
 | 
| 244 |  | -#=====================================================================================
 | 
| 245 |  | -  
 | 
| 246 |  | - 
 | 
| 247 |  | -  def write(self, offset, data, usedma, freezesched, *range):
 | 
| 248 |  | -    boffset = 0
 | 
| 249 |  | -      
 | 
| 250 |  | -    size = len(data)
 | 
| 251 |  | -      
 | 
| 252 |  | -    if len(range) > 0:
 | 
| 253 |  | -      boffset = range[0]
 | 
| 254 |  | -    if len(range) > 1:
 | 
| 255 |  | -      size = range[1]
 | 
| 256 |  | -        
 | 
| 257 |  | -    if (size == 0):
 | 
| 258 |  | -      return
 | 
| 259 |  | -     
 | 
| 260 |  | -    # correct alignment
 | 
| 261 |  | -    while (offset & 0xF) != 0:
 | 
| 262 |  | -      blocklen = size
 | 
| 263 |  | -        
 | 
| 264 |  | -      if (blocklen > size):
 | 
| 265 |  | -        blocklen = size
 | 
| 266 |  | -      if (blocklen > self.cout_maxsize - 0x10):
 | 
| 267 |  | -        blocklen = self.cout_maxsize - 0x10
 | 
| 268 |  | -      
 | 
| 269 |  | -      blocklen = (blocklen & 0xFFFFFFF0) +  (offset & 0xF)
 | 
| 270 |  | -      
 | 
| 271 |  | -      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 5, offset, blocklen, 0) + data[boffset:boffset+blocklen])
 | 
| 272 |  | -      response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 273 |  | -      self.__checkstatus(response)
 | 
| 274 |  | -      
 | 
| 275 |  | -      offset += blocklen
 | 
| 276 |  | -      boffset += blocklen
 | 
| 277 |  | -      size -= blocklen
 | 
|  | 65 | +    def __setstate__(self, state): | 
|  | 66 | +        self.update(state) | 
|  | 67 | +        self.__dict__ = self | 
| 278 | 68 |  | 
| 279 |  | -    # write data with DMA, if it makes sense (-> much data) and isn't forbidden
 | 
| 280 |  | -    if (usedma) and (size > 2 * (self.cout_maxsize - 16)): 
 | 
| 281 |  | -      if (freezesched):
 | 
| 282 |  | -        self.freezescheduler(1, 0)
 | 
| 283 |  | -    
 | 
| 284 |  | -      while (size > (self.cout_maxsize - 16)):
 | 
| 285 |  | -        blocklen = size
 | 
| 286 |  | -     
 | 
| 287 |  | -        if (blocklen > self.dout_maxsize):
 | 
| 288 |  | -          blocklen = self.dout_maxsize
 | 
| 289 |  | -          
 | 
| 290 |  | -        self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 7, offset, blocklen, 0))
 | 
| 291 |  | -        response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 292 |  | -        self.__checkstatus(response)
 | 
| 293 |  | -      
 | 
| 294 |  | -        self.handle.bulkWrite(self.__doutep, data[boffset:boffset+blocklen])
 | 
| 295 |  | -      
 | 
| 296 |  | -        offset += blocklen
 | 
| 297 |  | -        boffset += blocklen
 | 
| 298 |  | -        size -= blocklen
 | 
| 299 |  | -        
 | 
| 300 |  | -      if (freezesched):
 | 
| 301 |  | -        self.freezescheduler(0, 0)
 | 
| 302 |  | -        
 | 
| 303 |  | -    # write rest of data
 | 
| 304 |  | -    while (size > 0):
 | 
| 305 |  | -      blocklen = size
 | 
| 306 |  | -      
 | 
| 307 |  | -      if (blocklen > self.cout_maxsize - 0x10):
 | 
| 308 |  | -        blocklen = self.cout_maxsize - 0x10
 | 
| 309 |  | -    
 | 
| 310 |  | -      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 5, offset, blocklen, 0) + data[boffset:boffset+blocklen])
 | 
| 311 |  | -      response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 312 |  | -      self.__checkstatus(response)
 | 
| 313 |  | -      
 | 
| 314 |  | -      offset += blocklen
 | 
| 315 |  | -      boffset += blocklen
 | 
| 316 |  | -      size -= blocklen
 | 
| 317 |  | -    
 | 
| 318 | 69 |  | 
| 319 |  | -  def read(self, offset, size, usedma, freezesched):
 | 
| 320 |  | -    if (size == 0):
 | 
| 321 |  | -      return
 | 
|  | 70 | +class Embios(object): | 
|  | 71 | +    def __init__(self): | 
|  | 72 | +        self.lib = Lib(self) | 
| 322 | 73 |  | 
| 323 |  | -    data = ""
 | 
|  | 74 | +    @staticmethod | 
|  | 75 | +    def _alignsplit(addr, size, blksize, align): | 
|  | 76 | +        end = addr + size | 
|  | 77 | +        if addr & (align - 1): | 
|  | 78 | +            bodyaddr = (addr + min(size, blksize)) & ~(align - 1) | 
|  | 79 | +        else: bodyaddr = addr | 
|  | 80 | +        headsize = bodyaddr - addr | 
|  | 81 | +        if (size - headsize) & (align - 1): | 
|  | 82 | +            tailaddr = (end - min(end - bodyaddr, blksize) + align - 1) & ~(align - 1) | 
|  | 83 | +        else: tailaddr = end | 
|  | 84 | +        tailsize = end - tailaddr | 
|  | 85 | +        return (headsize, tailaddr - bodyaddr, tailsize) | 
| 324 | 86 |  | 
| 325 |  | -    # correct alignment
 | 
| 326 |  | -    while (offset & 0xF) != 0:
 | 
| 327 |  | -      blocklen = size
 | 
| 328 |  | -      
 | 
| 329 |  | -      if (blocklen > size):
 | 
| 330 |  | -        blocklen = size
 | 
| 331 |  | -      if (blocklen > self.cin_maxsize - 0x10):
 | 
| 332 |  | -        blocklen = self.cin_maxsize - 0x10
 | 
| 333 |  | -        
 | 
| 334 |  | -      blocklen = (blocklen & 0xFFFFFFF0) +  (offset & 0xF)
 | 
| 335 |  | -      
 | 
| 336 |  | -      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 4, offset, blocklen, 0))
 | 
| 337 |  | -      response = self.__getbulk(self.handle, self.__cinep, 0x10 + blocklen)
 | 
| 338 |  | -      self.__checkstatus(response)
 | 
| 339 |  | -      
 | 
| 340 |  | -      data += response[0x10:]
 | 
| 341 |  | -      
 | 
| 342 |  | -      offset += blocklen
 | 
| 343 |  | -      size -= blocklen
 | 
| 344 |  | -
 | 
| 345 |  | -    # read data with DMA, if it makes sense (-> much data) and isn't forbidden
 | 
| 346 |  | -    if (usedma) and (size > 2 * (self.cin_maxsize - 16)):
 | 
| 347 |  | -      if (freezesched):
 | 
| 348 |  | -        self.freezescheduler(1, 0)
 | 
| 349 |  | -
 | 
| 350 |  | -      while (size > (self.cin_maxsize - 16)):
 | 
| 351 |  | -        blocklen = size
 | 
| 352 |  | -      
 | 
| 353 |  | -        if (blocklen > self.din_maxsize):
 | 
| 354 |  | -          blocklen = self.din_maxsize
 | 
| 355 |  | -          
 | 
| 356 |  | -        self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 6, offset, blocklen, 0))
 | 
| 357 |  | -        response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 358 |  | -        self.__checkstatus(response)
 | 
| 359 |  | -      
 | 
| 360 |  | -        data += self.__getbulk(self.handle, self.__doutep, blocklen)
 | 
| 361 |  | -      
 | 
| 362 |  | -        offset += blocklen
 | 
| 363 |  | -        size -= blocklen
 | 
| 364 |  | -        
 | 
| 365 |  | -      if (freezesched):
 | 
| 366 |  | -        self.freezescheduler(0, 0)
 | 
| 367 |  | -        
 | 
| 368 |  | -    # read rest of data
 | 
| 369 |  | -    while (size > 0):
 | 
| 370 |  | -      blocklen = size
 | 
| 371 |  | -      
 | 
| 372 |  | -      if (blocklen > self.cin_maxsize - 0x10):
 | 
| 373 |  | -        blocklen = self.cin_maxsize - 0x10
 | 
|  | 87 | +    def getversioninfo(self): | 
|  | 88 | +        """ This returns the emBIOS version and device information. """ | 
|  | 89 | +        return self.lib.monitorcommand(struct.pack("IIII", 1, 0, 0, 0), "IBBBBI", ("revision", "majorv", "minorv", "patchv", "swtypeid", "hwtypeid")) | 
| 374 | 90 |  | 
| 375 |  | -      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 4, offset, blocklen, 0))
 | 
| 376 |  | -      response = self.__getbulk(self.handle, self.__cinep, 0x10 + blocklen)
 | 
| 377 |  | -      self.__checkstatus(response)
 | 
| 378 |  | -      
 | 
| 379 |  | -      data += response[0x10:]
 | 
| 380 |  | -      
 | 
| 381 |  | -      offset += blocklen
 | 
| 382 |  | -      size -= blocklen
 | 
| 383 |  | -      
 | 
| 384 |  | -    return data
 | 
| 385 |  | -
 | 
| 386 |  | - 
 | 
| 387 |  | -  def uploadfile(self, offset, file, usedma = 1, freezesched = 0, silent = 0):
 | 
| 388 |  | -    self.__myprint("Uploading %s to 0x%08x..." % (file, offset), silent)
 | 
| 389 |  | -    f = open(file, "rb")
 | 
| 390 |  | -
 | 
| 391 |  | -    while True:
 | 
| 392 |  | -      data = f.read(262144)
 | 
| 393 |  | -      if data == "": break
 | 
| 394 |  | -      self.write(offset, data, usedma, freezesched)
 | 
| 395 |  | -      offset += len(data)
 | 
| 396 |  | -      self.__myprint(".")
 | 
| 397 |  | -
 | 
| 398 |  | -    self.__myprint(" done\n", silent) 
 | 
|  | 91 | +    def getpacketsizeinfo(self): | 
|  | 92 | +        """ This returns the emBIOS max packet size information. | 
|  | 93 | +            It also sets the properties of the device object accordingly. | 
|  | 94 | +        """ | 
|  | 95 | +        resp = self.lib.monitorcommand(struct.pack("IIII", 1, 1, 0, 0), "HHII", ("coutmax", "cinmax", "doutmax", "dinmax")) | 
|  | 96 | +        self.lib.dev.packetsizelimit['cout'] = resp.coutmax | 
|  | 97 | +        self.lib.dev.packetsizelimit['cin'] = resp.cinmax | 
|  | 98 | +        self.lib.dev.packetsizelimit['din'] = resp.dinmax | 
|  | 99 | +        self.lib.dev.packetsizelimit['dout'] = resp.doutmax | 
|  | 100 | +        return resp | 
| 399 | 101 |  | 
| 400 |  | -  
 | 
| 401 |  | -  def downloadfile(self, offset, size, file, usedma = 1, freezesched = 0, silent = 0):
 | 
| 402 |  | -    self.__myprint("Downloading 0x%x bytes from 0x%08x to %s..." % (size, offset, file), silent)
 | 
| 403 |  | -    f = open(file, "wb")
 | 
| 404 |  | -
 | 
| 405 |  | -    while True:
 | 
| 406 |  | -      blocklen = size
 | 
| 407 |  | -      if blocklen == 0: break
 | 
| 408 |  | -      if blocklen > 262144: blocklen = 262144
 | 
| 409 |  | -      f.write(self.read(offset, blocklen, usedma, freezesched))
 | 
| 410 |  | -      offset += blocklen
 | 
| 411 |  | -      size -= blocklen
 | 
| 412 |  | -      self.__myprint(".")
 | 
| 413 |  | -
 | 
| 414 |  | -    self.__myprint(" done\n", silent)
 | 
|  | 102 | +    def getusermemrange(self): | 
|  | 103 | +        """ This returns the memory range the user has access to. """ | 
|  | 104 | +        return self.lib.monitorcommand(struct.pack("IIII", 1, 2, 0, 0), "III", ("lower", "upper", None)) | 
| 415 | 105 |  | 
|  | 106 | +    def reset(self, force=False): | 
|  | 107 | +        """ Reboot the device """ | 
|  | 108 | +        if force: | 
|  | 109 | +            return self.lib.monitorcommand(struct.pack("IIII", 2, 0, 0, 0)) | 
|  | 110 | +        else: | 
|  | 111 | +            return self.lib.monitorcommand(struct.pack("IIII", 2, 1, 0, 0), "III", (None, None, None)) | 
| 416 | 112 |  | 
| 417 |  | -  def uploadint(self, offset, data, silent = 0):
 | 
| 418 |  | -    self.__myprint("Uploading 0x%08x to 0x%08x..." % (data, offset), silent)
 | 
| 419 |  | -    data = struct.pack('<I', data)
 | 
| 420 |  | -    self.write(offset, data, 0, 0)
 | 
| 421 |  | -    self.__myprint(" done\n", silent)
 | 
| 422 |  | -
 | 
| 423 |  | -
 | 
| 424 |  | -  def downloadint(self, offset, silent = 0):
 | 
| 425 |  | -    self.__myprint("Downloading an integer from 0x%08x..." % (offset), silent)
 | 
| 426 |  | -    data = self.read(offset, 4, 0, 0)
 | 
| 427 |  | -    number = struct.unpack('<I', data)
 | 
| 428 |  | -    self.__myprint(" done\nValue was: 0x%08x\n" % (number), silent)
 | 
|  | 113 | +    def poweroff(self, force=False): | 
|  | 114 | +        """ Powers the device off. """ | 
|  | 115 | +        if force: | 
|  | 116 | +            return self.lib.monitorcommand(struct.pack("IIII", 3, 0, 0, 0)) | 
|  | 117 | +        else: | 
|  | 118 | +            return self.lib.monitorcommand(struct.pack("IIII", 3, 1, 0, 0), "III", (None, None, None)) | 
| 429 | 119 |  | 
| 430 |  | -    return data
 | 
|  | 120 | +    def read(self, addr, size): | 
|  | 121 | +        """ Reads the memory from location 'addr' with size 'size' | 
|  | 122 | +            from the device. This cares about too long packages | 
|  | 123 | +            and decides whether to use DMA or not. | 
|  | 124 | +        """ | 
|  | 125 | +        if not self.lib.connected: | 
|  | 126 | +            self.lib.connect() | 
|  | 127 | +        cin_maxsize = self.lib.dev.packetsizelimit["cin"] - 0x10 | 
|  | 128 | +        din_maxsize = self.lib.dev.packetsizelimit["din"] | 
|  | 129 | +        data = "" | 
|  | 130 | +        (headsize, bodysize, tailsize) = self._alignsplit(addr, size, cin_maxsize, 16) | 
|  | 131 | +        if headsize != 0: | 
|  | 132 | +            data += self.readmem(addr, headsize) | 
|  | 133 | +            addr += headsize | 
|  | 134 | +        while bodysize > 0: | 
|  | 135 | +            if bodysize >= 2 * cin_maxsize: | 
|  | 136 | +                readsize = min(bodysize, din_maxsize) | 
|  | 137 | +                data += self.readdma(addr, readsize) | 
|  | 138 | +            else: | 
|  | 139 | +                readsize = min(bodysize, cin_maxsize) | 
|  | 140 | +                data += self.readmem(addr, readsize) | 
|  | 141 | +            addr += readsize | 
|  | 142 | +            bodysize -= readsize | 
|  | 143 | +        if tailsize != 0: | 
|  | 144 | +            data += self.readmem(addr, tailsize) | 
|  | 145 | +        return data | 
| 431 | 146 |  | 
|  | 147 | +    def write(self, addr, data): | 
|  | 148 | +        """ Writes the data in 'data' to the location 'addr' | 
|  | 149 | +            in the memory of the device. This cares about too long packages | 
|  | 150 | +            and decides whether to use DMA or not. | 
|  | 151 | +        """ | 
|  | 152 | +        if not self.lib.connected: | 
|  | 153 | +            self.lib.connect() | 
|  | 154 | +        cout_maxsize = self.lib.dev.packetsizelimit["cout"] - 0x10 | 
|  | 155 | +        dout_maxsize = self.lib.dev.packetsizelimit["dout"] | 
|  | 156 | +        (headsize, bodysize, tailsize) = self._alignsplit(addr, len(data), cout_maxsize, 16) | 
|  | 157 | +        offset = 0 | 
|  | 158 | +        if headsize != 0: | 
|  | 159 | +            self.writemem(addr, headsize) | 
|  | 160 | +            offset += headsize | 
|  | 161 | +            addr += headsize | 
|  | 162 | +        while bodysize > 0: | 
|  | 163 | +            if bodysize >= 2 * cout_maxsize: | 
|  | 164 | +                writesize = min(bodysize, dout_maxsize) | 
|  | 165 | +                self.writedma(addr, data[offset:offset+writesize]) | 
|  | 166 | +            else: | 
|  | 167 | +                writesize = min(bodysize, cout_maxsize) | 
|  | 168 | +                self.writemem(addr, data[offset:offset+writesize]) | 
|  | 169 | +            offset += writesize | 
|  | 170 | +            addr += writesize | 
|  | 171 | +            bodysize -= writesize | 
|  | 172 | +        if tailsize != 0: | 
|  | 173 | +            self.writemem(addr, data[offset:offset+tailsize]) | 
|  | 174 | +        return data | 
| 432 | 175 |  | 
| 433 |  | -#=====================================================================================  
 | 
|  | 176 | +    def readmem(self, addr, size): | 
|  | 177 | +        """ Reads the memory from location 'addr' with size 'size' | 
|  | 178 | +            from the device. | 
|  | 179 | +        """ | 
|  | 180 | +        resp = self.lib.monitorcommand(struct.pack("IIII", 4, addr, size, 0), "III%ds" % size, (None, None, None, "data")) | 
|  | 181 | +        return resp.data | 
|  | 182 | + | 
|  | 183 | +    def writemem(self, addr, data): | 
|  | 184 | +        """ Writes the data in 'data' to the location 'addr' | 
|  | 185 | +            in the memory of the device. | 
|  | 186 | +        """ | 
|  | 187 | +        return self.lib.monitorcommand(struct.pack("IIII%ds" % len(data), 5, addr, len(data), 0, data), "III", (None, None, None)) | 
| 434 | 188 |  | 
|  | 189 | +    def readdma(self, addr, size): | 
|  | 190 | +        """ Reads the memory from location 'addr' with size 'size' | 
|  | 191 | +            from the device. This uses DMA and the data in endpoint. | 
|  | 192 | +        """ | 
|  | 193 | +        self.lib.monitorcommand(struct.pack("IIII", 6, addr, size, 0), "III", (None, None, None)) | 
|  | 194 | +        return struct.unpack("%ds" % size, self.lib.dev.din(size))[0] | 
| 435 | 195 |  | 
| 436 |  | -  def i2crecv(self, bus, slave, addr, size, silent = 0):
 | 
| 437 |  | -    if (size > self.cin_maxsize - 0x10) or (size > 0xFF):
 | 
| 438 |  | -      raise Exception ("The data exceeds the maximum amount that can be received with this instruction.")
 | 
| 439 |  | -  
 | 
| 440 |  | -    self.__myprint("Reading 0x%2x bytes from 0x%2x at I2C device at bus 0x%2x, slave adress 0x%2x ..." % (size, addr, bus, slave), silent)
 | 
|  | 196 | +    def writedma(self, addr, data): | 
|  | 197 | +        """ Writes the data in 'data' to the location 'addr' | 
|  | 198 | +            in the memory of the device. This uses DMA and the data out endpoint. | 
|  | 199 | +        """ | 
|  | 200 | +        self.lib.monitorcommand(struct.pack("IIII", 7, addr, len(data), 0), "III", (None, None, None)) | 
|  | 201 | +        return self.lib.dev.dout(data) | 
| 441 | 202 |  | 
| 442 |  | -    self.handle.bulkWrite(self.__coutep, struct.pack("<IBBBBII", 8, bus, slave, addr, size, 0, 0))
 | 
| 443 |  | -    data = self.__getbulk(self.handle, self.__cinep, 0x10 + size)
 | 
| 444 |  | -    self.__checkstatus(response)
 | 
|  | 203 | +    def i2cread(self, index, slaveaddr, startaddr, size): | 
|  | 204 | +        """ Reads data from an i2c slave """ | 
| 445 | 205 |  | 
| 446 |  | -    self.__myprint(" done\n data was:\n%s\n" % (self.__gethexviewprintout(data[16:])), silent)
 | 
|  | 206 | +    def i2cwrite(self, index, slaveaddr, startaddr, data): | 
|  | 207 | +        """ Writes data to an i2c slave """ | 
| 447 | 208 |  | 
| 448 |  | -    return data[16:]
 | 
| 449 |  | -
 | 
| 450 |  | -
 | 
| 451 |  | -  def i2csend(self, bus, slave, addr, data, silent = 0):
 | 
| 452 |  | -    size = len(data)
 | 
| 453 |  | -    if (size > self.cout_maxsize - 0x10) or (size > 0xFF):
 | 
| 454 |  | -      raise Exception ("The data exceeds the maximum amount that can be send with this instruction.")
 | 
| 455 |  | -  
 | 
| 456 |  | -    self.__myprint("Writing 0x%2x bytes to 0x%2x at I2C device at bus 0x%2x, slave adress 0x%2x ..." % (size, addr, bus, slave), silent)
 | 
| 457 |  | -  
 | 
| 458 |  | -    self.handle.bulkWrite(self.__coutep, struct.pack("<IBBBBII", 9, bus, slave, addr, size, 0, 0) + data)
 | 
| 459 |  | -    response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 460 |  | -    self.__checkstatus(response)
 | 
|  | 209 | +    def usbcread(self, size): | 
|  | 210 | +        """ Reads data with size 'size' from the USB console """ | 
| 461 | 211 |  | 
| 462 |  | -    self.__myprint(" done\n", silent)
 | 
|  | 212 | +    def usbcwrite(self, data): | 
|  | 213 | +        """ Writes data to the USB console """ | 
| 463 | 214 |  | 
| 464 |  | -    
 | 
| 465 |  | -#=====================================================================================      
 | 
|  | 215 | +    def cread(self, size, bitmask): | 
|  | 216 | +        """ Reads data with the specified size from the device consoles | 
|  | 217 | +            identified with the specified bitmask | 
|  | 218 | +        """ | 
| 466 | 219 |  | 
| 467 |  | -  def readusbcon(self, size, outtype = "", file = "", silent = 0):
 | 
| 468 |  | -    """ reads from USB console
 | 
| 469 |  | -      <size>: number of bytes to be read, if its length exceeds the Command In endpoint packet size - 0x10, it will be read in several steps
 | 
| 470 |  | -      <outtype>: how the data will be put out
 | 
| 471 |  | -        "file" => writes data to file <file>
 | 
| 472 |  | -        "printstring" => prints data as a string to the console window
 | 
| 473 |  | -        "printhex" => prints a hexview view of the data to the console window
 | 
| 474 |  | -        "" => only returns the data
 | 
| 475 |  | -      <silent>: if 0, nothing will be written to the console window (even if <outtype> defines something else)
 | 
| 476 |  | -      
 | 
| 477 |  | -      in every case, the data will be returned in an array with additional information
 | 
| 478 |  | -        [len, buffersize, datainbuffer, data]
 | 
| 479 |  | -          where len is the length of the data actually read,
 | 
| 480 |  | -                buffersize is the on-device read buffer size,
 | 
| 481 |  | -                datainbuffer is the number of bytes still left in the on device buffer,
 | 
| 482 |  | -                data is the actual data
 | 
| 483 |  | -      
 | 
| 484 |  | -      in case that within 5 secs, it's not possible to read <size> bytes, a timeout will occur
 | 
| 485 |  | -    """
 | 
| 486 |  | -    out_data = ""
 | 
| 487 |  | -    readbytes = 0
 | 
| 488 |  | -    buffersize = 0
 | 
| 489 |  | -    bytesleft = 0
 | 
| 490 |  | -    timeoutcounter = 0
 | 
|  | 220 | +    def cwrite(self, data): | 
|  | 221 | +        """ Writes data to the device consoles | 
|  | 222 | +            identified with the specified bitmask. | 
|  | 223 | +        """ | 
| 491 | 224 |  | 
| 492 |  | -    self.__myprint("Reading 0x%x bytes from USB console..." % (size), silent)
 | 
|  | 225 | +    def cflush(self, bitmask): | 
|  | 226 | +        """ Flushes the consoles specified with 'bitmask' """ | 
|  | 227 | +        return self.lib.monitorcommand(struct.pack("IIII", 14, bitmask, 0, 0), "III", (None, None, None)) | 
| 493 | 228 |  | 
| 494 |  | -    while size > 0 and timoutcounter < 50:
 | 
| 495 |  | -      blocklen = size
 | 
| 496 |  | -      
 | 
| 497 |  | -      if size > self.cin_maxsize - 0x10:
 | 
| 498 |  | -        blocklen = self.cin_maxsize - 0x10
 | 
| 499 |  | -      
 | 
| 500 |  | -      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 10, blocklen, 0, 0))
 | 
| 501 |  | -      response = self.__getbulk(self.handle, self.__cinep, blocklen + 0x10)
 | 
| 502 |  | -      self.__checkstatus(response)
 | 
| 503 |  | -      
 | 
| 504 |  | -      readbytes, buffersize, bytesleft = struct.unpack("<III", response[4:])
 | 
| 505 |  | -      out_data += response[0x10:0x10+readbytes]
 | 
| 506 |  | -      size -= blocklen
 | 
| 507 |  | -      
 | 
| 508 |  | -      if not bytesleft > 0:   # no data left to read => wait a bit and prevent an infinite loop trying to read data when there is none
 | 
| 509 |  | -        timeoutcounter += 1
 | 
| 510 |  | -        time.sleep(0.1)
 | 
| 511 |  | -      else:
 | 
| 512 |  | -        timeoutcounter -= 3
 | 
| 513 |  | -        if timeoutcounter < 0:
 | 
| 514 |  | -          timeoutcounter = 0
 | 
| 515 |  | -          
 | 
| 516 |  | -    self.__myprint(" done\n", silent)
 | 
| 517 |  | -    self.__myprint("\nBytes read: 0x%x\nOn-device buffersize: 0x%x\nBytes still in device's buffer: 0x%x\n\n"\
 | 
| 518 |  | -                    % (len(out_data), buffersize, bytesleft)                      
 | 
| 519 |  | -                    , silent)
 | 
|  | 229 | +    def getprocinfo(self, offset, size): | 
|  | 230 | +        """ Gets current state of the scheduler """ | 
| 520 | 231 |  | 
| 521 |  | -    if (outtype == "file"):
 | 
| 522 |  | -      f = open(file, "wb")
 | 
| 523 |  | -      f.write(out_data)
 | 
| 524 |  | -      
 | 
| 525 |  | -    elif (outtype == "printstring"):
 | 
| 526 |  | -      self.__myprint(out_data, silent)
 | 
| 527 |  | -      self.__myprint("\n\n", silent)
 | 
| 528 |  | -      
 | 
| 529 |  | -    elif (outtype == "printhex"):
 | 
| 530 |  | -      self.__myprint(self.__gethexviewprintout(out_data, "", 1), silent)
 | 
| 531 |  | -      self.__myprint("\n\n", silent)
 | 
|  | 232 | +    def freezescheduler(self, freeze=True): | 
|  | 233 | +        """ Freezes/Unfreezes the scheduler """ | 
|  | 234 | +        return self.lib.monitorcommand(struct.pack("IIII", 16, 1 if freeze else 0, 0, 0), "III", ("before", None, None)) | 
| 532 | 235 |  | 
| 533 |  | -    elif (outtype == ""):
 | 
| 534 |  | -      pass    # return only
 | 
| 535 |  | -      
 | 
| 536 |  | -    else:
 | 
| 537 |  | -      raise Exception ("Invalid argument for <outtype>: '%s'." % (outtype))
 | 
|  | 236 | +    def unfreezescheduler(self): | 
|  | 237 | +        """ Unfreezes the scheduler """ | 
|  | 238 | +        return self.lib.monitorcommand(struct.pack("IIII", 16, 0, 0, 0), "III", ("before", None, None)) | 
| 538 | 239 |  | 
| 539 |  | -    return [len(out_data), buffersize, bytesleft, out_data]
 | 
|  | 240 | +    def suspendthread(self, id, suspend=True): | 
|  | 241 | +        """ Suspends the thread with the specified id """ | 
|  | 242 | +        return self.lib.monitorcommand(struct.pack("IIII", 17, 1 if suspend else 0, id, 0), "III", ("before", None, None)) | 
| 540 | 243 |  | 
|  | 244 | +    def unsuspendthread(self, id): | 
|  | 245 | +        """ Suspends the thread with the specified id """ | 
|  | 246 | +        return self.lib.monitorcommand(struct.pack("IIII", 17, 0, id, 0), "III", ("before", None, None)) | 
| 541 | 247 |  | 
| 542 |  | -  def writeusbcon(self, data, silent = 0, *range):
 | 
| 543 |  | -    """ writes to USB console
 | 
| 544 |  | -      <data>: the data to be written
 | 
| 545 |  | -      <range>: the range in <data> that should be written, in the from [offset, length]
 | 
| 546 |  | -      <silent>: if 0, nothing will be written to the console window
 | 
| 547 |  | -      
 | 
| 548 |  | -      if the data to be written exceeds the Command Out endpoint packet size - 0x10, it will be written in several steps
 | 
| 549 |  | -    """
 | 
| 550 |  | -    size = len(data)
 | 
| 551 |  | -    boffset = 0
 | 
|  | 248 | +    def killthread(self, id): | 
|  | 249 | +        """ Kills the thread with the specified id """ | 
|  | 250 | +        return self.lib.monitorcommand(struct.pack("IIII", 18, id, 0, 0), "III", ("before", None, None)) | 
| 552 | 251 |  | 
| 553 |  | -    if len(range) > 0:
 | 
| 554 |  | -      boffset = range[0]
 | 
| 555 |  | -    if len(range) > 1:
 | 
| 556 |  | -      size = range[1]
 | 
|  | 252 | +    def createthread(self, nameptr, entrypoint, stackptr, stacksize, threadtype, priority, state): | 
|  | 253 | +        """ Creates a thread with the specified attributes """ | 
|  | 254 | +        if threadtype == "user": | 
|  | 255 | +            threadtype = 0 | 
|  | 256 | +        elif threadtype == "system": | 
|  | 257 | +            threadtype = 1 | 
|  | 258 | +        else: | 
|  | 259 | +            raise SyntaxError("Threadtype must be either 'system' or 'user'") | 
|  | 260 | +        if priority > 256 or priority < 0: | 
|  | 261 | +            raise SyntaxError("Priority must be a number between 0 and 256") | 
|  | 262 | +        if state == "ready": | 
|  | 263 | +            state = 0 | 
|  | 264 | +        elif state == "suspended": | 
|  | 265 | +            state = 1 | 
|  | 266 | +        else: | 
|  | 267 | +            raise SyntaxError("State must be either 'ready' or 'suspended'") | 
|  | 268 | +        resp = self.lib.monitorcommand(struct.pack("IIIIIIII", 19, nameptr, entrypoint, stackptr, stacksize, threadtype, priority, state), "III", (id, None, None)) | 
|  | 269 | +        if resp.id < 0: | 
|  | 270 | +            raise DeviceError("The device returned the error code "+str(resp.id)) | 
|  | 271 | +        return resp | 
| 557 | 272 |  | 
| 558 |  | -    self.__myprint("Writing 0x%x bytes to USB console..." % (size), silent)
 | 
|  | 273 | +    def flushcpucache(self): | 
|  | 274 | +        """ Flushes the CPU instruction and data cache """ | 
|  | 275 | +        return self.lib.monitorcommand(struct.pack("IIII", 20, 0, 0, 0), "III", (None, None, None)) | 
| 559 | 276 |  | 
| 560 |  | -    timeoutcounter = 0
 | 
|  | 277 | +    def run(self, addr): | 
|  | 278 | +        """ Runs the emBIOS app at 'addr' """ | 
|  | 279 | +        return self.lib.monitorcommand(struct.pack("IIII", 21, addr, 0, 0), "III", ("excecimage", None, None)) | 
| 561 | 280 |  | 
| 562 |  | -    while (size > 0) and (timeoutcounter < 50):
 | 
| 563 |  | -      blocklen = size
 | 
| 564 |  | -      if blocklen > self.cout_maxsize - 0x10:
 | 
| 565 |  | -        blocklen = self.cout_maxsize - 0x10
 | 
|  | 281 | +    def bootflashread(self, memaddr, flashaddr, size): | 
|  | 282 | +        """ Copies the data in the bootflash at 'flashaddr' of the specified size | 
|  | 283 | +            to the memory at addr 'memaddr' | 
|  | 284 | +        """ | 
| 566 | 285 |  | 
| 567 |  | -      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 11, size, 0, 0) + data[boffset:boffset+blocklen])
 | 
| 568 |  | -      response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 569 |  | -      self.__checkstatus(response)
 | 
| 570 |  | -      
 | 
| 571 |  | -      sendbytes = struct.unpack("<I", response[4:])[0]
 | 
| 572 |  | -      if sendbytes < blocklen:   # not everything has been written, need to resent some stuff but wait a bit before doing so
 | 
| 573 |  | -        time.sleep(0.1)
 | 
| 574 |  | -        timeoutcounter += 1
 | 
| 575 |  | -      elif timeoutcounter > 0:    # lower timeoutcounter again
 | 
| 576 |  | -        timeoutcounter -= 3
 | 
| 577 |  | -        if timeoutcounter < 0:
 | 
| 578 |  | -          timeoutcounter = 0
 | 
| 579 |  | -      
 | 
| 580 |  | -      size -= sendbytes
 | 
| 581 |  | -      boffset += sendbytes
 | 
| 582 |  | -
 | 
| 583 |  | -      
 | 
| 584 |  | -    if (timeoutcounter >=50):
 | 
| 585 |  | -      raise Exception("Timeout, 0x%x bytes couldn't be send." % size)
 | 
|  | 286 | +    def bootflashwrite(self, memaddr, flashaddr, size): | 
|  | 287 | +        """ Copies the data in the memory at 'memaddr' of the specified size | 
|  | 288 | +            to the boot flash at addr 'flashaddr' | 
|  | 289 | +        """ | 
| 586 | 290 |  | 
| 587 |  | -    self.__myprint(" done\n", silent)
 | 
|  | 291 | +    def execfirmware(self, addr): | 
|  | 292 | +        """ Executes the firmware at 'addr' and passes all control to it. """ | 
|  | 293 | +        return self.lib.monitorcommand(struct.pack("IIII", 24, addr, 0, 0), "III", (None, None, None)) | 
| 588 | 294 |  | 
| 589 |  | -    return size   # number of bytes that have not been sent
 | 
|  | 295 | +    def aesencrypt(self, addr, size, keyindex): | 
|  | 296 | +        """ Encrypts the buffer at 'addr' with the specified size | 
|  | 297 | +            with the hardware AES key index 'keyindex' | 
|  | 298 | +        """ | 
|  | 299 | +        return self.lib.monitorcommand(struct.pack("IBBHII", 25, 1, 0, keyindex, addr, size), "III", (None, None, None)) | 
| 590 | 300 |  | 
| 591 |  | -
 | 
| 592 |  | -  def readdevcon(self, bitmask, size, outtype = "", file = "", silent = 0):
 | 
| 593 |  | -    """ reads from one or more of the device's consoles
 | 
| 594 |  | -      <bitmask>: bitmask of consoles to be read from
 | 
| 595 |  | -      <size>: number of bytes to be read, if its length exceeds the Command In endpoint packet size - 0x10, it will be read in several steps
 | 
| 596 |  | -      <outtype>: how the data will be put out
 | 
| 597 |  | -        "file" => writes data to file <file>
 | 
| 598 |  | -        "printstring" => prints data as a string to the console window
 | 
| 599 |  | -        "printhex" => prints a hexview view of the data to the console window
 | 
| 600 |  | -        "" => only returns the data
 | 
| 601 |  | -      <silent>: if 0, nothing will be written to the console window (even if <outtype> defines something else)
 | 
| 602 |  | -      
 | 
| 603 |  | -      in every case, the data will be returned
 | 
| 604 |  | -      
 | 
| 605 |  | -      in case that within 5 secs, it's not possible to read <size> bytes, a timeout will occur
 | 
| 606 |  | -    """
 | 
| 607 |  | -    out_data = ""
 | 
| 608 |  | -    readbytes = 0
 | 
| 609 |  | -    timeoutcounter = 0
 | 
|  | 301 | +    def aesdecrypt(self, addr, size, keyindex): | 
|  | 302 | +        """ Decrypts the buffer at 'addr' with the specified size | 
|  | 303 | +            with the hardware AES key index 'keyindex' | 
|  | 304 | +        """ | 
|  | 305 | +        return self.lib.monitorcommand(struct.pack("IBBHII", 25, 0, 0, keyindex, addr, size), "III", (None, None, None)) | 
| 610 | 306 |  | 
| 611 |  | -    self.__myprint("Reading 0x%x bytes from device's console(s)..." % (size), silent)
 | 
| 612 |  | -    
 | 
| 613 |  | -    while size > 0 and timoutcounter < 50:
 | 
| 614 |  | -      blocklen = size
 | 
| 615 |  | -      
 | 
| 616 |  | -      if size > self.cin_maxsize - 0x10:
 | 
| 617 |  | -        blocklen = self.cin_maxsize - 0x10
 | 
| 618 |  | -      
 | 
| 619 |  | -      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 13, bitmask, blocklen, 0))
 | 
| 620 |  | -      response = self.__getbulk(self.handle, self.__cinep, blocklen + 0x10)
 | 
| 621 |  | -      self.__checkstatus(response)
 | 
| 622 |  | -      
 | 
| 623 |  | -      readbytes = struct.unpack("<III", response[4:])[0]
 | 
| 624 |  | -      out_data += response[0x10:0x10+readbytes]
 | 
| 625 |  | -      size -= blocklen
 | 
| 626 |  | -      
 | 
| 627 |  | -      if not readbytes > 0:   # no data read => wait a bit and prevent an infinite loop trying to read data when there is none
 | 
| 628 |  | -        timeoutcounter += 1
 | 
| 629 |  | -        time.sleep(0.1)
 | 
| 630 |  | -      else:
 | 
| 631 |  | -        timeoutcounter -= 3
 | 
| 632 |  | -        if timeoutcounter < 0:
 | 
| 633 |  | -          timeoutcounter = 0
 | 
| 634 |  | -          
 | 
| 635 |  | -    self.__myprint(" done\n", silent)
 | 
| 636 |  | -    self.__myprint("\nBytes read: 0x%x\n\n" % (len(out_data)), silent)
 | 
| 637 |  | -    
 | 
| 638 |  | -    if (outtype == "file"):
 | 
| 639 |  | -      f = open(file, "wb")
 | 
| 640 |  | -      f.write(out_data)
 | 
| 641 |  | -      
 | 
| 642 |  | -    elif (outtype == "printstring"):
 | 
| 643 |  | -      self.__myprint(out_data, silent)
 | 
| 644 |  | -      self.__myprint("\n\n", silent)
 | 
| 645 |  | -      
 | 
| 646 |  | -    elif (outtype == "printhex"):
 | 
| 647 |  | -      self.__myprint(self.__gethexviewprintout(out_data, "", 1), silent)
 | 
| 648 |  | -      self.__myprint("\n\n", silent)
 | 
| 649 |  | -    
 | 
| 650 |  | -    elif (outtype == ""):
 | 
| 651 |  | -      pass    # return only
 | 
| 652 |  | -      
 | 
| 653 |  | -    else:
 | 
| 654 |  | -      raise Exception ("Invalid argument for <outtype>: '%s'." % (outtype))
 | 
| 655 |  | -    
 | 
| 656 |  | -    return out_data
 | 
| 657 |  | -    
 | 
| 658 |  | -    
 | 
| 659 |  | -  def writedevcon(self, bitmask, data, silent = 0, *range):
 | 
| 660 |  | -    """ writes to USB console
 | 
| 661 |  | -      <bitmask>: bitmask of consoles to be written to
 | 
| 662 |  | -      <data>: the data to be written
 | 
| 663 |  | -      <range>: the range in <data> that should be written, in the from [offset, length]
 | 
| 664 |  | -      <silent>: if 0, nothing will be written to the console window
 | 
| 665 |  | -      
 | 
| 666 |  | -      if the data to be written exceeds the Command Out endpoint packet size - 0x10, it will be written in several steps
 | 
| 667 |  | -    """
 | 
| 668 |  | -    size = len(data)
 | 
| 669 |  | -    boffset = 0
 | 
| 670 |  | -    
 | 
| 671 |  | -    if len(range) > 0:
 | 
| 672 |  | -      boffset = range[0]
 | 
| 673 |  | -    if len(range) > 1:
 | 
| 674 |  | -      size = range[1]
 | 
| 675 |  | -    
 | 
| 676 |  | -    self.__myprint("Writing 0x%x bytes to device's console(s)..." % (size), silent)
 | 
| 677 |  | -    
 | 
| 678 |  | -    timeoutcounter = 0
 | 
| 679 |  | -    
 | 
| 680 |  | -    while size > 0:
 | 
| 681 |  | -      blocklen = size
 | 
| 682 |  | -      if blocklen > self.cout_maxsize - 0x10:
 | 
| 683 |  | -        blocklen = self.cout_maxsize - 0x10
 | 
| 684 |  | -    
 | 
| 685 |  | -      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 12, bitmask, size, 0) + data[boffset:boffset+blocklen])
 | 
| 686 |  | -      response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 687 |  | -      self.__checkstatus(response)
 | 
| 688 |  | -      
 | 
| 689 |  | -      size -= blocklen
 | 
| 690 |  | -      boffset += blocklen
 | 
| 691 |  | -    
 | 
| 692 |  | -    self.__myprint(" done\n", silent)
 | 
| 693 |  | -   
 | 
| 694 |  | -       
 | 
| 695 |  | -  def flushconsolebuffers(self, bitmask, silent = 0):
 | 
| 696 |  | -    self.__myprint("Flushing device console('s) buffer('s)...")
 | 
| 697 |  | -    
 | 
| 698 |  | -    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 14, bitmask, 0, 0))
 | 
| 699 |  | -    response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 700 |  | -    self.__checkstatus(response)
 | 
| 701 |  | -    
 | 
| 702 |  | -    self.__myprint(" done\n") 
 | 
|  | 307 | +    def hmac_sha1(self, addr, size, destination): | 
|  | 308 | +        """ Generates a HMAC-SHA1 hash of the buffer and saves it to 'destination' """ | 
|  | 309 | +        return self.lib.monitorcommand(struct.pack("IIII", 26, addr, size, destination), "III", (None, None, None)) | 
| 703 | 310 |  | 
| 704 |  | -    
 | 
| 705 |  | -#===================================================================================== 
 | 
| 706 | 311 |  | 
| 707 |  | -  
 | 
| 708 |  | -  def freezescheduler(self, freeze, silent = 0):
 | 
| 709 |  | -    if (freeze):
 | 
| 710 |  | -      self.__myprint("Freezing scheduler...", silent)
 | 
| 711 |  | -      freeze = 1
 | 
| 712 |  | -    else:
 | 
| 713 |  | -      self.__myprint("Unfreezing scheduler...", silent)
 | 
| 714 |  | -      freeze = 0
 | 
| 715 |  | -      
 | 
| 716 |  | -    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 16, freeze, 0, 0))
 | 
| 717 |  | -    response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 718 |  | -    self.__checkstatus(response)
 | 
|  | 312 | +class Lib(object): | 
|  | 313 | +    def __init__(self, embios): | 
|  | 314 | +        self.idVendor = 0xFFFF | 
|  | 315 | +        self.idProduct = 0xE000 | 
|  | 316 | + | 
|  | 317 | +        self.embios = embios | 
|  | 318 | +        self.connected = False | 
| 719 | 319 |  | 
| 720 |  | -    self.__myprint(" done\n", silent)    
 | 
|  | 320 | +    def connect(self): | 
|  | 321 | +        self.dev = Dev(self.idVendor, self.idProduct) | 
|  | 322 | +        self.connected = True | 
|  | 323 | +        self.embios.getpacketsizeinfo() | 
| 721 | 324 |  | 
| 722 |  | -    
 | 
| 723 |  | -  def suspendthread(self, suspend, threadid, silent = 0):
 | 
| 724 |  | -    if (suspend):
 | 
| 725 |  | -      self.__myprint("Suspending thread 0x%08x..." % threadid, silent)
 | 
| 726 |  | -      suspend = 1
 | 
| 727 |  | -    else:
 | 
| 728 |  | -      self.__myprint("Unsuspending thread 0x%08x..." % threadid, silent)
 | 
| 729 |  | -      suspend = 0
 | 
| 730 |  | -      
 | 
| 731 |  | -    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 17, suspend, threadid, 0))
 | 
| 732 |  | -    response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 733 |  | -    self.__checkstatus(response)
 | 
| 734 |  | -    
 | 
| 735 |  | -    self.__myprint(" done\n", silent) 
 | 
|  | 325 | +    def monitorcommand(self, cmd, rcvdatatypes=None, rcvstruct=None): | 
|  | 326 | +        if not self.connected: | 
|  | 327 | +            self.connect() | 
|  | 328 | +        self.dev.cout(cmd) | 
|  | 329 | +        if rcvdatatypes: | 
|  | 330 | +            rcvdatatypes = "I" + rcvdatatypes # add the response | 
|  | 331 | +            data = self.dev.cin(struct.calcsize(rcvdatatypes)) | 
|  | 332 | +            data = struct.unpack(rcvdatatypes, data) | 
|  | 333 | +            response = data[0] | 
|  | 334 | +            if libembiosdata.responsecodes[response] == "ok": | 
|  | 335 | +                if rcvstruct: | 
|  | 336 | +                    datadict = Bunch() | 
|  | 337 | +                    counter = 1 # start with 1, 0 is the id | 
|  | 338 | +                    for item in rcvstruct: | 
|  | 339 | +                        if item != None: # else the data is undefined | 
|  | 340 | +                            datadict[item] = data[counter] | 
|  | 341 | +                        counter += 1 | 
|  | 342 | +                    return datadict | 
|  | 343 | +                else: | 
|  | 344 | +                    return data | 
|  | 345 | +            elif libembiosdata.responsecodes[response] == "unsupported": | 
|  | 346 | +                raise DeviceError("The device does not support this command.") | 
|  | 347 | +            elif libembiosdata.responsecodes[response] == "invalid": | 
|  | 348 | +                raise DeviceError("Invalid command! This should NOT happen!") | 
|  | 349 | +            elif libembiosdata.responsecodes[response] == "busy": | 
|  | 350 | +                raise DeviceError("Device busy") | 
| 736 | 351 |  | 
| 737 | 352 |  | 
| 738 |  | -  def killthread(self, threadid, silent = 0):
 | 
| 739 |  | -    self.__myprint("Killing thread 0x%08x..." % threadid, silent)
 | 
| 740 |  | -      
 | 
| 741 |  | -    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 18, threadid, 0, 0))
 | 
| 742 |  | -    response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 743 |  | -    self.__checkstatus(response)
 | 
| 744 |  | -    
 | 
| 745 |  | -    self.__myprint(" done\n", silent) 
 | 
| 746 |  | -    
 | 
| 747 |  | -    
 | 
| 748 |  | -  def createthread(self, namepointer, entrypoint, stackpointer, stacksize, type, priority, state, silent = 0):
 | 
| 749 |  | -    self.__myprint("Creating thread...", silent)
 | 
| 750 |  | -      
 | 
| 751 |  | -    self.handle.bulkWrite(self.__coutep, struct.pack("<IIIIIIII", 19, namepointer, entrypoint, stackpointer, stacksize, type, priority, state))
 | 
| 752 |  | -    response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 753 |  | -    self.__checkstatus(response)
 | 
| 754 |  | -    
 | 
| 755 |  | -    if (struct.unpack("<i", response[4:8])[0] < 0):
 | 
| 756 |  | -      self.__myprint(" failed, error code: 0x%x" % (struct.unpack("<i", response[4:8])[0]), silent)
 | 
| 757 |  | -    else:
 | 
| 758 |  | -      self.__myprint(" done\n, thread ID: 0x%x" % (struct.unpack("<I", response[4:8])[0]), silent)     
 | 
| 759 |  | -    
 | 
| 760 |  | -    
 | 
| 761 |  | -  def getprocinfo(self, silent = 0):
 | 
| 762 |  | -    """
 | 
| 763 |  | -      printout on console window:
 | 
| 764 |  | -        <silent> = 0: Process information struct version, Process information table size
 | 
| 765 |  | -        <silent> = 1: nothing
 | 
| 766 |  | -    """
 | 
| 767 |  | -    # inline functions ----------------------------------------------
 | 
| 768 |  | -    def procinfotolist(processinfo, structver):
 | 
| 769 |  | -      if (structver == 1):   # Process information struct version == 1
 | 
| 770 |  | -        ptr = 0
 | 
| 771 |  | -        process_n = 0
 | 
| 772 |  | -        retval = []
 | 
| 773 |  | -        while ptr < len(processinfo):
 | 
| 774 |  | -          if struct.unpack("<I", processinfo[ptr + 68:ptr + 72])[0] == 0:    # THREAD_FREE
 | 
| 775 |  | -            ptr += 120
 | 
| 776 |  | -            process_n += 1
 | 
| 777 |  | -            continue
 | 
| 778 |  | -          
 | 
| 779 |  | -          retval.append({})
 | 
| 780 |  | -          
 | 
| 781 |  | -          retval[process_n]['regs'] = struct.unpack("<IIIIIIIIIIIIIIII", processinfo[ptr:ptr + 64])
 | 
| 782 |  | -          ptr += 16 * 0x4
 | 
| 783 |  | -          retval[process_n]['cpsr'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
 | 
| 784 |  | -          ptr += 1 * 0x4
 | 
| 785 |  | -          retval[process_n]['state'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
 | 
| 786 |  | -          ptr += 1 * 0x4
 | 
| 787 |  | -          retval[process_n]['name_ptr'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
 | 
| 788 |  | -          ptr += 1 * 0x4
 | 
| 789 |  | -          retval[process_n]['cputime_current'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
 | 
| 790 |  | -          ptr += 1 * 0x4
 | 
| 791 |  | -          retval[process_n]['cputime_total'] = struct.unpack("<Q", processinfo[ptr:ptr + 8])[0]
 | 
| 792 |  | -          ptr += 1 * 0x8
 | 
| 793 |  | -          retval[process_n]['startusec'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
 | 
| 794 |  | -          ptr += 1 * 0x4
 | 
| 795 |  | -          retval[process_n]['queue_next_ptr'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
 | 
| 796 |  | -          ptr += 1 * 0x4
 | 
| 797 |  | -          retval[process_n]['timeout'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
 | 
| 798 |  | -          ptr += 1 * 0x4
 | 
| 799 |  | -          retval[process_n]['blocked_since'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
 | 
| 800 |  | -          ptr += 1 * 0x4
 | 
| 801 |  | -          retval[process_n]['blocked_by_ptr'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
 | 
| 802 |  | -          ptr += 1 * 0x4
 | 
| 803 |  | -          retval[process_n]['stack_ptr'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
 | 
| 804 |  | -          ptr += 1 * 0x4
 | 
| 805 |  | -          retval[process_n]['err_no'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
 | 
| 806 |  | -          ptr += 1 * 0x4
 | 
| 807 |  | -          retval[process_n]['block_type'] = struct.unpack("<B", processinfo[ptr:ptr + 1])[0]
 | 
| 808 |  | -          ptr += 1 * 0x1
 | 
| 809 |  | -          retval[process_n]['thread_type'] = struct.unpack("<B", processinfo[ptr:ptr + 1])[0]
 | 
| 810 |  | -          ptr += 1 * 0x1
 | 
| 811 |  | -          retval[process_n]['priority'] = struct.unpack("<B", processinfo[ptr:ptr + 1])[0]
 | 
| 812 |  | -          ptr += 1 * 0x1
 | 
| 813 |  | -          retval[process_n]['cpuload'] = struct.unpack("<B", processinfo[ptr:ptr + 1])[0]
 | 
| 814 |  | -          ptr += 1 * 0x1
 | 
| 815 |  | -          
 | 
| 816 |  | -          process_n += 1
 | 
| 817 |  | -          
 | 
| 818 |  | -        return retval
 | 
| 819 |  | -      
 | 
| 820 |  | -      
 | 
| 821 |  | -    def state2name(state, structver):
 | 
| 822 |  | -      if structver == 1:
 | 
| 823 |  | -        if state == 0: return "THREAD_FREE"
 | 
| 824 |  | -        elif state == 1: return "THREAD_SUSPENDED"
 | 
| 825 |  | -        elif state == 2: return "THREAD_READY"
 | 
| 826 |  | -        elif state == 3: return "THREAD_RUNNING"
 | 
| 827 |  | -        elif state == 4: return "THREAD_BLOCKED"
 | 
| 828 |  | -        elif state == 5: return "THREAD_DEFUNCT"
 | 
| 829 |  | -        elif state == 6: return "THREAD_DEFUNCT_ACK"
 | 
| 830 |  | -        else: return "UNKNOWN"
 | 
| 831 |  | -      else: return "UNKNOWN"
 | 
| 832 |  | -      
 | 
| 833 |  | -    def blocktype2name(blocktype, structver):
 | 
| 834 |  | -      if structver == 1:
 | 
| 835 |  | -        if blocktype == 0: return "THREAD_NOT_BLOCKED"
 | 
| 836 |  | -        elif blocktype == 1: return "THREAD_BLOCK_SLEEP"
 | 
| 837 |  | -        elif blocktype == 2: return "THREAD_BLOCK_MUTEX"
 | 
| 838 |  | -        elif blocktype == 3: return "THREAD_BLOCK_WAKEUP"
 | 
| 839 |  | -        elif blocktype == 4: return "THREAD_DEFUNCT_STKOV"
 | 
| 840 |  | -        elif blocktype == 5: return "THREAD_DEFUNCT_PANIC"
 | 
| 841 |  | -        else: return "UNKNOWN"
 | 
| 842 |  | -      else: return "UNKNOWN"
 | 
| 843 |  | -      
 | 
| 844 |  | -    def threadtype2name (threadtype, structver):
 | 
| 845 |  | -      if structver == 1:
 | 
| 846 |  | -        if threadtype == 0: return "USER_THREAD"
 | 
| 847 |  | -        elif threadtype == 1: return "OS_THREAD"
 | 
| 848 |  | -        elif threadtype == 2: return "CORE_THREAD"
 | 
| 849 |  | -        else: return "UNKNOWN"
 | 
| 850 |  | -      else: return "UNKNOWN"
 | 
| 851 |  | -      
 | 
| 852 |  | -    def procinfotostring(procinfolist, structver):
 | 
| 853 |  | -      processinfoprint = ""
 | 
| 854 |  | -      ptr = 0
 | 
| 855 |  | -      while structver == 1 and ptr < len(procinfolist):      # Process information struct version == 1
 | 
| 856 |  | -        processinfoprint += "--------------------------------------------------------------------------------\n"
 | 
| 857 |  | -        processinfoprint += "R0: 0x%08x,  R1: 0x%08x,  R2: 0x%08x,  R3: 0x%08x,\n"\
 | 
| 858 |  | -                            % (procinfolist[ptr]['regs'][0], procinfolist[ptr]['regs'][1], procinfolist[ptr]['regs'][2], procinfolist[ptr]['regs'][3])\
 | 
| 859 |  | -                            + "R4: 0x%08x,  R5: 0x%08x,  R6: 0x%08x,  R7: 0x%08x,\n"\
 | 
| 860 |  | -                            % (procinfolist[ptr]['regs'][4], procinfolist[ptr]['regs'][5], procinfolist[ptr]['regs'][6], procinfolist[ptr]['regs'][7])\
 | 
| 861 |  | -                            + "R8: 0x%08x,  R9: 0x%08x,  R10: 0x%08x, R11: 0x%08x,\n"\
 | 
| 862 |  | -                            % (procinfolist[ptr]['regs'][8], procinfolist[ptr]['regs'][9], procinfolist[ptr]['regs'][10], procinfolist[ptr]['regs'][11])\
 | 
| 863 |  | -                            + "R12: 0x%08x, SP: 0x%08x,  LR: 0x%08x,  PC: 0x%08x\n" \
 | 
| 864 |  | -                            % (procinfolist[ptr]['regs'][12], procinfolist[ptr]['regs'][13], procinfolist[ptr]['regs'][14], procinfolist[ptr]['regs'][15])
 | 
| 865 |  | -        processinfoprint += "cpsr: 0x%08x      " %             (procinfolist[ptr]['cpsr'])
 | 
| 866 |  | -        processinfoprint += "state: %s      " %                 (state2name([procinfolist[ptr]['state']], structver))
 | 
| 867 |  | -        processinfoprint += "nameptr: 0x%08x\n" %               (procinfolist[ptr]['name_ptr'])
 | 
| 868 |  | -        processinfoprint += "current cpu time: 0x%08x      " %  (procinfolist[ptr]['cputime_current'])
 | 
| 869 |  | -        processinfoprint += "total cpu time: 0x%016x\n" %       (procinfolist[ptr]['cputime_total'])
 | 
| 870 |  | -        processinfoprint += "startusec: 0x%08x      " %         (procinfolist[ptr]['startusec'])
 | 
| 871 |  | -        processinfoprint += "queue next ptr: 0x%08x\n" %        (procinfolist[ptr]['queue_next_ptr'])
 | 
| 872 |  | -        processinfoprint += "timeout: 0x%08x\n" %               (procinfolist[ptr]['timeout'])
 | 
| 873 |  | -        processinfoprint += "blocked since: 0x%08x      " %     (procinfolist[ptr]['blocked_since'])
 | 
| 874 |  | -        processinfoprint += "blocked by ptr: 0x%08x\n" %        (procinfolist[ptr]['blocked_by_ptr'])
 | 
| 875 |  | -        processinfoprint += "err_no: 0x%08x      " %            (procinfolist[ptr]['err_no'])
 | 
| 876 |  | -        processinfoprint += "block type: %s\n" %                (blocktype2name([procinfolist[ptr]['block_type']], structver))
 | 
| 877 |  | -        processinfoprint += "thread type: %s\n" %               (threadtype2name([procinfolist[ptr]['thread_type']], structver))
 | 
| 878 |  | -        processinfoprint += "priority: 0x%02x      " %          (procinfolist[ptr]['priority'])
 | 
| 879 |  | -        processinfoprint += "cpu load: 0x%02x\n" %              (procinfolist[ptr]['cpuload'])
 | 
| 880 |  | -          
 | 
| 881 |  | -        ptr += 1
 | 
|  | 353 | +class Dev(object): | 
|  | 354 | +    def __init__(self, idVendor, idProduct): | 
|  | 355 | +        self.idVendor = idVendor | 
|  | 356 | +        self.idProduct = idProduct | 
| 882 | 357 |  | 
| 883 |  | -      processinfoprint += "--------------------------------------------------------------------------------\n"
 | 
|  | 358 | +        self.interface = 0 | 
|  | 359 | +        self.timeout = 100 | 
| 884 | 360 |  | 
| 885 |  | -      return processinfoprint
 | 
| 886 |  | -     
 | 
| 887 |  | -    # reading code --------------------------------------------------
 | 
| 888 |  | -    self.__myprint("Retrieving process information...", silent)
 | 
|  | 361 | +        self.connect() | 
|  | 362 | +        self.findEndpoints() | 
|  | 363 | + | 
|  | 364 | +        self.packetsizelimit = {} | 
|  | 365 | +        self.packetsizelimit['cout'] = None | 
|  | 366 | +        self.packetsizelimit['cin'] = None | 
|  | 367 | +        self.packetsizelimit['dout'] = None | 
|  | 368 | +        self.packetsizelimit['din'] = None | 
| 889 | 369 |  | 
| 890 |  | -    offset = 0
 | 
| 891 |  | -    blocklen = tablesize = self.cin_maxsize - 0x10
 | 
| 892 |  | -    procinfo = ""
 | 
| 893 |  | -    structversion = 0
 | 
|  | 370 | +    def __del__(self): | 
|  | 371 | +        self.disconnect() | 
| 894 | 372 |  | 
| 895 |  | -    # reading loop
 | 
| 896 |  | -    while (offset < tablesize):
 | 
| 897 |  | -      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 15, offset, blocklen, 0))
 | 
| 898 |  | -      response = self.__getbulk(self.handle, self.__cinep, blocklen + 0x10)
 | 
| 899 |  | -      self.__checkstatus(response)
 | 
| 900 |  | -      
 | 
| 901 |  | -      tablesize = struct.unpack("<I", response[8:12])[0]
 | 
| 902 |  | -      
 | 
| 903 |  | -      if tablesize <= offset + blocklen:
 | 
| 904 |  | -        blocklen = tablesize - offset
 | 
| 905 |  | -        procinfo += response[0x10:0x10 + blocklen]
 | 
| 906 |  | -        structversion = struct.unpack("<I", response[4:8])[0]
 | 
| 907 |  | -        tablesize = struct.unpack("<I", response[8:12])[0]
 | 
| 908 |  | -      else:
 | 
| 909 |  | -        procinfo += response[0x10:0x10 + blocklen]
 | 
| 910 |  | -      
 | 
| 911 |  | -      offset += blocklen
 | 
| 912 |  | -      
 | 
| 913 |  | -      blocklen = self.cin_maxsize - 0x10
 | 
| 914 |  | -      if blocklen > tablesize - offset:
 | 
| 915 |  | -        blocklen = tablesize - offset
 | 
|  | 373 | +    def findEndpoints(self): | 
|  | 374 | +        epcounter = 0 | 
|  | 375 | +        self.endpoint = {} | 
|  | 376 | +        for cfg in self.dev: | 
|  | 377 | +            for intf in cfg: | 
|  | 378 | +                for ep in intf: | 
|  | 379 | +                    if epcounter == 0: | 
|  | 380 | +                        self.endpoint['cout'] = ep.bEndpointAddress | 
|  | 381 | +                    elif epcounter == 1: | 
|  | 382 | +                        self.endpoint['cin'] = ep.bEndpointAddress | 
|  | 383 | +                    elif epcounter == 2: | 
|  | 384 | +                        self.endpoint['dout'] = ep.bEndpointAddress | 
|  | 385 | +                    elif epcounter == 3: | 
|  | 386 | +                        self.endpoint['din'] = ep.bEndpointAddress | 
|  | 387 | +                    epcounter += 1 | 
|  | 388 | +        if epcounter <= 3: | 
|  | 389 | +            raise DeviceError("Not all endpoints found in the descriptor. Only "+str(epcounter)+" found, we need 4") | 
| 916 | 390 |  | 
|  | 391 | +    def connect(self): | 
|  | 392 | +        self.dev = usb.core.find(idVendor=self.idVendor, idProduct=self.idProduct) | 
|  | 393 | +        if self.dev is None: | 
|  | 394 | +            raise DeviceNotFoundError() | 
|  | 395 | +        self.dev.set_configuration() | 
| 917 | 396 |  | 
| 918 |  | -    out = (structversion, tablesize, procinfotolist(procinfo, structversion))
 | 
| 919 |  | -
 | 
| 920 |  | -    self.__myprint(" done\n"\
 | 
| 921 |  | -                   + "Process information struct version: 0x%08x\n" % out[0]\
 | 
| 922 |  | -                   + "Total size of process information table: 0x%08x\n" % out[1]\
 | 
| 923 |  | -                   + procinfotostring(out[2], 1)\
 | 
| 924 |  | -                   + "\n\n")
 | 
|  | 397 | +    def disconnect(self): | 
|  | 398 | +        pass | 
| 925 | 399 |  | 
| 926 |  | -    return out
 | 
| 927 |  | -  
 | 
|  | 400 | +    def send(self, endpoint, data): | 
|  | 401 | +        size = self.dev.write(endpoint, data, self.interface, self.timeout) | 
|  | 402 | +        if size != len(data): | 
|  | 403 | +            raise SendError | 
|  | 404 | +        return len | 
| 928 | 405 |  | 
| 929 |  | -  def execimage(self, offset, silent = 0):
 | 
| 930 |  | -    self.__myprint("Executing emBIOS executable image at 0x%08x..." % offset, silent)
 | 
| 931 |  | -      
 | 
| 932 |  | -    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 21, offset, 0, 0))
 | 
| 933 |  | -    response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 934 |  | -    self.__checkstatus(response)
 | 
|  | 406 | +    def receive(self, endpoint, size): | 
|  | 407 | +        read = self.dev.read(endpoint, size, self.interface, self.timeout) | 
|  | 408 | +        if len(read) != size: | 
|  | 409 | +            raise ReceiveError | 
|  | 410 | +        return read | 
| 935 | 411 |  | 
| 936 |  | -    self.__myprint(" done\n    execimage() return code: 0x%08x\n" % struct.unpack("<I", response[4:8])[0], silent)
 | 
|  | 412 | +    def cout(self, data): | 
|  | 413 | +        if self.packetsizelimit['cout'] and len(data) > self.packetsizelimit['cout']: | 
|  | 414 | +            raise SendError("Packet too big") | 
|  | 415 | +        return self.send(self.endpoint['cout'], data) | 
| 937 | 416 |  | 
| 938 |  | -    return struct.unpack("<I", response[4:8])[0]
 | 
|  | 417 | +    def cin(self, size): | 
|  | 418 | +        if self.packetsizelimit['cin'] and size > self.packetsizelimit['cin']: | 
|  | 419 | +            raise ReceiveError("Packet too big") | 
|  | 420 | +        return self.receive(self.endpoint['cin'], size) | 
| 939 | 421 |  | 
|  | 422 | +    def dout(self, data): | 
|  | 423 | +        if self.packetsizelimit['dout'] and len(data) > self.packetsizelimit['dout']: | 
|  | 424 | +            raise SendError("Packet too big") | 
|  | 425 | +        return self.send(self.endpoint['dout'], data) | 
| 940 | 426 |  | 
| 941 |  | -  def execfirmware(self, offset, silent = 0):
 | 
| 942 |  | -    self.__myprint("Executing firmware image at 0x%08x..." % offset, silent)
 | 
| 943 |  | -      
 | 
| 944 |  | -    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 24, offset, 0, 0))
 | 
| 945 |  | -    response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 946 |  | -    self.__checkstatus(response)
 | 
| 947 |  | -    
 | 
| 948 |  | -    self.__myprint(" done\n", silent)
 | 
| 949 |  | -    
 | 
| 950 |  | -    return
 | 
| 951 |  | -    
 | 
| 952 |  | -    
 | 
| 953 |  | -#===================================================================================== 
 | 
|  | 427 | +    def din(self, size): | 
|  | 428 | +        if self.packetsizelimit['din'] and size > self.packetsizelimit['din']: | 
|  | 429 | +            raise ReceiveError("Packet too big") | 
|  | 430 | +        return self.receive(self.endpoint['din'], size) | 
| 954 | 431 |  | 
| 955 | 432 |  | 
| 956 |  | -  def readrawbootflash(self, addr_bootflsh, addr_mem, size, silent = 0):
 | 
| 957 |  | -    self.__myprint("Reading 0x%x bytes from 0x%08x at bootflash to 0x%08x..." % (size, addr_bootflsh, addr_mem), silent)
 | 
| 958 |  | -      
 | 
| 959 |  | -    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 22, addr_mem, addr_bootflsh, size))
 | 
| 960 |  | -    response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 961 |  | -    self.__checkstatus(response)
 | 
| 962 |  | -    
 | 
| 963 |  | -    self.__myprint(" done\n", silent)
 | 
| 964 |  | -
 | 
| 965 |  | -
 | 
| 966 |  | -  def writerawbootflash(self, addr_mem, addr_bootflsh, size, silent = 0):
 | 
| 967 |  | -    self.__myprint("Writing 0x%x bytes from 0x%08x to bootflash at 0x%08x..." % (size, addr_fmem, addr_bootflsh), silent)
 | 
| 968 |  | -      
 | 
| 969 |  | -    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 23, addr_mem, addr_bootflsh, size))
 | 
| 970 |  | -    response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 971 |  | -    self.__checkstatus(response)
 | 
| 972 |  | -    
 | 
| 973 |  | -    self.__myprint(" done\n", silent)
 | 
| 974 |  | -    
 | 
| 975 |  | -
 | 
| 976 |  | -#=====================================================================================
 | 
| 977 |  | -
 | 
| 978 |  | - 
 | 
| 979 |  | -  def flushcaches(self, silent = 0):
 | 
| 980 |  | -    self.__myprint("Flushing caches...", silent)
 | 
| 981 |  | -    
 | 
| 982 |  | -    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 20, 0, 0, 0))
 | 
| 983 |  | -    response = self.__getbulk(self.handle, self.__cinep, 0x10)
 | 
| 984 |  | -    self.__checkstatus(response)
 | 
| 985 |  | -    
 | 
| 986 |  | -    self.__myprint(" done\n", silent) 
 | 
| 987 |  | -    
 | 
| 988 |  | -  
 | 
| 989 |  | -#======================================================================================
 | 
| 990 |  | -# backlight control, remnant from libibugger adjusted to work with libembios ==========
 | 
| 991 |  | -
 | 
| 992 |  | -
 | 
| 993 |  | -  def backlighton(self, fade, brightness, silent = 0):
 | 
| 994 |  | -    self.__myprint("Turning on backlight...", silent)
 | 
| 995 |  | -    if self.devtype == 2:
 | 
| 996 |  | -      self.i2csend(0, 0xe6, 0x2b, struct.pack("<B", fade), 1)
 | 
| 997 |  | -      self.i2csend(0, 0xe6, 0x28, struct.pack("<B", int(brightness * 46)), 1)
 | 
| 998 |  | -      self.i2csend(0, 0xe6, 0x29, struct.pack("<B", 1), 1)
 | 
| 999 |  | -      self.__myprint(" done\n", silent)
 | 
| 1000 |  | -    elif self.devtype == 4:
 | 
| 1001 |  | -      self.i2csend(0, 0xe6, 0x30, struct.pack("<B", int(brightness * 250)), 1)
 | 
| 1002 |  | -      self.i2csend(0, 0xe6, 0x31, struct.pack("<B", 3), 1)
 | 
| 1003 |  | -      self.__myprint(" done\n", silent)
 | 
| 1004 |  | -    else: self.__myprint(" unsupported (%s)\n" % self.devtype2name(self.devtype), silent)
 | 
| 1005 |  | -
 | 
| 1006 |  | -
 | 
| 1007 |  | -  def backlightoff(self, fade, silent = 0):
 | 
| 1008 |  | -    self.__myprint("Turning off backlight...", silent)
 | 
| 1009 |  | -    if self.devtype == 2:
 | 
| 1010 |  | -      self.i2csend(0, 0xe6, 0x2b, struct.pack("<B", fade), 1)
 | 
| 1011 |  | -      self.i2csend(0, 0xe6, 0x29, struct.pack("<B", 0), 1)
 | 
| 1012 |  | -      self.__myprint(" done\n", silent)
 | 
| 1013 |  | -    elif self.devtype == 4:
 | 
| 1014 |  | -      self.i2csend(0, 0xe6, 0x31, struct.pack("<B", 2), 1)
 | 
| 1015 |  | -      self.__myprint(" done\n", silent)
 | 
| 1016 |  | -    else: self.__myprint(" unsupported (%s)\n" % self.devtype2name(self.devtype), silent)
 | 
| 1017 |  | -  
 | 
|  | 433 | +if __name__ == "__main__": | 
|  | 434 | +    # Some tests | 
|  | 435 | +    import sys | 
|  | 436 | +    embios = Embios() | 
|  | 437 | +    resp = embios.getversioninfo() | 
|  | 438 | +    sys.stdout.write("Embios device version information: " + libembiosdata.swtypes[resp.swtypeid] + " v" + str(resp.majorv) + "." + str(resp.minorv) + | 
|  | 439 | +                     "." + str(resp.patchv) + " r" + str(resp.revision) + " running on " + libembiosdata.hwtypes[resp.hwtypeid] + "\n") | 
|  | 440 | +    resp = embios.getusermemrange() | 
|  | 441 | +    sys.stdout.write("Usermemrange: "+hex(resp.lower)+" - "+hex(resp.upper)+"\n") | 
|  | 442 | +    memaddr = resp.lower | 
|  | 443 | +    maxlen = resp.upper - resp.lower | 
|  | 444 | +    f = open("./embios.py", "rb") | 
|  | 445 | +    sys.stdout.write("Loading test file (embios.py) to send over USB...\n") | 
|  | 446 | +    datastr = f.read()[:maxlen] | 
|  | 447 | +    sys.stdout.write("Sending data...\n") | 
|  | 448 | +    embios.write(memaddr, datastr) | 
|  | 449 | +    sys.stdout.write("Encrypting data with the hardware key...\n") | 
|  | 450 | +    embios.aesencrypt(memaddr, len(datastr), 0) | 
|  | 451 | +    sys.stdout.write("Reading data back and saving it to 'libembios-test-encrypted.bin'...\n") | 
|  | 452 | +    f = open("./libembios-test-encrypted.bin", "wb") | 
|  | 453 | +    f.write(embios.read(memaddr, len(datastr))) | 
|  | 454 | +    sys.stdout.write("Decrypting the data again...\n") | 
|  | 455 | +    embios.aesdecrypt(memaddr, len(datastr), 0) | 
|  | 456 | +    sys.stdout.write("Reading data back from device...\n") | 
|  | 457 | +    readdata = embios.read(memaddr, len(datastr)) | 
|  | 458 | +    if readdata == datastr: | 
|  | 459 | +        sys.stdout.write("Data matches!") | 
|  | 460 | +    else: | 
|  | 461 | +        sys.stdout.write("Data does NOT match. Something got wrong") | 
| \ No newline at end of file |