Subversion Repositories freemyipod

Rev

Rev 396 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 396 Rev 398
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":