freemyipod r171 - Code Review

Jump to: navigation, search
Repository:freemyipod
Revision:r170‎ | r171 | r172 >
Date:16:04, 23 August 2010
Author:farthen
Status:new
Tags:
Comment:
Rewrite libembios. Not all functions are implemented yet.
Modified paths:
  • /embios/trunk/tools/embios.py (modified) (history)
  • /embios/trunk/tools/libembios.py (modified) (history)
  • /embios/trunk/tools/libembiosdata.py (added) (history)

Diff [purge]

Index: embios/trunk/tools/embios.py
@@ -1,7 +1,7 @@
22 #!/usr/bin/env python
33 #
44 #
5 -# Copyright 2010 TheSeven, benedikt93
 5+# Copyright 2010 TheSeven, benedikt93, Farthen
66 #
77 #
88 # This file is part of emBIOS.
@@ -21,378 +21,595 @@
2222 #
2323 #
2424
25 -# note: handles commands 1 to 20
 25+import sys
 26+import os
 27+import inspect
 28+import re
2629
27 -import sys
28 -import time
2930 import libembios
30 -import struct
 31+from libembios import Error
 32+import libembiosdata
3133
 34+class NotImplementedError(Error):
 35+ pass
3236
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
19939
 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"
20049
201 -def parsecommand(dev, argv):
202 - if len(argv) < 2: usage()
20350
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
21588
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")
22592 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")
255107
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)
273126
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)
301130
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)
311134
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)
339138
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")
350209
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 + "'")
354257
355 - elif argv[1] == "unlockscheduler":
356 - if len(argv) != 2: usage()
357 - dev.freezescheduler(0)
358258
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)
362277
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)
366289
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)
370301
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
374591
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)
378601
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)
397611
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 @@
22 #!/usr/bin/env python
33 #
44 #
5 -# Copyright 2010 TheSeven, benedikt93
 5+# Copyright 2010 TheSeven, benedikt93, Farthen
66 #
77 #
88 # This file is part of emBIOS.
@@ -21,996 +21,440 @@
2222 #
2323 #
2424
25 -# note: handles commands 1 to 21
26 -
2725 import sys
28 -import math
2926 import struct
30 -import time
31 -import usb
 27+import usb.core
 28+import libembiosdata
3229
 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)
3336
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
7539
76 - raise Exception("Could not find specified device (devtype = %d, type = %d)" % (devtype, type))
 40+class DeviceNotFoundError(Error):
 41+ pass
7742
 43+class DeviceError(Error):
 44+ pass
7845
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
8748
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
11051
111 -
112 - @staticmethod
113 - def __getbulk(handle, endpoint, size):
114 - data = handle.bulkRead(endpoint, size, 1000)
115 - return struct.pack("%dB" % len(data), *data)
11652
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):
20654 """
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.
22757 """
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
23561
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
24064
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
27868
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 -
31869
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)
32273
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)
32486
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"))
37490
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
399101
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))
415105
 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))
416112
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))
429119
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
431146
 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
432175
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))
434188
 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]
435195
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)
441202
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 """
445205
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 """
447208
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 """
461211
462 - self.__myprint(" done\n", silent)
 212+ def usbcwrite(self, data):
 213+ """ Writes data to the USB console """
463214
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+ """
466219
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+ """
491224
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))
493228
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 """
520231
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))
532235
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))
538239
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))
540243
 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))
541247
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))
552251
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
557272
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))
559276
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))
561280
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+ """
566285
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+ """
586290
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))
588294
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))
590300
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))
610306
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))
703310
704 -
705 -#=====================================================================================
706311
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
719319
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()
721324
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")
736351
737352
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
882357
883 - processinfoprint += "--------------------------------------------------------------------------------\n"
 358+ self.interface = 0
 359+ self.timeout = 100
884360
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
889369
890 - offset = 0
891 - blocklen = tablesize = self.cin_maxsize - 0x10
892 - procinfo = ""
893 - structversion = 0
 370+ def __del__(self):
 371+ self.disconnect()
894372
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")
916390
 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()
917396
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
925399
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
928405
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
935411
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)
937416
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)
939421
 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)
940426
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)
954431
955432
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