freemyipod r173 - Code Review

Jump to: navigation, search
Repository:freemyipod
Revision:r172‎ | r173 | r174 >
Date:00:17, 24 August 2010
Author:farthen
Status:new
Tags:
Comment:
libembios: implement getprocinfo(), fix some bugs
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
@@ -180,7 +180,11 @@
181181 except libembios.DeviceNotFoundError:
182182 self.logger.error("No emBIOS device found!")
183183 end(1)
184 - self.getinfo("version")
 184+ try:
 185+ self.getinfo("version")
 186+ except libembios.DeviceNotFoundError:
 187+ self.logger.error("Device not found!")
 188+ exit(2)
185189
186190 def _parsecommand(self, func, args):
187191 # adds self to the commandline args.
@@ -197,8 +201,6 @@
198202 usage(e)
199203 except NotImplementedError:
200204 self.logger.error("This function is not implemented yet!")
201 - except libembios.DeviceNotFoundError:
202 - self.logger.error("Device not found!")
203205 except libembios.DeviceError, e:
204206 self.logger.error(str(e))
205207 except TypeError, e:
@@ -257,6 +259,9 @@
258260 expected = expected[:-2]
259261 raise ArgumentTypeError("one out of " + expected, "'" + string + "'")
260262
 263+ @staticmethod
 264+ def _hex(integer):
 265+ return "0x%x" % integer
261266
262267 @command
263268 def getinfo(self, infotype):
@@ -273,7 +278,7 @@
274279 self.logger.info("Maximum packet sizes: "+str(resp))
275280 elif infotype == "usermemrange":
276281 resp = self.embios.getusermemrange()
277 - self.logger.info("The user memory range is "+hex(resp.lower)+" - "+hex(resp.upper-1))
 282+ self.logger.info("The user memory range is "+self._hex(resp.lower)+" - "+self._hex(resp.upper-1))
278283 else:
279284 raise ArgumentTypeError("one out of 'version', 'packetsize', 'usermemrange'", infotype)
280285
@@ -313,7 +318,7 @@
314319 f = open(filename, 'rb')
315320 except IOError:
316321 raise ArgumentError("File not readable. Does it exist?")
317 - self.logger.info("Writing file '"+filename+"' to memory at "+hex(addr)+"...")
 322+ self.logger.info("Writing file '"+filename+"' to memory at "+self._hex(addr)+"...")
318323 with f:
319324 self.embios.write(addr, f.read())
320325 self.logger.info("done\n")
@@ -334,7 +339,7 @@
335340 f = open(filename, 'wb')
336341 except IOError:
337342 raise ArgumentError("Can not open file for write!")
338 - self.logger.info("Reading data from address "+hex(addr)+" with the size "+hex(size)+" to '"+filename+"'...")
 343+ self.logger.info("Reading data from address "+self._hex(addr)+" with the size "+self._hex(size)+" to '"+filename+"'...")
339344 with f:
340345 f.write(self.embios.read(addr, size))
341346 self.logger.info("done\n")
@@ -352,7 +357,7 @@
353358 raise ArgumentError("Specified integer too long")
354359 data = chr(integer)
355360 self.embios.writemem(addr, data)
356 - self.logger.info("Integer '"+hex(integer)+"' written successfully to "+hex(addr))
 361+ self.logger.info("Integer '"+self._hex(integer)+"' written successfully to "+self._hex(addr))
357362
358363 @command
359364 def downloadint(self, addr):
@@ -363,7 +368,7 @@
364369 addr = self._hexint(addr)
365370 data = self.embios.readmem(addr, 1)
366371 integer = ord(data)
367 - self.logger.info("Integer '"+hex(integer)+"' read from address "+hex(addr))
 372+ self.logger.info("Integer '"+self._hex(integer)+"' read from address "+self._hex(addr))
368373
369374 @command
370375 def i2crecv(self, bus, slave, addr, size):
@@ -420,7 +425,7 @@
421426 Writes the file <file> to the USB console.
422427 Optional params <offset> <length>: specify the range in <file> to write
423428 """
424 - # We don't care about file here, this is done when opening it
 429+
425430 offset = self._hexint(offset)
426431 length = self._hexint(length)
427432 raise NotImplementedError
@@ -457,7 +462,7 @@
458463 Optional params <offset> <length>: specify the range in <file> to write
459464 """
460465 bitmask = self._hexint(bitmask)
461 - # We don't care about file here, this is done when opening it
 466+
