freemyipod r176 - Code Review

Jump to: navigation, search
Repository:freemyipod
Revision:r175‎ | r176 | r177 >
Date:21:47, 25 August 2010
Author:farthen
Status:new
Tags:
Comment:
embios.py/libembios: Add some more functions (i2c, usb and dev consoles...), disable run() temporarily until it can read the header properly
Modified paths:
  • /embios/trunk/tools/embios.py (modified) (history)
  • /embios/trunk/tools/libembios.py (modified) (history)
  • /embios/trunk/tools/libembiosdata.py (modified) (history)

Diff [purge]

Index: embios/trunk/tools/embios.py
@@ -25,7 +25,10 @@
2626 import os
2727 import inspect
2828 import re
 29+import time
2930
 31+from functools import wraps
 32+
3033 import libembios
3134 from libembios import Error
3235 import libembiosdata
@@ -144,6 +147,7 @@
145148 Decorator for all commands.
146149 The decorated function is called with (self, all, other, arguments, ...)
147150 """
 151+ @wraps(func)
148152 def decorator(*args):
149153 return func(args[0], *args[1:])
150154 func._command = True
@@ -179,12 +183,8 @@
180184 self.embios = libembios.Embios()
181185 except libembios.DeviceNotFoundError:
182186 self.logger.error("No emBIOS device found!")
183 - end(1)
184 - try:
185 - self.getinfo("version")
186 - except libembios.DeviceNotFoundError:
187 - self.logger.error("Device not found!")
188 - exit(2)
 187+ exit(1)
 188+ self.getinfo("version")
189189
190190 def _parsecommand(self, func, args):
191191 # adds self to the commandline args.
@@ -194,20 +194,24 @@
195195 try:
196196 self.cmddict[func](*args)
197197 except ArgumentError, e:
198 - usage(e)
 198+ usage(e, specific=func)
199199 except ArgumentError:
200 - usage("Syntax Error in function '" + func + "'")
 200+ usage("Syntax Error in function '" + func + "'", specific=func)
201201 except ArgumentTypeError, e:
202 - usage(e)
 202+ usage(e, specific=func)
203203 except NotImplementedError:
204204 self.logger.error("This function is not implemented yet!")
205205 except libembios.DeviceError, e:
206206 self.logger.error(str(e))
 207+ except ValueError:
 208+ usage(specific=func)
207209 except TypeError, e:
208210 if str(e).split(" ", 1)[0] == func + "()":
209211 self.logger.error(usage("Argument Error in '" + func + "': Wrong argument count", specific=func))
210212 else:
211213 raise
 214+ except libembios.usb.core.USBError:
 215+ self.logger.error("Problem with USB connection.")
212216 else:
213217 usage("No such command")
214218
@@ -322,9 +326,7 @@
323327 with f:
324328 self.embios.write(addr, f.read())
325329 self.logger.info("done\n")
326 -
327 -
328 -
 330+
329331 @command
330332 def downloadfile(self, addr, size, filename):
331333 """
@@ -371,7 +373,7 @@
372374 self.logger.info("Integer '"+self._hex(integer)+"' read from address "+self._hex(addr))
373375
374376 @command
375 - def i2crecv(self, bus, slave, addr, size):
 377+ def i2cread(self, bus, slave, addr, size):
376378 """
377379 Reads data from an I2C device
378380 <bus> the bus index
@@ -383,103 +385,75 @@
384386 slave = self._hexint(slave)
385387 addr = self._hexint(addr)
386388 size = self._hexint(size)
387 - raise NotImplementedError
 389+ self.embios.i2cread(bus, slave, addr, size)
388390
389391 @command
390 - def i2csend(self, bus, slave, addr, *args):
 392+ def i2cwrite(self, bus, slave, addr, *args):
391393 """
392394 Writes data to an I2C device
393395 <bus> the bus index
394396 <slave> the slave address
395397 <addr> the start address on the I2C device
396 - <db1> ... <dbN> the data in single bytes, seperated by whitespaces,
397 - eg. 0x37 0x56 0x45 0x12
 398+ <db1> ... <dbN> the data in single bytes, encoded in hex,
 399+ seperated by whitespaces, eg. 37 56 45 12
