Subversion Repositories freemyipod

Rev

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

Rev 424 Rev 427
Line 2... Line 2...
2
#
2
#
3
#
3
#
4
#    Copyright 2010 TheSeven, benedikt93, Farthen
4
#    Copyright 2010 TheSeven, benedikt93, Farthen
5
#
5
#
6
#
6
#
7
#    This file is part of emBIOS.
7
#    This file is part of emCORE.
8
#
8
#
9
#    emBIOS is free software: you can redistribute it and/or
9
#    emCORE is free software: you can redistribute it and/or
10
#    modify it under the terms of the GNU General Public License as
10
#    modify it under the terms of the GNU General Public License as
11
#    published by the Free Software Foundation, either version 2 of the
11
#    published by the Free Software Foundation, either version 2 of the
12
#    License, or (at your option) any later version.
12
#    License, or (at your option) any later version.
13
#
13
#
14
#    emBIOS is distributed in the hope that it will be useful,
14
#    emCORE is distributed in the hope that it will be useful,
15
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
16
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
#    See the GNU General Public License for more details.
17
#    See the GNU General Public License for more details.
18
#
18
#
19
#    You should have received a copy of the GNU General Public License
19
#    You should have received a copy of the GNU General Public License
20
#    along with emBIOS.  If not, see <http://www.gnu.org/licenses/>.
20
#    along with emCORE.  If not, see <http://www.gnu.org/licenses/>.
21
#
21
#
22
#
22
#
23
 
23
 
24
"""
24
"""
25
    emBIOS client library.
25
    emCORE client library.
26
    Provides functions to communicate with emBIOS devices via the USB bus.
26
    Provides functions to communicate with emCORE devices via the USB bus.
27
"""
27
"""
28
 
28
 
29
import sys
29
import sys
30
import struct
30
import struct
31
import usb.core
31
import usb.core
32
import libembiosdata
32
import libemcoredata
33
 
33
 
34
from misc import Logger, Bunch, Error, gethwname
34
from misc import Logger, Bunch, Error, gethwname
35
from functools import wraps
35
from functools import wraps
36
 
36
 
37
class ArgumentError(Error):
37
class ArgumentError(Error):
Line 85... Line 85...
85
        wrapper.func = func
85
        wrapper.func = func
86
        return wrapper
86
        return wrapper
87
    return decorator
87
    return decorator
88
 
88
 
89
 
89
 
90
class Embios(object):
90
class Emcore(object):
91
    """
91
    """
92
        Class for all embios functions.
92
        Class for all emcore functions.
93
        They all get the "@command()" decorator.
93
        They all get the "@command()" decorator.
94
        This decorator has a timeout variable that can be set to change the
94
        This decorator has a timeout variable that can be set to change the
95
        device timeout for the duration of the function.
95
        device timeout for the duration of the function.
96
        It also adds a "timeout" argument to every function to access this
96
        It also adds a "timeout" argument to every function to access this
97
        feature from external. So DON'T EVER use a parameter called 'timeout'
97
        feature from external. So DON'T EVER use a parameter called 'timeout'
98
        in your commands. Variables are ok.
98
        in your commands. Variables are ok.
99
    """
99
    """
100
    def __init__(self, loglevel = 2, logtarget = "stdout", logfile = "tools.log"):
100
    def __init__(self, loglevel = 2, logtarget = "stdout", logfile = "tools.log"):
101
        self.logger = Logger(loglevel, logtarget, logfile)
101
        self.logger = Logger(loglevel, logtarget, logfile)
102
        self.logger.debug("Initializing Embios object\n")
102
        self.logger.debug("Initializing Emcore object\n")
103
        self.lib = Lib(self.logger)
103
        self.lib = Lib(self.logger)
104
        
104
        
105
        self.getversioninfo()
105
        self.getversioninfo()
106
        self.getpacketsizeinfo()
106
        self.getpacketsizeinfo()
107
        self.getusermemrange()
107
        self.getusermemrange()
Line 151... Line 151...
151
        self.lib.monitorcommand(struct.pack("IIII", 7, addr, len(data), 0), "III", (None, None, None))
151
        self.lib.monitorcommand(struct.pack("IIII", 7, addr, len(data), 0), "III", (None, None, None))
152
        return self.lib.dev.dout(data)
152
        return self.lib.dev.dout(data)
153
    
153
    
154
    @command()
154
    @command()
155
    def getversioninfo(self):