462467 offset = self._hexint(offset)
463468 length = self._hexint(length)
464469 raise NotImplementedError
@@ -487,18 +492,30 @@
488493 def getprocinfo(self):
489494 """
490495 Fetches data on the currently running processes
491 - ATTENTION: this function will be print the information to the console window.
492 - If several threads are running this might overflow the window,
493 - causing not everything to be shown.
494496 """
495 - raise NotImplementedError
496 -
 497+ import datetime
 498+ threads = self.embios.getprocinfo()
 499+ self.logger.info("The device has "+str(len(threads))+" running threads:\n\n")
 500+ for thread in threads:
 501+ self.logger.info(" "+thread.name+":\n")
 502+ self.logger.info(" Thread id: "+str(thread.id)+"\n")
 503+ self.logger.info(" Thread type: "+thread.type+"\n")
 504+ self.logger.info(" Thread state: "+thread.state+"\n")
 505+ self.logger.info(" Priority: "+str(thread.priority)+"/256\n")
 506+ self.logger.info(" CPU time (total): "+str(datetime.timedelta(microseconds=thread.cputime_total))+"\n")
 507+ self.logger.info(" Stack address: "+self._hex(thread.stackaddr)+"\n")
 508+ self.logger.info(" Registers:\n")
 509+ for register in range(16):
 510+ self.logger.info(" r"+str(register)+": "+self._hex(thread.regs["r"+str(register)])+"\n")
 511+ self.logger.info(" cpsr: "+self._hex(thread.regs.cpsr))
 512+ self.logger.info("\n")
 513+
497514 @command
498515 def lockscheduler(self):
499516 """
500517 Locks (freezes) the scheduler
501518 """
502 - raise NotImplementedError
 519+ self.embios.lockscheduler()
503520
504521 @command
505522 def unlockscheduler(self):
@@ -505,7 +522,7 @@
506523 """
507524 Unlocks (unfreezes) the scheduler
508525 """
509 - raise NotImplementedError
 526+ self.embios.unlockscheduler()
510527
511528 @command
512529 def suspendthread(self, threadid):
@@ -513,7 +530,7 @@
514531 Suspends/resumes the thread with thread ID <threadid>
515532 """
516533 threadid = self._hexint(threadid)
517 - raise NotImplementedError
 534+ self.embios.resumethread(threadid)
518535
519536 @command
520537 def resumethread(self, threadid):
@@ -521,7 +538,7 @@
522539 Resumes the thread with thread ID <threadid>
523540 """
524541 threadid = self._hexint(threadid)
525 - raise NotImplementedError
 542+ self.embios.resumethread(threadid)
526543
527544 @command
528545 def killthread(self, threadid):
@@ -529,7 +546,7 @@
530547 Kills the thread with thread ID <threadid>
531548 """
532549 threadid = self._hexint(threadid)
533 - raise NotImplementedError
 550+ self.embios.killthread(threadid)
534551
535552 @command
536553 def createthread(self, nameptr, entrypoint, stackptr, stacksize, threadtype, priority, state):
@@ -553,8 +570,8 @@
554571 @command
555572 def run(self, filename):
556573 """
557 - Uploads the emBIOS application to an address in the user memory
558 - and executes it
 574+ Uploads the emBIOS application <filename> to
 575+ the beginning of the user memory and executes it
559576 """
560577 try:
561578 f = open(filename, "rb")
@@ -566,17 +583,17 @@
567584 filesize = os.path.getsize(filename)
568585 if filesize > maxsize:
569586 raise ArgumentError("The file is too big, it doesn't fit into the user memory.")
570 - self.logger.info("Uploading application to "+hex(addr)+" - "+hex(addr+filesize)+"\n")
 587+ self.logger.info("Uploading application to "+self._hex(addr)+" - "+self._hex(addr+filesize)+"\n")
571588 self.embios.write(addr, f.read())
572 - self.execute(addr)
 589+ self.execimage(addr)
573590
574591 @command
575 - def execute(self, addr):
 592+ def execimage(self, addr):
576593 """
577 - Executes the emBIOS application at <address>.
 594+ Executes the emBIOS application at <addr>.