398400 """
399401 bus = self._hexint(bus)
400402 slave = self._hexint(slave)
401403 addr = self._hexint(addr)
402 - data = []
 404+ data = ""
403405 for arg in args:
404 - data.append(self._hexint(arg))
405 - raise NotImplementedError
 406+ data += chr(self._hexint(arg))
 407+ self.embios.i2cwrite(bus, slave, addr, data)
406408
407409 @command
408 - def readusbconsole(self, size, outtype):
 410+ def console(self):
409411 """
410 - Reads data from the USB console.
411 - <size>: the number of bytes to read
412 - <outtype>: defines how to output the result:
413 - 'file': writes the result to file <file>
414 - 'printstring': writes the result as string to the console window
415 - 'printhex': writes the result in hexedit notation to the console window
416 - <file>: the file to write the result to, can be omitted
417 - if <outtype> is not 'file'
 412+ Reads data from the USB console continuously
418413 """
419 - size = self._hexint(size)
420 - raise NotImplementedError
421 -
 414+ while True:
 415+ resp = self.embios.usbcread()
 416+ self.logger.log(resp.data)
 417+ time.sleep(0.1 / resp.maxsize * (resp.maxsize - len(resp.data)))
422418
423419 @command
424 - def writeusbconsole_file(self, file, offset=0, length=None):
 420+ def writeusbconsole(self, *args):
425421 """
426 - Writes the file <file> to the USB console.
427 - Optional params <offset> <length>: specify the range in <file> to write
 422+ Writes the string <db1> ... <dbN> to the USB console.
428423 """
429 -
430 - offset = self._hexint(offset)
431 - length = self._hexint(length)
432 - raise NotImplementedError
 424+ text = ""
 425+ for word in args:
 426+ text += word + " "
 427+ text = text[:-1]
 428+ self.logger.info("Writing '"+text+"' to the usb console\n")
 429+ self.embios.usbcwrite(text)
433430
434431 @command
435 - def writeusbconsole_direct(self, *args):
 432+ def readdevconsole(self, bitmask):
436433 """
437 - Writes the strings <db1> ... <dbN> to the USB console."
 434+ Reads data continuously from one or more of the device's consoles.
 435+ <bitmask>: the bitmask of the consoles to read from.
438436 """
439 - raise NotImplementedError
440 -
441 - @command
442 - def readdevconsole(self, bitmask, size, outtype, file=None):
443 - """
444 - Reads data from one or more of the device's consoles.
445 - <bitmask>: the bitmask of the consoles to read from
446 - <size>: the number of bytes to read
447 - <outtype>: defines how to output the result:
448 - 'file': writes the result to file <file>
449 - 'printstring': writes the result as string to the console window
450 - 'printhex': writes the result in hexedit notation to the console window
451 - <file>: the file to write the result to, can be omitted
452 - if <outtype> is not 'file'
453 - """
454437 bitmask = self._hexint(bitmask)
455 - size = self._hexint(size)
456 - outtype = self._strcheck(['file', 'printstring', 'printhex'])
457 - raise NotImplementedError
458 -
 438+ while True:
 439+ resp = self.embios.cread()
 440+ self.logger.log(resp.data)
 441+ time.sleep(0.1 / resp.maxsize * (resp.maxsize - len(resp.data)))
 442+
459443 @command
460 - def writedevconsole_file(self, bitmask, file, offset=0, length=None):
 444+ def writedevconsole(self, bitmask, *args):
461445 """
462 - Writes the file <file> to the device consoles specified by <bitmask>
463 - Optional params <offset> <length>: specify the range in <file> to write
 446+ Writes the string <db1> ... <dbN> to one or more of the device's consoles.
 447+ <bitmask>: the bitmask of the consoles to write to
