| Index: embios/trunk/tools/embios.py |
| — | — | @@ -180,7 +180,11 @@ |
| 181 | 181 | except libembios.DeviceNotFoundError:
|
| 182 | 182 | self.logger.error("No emBIOS device found!")
|
| 183 | 183 | 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)
|
| 185 | 189 |
|
| 186 | 190 | def _parsecommand(self, func, args):
|
| 187 | 191 | # adds self to the commandline args.
|
| — | — | @@ -197,8 +201,6 @@ |
| 198 | 202 | usage(e)
|
| 199 | 203 | except NotImplementedError:
|
| 200 | 204 | self.logger.error("This function is not implemented yet!")
|
| 201 | | - except libembios.DeviceNotFoundError:
|
| 202 | | - self.logger.error("Device not found!")
|
| 203 | 205 | except libembios.DeviceError, e:
|
| 204 | 206 | self.logger.error(str(e))
|
| 205 | 207 | except TypeError, e:
|
| — | — | @@ -257,6 +259,9 @@ |
| 258 | 260 | expected = expected[:-2]
|
| 259 | 261 | raise ArgumentTypeError("one out of " + expected, "'" + string + "'")
|
| 260 | 262 |
|
| | 263 | + @staticmethod
|
| | 264 | + def _hex(integer):
|
| | 265 | + return "0x%x" % integer
|
| 261 | 266 |
|
| 262 | 267 | @command
|
| 263 | 268 | def getinfo(self, infotype):
|
| — | — | @@ -273,7 +278,7 @@ |
| 274 | 279 | self.logger.info("Maximum packet sizes: "+str(resp))
|
| 275 | 280 | elif infotype == "usermemrange":
|
| 276 | 281 | 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))
|
| 278 | 283 | else:
|
| 279 | 284 | raise ArgumentTypeError("one out of 'version', 'packetsize', 'usermemrange'", infotype)
|
| 280 | 285 |
|
| — | — | @@ -313,7 +318,7 @@ |
| 314 | 319 | f = open(filename, 'rb')
|
| 315 | 320 | except IOError:
|
| 316 | 321 | 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)+"...")
|
| 318 | 323 | with f:
|
| 319 | 324 | self.embios.write(addr, f.read())
|
| 320 | 325 | self.logger.info("done\n")
|
| — | — | @@ -334,7 +339,7 @@ |
| 335 | 340 | f = open(filename, 'wb')
|
| 336 | 341 | except IOError:
|
| 337 | 342 | 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+"'...")
|
| 339 | 344 | with f:
|
| 340 | 345 | f.write(self.embios.read(addr, size))
|
| 341 | 346 | self.logger.info("done\n")
|
| — | — | @@ -352,7 +357,7 @@ |
| 353 | 358 | raise ArgumentError("Specified integer too long")
|
| 354 | 359 | data = chr(integer)
|
| 355 | 360 | 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))
|
| 357 | 362 |
|
| 358 | 363 | @command
|
| 359 | 364 | def downloadint(self, addr):
|
| — | — | @@ -363,7 +368,7 @@ |
| 364 | 369 | addr = self._hexint(addr)
|
| 365 | 370 | data = self.embios.readmem(addr, 1)
|
| 366 | 371 | 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))
|
| 368 | 373 |
|
| 369 | 374 | @command
|
| 370 | 375 | def i2crecv(self, bus, slave, addr, size):
|
| — | — | @@ -420,7 +425,7 @@ |
| 421 | 426 | Writes the file <file> to the USB console.
|
| 422 | 427 | Optional params <offset> <length>: specify the range in <file> to write
|
| 423 | 428 | """
|
| 424 | | - # We don't care about file here, this is done when opening it
|
| | 429 | +
|
| 425 | 430 | offset = self._hexint(offset)
|
| 426 | 431 | length = self._hexint(length)
|
| 427 | 432 | raise NotImplementedError
|
| — | — | @@ -457,7 +462,7 @@ |
| 458 | 463 | Optional params <offset> <length>: specify the range in <file> to write
|
| 459 | 464 | """
|
| 460 | 465 | bitmask = self._hexint(bitmask)
|
| 461 | | - # We don't care about file here, this is done when opening it
|
| | 466 | +
|
| 462 | 467 | offset = self._hexint(offset)
|
| 463 | 468 | length = self._hexint(length)
|
| 464 | 469 | raise NotImplementedError
|
| — | — | @@ -487,18 +492,30 @@ |
| 488 | 493 | def getprocinfo(self):
|
| 489 | 494 | """
|
| 490 | 495 | 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.
|
| 494 | 496 | """
|
| 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 | +
|
| 497 | 514 | @command
|
| 498 | 515 | def lockscheduler(self):
|
| 499 | 516 | """
|
| 500 | 517 | Locks (freezes) the scheduler
|
| 501 | 518 | """
|
| 502 | | - raise NotImplementedError
|
| | 519 | + self.embios.lockscheduler()
|
| 503 | 520 |
|
| 504 | 521 | @command
|
| 505 | 522 | def unlockscheduler(self):
|
| — | — | @@ -505,7 +522,7 @@ |
| 506 | 523 | """
|
| 507 | 524 | Unlocks (unfreezes) the scheduler
|
| 508 | 525 | """
|
| 509 | | - raise NotImplementedError
|
| | 526 | + self.embios.unlockscheduler()
|
| 510 | 527 |
|
| 511 | 528 | @command
|
| 512 | 529 | def suspendthread(self, threadid):
|
| — | — | @@ -513,7 +530,7 @@ |
| 514 | 531 | Suspends/resumes the thread with thread ID <threadid>
|
| 515 | 532 | """
|
| 516 | 533 | threadid = self._hexint(threadid)
|
| 517 | | - raise NotImplementedError
|
| | 534 | + self.embios.resumethread(threadid)
|
| 518 | 535 |
|
| 519 | 536 | @command
|
| 520 | 537 | def resumethread(self, threadid):
|
| — | — | @@ -521,7 +538,7 @@ |
| 522 | 539 | Resumes the thread with thread ID <threadid>
|
| 523 | 540 | """
|
| 524 | 541 | threadid = self._hexint(threadid)
|
| 525 | | - raise NotImplementedError
|
| | 542 | + self.embios.resumethread(threadid)
|
| 526 | 543 |
|
| 527 | 544 | @command
|
| 528 | 545 | def killthread(self, threadid):
|
| — | — | @@ -529,7 +546,7 @@ |
| 530 | 547 | Kills the thread with thread ID <threadid>
|
| 531 | 548 | """
|
| 532 | 549 | threadid = self._hexint(threadid)
|
| 533 | | - raise NotImplementedError
|
| | 550 | + self.embios.killthread(threadid)
|
| 534 | 551 |
|
| 535 | 552 | @command
|
| 536 | 553 | def createthread(self, nameptr, entrypoint, stackptr, stacksize, threadtype, priority, state):
|
| — | — | @@ -553,8 +570,8 @@ |
| 554 | 571 | @command
|
| 555 | 572 | def run(self, filename):
|
| 556 | 573 | """
|
| 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
|
| 559 | 576 | """
|
| 560 | 577 | try:
|
| 561 | 578 | f = open(filename, "rb")
|
| — | — | @@ -566,17 +583,17 @@ |
| 567 | 584 | filesize = os.path.getsize(filename)
|
| 568 | 585 | if filesize > maxsize:
|
| 569 | 586 | 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")
|
| 571 | 588 | self.embios.write(addr, f.read())
|
| 572 | | - self.execute(addr)
|
| | 589 | + self.execimage(addr)
|
| 573 | 590 |
|
| 574 | 591 | @command
|
| 575 | | - def execute(self, addr):
|
| | 592 | + def execimage(self, addr):
|
| 576 | 593 | """
|
| 577 | | - Executes the emBIOS application at <address>.
|
| | 594 | + Executes the emBIOS application at <addr>.
|
| 578 | 595 | """
|
| 579 | 596 | 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")
|
| 581 | 598 | self.embios.execimage(addr)
|
| 582 | 599 |
|
| 583 | 600 | @command
|
| — | — | @@ -643,13 +660,13 @@ |
| 644 | 661 | size = self._hexint(size)
|
| 645 | 662 | destination = self._hexint(destination)
|
| 646 | 663 | 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)+"...")
|
| 649 | 666 | self.embios.hmac_sha1(addr, size, destination)
|
| 650 | 667 | self.logger.info("done\n")
|
| 651 | 668 | data = self.embios.readmem(destination, sha1size)
|
| 652 | 669 | hash = ord(data)
|
| 653 | | - self.logger.info("The generated hash is "+hex(hash))
|
| | 670 | + self.logger.info("The generated hash is "+self._hex(hash))
|
| 654 | 671 |
|
| 655 | 672 | if __name__ == "__main__":
|
| 656 | 673 | 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 | +
|
| 2 | 27 | hwtypes = {
|
| 3 | 28 | 0: "invalid",
|
| 4 | 29 | 0x47324e49: "iPod nano 2g",
|
| Index: embios/trunk/tools/libembios.py |
| — | — | @@ -199,6 +199,23 @@ |
| 200 | 200 | self.lib.monitorcommand(struct.pack("IIII", 7, addr, len(data), 0), "III", (None, None, None))
|
| 201 | 201 | return self.lib.dev.dout(data)
|
| 202 | 202 |
|
| | 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 | +
|
| 203 | 220 | def i2cread(self, index, slaveaddr, startaddr, size):
|
| 204 | 221 | """ Reads data from an i2c slave """
|
| 205 | 222 |
|
| — | — | @@ -225,23 +242,89 @@ |
| 226 | 243 | """ Flushes the consoles specified with 'bitmask' """
|
| 227 | 244 | return self.lib.monitorcommand(struct.pack("IIII", 14, bitmask, 0, 0), "III", (None, None, None))
|
| 228 | 245 |
|
| 229 | | - def getprocinfo(self, offset, size):
|
| | 246 | + def getprocinfo(self):
|
| 230 | 247 | """ 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"))
|
| 231 | 312 |
|
| 232 | | - def freezescheduler(self, freeze=True):
|
| | 313 | + def lockscheduler(self, freeze=True):
|
| 233 | 314 | """ 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
|
| 235 | 317 |
|
| 236 | | - def unfreezescheduler(self):
|
| | 318 | + def unlockscheduler(self):
|
| 237 | 319 | """ Unfreezes the scheduler """
|
| 238 | 320 | return self.lib.monitorcommand(struct.pack("IIII", 16, 0, 0, 0), "III", ("before", None, None))
|
| 239 | 321 |
|
| 240 | 322 | def suspendthread(self, id, suspend=True):
|
| 241 | 323 | """ 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
|
| 243 | 326 |
|
| 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 """
|
| 246 | 329 | return self.lib.monitorcommand(struct.pack("IIII", 17, 0, id, 0), "III", ("before", None, None))
|
| 247 | 330 |
|
| 248 | 331 | def killthread(self, id):
|