578595 """
579596 addr = self._hexint(addr)
580 - self.logger.info("Starting emBIOS app at "+hex(addr)+"\n")
 597+ self.logger.info("Starting emBIOS app at "+self._hex(addr)+"\n")
581598 self.embios.execimage(addr)
582599
583600 @command
@@ -643,13 +660,13 @@
644661 size = self._hexint(size)
645662 destination = self._hexint(destination)
646663 sha1size = 0x14
647 - self.logger.info("Generating hmac-sha1 hash from the buffer at "+hex(addr)+" with the size "+hex(size)+
648 - " and saving it to "+hex(destination)+" - "+hex(destination+sha1size)+"...")
 664+ self.logger.info("Generating hmac-sha1 hash from the buffer at "+self._hex(addr)+" with the size "+self._hex(size)+
 665+ " and saving it to "+self._hex(destination)+" - "+self._hex(destination+sha1size)+"...")
649666 self.embios.hmac_sha1(addr, size, destination)
650667 self.logger.info("done\n")
651668 data = self.embios.readmem(destination, sha1size)
652669 hash = ord(data)
653 - self.logger.info("The generated hash is "+hex(hash))
 670+ self.logger.info("The generated hash is "+self._hex(hash))
654671
655672 if __name__ == "__main__":
656673 if len(sys.argv) < 2:
Index: embios/trunk/tools/libembiosdata.py
@@ -1,3 +1,28 @@
 2+thread_state = (
 3+ "THREAD_FREE",
 4+ "THREAD_SUSPENDED",
 5+ "THREAD_READY",
 6+ "THREAD_RUNNING",
 7+ "THREAD_BLOCKED",
 8+ "THREAD_DEFUNCT",
 9+ "THREAD_DEFUNCT_ACK"
 10+)
 11+
 12+thread_block = (
 13+ "THREAD_NOT_BLOCKED",
 14+ "THREAD_BLOCK_SLEEP",
 15+ "THREAD_BLOCK_MUTEX",
 16+ "THREAD_BLOCK_WAKEUP",
 17+ "THREAD_DEFUNCT_STKOV",
 18+ "THREAD_DEFUNCT_PANIC"
 19+)
 20+
 21+thread_type = (
 22+ "USER_THREAD",
 23+ "OS_THREAD",
 24+ "ORE_THREAD"
 25+)
 26+
227 hwtypes = {
328 0: "invalid",
429 0x47324e49: "iPod nano 2g",
Index: embios/trunk/tools/libembios.py
@@ -199,6 +199,23 @@
200200 self.lib.monitorcommand(struct.pack("IIII", 7, addr, len(data), 0), "III", (None, None, None))
201201 return self.lib.dev.dout(data)
202202
 203+ def readstring(self, addr, maxlength = 256):
 204+ """ Reads a zero terminated string from memory
 205+ Reads only a maximum of 'maxlength' chars.
 206+ """
 207+ cin_maxsize = self.lib.dev.packetsizelimit["cin"] - 0x10
 208+ string = ""
 209+ while (len(string) < maxlength or maxlength < 0):
 210+ data = self.readmem(addr, min(maxlength - len(string), cin_maxsize))
 211+ length = data.find("\0")
 212+ if length >= 0:
 213+ string += data[:length]
 214+ break
 215+ else:
 216+ string += data
 217+ addr += cin_maxsize
 218+ return string
 219+
203220 def i2cread(self, index, slaveaddr, startaddr, size):
204221 """ Reads data from an i2c slave """
205222
@@ -225,23 +242,89 @@
226243 """ Flushes the consoles specified with 'bitmask' """
227244 return self.lib.monitorcommand(struct.pack("IIII", 14, bitmask, 0, 0), "III", (None, None, None))
228245
229 - def getprocinfo(self, offset, size):
 246+ def getprocinfo(self):
230247 """ Gets current state of the scheduler """
 248+ cin_maxsize = self.lib.dev.packetsizelimit["cin"] - 0x10
 249+ # Get the size
 250+ schedulerstate = self.lockscheduler()
 251+ resp = self.lib.monitorcommand(struct.pack("IIII", 15, 0, 0, 0), "III", ("structver", "tablesize", None))
 252+ tablesize = resp.tablesize
 253+ size = tablesize
 254+ structver = resp.structver
 255+ offset = 0
 256+ data = ""
 257+ while size > 0:
 258+ if size > cin_maxsize:
 259+ readsize = cin_maxsize
 260+ else:
 261+ readsize = size
 262+ resp = self.lib.monitorcommand(struct.pack("IIII", 15, offset, readsize, 0), "III%ds" % readsize, ("structver", "tablesize", None, "data"))
 263+ data += resp.data
 264+ offset += readsize
 265+ size -= readsize
 266+ self.lockscheduler(schedulerstate)
 267+ threadstructsize = 120
 268+ registersize = 32
 269+ if len(data) % threadstructsize != 0:
 270+ raise DeviceError("The thread struct is not a multiple of "+str(threadsturcsize)+"!")
 271+ threadcount = len(data) / threadstructsize
 272+ threads = []
 273+ id = 0
 274+ for thread in range(threadcount):
 275+ offset = threadstructsize * thread
 276+ threaddata = struct.unpack("<16IIIIIQIIIIIIIBBBB", data[offset:offset+threadstructsize])
 277+ info = Bunch()
 278+ info.id = id
 279+ state = threaddata[17]
 280+ info.state = libembiosdata.thread_state[state]
 281+ if info.state == "THREAD_FREE":
 282+ id += 1
 283+ continue
 284+ info.regs = Bunch()
 285+ for register in range(16):
 286+ info.regs["r"+str(register)] = threaddata[register]
 287+ info.regs.cpsr = threaddata[16]
 288+ info.nameptr = threaddata[18]
 289+ if info.nameptr == 0:
 290+ info.name = "Thread %d" % info.id
 291+ else:
 292+ info.name = self.readstring(info.nameptr)
 293+ info.cputime_current = threaddata[19]
 294+ info.cputime_total = threaddata[20]
 295+ info.startusec = threaddata[21]
 296+ info.queue_next_ptr = threaddata[22]
 297+ info.timeout = threaddata[23]
 298+ info.blocked_since = threaddata[24]
 299+ info.blocked_by_ptr = threaddata[25]
 300+ info.stackaddr = threaddata[26]
 301+ info.err_no = threaddata[27]
 302+ info.block_type = libembiosdata.thread_block[threaddata[28]]
 303+ info.type = libembiosdata.thread_type[threaddata[29]]
 304+ info.priority = threaddata[30]
 305+ info.cpuload = threaddata[31]
 306+ threads.append(info)
 307+ id += 1
 308+ return threads
 309+
 310+
 311+ return self.lib.monitorcommand(struct.pack("IIII", 15, offset, size, 0), "III%ds" % size, ("structver", "tablesize", None, "data"))
231312
232 - def freezescheduler(self, freeze=True):
 313+ def lockscheduler(self, freeze=True):
233314 """ Freezes/Unfreezes the scheduler """
234 - return self.lib.monitorcommand(struct.pack("IIII", 16, 1 if freeze else 0, 0, 0), "III", ("before", None, None))
 315+ resp = self.lib.monitorcommand(struct.pack("IIII", 16, 1 if freeze else 0, 0, 0), "III", ("before", None, None))
 316+ return True if resp.before == 1 else False
235317
236 - def unfreezescheduler(self):
 318+ def unlockscheduler(self):
237319 """ Unfreezes the scheduler """
238320 return self.lib.monitorcommand(struct.pack("IIII", 16, 0, 0, 0), "III", ("before", None, None))
239321
240322 def suspendthread(self, id, suspend=True):
241323 """ 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))
 324+ resp = self.lib.monitorcommand(struct.pack("IIII", 17, 1 if suspend else 0, id, 0), "III", ("before", None, None))
 325+ return True if resp.before == 1 else False
243326
244 - def unsuspendthread(self, id):
245 - """ Suspends the thread with the specified id """
 327+ def resumethread(self, id):
 328+ """ Resumes the thread with the specified id """
246329 return self.lib.monitorcommand(struct.pack("IIII", 17, 0, id, 0), "III", ("before", None, None))
247330
248331 def killthread(self, id):