464448 """
465449 bitmask = self._hexint(bitmask)
466 -
467 - offset = self._hexint(offset)
468 - length = self._hexint(length)
469 - raise NotImplementedError
 450+ text = ""
 451+ for word in args:
 452+ text += word + " "
 453+ text = text[:-1]
 454+ self.logger.info("Writing '"+text+"' to the device consoles identified with "+self._hex(bitmask)+"\n")
 455+ self.embios.cwrite(text, bitmask)
470456
471457 @command
472 - def writedevconsole_direct(self, bitmask, *args):
473 - """
474 - Writes the integers <db1> ... <dbN> to the device consoles specified
475 - by <bitmask>
476 - """
477 - bitmask = self._hexint(bitmask)
478 - data = []
479 - for arg in args:
480 - data.append(self._hexint(arg))
481 - raise NotImplementedError
482 -
483 - @command
484458 def flushconsolebuffers(self, bitmask):
485459 """
486460 flushes one or more of the device consoles' buffers.
@@ -515,6 +489,7 @@
516490 """
517491 Locks (freezes) the scheduler
518492 """
 493+ self.logger.info("Will now lock scheduler\n")
519494 self.embios.lockscheduler()
520495
521496 @command
@@ -522,6 +497,7 @@
523498 """
524499 Unlocks (unfreezes) the scheduler
525500 """
 501+ self.logger.info("Will now unlock scheduler\n")
526502 self.embios.unlockscheduler()
527503
528504 @command
@@ -573,19 +549,8 @@
574550 Uploads the emBIOS application <filename> to
575551 the beginning of the user memory and executes it
576552 """
577 - try:
578 - f = open(filename, "rb")
579 - except IOError:
580 - raise ArgumentError("File not readable. Does it exist?")
581 - data = self.embios.getusermemrange()
582 - addr = data.lower
583 - maxsize = data.upper - data.lower
584 - filesize = os.path.getsize(filename)
585 - if filesize > maxsize:
586 - raise ArgumentError("The file is too big, it doesn't fit into the user memory.")
587 - self.logger.info("Uploading application to "+self._hex(addr)+" - "+self._hex(addr+filesize)+"\n")
588 - self.embios.write(addr, f.read())
589 - self.execimage(addr)
 553+ #self.execimage(addr)
 554+ raise NotImplementedError
590555
591556 @command
592557 def execimage(self, addr):
@@ -595,10 +560,19 @@
596561 addr = self._hexint(addr)
597562 self.logger.info("Starting emBIOS app at "+self._hex(addr)+"\n")
598563 self.embios.execimage(addr)
599 -
 564+
600565 @command
601 - def readrawbootflash(self, addr_flash, addr_mem, size):
 566+ def flushcaches(self):
602567 """
 568+ Flushes the CPUs data and instruction caches.
 569+ """
 570+ self.logger.info("Flushing CPU data and instruction caches...")
 571+ self.embios.flushcaches()
 572+ self.logger.info("done\n")
 573+
 574+ @command
 575+ def readbootflash(self, addr_flash, addr_mem, size):
 576+ """
603577 Reads <size> bytes from bootflash to memory.
604578 <addr_bootflsh>: the address in bootflash to read from
605579 <addr_mem>: the address in memory to copy the data to
@@ -609,9 +583,9 @@
610584 self.logger.info("Dumping boot flash addresses "+self._hex(addr_flash)+" - "+
611585 hex(addr_flash+size)+" to "+self._hex(addr_mem)+" - "+self._hex(addr_mem+size)+"\n")
612586 self.embios.bootflashread(addr_flash, addr_mem, size)
613 -
 587+
614588 @command
615 - def writerawbootflash(self, addr_flash, addr_mem, size, force=False):
 589+ def writebootflash(self, addr_flash, addr_mem, size, force=False):
