| Line 24... |
Line 24... |
| 24 |
import sys
|
24 |
import sys
|
| 25 |
import struct
|
25 |
import struct
|
| 26 |
import usb.core
|
26 |
import usb.core
|
| 27 |
import libembiosdata
|
27 |
import libembiosdata
|
| 28 |
|
28 |
|
| 29 |
from misc import Bunch, Error
|
29 |
from misc import Bunch, Error, gethwname
|
| 30 |
from functools import wraps
|
30 |
from functools import wraps
|
| 31 |
|
31 |
|
| 32 |
class ArgumentError(Error):
|
32 |
class ArgumentError(Error):
|
| 33 |
pass
|
33 |
pass
|
| 34 |
|
34 |
|
| Line 43... |
Line 43... |
| 43 |
|
43 |
|
| 44 |
class ReceiveError(Error):
|
44 |
class ReceiveError(Error):
|
| 45 |
pass
|
45 |
pass
|
| 46 |
|
46 |
|
| 47 |
|
47 |
|
| 48 |
def command(timeout = None):
|
48 |
def command(timeout = None, target = None):
|
| 49 |
"""
|
49 |
"""
|
| 50 |
Decorator for all commands.
|
50 |
Decorator for all commands.
|
| 51 |
It adds the "timeout" variable to all commands.
|
51 |
It adds the "timeout" variable to all commands.
|
| 52 |
It also provides the possibility to set the timeout directly in the decorator.
|
52 |
It also provides the possibility to set the timeout directly in the decorator.
|
| 53 |
It also includes some dirty hacks to not learn from.
|
53 |
It also includes some dirty hacks to not learn from.
|
| Line 55... |
Line 55... |
| 55 |
time = timeout # dirty hack because otherwise it would raise a scoping problem.
|
55 |
time = timeout # dirty hack because otherwise it would raise a scoping problem.
|
| 56 |
# The reason is probably because I suck but I can't find any good explanation of this.
|
56 |
# The reason is probably because I suck but I can't find any good explanation of this.
|
| 57 |
def decorator(func):
|
57 |
def decorator(func):
|
| 58 |
@wraps(func)
|
58 |
@wraps(func)
|
| 59 |
def wrapper(*args, **kwargs):
|
59 |
def wrapper(*args, **kwargs):
|
| 60 |
# precommand stuff
|
- |
|
| 61 |
self = args[0] # little cheat as it expects self being always the first argument
|
60 |
self = args[0] # little cheat as it expects self being always the first argument
|
| - |
|
61 |
# precommand stuff
|
| - |
|
62 |
if target is not None:
|
| - |
|
63 |
if self.lib.dev.hwtypeid != target:
|
| - |
|
64 |
raise DeviceError("Wrong device for target-specific command. Expected \'" + gethwname(target) + "\' but got \'" + gethwname(self.lib.dev.hwtypeid) + "\'")
|
| 62 |
timeout = None
|
65 |
timeout = None
|
| 63 |
if "timeout" in kwargs.keys():
|
66 |
if "timeout" in kwargs.keys():
|
| 64 |
timeout = kwargs['timeout']
|
67 |
timeout = kwargs['timeout']
|
| 65 |
elif time is not None:
|
68 |
elif time is not None:
|
| 66 |
timeout = time
|
69 |
timeout = time
|
| Line 519... |
Line 522... |
| 519 |
@command(timeout = 30000)
|
522 |
@command(timeout = 30000)
|
| 520 |
def hmac_sha1(self, addr, size, destination):
|
523 |
def hmac_sha1(self, addr, size, destination):
|
| 521 |
""" Generates a HMAC-SHA1 hash of the buffer and saves it to 'destination' """
|
524 |
""" Generates a HMAC-SHA1 hash of the buffer and saves it to 'destination' """
|
| 522 |
return self.lib.monitorcommand(struct.pack("IIII", 26, addr, size, destination), "III", (None, None, None))
|
525 |
return self.lib.monitorcommand(struct.pack("IIII", 26, addr, size, destination), "III", (None, None, None))
|
| 523 |
|
526 |
|
| 524 |
@command()
|
527 |
@command(target = 0x47324e49)
|
| 525 |
def ipodnano2g_getnandinfo(self):
|
528 |
def ipodnano2g_getnandinfo(self):
|
| 526 |
""" Target-specific function: ipodnano2g
|
529 |
""" Target-specific function: ipodnano2g
|
| 527 |
Gathers some information about the NAND chip used
|
530 |
Gathers some information about the NAND chip used
|
| 528 |
"""
|
531 |
"""
|
| 529 |
if self.lib.dev.hwtypeid != 0x47324e49: raise DeviceError("Wrong device for target-specific command.")
|
- |
|
| 530 |
return self.lib.monitorcommand(struct.pack("IIII", 0xffff0001, 0, 0, 0), "IHHHH", ("type", "pagesperblock", "banks", "userblocks", "blocks"))
|
532 |
return self.lib.monitorcommand(struct.pack("IIII", 0xffff0001, 0, 0, 0), "IHHHH", ("type", "pagesperblock", "banks", "userblocks", "blocks"))
|
| 531 |
|
533 |
|
| 532 |
@command(timeout = 30000)
|
534 |
@command(timeout = 30000, target = 0x47324e49)
|
| 533 |
def ipodnano2g_nandread(self, addr, start, count, doecc, checkempty):
|
535 |
def ipodnano2g_nandread(self, addr, start, count, doecc, checkempty):
|
| 534 |
""" Target-specific function: ipodnano2g
|
536 |
""" Target-specific function: ipodnano2g
|
| 535 |
Reads data from the NAND chip into memory
|
537 |
Reads data from the NAND chip into memory
|
| 536 |
"""
|
538 |
"""
|
| 537 |
if self.lib.dev.hwtypeid != 0x47324e49: raise DeviceError("Wrong device for target-specific command.")
|
- |
|
| 538 |
return self.lib.monitorcommand(struct.pack("IIII", 0xffff0002, addr | (0x80000000 if doecc != 0 else 0) | (0x40000000 if checkempty != 0 else 0), start, count), "III", (None, None, None))
|
539 |
return self.lib.monitorcommand(struct.pack("IIII", 0xffff0002, addr | (0x80000000 if doecc != 0 else 0) | (0x40000000 if checkempty != 0 else 0), start, count), "III", (None, None, None))
|
| 539 |
|
540 |
|
| 540 |
@command(timeout = 30000)
|
541 |
@command(timeout = 30000, target = 0x47324e49)
|
| 541 |
def ipodnano2g_nandwrite(self, addr, start, count, doecc):
|
542 |
def ipodnano2g_nandwrite(self, addr, start, count, doecc):
|
| 542 |
""" Target-specific function: ipodnano2g
|
543 |
""" Target-specific function: ipodnano2g
|
| 543 |
Writes data to the NAND chip
|
544 |
Writes data to the NAND chip
|
| 544 |
"""
|
545 |
"""
|
| 545 |
if self.lib.dev.hwtypeid != 0x47324e49: raise DeviceError("Wrong device for target-specific command.")
|
- |
|
| 546 |
return self.lib.monitorcommand(struct.pack("IIII", 0xffff0003, addr | (0x80000000 if doecc != 0 else 0), start, count), "III", (None, None, None))
|
546 |
return self.lib.monitorcommand(struct.pack("IIII", 0xffff0003, addr | (0x80000000 if doecc != 0 else 0), start, count), "III", (None, None, None))
|
| 547 |
|
547 |
|
| 548 |
@command(timeout = 30000)
|
548 |
@command(timeout = 30000, target = 0x47324e49)
|
| 549 |
def ipodnano2g_nanderase(self, addr, start, count):
|
549 |
def ipodnano2g_nanderase(self, addr, start, count):
|
| 550 |
""" Target-specific function: ipodnano2g
|
550 |
""" Target-specific function: ipodnano2g
|
| 551 |
Erases blocks on the NAND chip and stores the results to memory
|
551 |
Erases blocks on the NAND chip and stores the results to memory
|
| 552 |
"""
|
552 |
"""
|
| 553 |
if self.lib.dev.hwtypeid != 0x47324e49: raise DeviceError("Wrong device for target-specific command.")
|
- |
|
| 554 |
return self.lib.monitorcommand(struct.pack("IIII", 0xffff0004, addr, start, count), "III", (None, None, None))
|
553 |
return self.lib.monitorcommand(struct.pack("IIII", 0xffff0004, addr, start, count), "III", (None, None, None))
|
| 555 |
|
554 |
|
| 556 |
@command()
|
555 |
@command(target = 0x4c435049)
|
| 557 |
def ipodclassic_gethddinfo(self):
|
556 |
def ipodclassic_gethddinfo(self):
|
| 558 |
""" Target-specific function: ipodclassic
|
557 |
""" Target-specific function: ipodclassic
|
| 559 |
Gather information about the hard disk drive
|
558 |
Gather information about the hard disk drive
|
| 560 |
"""
|
559 |
"""
|
| 561 |
if self.lib.dev.hwtypeid != 0x4c435049: raise DeviceError("Wrong device for target-specific command.")
|
- |
|
| 562 |
return self.lib.monitorcommand(struct.pack("IIII", 0xffff0001, 0, 0, 0), "IQQII", ("identifyptr", "totalsectors", "virtualsectors", "bbtptr", "bbtsize"))
|
560 |
return self.lib.monitorcommand(struct.pack("IIII", 0xffff0001, 0, 0, 0), "IQQII", ("identifyptr", "totalsectors", "virtualsectors", "bbtptr", "bbtsize"))
|
| 563 |
|
561 |
|
| 564 |
@command(timeout = 30000)
|
562 |
@command(timeout = 30000, target = 0x4c435049)
|
| 565 |
def ipodclassic_hddaccess(self, type, sector, count, addr):
|
563 |
def ipodclassic_hddaccess(self, type, sector, count, addr):
|
| 566 |
""" Target-specific function: ipodclassic
|
564 |
""" Target-specific function: ipodclassic
|
| 567 |
Access the hard disk, type = 0 (read) / 1 (write)
|
565 |
Access the hard disk, type = 0 (read) / 1 (write)
|
| 568 |
"""
|
566 |
"""
|
| 569 |
if self.lib.dev.hwtypeid != 0x4c435049: raise DeviceError("Wrong device for target-specific command.")
|
- |
|
| 570 |
rc = self.lib.monitorcommand(struct.pack("IIQIIII", 0xffff0002, type, sector, count, addr, 0, 0), "III", ("rc", None, None))
|
567 |
rc = self.lib.monitorcommand(struct.pack("IIQIIII", 0xffff0002, type, sector, count, addr, 0, 0), "III", ("rc", None, None))
|
| 571 |
if (rc > 0x80000000):
|
568 |
if (rc > 0x80000000):
|
| 572 |
raise DeviceError("HDD access (type=%d, sector=%d, count=%d, addr=0x%08X) failed with RC 0x%08X" % (type, sector, count, addr, rc))
|
569 |
raise DeviceError("HDD access (type=%d, sector=%d, count=%d, addr=0x%08X) failed with RC 0x%08X" % (type, sector, count, addr, rc))
|
| 573 |
|
570 |
|
| 574 |
@command()
|
571 |
@command(target = 0x4c435049)
|
| 575 |
def ipodclassic_writebbt(self, bbt, tempaddr):
|
572 |
def ipodclassic_writebbt(self, bbt, tempaddr):
|
| 576 |
""" Target-specific function: ipodclassic
|
573 |
""" Target-specific function: ipodclassic
|
| 577 |
Write hard drive bad block table
|
574 |
Write hard drive bad block table
|
| 578 |
"""
|
575 |
"""
|
| 579 |
if self.lib.dev.hwtypeid != 0x4c435049: raise DeviceError("Wrong device for target-specific command.")
|
- |
|
| 580 |
try:
|
576 |
try:
|
| 581 |
bbtheader = struct.unpack("<8s2024sQII512I", bbt[:4096])
|
577 |
bbtheader = struct.unpack("<8s2024sQII512I", bbt[:4096])
|
| 582 |
except struct.error:
|
578 |
except struct.error:
|
| 583 |
raise ArgumentError("The specified file is not an emBIOS hard disk BBT")
|
579 |
raise ArgumentError("The specified file is not an emBIOS hard disk BBT")
|
| 584 |
if bbtheader[0] != "emBIbbth":
|
580 |
if bbtheader[0] != "emBIbbth":
|