155
    def getversioninfo(self):
156
        """ This returns the emBIOS version and device information. """
156
        """ This returns the emCORE version and device information. """
157
        resp = self.lib.monitorcommand(struct.pack("IIII", 1, 0, 0, 0), "IBBBBI", ("revision", "majorv", "minorv", "patchv", "swtypeid", "hwtypeid"))
157
        resp = self.lib.monitorcommand(struct.pack("IIII", 1, 0, 0, 0), "IBBBBI", ("revision", "majorv", "minorv", "patchv", "swtypeid", "hwtypeid"))
158
        self.lib.dev.version.revision = resp.revision
158
        self.lib.dev.version.revision = resp.revision
159
        self.lib.dev.version.majorv = resp.majorv
159
        self.lib.dev.version.majorv = resp.majorv
160
        self.lib.dev.version.minorv = resp.minorv
160
        self.lib.dev.version.minorv = resp.minorv
161
        self.lib.dev.version.patchv = resp.patchv
161
        self.lib.dev.version.patchv = resp.patchv
Line 165... Line 165...
165
        self.lib.dev.hwtypeid = resp.hwtypeid
165
        self.lib.dev.hwtypeid = resp.hwtypeid
166
        return resp
166
        return resp
167
    
167
    
168
    @command()
168
    @command()
169
    def getpacketsizeinfo(self):
169
    def getpacketsizeinfo(self):
170
        """ This returns the emBIOS max packet size information.
170
        """ This returns the emCORE max packet size information.
171
            It also sets the properties of the device object accordingly.
171
            It also sets the properties of the device object accordingly.
172
        """
172
        """
173
        resp = self.lib.monitorcommand(struct.pack("IIII", 1, 1, 0, 0), "HHII", ("coutmax", "cinmax", "doutmax", "dinmax"))
173
        resp = self.lib.monitorcommand(struct.pack("IIII", 1, 1, 0, 0), "HHII", ("coutmax", "cinmax", "doutmax", "dinmax"))
174
        self.logger.debug("Device cout packet size limit = " + str(resp.coutmax) + "\n")
174
        self.logger.debug("Device cout packet size limit = " + str(resp.coutmax) + "\n")
175
        self.lib.dev.packetsizelimit.cout = resp.coutmax
175
        self.lib.dev.packetsizelimit.cout = resp.coutmax
Line 379... Line 379...
379
            offset = threadstructsize * thread
379
            offset = threadstructsize * thread
380
            threaddata = struct.unpack("<16IIIIIQIIIIIIIBBBB", data[offset:offset+threadstructsize])
380
            threaddata = struct.unpack("<16IIIIIQIIIIIIIBBBB", data[offset:offset+threadstructsize])
381
            info = Bunch()
381
            info = Bunch()
382
            info.id = id
382
            info.id = id
383
            state = threaddata[17]
383
            state = threaddata[17]
384
            info.state = libembiosdata.thread_state[state]
384
            info.state = libemcoredata.thread_state[state]
385
            if info.state == "THREAD_FREE":
385
            if info.state == "THREAD_FREE":
386
                id += 1
386
                id += 1
387
                continue
387
                continue
388
            info.regs = Bunch()
388
            info.regs = Bunch()
389
            for register in range(16):
389
            for register in range(16):
Line 401... Line 401...
401
            info.timeout = threaddata[23]
401
            info.timeout = threaddata[23]
402
            info.blocked_since = threaddata[24]
402
            info.blocked_since = threaddata[24]
403
            info.blocked_by_ptr = threaddata[25]
403
            info.blocked_by_ptr = threaddata[25]
404
            info.stackaddr = threaddata[26]
404
            info.stackaddr = threaddata[26]
405
            info.err_no = threaddata[27]
405
            info.err_no = threaddata[27]
406
            info.block_type = libembiosdata.thread_block[threaddata[28]]
406
            info.block_type = libemcoredata.thread_block[threaddata[28]]
407
            info.type = libembiosdata.thread_type[threaddata[29]]
407
            info.type = libemcoredata.thread_type[threaddata[29]]
408
            info.priority = threaddata[30]
408
            info.priority = threaddata[30]
409
            info.cpuload = threaddata[31]
409
            info.cpuload = threaddata[31]
410
            threads.append(info)
410
            threads.append(info)
411
            id += 1
411
            id += 1
412
        return threads
412
        return threads
Line 465... Line 465...
465
        """ Flushes the CPU instruction and data cache """