616590 """
617591 Writes <size> bytes from memory to bootflash.
618592 ATTENTION: Don't call this unless you really know what you're doing!
@@ -628,23 +602,32 @@
629603 hex(addr_mem+size)+" to "+self._hex(addr_flash)+" - "+self._hex(addr_flash+size)+"\n")
630604 if force == False:
631605 self.logger.info("If this was not what you intended press Ctrl-C NOW")
632 - import time
633 - for i in range(5):
 606+ for i in range(10):
634607 self.logger.info(".")
635608 time.sleep(1)
636609 self.logger.info("\n")
637610 self.embios.bootflashwrite(addr_flash, addr_mem, size)
638 -
 611+
639612 @command
640 - def flushcaches(self):
 613+ def runfirmware(self, addr, filename):
641614 """
642 - Flushes the CPUs data and instruction caches.
 615+ Uploads the firmware in 'filename' to the beginning of the
 616+ user memory and executes it
643617 """
644 - self.logger.info("Flushing CPU data and instruction caches...")
645 - self.embios.flushcaches()
646 - self.logger.info("done\n")
 618+ addr = self._hexint(addr)
 619+ self.uploadfile(addr, filename)
 620+ self.execfirmware(addr)
647621
648622 @command
 623+ def execfirmware(self, addr):
 624+ """
 625+ Executes the firmware at addr
 626+ """
 627+ addr = self._hexint(addr)
 628+ self.logger.info("Running firmware at "+self._hex(addr)+". Bye.")
 629+ self.embios.execfirmware(addr)
 630+
 631+ @command
649632 def aesencrypt(self, addr, size, keyindex):
650633 """
651634 Encrypts a buffer using a hardware key
Index: embios/trunk/tools/libembiosdata.py
@@ -1,3 +1,26 @@
 2+#!/usr/bin/env python
 3+#
 4+#
 5+# Copyright 2010 TheSeven, benedikt93, Farthen
 6+#
 7+#
 8+# This file is part of emBIOS.
 9+#
 10+# emBIOS is free software: you can redistribute it and/or
 11+# modify it under the terms of the GNU General Public License as
 12+# published by the Free Software Foundation, either version 2 of the
 13+# License, or (at your option) any later version.
 14+#
 15+# emBIOS is distributed in the hope that it will be useful,
 16+# but WITHOUT ANY WARRANTY; without even the implied warranty of
 17+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 18+# See the GNU General Public License for more details.
 19+#
 20+# You should have received a copy of the GNU General Public License
 21+# along with emBIOS. If not, see <http://www.gnu.org/licenses/>.
 22+#
 23+#
 24+
