| 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): |