465
        """ Flushes the CPU instruction and data cache """
466
        return self.lib.monitorcommand(struct.pack("IIII", 20, 0, 0, 0), "III", (None, None, None))
466
        return self.lib.monitorcommand(struct.pack("IIII", 20, 0, 0, 0), "III", (None, None, None))
467
    
467
    
468
    @command()
468
    @command()
469
    def execimage(self, addr):
469
    def execimage(self, addr):
470
        """ Runs the emBIOS app at 'addr' """
470
        """ Runs the emCORE app at 'addr' """
471
        return self.lib.monitorcommand(struct.pack("IIII", 21, addr, 0, 0), "III", ("rc", None, None))
471
        return self.lib.monitorcommand(struct.pack("IIII", 21, addr, 0, 0), "III", ("rc", None, None))
472
    
472
    
473
    @command()
473
    @command()
474
    def run(self, app):
474
    def run(self, app):
475
        """ Uploads and runs the emBIOS app in the string 'app' """
475
        """ Uploads and runs the emCORE app in the string 'app' """
476
        try:
476
        try:
477
            appheader = struct.unpack("<8sIIIIIIIIII", app[:48])
477
            appheader = struct.unpack("<8sIIIIIIIIII", app[:48])
478
        except struct.error:
478
        except struct.error:
479
            raise ArgumentError("The specified app is not an emBIOS application")
479
            raise ArgumentError("The specified app is not an emCORE application")
480
        header = appheader[0]
480
        header = appheader[0]
481
        if header != "emBIexec":
481
        if header != "emBIexec":
482
            raise ArgumentError("The specified app is not an emBIOS application")
482
            raise ArgumentError("The specified app is not an emCORE application")
483
        baseaddr = appheader[2]
483
        baseaddr = appheader[2]
484
        threadnameptr = appheader[8]
484
        threadnameptr = appheader[8]
485
        nameptr = threadnameptr - baseaddr
485
        nameptr = threadnameptr - baseaddr
486
        name = ""
486
        name = ""
487
        while True:
487
        while True:
488
            char = app[nameptr:nameptr+1]
488
            char = app[nameptr:nameptr+1]
489
            try:
489
            try:
490
                if ord(char) == 0:
490
                if ord(char) == 0:
491
                    break
491
                    break
492
            except TypeError:
492
            except TypeError:
493
                raise ArgumentError("The specified app is not an emBIOS application")
493
                raise ArgumentError("The specified app is not an emCORE application")
494
            name += char
494
            name += char
495
            nameptr += 1
495
            nameptr += 1
496
        usermem = self.getusermemrange()
496
        usermem = self.getusermemrange()
497
        if usermem.lower > baseaddr or usermem.upper < baseaddr + len(app):
497
        if usermem.lower > baseaddr or usermem.upper < baseaddr + len(app):
498
            raise ArgumentError("The baseaddress of the specified emBIOS application is out of range of the user memory range on the device. Are you sure that this application is compatible with your device?")
498
            raise ArgumentError("The baseaddress of the specified emCORE application is out of range of the user memory range on the device. Are you sure that this application is compatible with your device?")
499
        self.write(baseaddr, app)
499
        self.write(baseaddr, app)
500
        self.execimage(baseaddr)
500
        self.execimage(baseaddr)
501
        return Bunch(baseaddr=baseaddr, name=name)
501
        return Bunch(baseaddr=baseaddr, name=name)
502
    
502
    
503
    @command(timeout = 5000)
503
    @command(timeout = 5000)
Line 588... Line 588...
588
            Write hard drive bad block table
588
            Write hard drive bad block table
589
        """
589
        """
590
        try:
590
        try:
591
            bbtheader = struct.unpack("<8s2024sQII512I", bbt[:4096])
591
            bbtheader = struct.unpack("<8s2024sQII512I", bbt[:4096])
592
        except struct.error:
592
        except struct.error:
593
            raise ArgumentError("The specified file is not an emBIOS hard disk BBT")
593
            raise ArgumentError("The specified file is not an emCORE hard disk BBT")
594
        if bbtheader[0] != "emBIbbth":
594
        if bbtheader[0] != "emBIbbth":
595
            raise ArgumentError("The specified file is not an emBIOS hard disk BBT")
595
            raise ArgumentError("The specified file is not an emCORE hard disk BBT")
596
        virtualsectors = bbtheader[2]
596
        virtualsectors = bbtheader[2]