225 thread_state = (
326 "THREAD_FREE",
427 "THREAD_SUSPENDED",
@@ -20,7 +43,7 @@
2144 thread_type = (
2245 "USER_THREAD",
2346 "OS_THREAD",
24 - "ORE_THREAD"
 47+ "CORE_THREAD"
2548 )
2649
2750 hwtypes = {
Index: embios/trunk/tools/libembios.py
@@ -67,8 +67,12 @@
6868
6969
7070 class Embios(object):
 71+ """
 72+ Class for all embios functions.
 73+ """
7174 def __init__(self):
72 - self.lib = Lib(self)
 75+ self.lib = Lib()
 76+ self.getpacketsizeinfo()
7377
7478 @staticmethod
7579 def _alignsplit(addr, size, blksize, align):
@@ -121,9 +125,7 @@
122126 from the device. This cares about too long packages
123127 and decides whether to use DMA or not.
124128 """
125 - if not self.lib.connected:
126 - self.lib.connect()
127 - cin_maxsize = self.lib.dev.packetsizelimit["cin"] - 0x10
 129+ cin_maxsize = self.lib.dev.packetsizelimit["cin"] - self.lib.headersize
128130 din_maxsize = self.lib.dev.packetsizelimit["din"]
129131 data = ""
130132 (headsize, bodysize, tailsize) = self._alignsplit(addr, size, cin_maxsize, 16)
@@ -148,9 +150,7 @@
149151 in the memory of the device. This cares about too long packages
150152 and decides whether to use DMA or not.
151153 """
152 - if not self.lib.connected:
153 - self.lib.connect()
154 - cout_maxsize = self.lib.dev.packetsizelimit["cout"] - 0x10
 154+ cout_maxsize = self.lib.dev.packetsizelimit["cout"] - self.lib.headersize
155155 dout_maxsize = self.lib.dev.packetsizelimit["dout"]
156156 (headsize, bodysize, tailsize) = self._alignsplit(addr, len(data), cout_maxsize, 16)
157157 offset = 0
@@ -203,7 +203,7 @@
204204 """ Reads a zero terminated string from memory
205205 Reads only a maximum of 'maxlength' chars.
206206 """
207 - cin_maxsize = self.lib.dev.packetsizelimit["cin"] - 0x10
 207+ cin_maxsize = self.lib.dev.packetsizelimit["cin"] - self.lib.headersize
208208 string = ""
209209 while (len(string) < maxlength or maxlength < 0):
210210 data = self.readmem(addr, min(maxlength - len(string), cin_maxsize))
@@ -218,25 +218,61 @@
219219
220220 def i2cread(self, index, slaveaddr, startaddr, size):
221221 """ Reads data from an i2c slave """
 222+ if size > 256 or size < 1:
 223+ raise ValueError("Size must be a number between 1 and 256")
 224+ if size == 256:
 225+ size = 0
 226+ resp = self.lib.monitorcommand(struct.pack("IBBBBII", 8, index, slaveaddr, startaddr, size, 0, 0), "III%ds" % size, (None, None, None, "data"))
 227+ return resp.data
222228
223229 def i2cwrite(self, index, slaveaddr, startaddr, data):
224230 """ Writes data to an i2c slave """
 231+ size = len(data)
 232+ if size > 256 or size < 1:
 233+ raise ValueError("Size must be a number between 1 and 256")
 234+ if size == 256:
 235+ size = 0
 236+ return self.lib.monitorcommand(struct.pack("IBBBBII%ds" % size, 9, index, slaveaddr, startaddr, size, 0, 0, data), "III" % size, (None, None, None))
225237
226 - def usbcread(self, size):
227 - """ Reads data with size 'size' from the USB console """
 238+ def usbcread(self):
 239+ """ Reads one packet with the maximal cin size """
 240+ cin_maxsize = self.lib.dev.packetsizelimit["cin"] - self.lib.headersize
 241+ resp = self.lib.monitorcommand(struct.pack("IIII", 10, cin_maxsize, 0, 0), "III%ds" % cin_maxsize, ("validsize", "buffersize", "queuesize", "data"))
 242+ resp.data = resp.data[:resp.validsize]
 243+ resp.maxsize = cin_maxsize
 244+ return resp
228245
229246 def usbcwrite(self, data):
230247 """ Writes data to the USB console """
 248+ cin_maxsize = self.lib.dev.packetsizelimit["cin"] - self.lib.headersize
 249+ size = len(data)
 250+ while len(data) > 0:
 251+ writesize = min(cin_maxsize, len(data))
 252+ resp = self.lib.monitorcommand(struct.pack("IIII%ds" % writesize, 11, writesize, 0, 0, data[:writesize]), "III", ("validsize", "buffersize", "freesize"))
 253+ data = data[resp.validsize:]
 254+ return size
231255
232 - def cread(self, size, bitmask):
233 - """ Reads data with the specified size from the device consoles
 256+ def cread(self, bitmask=0x1):
 257+ """ Reads one packet with the maximal cin size from the device consoles
234258 identified with the specified bitmask
235259 """
 260+ cin_maxsize = self.lib.dev.packetsizelimit["cin"] - self.lib.headersize
 261+ resp = self.lib.monitorcommand(struct.pack("IIII", 14, cin_maxsize, 0, 0), "III%ds" % cin_maxsize, ("size", None, None))
 262+ resp.data = resp.data[size:]
 263+ resp.maxsize = cin_maxsize
 264+ return resp
236265
237 - def cwrite(self, data):
 266+ def cwrite(self, data, bitmask=0x1):
238267 """ Writes data to the device consoles
239268 identified with the specified bitmask.
240269 """
 270+ cin_maxsize = self.lib.dev.packetsizelimit["cin"] - self.lib.headersize
 271+ size = len(data)
 272+ while len(data) > 0:
 273+ writesize = min(cin_maxsize, len(data))
 274+ resp = self.lib.monitorcommand(struct.pack("IIII%ds" % writesize, 13, writesize, 0, 0, data[:writesize]), "III", (None, None, None))
 275+ data = data[writesize:]
 276+ return size
241277
242278 def cflush(self, bitmask):
243279 """ Flushes the consoles specified with 'bitmask' """
@@ -244,7 +280,7 @@
245281
246282 def getprocinfo(self):
247283 """ Gets current state of the scheduler """
248 - cin_maxsize = self.lib.dev.packetsizelimit["cin"] - 0x10
 284+ cin_maxsize = self.lib.dev.packetsizelimit["cin"] - self.lib.headersize
249285 # Get the size
250286 schedulerstate = self.lockscheduler()
251287 resp = self.lib.monitorcommand(struct.pack("IIII", 15, 0, 0, 0), "III", ("structver", "tablesize", None))
@@ -338,15 +374,15 @@
339375 elif threadtype == "system":
340376 threadtype = 1
341377 else:
342 - raise SyntaxError("Threadtype must be either 'system' or 'user'")
 378+ raise ValueError("Threadtype must be either 'system' or 'user'")
343379 if priority > 256 or priority < 0:
344 - raise SyntaxError("Priority must be a number between 0 and 256")
 380+ raise ValueError("Priority must be a number between 0 and 256")
345381 if state == "ready":
346382 state = 0
347383 elif state == "suspended":
348384 state = 1
349385 else:
350 - raise SyntaxError("State must be either 'ready' or 'suspended'")
 386+ raise ValueError("State must be either 'ready' or 'suspended'")
351387 resp = self.lib.monitorcommand(struct.pack("IIIIIIII", 19, nameptr, entrypoint, stackptr, stacksize, threadtype, priority, state), "III", (id, None, None))
352388 if resp.id < 0:
353389 raise DeviceError("The device returned the error code "+str(resp.id))
@@ -394,21 +430,19 @@
395431
396432
397433 class Lib(object):
398 - def __init__(self, embios):
 434+ def __init__(self):
399435 self.idVendor = 0xFFFF
400436 self.idProduct = 0xE000
401 -
402 - self.embios = embios
403 - self.connected = False
 437+
 438+ self.headersize = 0x10
 439+
 440+ self.connect()
404441
405442 def connect(self):
406443 self.dev = Dev(self.idVendor, self.idProduct)
407444 self.connected = True
408 - self.embios.getpacketsizeinfo()
409445
410446 def monitorcommand(self, cmd, rcvdatatypes=None, rcvstruct=None):
411 - if not self.connected:
412 - self.connect()
413447 self.dev.cout(cmd)
414448 if rcvdatatypes:
415449 rcvdatatypes = "I" + rcvdatatypes # add the response
@@ -441,7 +475,7 @@
442476
443477 self.interface = 0
444478 self.timeout = 100
445 -
 479+
446480 self.connect()
447481 self.findEndpoints()
448482
@@ -484,13 +518,13 @@
485519 def send(self, endpoint, data):
486520 size = self.dev.write(endpoint, data, self.interface, self.timeout)
487521 if size != len(data):
488 - raise SendError
 522+ raise SendError("Not all data was written!")
489523 return len
490524
491525 def receive(self, endpoint, size):
492526 read = self.dev.read(endpoint, size, self.interface, self.timeout)
493527 if len(read) != size:
494 - raise ReceiveError
 528+ raise ReceiveError("Requested size and read size don't match!")
495529 return read
496530
497531 def cout(self, data):