597
        bbtsectors = bbtheader[3]
597
        bbtsectors = bbtheader[3]
598
        self.write(tempaddr, bbt)
598
        self.write(tempaddr, bbt)
599
        sector = 0
599
        sector = 0
600
        count = 1
600
        count = 1
Line 836... Line 836...
836
        if rcvdatatypes:
836
        if rcvdatatypes:
837
            rcvdatatypes = "I" + rcvdatatypes # add the response
837
            rcvdatatypes = "I" + rcvdatatypes # add the response
838
            data = self.dev.cin(struct.calcsize(rcvdatatypes))
838
            data = self.dev.cin(struct.calcsize(rcvdatatypes))
839
            data = struct.unpack(rcvdatatypes, data)
839
            data = struct.unpack(rcvdatatypes, data)
840
            response = data[0]
840
            response = data[0]
841
            if libembiosdata.responsecodes[response] == "ok":
841
            if libemcoredata.responsecodes[response] == "ok":
842
                self.logger.debug("Response: OK\n")
842
                self.logger.debug("Response: OK\n")
843
                if rcvstruct:
843
                if rcvstruct:
844
                    datadict = Bunch()
844
                    datadict = Bunch()
845
                    counter = 1 # start with 1, 0 is the id
845
                    counter = 1 # start with 1, 0 is the id
846
                    for item in rcvstruct:
846
                    for item in rcvstruct:
Line 848... Line 848...
848
                            datadict[item] = data[counter]
848
                            datadict[item] = data[counter]
849
                        counter += 1
849
                        counter += 1
850
                    return datadict
850
                    return datadict
851
                else:
851
                else:
852
                    return data
852
                    return data
853
            elif libembiosdata.responsecodes[response] == "unsupported":
853
            elif libemcoredata.responsecodes[response] == "unsupported":
854
                self.logger.debug("Response: UNSUPPORTED\n")
854
                self.logger.debug("Response: UNSUPPORTED\n")
855
                raise DeviceError("The device does not support this command.")
855
                raise DeviceError("The device does not support this command.")
856
            elif libembiosdata.responsecodes[response] == "invalid":
856
            elif libemcoredata.responsecodes[response] == "invalid":
857
                self.logger.debug("Response: INVALID\n")
857
                self.logger.debug("Response: INVALID\n")
858
                raise DeviceError("Invalid command! This should NOT happen!")
858
                raise DeviceError("Invalid command! This should NOT happen!")
859
            elif libembiosdata.responsecodes[response] == "busy":
859
            elif libemcoredata.responsecodes[response] == "busy":
860
                self.logger.debug("Response: BUSY\n")
860
                self.logger.debug("Response: BUSY\n")
861
                raise DeviceError("Device busy")
861
                raise DeviceError("Device busy")
862
            else:
862
            else:
863
                self.logger.debug("Response: UNKOWN\n")
863
                self.logger.debug("Response: UNKOWN\n")
864
                raise DeviceError("Invalid response! This should NOT happen!")
864
                raise DeviceError("Invalid response! This should NOT happen!")
Line 926... Line 926...
926
                    epcounter += 1
926
                    epcounter += 1
927
        if epcounter <= 3:
927
        if epcounter <= 3:
928
            raise DeviceError("Not all endpoints found in the descriptor. Only "+str(epcounter)+" found, we need 4")
928
            raise DeviceError("Not all endpoints found in the descriptor. Only "+str(epcounter)+" found, we need 4")
929
    
929
    
930
    def connect(self):
930
    def connect(self):
931
        self.logger.debug("Looking for emBIOS device\n")
931
        self.logger.debug("Looking for emCORE device\n")
932
        self.dev = usb.core.find(idVendor=self.idVendor, idProduct=self.idProduct)
932
        self.dev = usb.core.find(idVendor=self.idVendor, idProduct=self.idProduct)
933
        if self.dev is None:
933
        if self.dev is None:
934
            raise DeviceNotFoundError()
934
            raise DeviceNotFoundError()
935
        self.logger.debug("Device Found!\n")
935
        self.logger.debug("Device Found!\n")
936
        self.logger.debug("Setting first configuration\n")
936
        self.logger.debug("Setting first configuration\n")
Line 980... Line 980...
980
    from misc import Logger
980
    from misc import Logger
981
    logger = Logger()
981
    logger = Logger()
982
    if sys.argv[1] == "test":
982
    if sys.argv[1] == "test":
983
        # Some tests
983
        # Some tests
984
        import sys
984
        import sys
985
        embios = Embios()
985
        emcore = Emcore()
986
        resp = embios.getversioninfo()
986
        resp = emcore.getversioninfo()
987
        logger.log("Embios device version information: " + libembiosdata.swtypes[resp.swtypeid] + " v" + str(resp.majorv) + "." + str(resp.minorv) + 
987
        logger.log("Emcore device version information: " + libemcoredata.swtypes[resp.swtypeid] + " v" + str(resp.majorv) + "." + str(resp.minorv) + 
988
                         "." + str(resp.patchv) + " r" + str(resp.revision) + " running on " + libembiosdata.hwtypes[resp.hwtypeid] + "\n")
988
                         "." + str(resp.patchv) + " r" + str(resp.revision) + " running on " + libemcoredata.hwtypes[resp.hwtypeid] + "\n")
989
        resp = embios.getusermemrange()
989
        resp = emcore.getusermemrange()
990
        logger.log("Usermemrange: "+hex(resp.lower)+" - "+hex(resp.upper)+"\n")
990
        logger.log("Usermemrange: "+hex(resp.lower)+" - "+hex(resp.upper)+"\n")
991
        memaddr = resp.lower
991
        memaddr = resp.lower
992
        maxlen = resp.upper - resp.lower
992
        maxlen = resp.upper - resp.lower
993
        f = open("./embios.py", "rb")
993
        f = open("./emcore.py", "rb")
994
        logger.log("Loading test file (embios.py) to send over USB...\n")
994
        logger.log("Loading test file (emcore.py) to send over USB...\n")
995
        datastr = f.read()[:maxlen]
995
        datastr = f.read()[:maxlen]
996
        logger.log("Sending data...\n")
996
        logger.log("Sending data...\n")
997
        embios.write(memaddr, datastr)
997
        emcore.write(memaddr, datastr)
998
        logger.log("Encrypting data with the hardware key...\n")
998
        logger.log("Encrypting data with the hardware key...\n")
999
        embios.aesencrypt(memaddr, len(datastr), 0)
999
        emcore.aesencrypt(memaddr, len(datastr), 0)
1000
        logger.log("Reading data back and saving it to 'libembios-test-encrypted.bin'...\n")
1000
        logger.log("Reading data back and saving it to 'libemcore-test-encrypted.bin'...\n")
1001
        f = open("./libembios-test-encrypted.bin", "wb")
1001
        f = open("./libemcore-test-encrypted.bin", "wb")
1002
        f.write(embios.read(memaddr, len(datastr)))
1002
        f.write(emcore.read(memaddr, len(datastr)))
1003
        logger.log("Decrypting the data again...\n")
1003
        logger.log("Decrypting the data again...\n")
1004
        embios.aesdecrypt(memaddr, len(datastr), 0)
1004
        emcore.aesdecrypt(memaddr, len(datastr), 0)
1005
        logger.log("Reading data back from device...\n")
1005
        logger.log("Reading data back from device...\n")
1006
        readdata = embios.read(memaddr, len(datastr))
1006
        readdata = emcore.read(memaddr, len(datastr))
1007
        if readdata == datastr:
1007
        if readdata == datastr:
1008
            logger.log("Data matches!")
1008
            logger.log("Data matches!")
1009
        else:
1009
        else:
1010
            logger.log("Data does NOT match. Something went wrong")
1010
            logger.log("Data does NOT match. Something went wrong")
1011
    
1011
    
1012
    elif sys.argv[1] == "gendoc":
1012
    elif sys.argv[1] == "gendoc":
1013
        # Generates Documentation
1013
        # Generates Documentation
1014
        from misc import gendoc
1014
        from misc import gendoc
1015
        logger.log("Generating documentation\n")
1015
        logger.log("Generating documentation\n")
1016
        cmddict = {}
1016
        cmddict = {}
1017
        for attr, value in Embios.__dict__.iteritems():
1017
        for attr, value in Emcore.__dict__.iteritems():
1018
            if getattr(value, 'func', False):
1018
            if getattr(value, 'func', False):
1019
                if getattr(value.func, '_command', False):
1019
                if getattr(value.func, '_command', False):
1020
                    cmddict[value.func.__name__] = value
1020
                    cmddict[value.func.__name__] = value
1021
        logger.log(gendoc(cmddict))
1021
        logger.log(gendoc(cmddict))
1022
1022