Subversion Repositories freemyipod

Rev

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

Rev 139 Rev 171
Line 1... Line 1...
1
#!/usr/bin/env python
1
#!/usr/bin/env python
2
#
2
#
3
#
3
#
4
#    Copyright 2010 TheSeven, benedikt93
4
#    Copyright 2010 TheSeven, benedikt93, Farthen
5
#
5
#
6
#
6
#
7
#    This file is part of emBIOS.
7
#    This file is part of emBIOS.
8
#
8
#
9
#    emBIOS is free software: you can redistribute it and/or
9
#    emBIOS is free software: you can redistribute it and/or
Line 19... Line 19...
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 emBIOS.  If not, see <http://www.gnu.org/licenses/>.
21
#
21
#
22
#
22
#
23
 
23
 
24
# note: handles commands 1 to 21
-
 
25
 
-
 
26
import sys
24
import sys
27
import math
-
 
28
import struct
25
import struct
29
import time
26
import usb.core
30
import usb
27
import libembiosdata
31
 
28
 
-
 
29
class Error(Exception):
-
 
30
    def __init__(self, value=None):
-
 
31
        self.value = value
-
 
32
    def __str__(self):
-
 
33
        if self.value != None:
-
 
34
            return repr(self.value)
32
 
35
 
33
class embios:
-
 
34
  def __init__(self, devtype = 0, type = 0):
-
 
35
    busses = usb.busses()
-
 
36
 
-
 
37
    for bus in busses:
-
 
38
      devices = bus.devices
-
 
39
      for dev in devices:
-
 
40
        if dev.idVendor == 0xffff and dev.idProduct == 0xe000:
-
 
41
          # get endpoints
-
 
42
          self.__coutep = dev.configurations[0].interfaces[0][0].endpoints[0].address
-
 
43
          self.__cinep = dev.configurations[0].interfaces[0][0].endpoints[1].address
-
 
44
          self.__doutep = dev.configurations[0].interfaces[0][0].endpoints[2].address
-
 
45
          self.__dinep = dev.configurations[0].interfaces[0][0].endpoints[3].address
-
 
46
          
-
 
47
          handle = dev.open()
-
 
48
          handle.setConfiguration(1)
-
 
49
          handle.claimInterface(0)
-
 
50
          
-
 
51
          # get version info
-
 
52
          handle.bulkWrite(self.__coutep, struct.pack("<IIII", 1, 0, 0, 0))
-
 
53
          response = self.__getbulk(handle, self.__cinep, 0x10)
-
 
54
          self.__checkstatus(response)
-
 
55
          i = struct.unpack("<IIBBBBI", response)
-
 
56
          
-
 
57
          if devtype in [0, i[6]] and type in [0, i[5]]:
-
 
58
            # correct device
-
 
59
            self.handle = handle
-
 
60
            self.dev = dev
-
 
61
            
-
 
62
            self.svnrev, self.major, self.minor, self.patch, self.type, self.devtype = i[1:]
-
 
63
            self.__myprint("Connected to emBIOS %s v%d.%d.%d (SVN revision: %d) on %s, USB version %s\n" \
-
 
64
                  % (self.type2name(self.type), self.major, self.minor, self.patch, self.svnrev, \
-
 
65
                     self.devtype2name(self.devtype), dev.deviceVersion))
-
 
66
                     
-
 
67
            # get packet size info
-
 
68
            self.getinfo("packetsize", 1)
-
 
69
            
-
 
70
            return
-
 
71
          
-
 
72
          # wrong device
-
 
73
          handle.releaseInterface()
-
 
74
 
-
 
75
    raise Exception("Could not find specified device (devtype = %d, type = %d)" % (devtype, type))
-
 
76
 
-
 
77
 
-
 
78
#=====================================================================================    
-
 
79
    
-
 
80
    
-
 
81
  @staticmethod
-
 
82
  def __myprint(data, silent = 0):
-
 
83
    if not silent:
-
 
84
      sys.stdout.write(data)
-
 
85
      sys.stdout.flush()
-
 
86
 
-
 
87
      
-
 
88
  @staticmethod
-
 
89
  def __gethexviewprintout(data, title, showaddr):
-
 
90
    printout_temp = struct.unpack("%dB" % (len(data)), data)
-
 
91
      
-
 
92
    printout = title + ":\n"
-
 
93
    pointer = 0
-
 
94
    pointer2 = 0
-
 
95
    
-
 
96
    while (pointer < len(printout_temp)):
-
 
97
      pointer2 = 0
-
 
98
      if (showaddr): printout += "0x%08x     " % (pointer)
-
 
99
      while (pointer2 < 0x10) and (pointer < len(printout_temp)):
-
 
100
        printout += ("%2x " % (printout_temp[pointer]))
-
 
101
        pointer += 1
-
 
102
        pointer2 += 1
-
 
103
      printout += "\n"
-
 
104
        
-
 
105
    if (pointer2 != 0x10):
36
class ArgumentError(Error):
106
      printout += "\n"
-
 
107
      
-
 
108
    return printout
-
 
109
 
-
 
110
    
-
 
111
  @staticmethod
-
 
112
  def __getbulk(handle, endpoint, size):
-
 
113
    data = handle.bulkRead(endpoint, size, 1000)
-
 
114
    return struct.pack("%dB" % len(data), *data)
-
 
115
 
-
 
116
 
-
 
117
  @staticmethod
-
 
118
  def __checkstatus(data):
-
 
119
    errorcode = struct.unpack("<I", data[:4])[0]
-
 
120
    if errorcode == 1:
-
 
121
      # everything went fine
-
 
122
      return
-
 
123
    elif errorcode == 2:
-
 
124
      print("\nError: Device doesn't support this function!")
-
 
125
      raise Exception("emBIOS device doesn't support this function!")
-
 
126
    elif errorcode == 3:
-
 
127
      print("\nError: Device is busy!")
-
 
128
      raise Exception("emBIOS device is busy!")
-
 
129
    else:
37
    pass
130
      print("\nUnknown error %d" % errorcode)
-
 
131
      raise Exception("Unknown emBIOS error %d" % errorcode)
-
 
132
 
38
 
-
 
39
class DeviceNotFoundError(Error):
-
 
40
    pass
133
 
41
 
134
  @staticmethod
-
 
135
  def type2name(type):
42
class DeviceError(Error):
136
    if type == 1: return "Debugger"
-
 
137
    else: return "UNKNOWN (0x%08x)" % type
-
 
138
 
-
 
139
 
-
 
140
  @staticmethod
43
    pass
141
  def devtype2name(devtype):
-
 
142
    if devtype == 0x47324e49: return "iPod Nano 2G"
-
 
143
    if devtype == 0x47334e49: return "iPod Nano 3G"
-
 
144
    if devtype == 0x47344e49: return "iPod Nano 4G"
-
 
145
    if devtype == 0x4c435049: return "iPod Classic"
-
 
146
    else: return "UNKNOWN (0x%08x)" % devtype
-
 
147
 
-
 
148
 
44
 
149
#=====================================================================================
-
 
150
    
-
 
151
    
-
 
152
  def getinfo (self, infotype, silent = 0):
-
 
153
    if (infotype == "version"):
45
class SendError(Error):
154
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 1, 0, 0, 0))
-
 
155
      response = self.__getbulk(self.handle, self.__cinep, 0x10)
-
 
156
      self.__checkstatus(response)
-
 
157
      
-
 
158
      i = struct.unpack("<IIBBBBI", response)
-
 
159
      
-
 
160
      self.svnrev, self.major, self.minor, self.patch, self.type, self.devtype = i[1:]
-
 
161
      
-
 
162
      self.__myprint("emBIOS %s v%d.%d.%d (SVN revision: %d) on %s, USB version %s\n" \
-
 
163
              % (self.type2name(self.type), self.major, self.minor, self.patch, self.svnrev, \
-
 
164
                 self.devtype2name(self.devtype), self.dev.deviceVersion)\
-
 
165
            , silent)
-
 
166
      
-
 
167
    elif (infotype == "packetsize"):
-
 
168
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 1, 1, 0, 0))
-
 
169
      response = self.__getbulk(self.handle, self.__cinep, 0x10)
-
 
170
      self.__checkstatus(response)
-
 
171
      
-
 
172
      i = struct.unpack("<IHHII", response)
-
 
173
      
-
 
174
      self.cout_maxsize = i[1]
-
 
175
      self.cin_maxsize = i[2]
-
 
176
      self.dout_maxsize = i[3]
-
 
177
      self.din_maxsize = i[4]
-
 
178
      
46
    pass
179
      self.__myprint("Maximum packet sizes:\n     Command out: %d bytes\n     Command in: %d bytes\n     Data out: %d bytes\n     Data in: %d bytes\n" \
-
 
180
              % (self.cout_maxsize, self.cin_maxsize, self.dout_maxsize, self.din_maxsize)
-
 
181
            , silent)
-
 
182
    
47
 
183
    elif (infotype == "usermemrange"):
-
 
184
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 1, 1, 0, 0))
-
 
185
      response = self.__getbulk(self.handle, self.__cinep, 0x10)
-
 
186
      self.__checkstatus(response)
-
 
187
      
-
 
188
      i = struct.unpack("<IIII", response)
-
 
189
      
-
 
190
      self.usermem_lower = i[1]
48
class ReceiveError(Error):
191
      self.usermem_upper = i[2]
-
 
192
      
-
 
193
      self.__myprint("User memory range:\n     Lower bound (inclusive): %x\n     Upper bound (exclusive) %x\n" \
-
 
194
              % (self.usermem_lower, self.usermem_upper)
-
 
195
            , silent)
-
 
196
      
-
 
197
    else:
49
    pass
198
      self.__myprint("Unsupported type of info: %d" % (infotype))
-
 
199
    
50
 
200
  
51
 
201
  def reset(self, force, silent = 0):
-
 
202
    """ Resets the device.
52
class Bunch(dict):
203
      <force>: if 0, the reset will be gracefully, otherwise it will be forced.
-
 
204
      <silent>: if not 0, nothing will be printed to the console window
-
 
205
    """
53
    """
206
    if (force == 0):
-
 
207
      force = 1
-
 
208
    else:
-
 
209
      force = 0
-
 
210
  
-
 
211
    self.__myprint("Resetting device...", silent)
-
 
212
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 2, force, 0, 0))
-
 
213
    
-
 
214
    if (force == 1):
-
 
215
      # reset not forced
-
 
216
      response = self.__getbulk(self.handle, self.__cinep, 0x10)
54
        This is a dict whose items can also be accessed with
217
      self.__checkstatus(response)
55
        bunchinstance.something.
218
    
-
 
219
    self.__myprint(" done\n", silent)  
-
 
220
  
-
 
221
 
-
 
222
  def poweroff(self, force, silent = 0):
-
 
223
    """ Powers the device off.
-
 
224
      <force>: if 0, the poweroff will be gracefully, otherwise it will be forced.
-
 
225
      <silent>: if not 0, nothing will be printed to the console window
-
 
226
    """
56
    """
227
    if (force == 0):
57
    def __init__(self, **kw):
-
 
58
        dict.__init__(self, kw)
228
      force = 1
59
        self.__dict__ = self
229
    else:
60
    
-
 
61
    def __getstate__(self):
230
      force = 0
62
        return self
231
  
63
    
232
    self.__myprint("Powering device off...", silent)
64
    def __setstate__(self, state):
-
 
65
        self.update(state)
233
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 3, force, 0, 0))
66
        self.__dict__ = self
-
 
67
 
-
 
68
 
-
 
69
class Embios(object):
-
 
70
    def __init__(self):
-
 
71
        self.lib = Lib(self)
234
    
72
    
-
 
73
    @staticmethod
-
 
74
    def _alignsplit(addr, size, blksize, align):
-
 
75
        end = addr + size
235
    if (force == 1):
76
        if addr & (align - 1):
-
 
77
            bodyaddr = (addr + min(size, blksize)) & ~(align - 1)
236
      # shutdown not forced
78
        else: bodyaddr = addr
-
 
79
        headsize = bodyaddr - addr
237
      response = self.__getbulk(self.handle, self.__cinep, 0x10)
80
        if (size - headsize) & (align - 1):
-
 
81
            tailaddr = (end - min(end - bodyaddr, blksize) + align - 1) & ~(align - 1)
238
      self.__checkstatus(response)
82
        else: tailaddr = end
-
 
83
        tailsize = end - tailaddr
-
 
84
        return (headsize, tailaddr - bodyaddr, tailsize)
239
    
85
    
240
    self.__myprint(" done\n", silent)
86
    def getversioninfo(self):
-
 
87
        """ This returns the emBIOS version and device information. """
-
 
88
        return self.lib.monitorcommand(struct.pack("IIII", 1, 0, 0, 0), "IBBBBI", ("revision", "majorv", "minorv", "patchv", "swtypeid", "hwtypeid"))
241
  
89
    
242
  
90
    def getpacketsizeinfo(self):
-
 
91
        """ This returns the emBIOS max packet size information.
243
#=====================================================================================
92
            It also sets the properties of the device object accordingly.
244
  
93
        """
245
 
-
 
-
 
94
        resp = self.lib.monitorcommand(struct.pack("IIII", 1, 1, 0, 0), "HHII", ("coutmax", "cinmax", "doutmax", "dinmax"))
-
 
95
        self.lib.dev.packetsizelimit['cout'] = resp.coutmax
-
 
96
        self.lib.dev.packetsizelimit['cin'] = resp.cinmax
246
  def write(self, offset, data, usedma, freezesched, *range):
97
        self.lib.dev.packetsizelimit['din'] = resp.dinmax
-
 
98
        self.lib.dev.packetsizelimit['dout'] = resp.doutmax
247
    boffset = 0
99
        return resp
248
      
100
    
249
    size = len(data)
101
    def getusermemrange(self):
-
 
102
        """ This returns the memory range the user has access to. """
-
 
103
        return self.lib.monitorcommand(struct.pack("IIII", 1, 2, 0, 0), "III", ("lower", "upper", None))
250
      
104
    
251
    if len(range) > 0:
105
    def reset(self, force=False):
252
      boffset = range[0]
106
        """ Reboot the device """
253
    if len(range) > 1:
107
        if force:
-
 
108
            return self.lib.monitorcommand(struct.pack("IIII", 2, 0, 0, 0))
254
      size = range[1]
109
        else:
-
 
110
            return self.lib.monitorcommand(struct.pack("IIII", 2, 1, 0, 0), "III", (None, None, None))
255
        
111
    
-
 
112
    def poweroff(self, force=False):
-
 
113
        """ Powers the device off. """
256
    if (size == 0):
114
        if force:
-
 
115
            return self.lib.monitorcommand(struct.pack("IIII", 3, 0, 0, 0))
257
      return
116
        else:
-
 
117
            return self.lib.monitorcommand(struct.pack("IIII", 3, 1, 0, 0), "III", (None, None, None))
258
     
118
    
259
    # correct alignment
119
    def read(self, addr, size):
-
 
120
        """ Reads the memory from location 'addr' with size 'size'
-
 
121
            from the device. This cares about too long packages
-
 
122
            and decides whether to use DMA or not.
-
 
123
        """
260
    while (offset & 0xF) != 0:
124
        if not self.lib.connected:
261
      blocklen = size
125
            self.lib.connect()
-
 
126
        cin_maxsize = self.lib.dev.packetsizelimit["cin"] - 0x10
-
 
127
        din_maxsize = self.lib.dev.packetsizelimit["din"]
262
        
128
        data = ""
-
 
129
        (headsize, bodysize, tailsize) = self._alignsplit(addr, size, cin_maxsize, 16)
263
      if (blocklen > size):
130
        if headsize != 0:
-
 
131
            data += self.readmem(addr, headsize)
264
        blocklen = size
132
            addr += headsize
-
 
133
        while bodysize > 0:
265
      if (blocklen > self.cout_maxsize - 0x10):
134
            if bodysize >= 2 * cin_maxsize:
-
 
135
                readsize = min(bodysize, din_maxsize)
266
        blocklen = self.cout_maxsize - 0x10
136
                data += self.readdma(addr, readsize)
267
      
137
            else:
268
      blocklen = (blocklen & 0xFFFFFFF0) +  (offset & 0xF)
138
                readsize = min(bodysize, cin_maxsize)
-
 
139
                data += self.readmem(addr, readsize)
-
 
140
            addr += readsize
-
 
141
            bodysize -= readsize
-
 
142
        if tailsize != 0:
-
 
143
            data += self.readmem(addr, tailsize)
-
 
144
        return data
269
      
145
    
-
 
146
    def write(self, addr, data):
270
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 5, offset, blocklen, 0) + data[boffset:boffset+blocklen])
147
        """ Writes the data in 'data' to the location 'addr'
271
      response = self.__getbulk(self.handle, self.__cinep, 0x10)
148
            in the memory of the device. This cares about too long packages
272
      self.__checkstatus(response)
149
            and decides whether to use DMA or not.
273
      
150
        """
274
      offset += blocklen
151
        if not self.lib.connected:
275
      boffset += blocklen
152
            self.lib.connect()
276
      size -= blocklen
153
        cout_maxsize = self.lib.dev.packetsizelimit["cout"] - 0x10
277
 
-
 
278
    # write data with DMA, if it makes sense (-> much data) and isn't forbidden
154
        dout_maxsize = self.lib.dev.packetsizelimit["dout"]
279
    if (usedma) and (size > 2 * (self.cout_maxsize - 16)): 
155
        (headsize, bodysize, tailsize) = self._alignsplit(addr, len(data), cout_maxsize, 16)
-
 
156
        offset = 0
280
      if (freezesched):
157
        if headsize != 0:
281
        self.freezescheduler(1, 0)
158
            self.writemem(addr, headsize)
282
    
-
 
283
      while (size > (self.cout_maxsize - 16)):
159
            offset += headsize
284
        blocklen = size
160
            addr += headsize
285
     
161
        while bodysize > 0:
286
        if (blocklen > self.dout_maxsize):
162
            if bodysize >= 2 * cout_maxsize:
287
          blocklen = self.dout_maxsize
163
                writesize = min(bodysize, dout_maxsize)
-
 
164
                self.writedma(addr, data[offset:offset+writesize])
288
          
165
            else:
289
        self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 7, offset, blocklen, 0))
166
                writesize = min(bodysize, cout_maxsize)
290
        response = self.__getbulk(self.handle, self.__cinep, 0x10)
167
                self.writemem(addr, data[offset:offset+writesize])
291
        self.__checkstatus(response)
168
            offset += writesize
-
 
169
            addr += writesize
-
 
170
            bodysize -= writesize
292
      
171
        if tailsize != 0:
293
        self.handle.bulkWrite(self.__doutep, data[boffset:boffset+blocklen])
172
            self.writemem(addr, data[offset:offset+tailsize])
-
 
173
        return data
294
      
174
    
295
        offset += blocklen
175
    def readmem(self, addr, size):
-
 
176
        """ Reads the memory from location 'addr' with size 'size'
296
        boffset += blocklen
177
            from the device.
-
 
178
        """
-
 
179
        resp = self.lib.monitorcommand(struct.pack("IIII", 4, addr, size, 0), "III%ds" % size, (None, None, None, "data"))
297
        size -= blocklen
180
        return resp.data
298
        
181
        
-
 
182
    def writemem(self, addr, data):
-
 
183
        """ Writes the data in 'data' to the location 'addr'
-
 
184
            in the memory of the device.
-
 
185
        """
-
 
186
        return self.lib.monitorcommand(struct.pack("IIII%ds" % len(data), 5, addr, len(data), 0, data), "III", (None, None, None))
-
 
187
    
-
 
188
    def readdma(self, addr, size):
-
 
189
        """ Reads the memory from location 'addr' with size 'size'
-
 
190
            from the device. This uses DMA and the data in endpoint.
-
 
191
        """
-
 
192
        self.lib.monitorcommand(struct.pack("IIII", 6, addr, size, 0), "III", (None, None, None))
-
 
193
        return struct.unpack("%ds" % size, self.lib.dev.din(size))[0]
-
 
194
    
-
 
195
    def writedma(self, addr, data):
-
 
196
        """ Writes the data in 'data' to the location 'addr'
-
 
197
            in the memory of the device. This uses DMA and the data out endpoint.
-
 
198
        """
-
 
199
        self.lib.monitorcommand(struct.pack("IIII", 7, addr, len(data), 0), "III", (None, None, None))
-
 
200
        return self.lib.dev.dout(data)
-
 
201
    
-
 
202
    def i2cread(self, index, slaveaddr, startaddr, size):
-
 
203
        """ Reads data from an i2c slave """
-
 
204
    
-
 
205
    def i2cwrite(self, index, slaveaddr, startaddr, data):
-
 
206
        """ Writes data to an i2c slave """
-
 
207
    
-
 
208
    def usbcread(self, size):
-
 
209
        """ Reads data with size 'size' from the USB console """
-
 
210
    
-
 
211
    def usbcwrite(self, data):
-
 
212
        """ Writes data to the USB console """
-
 
213
    
-
 
214
    def cread(self, size, bitmask):
-
 
215
        """ Reads data with the specified size from the device consoles
-
 
216
            identified with the specified bitmask
-
 
217
        """
-
 
218
 
-
 
219
    def cwrite(self, data):
-
 
220
        """ Writes data to the device consoles 
-
 
221
            identified with the specified bitmask.
-
 
222
        """
-
 
223
    
-
 
224
    def cflush(self, bitmask):
-
 
225
        """ Flushes the consoles specified with 'bitmask' """
-
 
226
        return self.lib.monitorcommand(struct.pack("IIII", 14, bitmask, 0, 0), "III", (None, None, None))
-
 
227
    
-
 
228
    def getprocinfo(self, offset, size):
-
 
229
        """ Gets current state of the scheduler """
-
 
230
    
-
 
231
    def freezescheduler(self, freeze=True):
-
 
232
        """ Freezes/Unfreezes the scheduler """
-
 
233
        return self.lib.monitorcommand(struct.pack("IIII", 16, 1 if freeze else 0, 0, 0), "III", ("before", None, None))
-
 
234
    
299
      if (freezesched):
235
    def unfreezescheduler(self):
300
        self.freezescheduler(0, 0)
236
        """ Unfreezes the scheduler """
-
 
237
        return self.lib.monitorcommand(struct.pack("IIII", 16, 0, 0, 0), "III", ("before", None, None))
-
 
238
    
-
 
239
    def suspendthread(self, id, suspend=True):
-
 
240
        """ Suspends the thread with the specified id """
-
 
241
        return self.lib.monitorcommand(struct.pack("IIII", 17, 1 if suspend else 0, id, 0), "III", ("before", None, None))
-
 
242
    
-
 
243
    def unsuspendthread(self, id):
-
 
244
        """ Suspends the thread with the specified id """
-
 
245
        return self.lib.monitorcommand(struct.pack("IIII", 17, 0, id, 0), "III", ("before", None, None))
-
 
246
    
-
 
247
    def killthread(self, id):
-
 
248
        """ Kills the thread with the specified id """
-
 
249
        return self.lib.monitorcommand(struct.pack("IIII", 18, id, 0, 0), "III", ("before", None, None))
-
 
250
    
-
 
251
    def createthread(self, nameptr, entrypoint, stackptr, stacksize, threadtype, priority, state):
-
 
252
        """ Creates a thread with the specified attributes """
-
 
253
        if threadtype == "user":
-
 
254
            threadtype = 0
-
 
255
        elif threadtype == "system":
-
 
256
            threadtype = 1
-
 
257
        else:
-
 
258
            raise SyntaxError("Threadtype must be either 'system' or 'user'")
-
 
259
        if priority > 256 or priority < 0:
-
 
260
            raise SyntaxError("Priority must be a number between 0 and 256")
-
 
261
        if state == "ready":
-
 
262
            state = 0
-
 
263
        elif state == "suspended":
-
 
264
            state = 1
-
 
265
        else:
-
 
266
            raise SyntaxError("State must be either 'ready' or 'suspended'")
-
 
267
        resp = self.lib.monitorcommand(struct.pack("IIIIIIII", 19, nameptr, entrypoint, stackptr, stacksize, threadtype, priority, state), "III", (id, None, None))
-
 
268
        if resp.id < 0:
-
 
269
            raise DeviceError("The device returned the error code "+str(resp.id))
-
 
270
        return resp
-
 
271
    
-
 
272
    def flushcpucache(self):
-
 
273
        """ Flushes the CPU instruction and data cache """
-
 
274
        return self.lib.monitorcommand(struct.pack("IIII", 20, 0, 0, 0), "III", (None, None, None))
-
 
275
    
-
 
276
    def run(self, addr):
-
 
277
        """ Runs the emBIOS app at 'addr' """
-
 
278
        return self.lib.monitorcommand(struct.pack("IIII", 21, addr, 0, 0), "III", ("excecimage", None, None))
-
 
279
    
-
 
280
    def bootflashread(self, memaddr, flashaddr, size):
-
 
281
        """ Copies the data in the bootflash at 'flashaddr' of the specified size
-
 
282
            to the memory at addr 'memaddr'
-
 
283
        """
-
 
284
    
-
 
285
    def bootflashwrite(self, memaddr, flashaddr, size):
-
 
286
        """ Copies the data in the memory at 'memaddr' of the specified size
-
 
287
            to the boot flash at addr 'flashaddr'
-
 
288
        """
-
 
289
    
-
 
290
    def execfirmware(self, addr):
-
 
291
        """ Executes the firmware at 'addr' and passes all control to it. """
-
 
292
        return self.lib.monitorcommand(struct.pack("IIII", 24, addr, 0, 0), "III", (None, None, None))
-
 
293
    
-
 
294
    def aesencrypt(self, addr, size, keyindex):
-
 
295
        """ Encrypts the buffer at 'addr' with the specified size
-
 
296
            with the hardware AES key index 'keyindex'
-
 
297
        """
-
 
298
        return self.lib.monitorcommand(struct.pack("IBBHII", 25, 1, 0, keyindex, addr, size), "III", (None, None, None))
-
 
299
    
-
 
300
    def aesdecrypt(self, addr, size, keyindex):
-
 
301
        """ Decrypts the buffer at 'addr' with the specified size
-
 
302
            with the hardware AES key index 'keyindex'
-
 
303
        """
-
 
304
        return self.lib.monitorcommand(struct.pack("IBBHII", 25, 0, 0, keyindex, addr, size), "III", (None, None, None))
-
 
305
    
-
 
306
    def hmac_sha1(self, addr, size, destination):
-
 
307
        """ Generates a HMAC-SHA1 hash of the buffer and saves it to 'destination' """
-
 
308
        return self.lib.monitorcommand(struct.pack("IIII", 26, addr, size, destination), "III", (None, None, None))
-
 
309
 
-
 
310
 
-
 
311
class Lib(object):
-
 
312
    def __init__(self, embios):
-
 
313
        self.idVendor = 0xFFFF
-
 
314
        self.idProduct = 0xE000
-
 
315
 
-
 
316
        self.embios = embios
-
 
317
        self.connected = False
-
 
318
    
-
 
319
    def connect(self):
-
 
320
        self.dev = Dev(self.idVendor, self.idProduct)
-
 
321
        self.connected = True
-
 
322
        self.embios.getpacketsizeinfo()
-
 
323
    
-
 
324
    def monitorcommand(self, cmd, rcvdatatypes=None, rcvstruct=None):
-
 
325
        if not self.connected:
-
 
326
            self.connect()
-
 
327
        self.dev.cout(cmd)
-
 
328
        if rcvdatatypes:
-
 
329
            rcvdatatypes = "I" + rcvdatatypes # add the response
-
 
330
            data = self.dev.cin(struct.calcsize(rcvdatatypes))
-
 
331
            data = struct.unpack(rcvdatatypes, data)
-
 
332
            response = data[0]
-
 
333
            if libembiosdata.responsecodes[response] == "ok":
-
 
334
                if rcvstruct:
-
 
335
                    datadict = Bunch()
-
 
336
                    counter = 1 # start with 1, 0 is the id
-
 
337
                    for item in rcvstruct:
-
 
338
                        if item != None: # else the data is undefined
-
 
339
                            datadict[item] = data[counter]
-
 
340
                        counter += 1
-
 
341
                    return datadict
-
 
342
                else:
-
 
343
                    return data
-
 
344
            elif libembiosdata.responsecodes[response] == "unsupported":
-
 
345
                raise DeviceError("The device does not support this command.")
-
 
346
            elif libembiosdata.responsecodes[response] == "invalid":
-
 
347
                raise DeviceError("Invalid command! This should NOT happen!")
-
 
348
            elif libembiosdata.responsecodes[response] == "busy":
-
 
349
                raise DeviceError("Device busy")
-
 
350
 
-
 
351
 
-
 
352
class Dev(object):
-
 
353
    def __init__(self, idVendor, idProduct):
-
 
354
        self.idVendor = idVendor
-
 
355
        self.idProduct = idProduct
301
        
356
        
302
    # write rest of data
-
 
303
    while (size > 0):
-
 
304
      blocklen = size
-
 
305
      
-
 
306
      if (blocklen > self.cout_maxsize - 0x10):
-
 
307
        blocklen = self.cout_maxsize - 0x10
-
 
308
    
-
 
309
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 5, offset, blocklen, 0) + data[boffset:boffset+blocklen])
-
 
310
      response = self.__getbulk(self.handle, self.__cinep, 0x10)
-
 
311
      self.__checkstatus(response)
-
 
312
      
-
 
313
      offset += blocklen
357
        self.interface = 0
314
      boffset += blocklen
-
 
315
      size -= blocklen
-
 
316
    
-
 
317
 
-
 
318
  def read(self, offset, size, usedma, freezesched):
-
 
319
    if (size == 0):
-
 
320
      return
-
 
321
    
-
 
322
    data = ""
-
 
323
    
-
 
324
    # correct alignment
-
 
325
    while (offset & 0xF) != 0:
-
 
326
      blocklen = size
-
 
327
      
-
 
328
      if (blocklen > size):
-
 
329
        blocklen = size
358
        self.timeout = 100
330
      if (blocklen > self.cin_maxsize - 0x10):
-
 
331
        blocklen = self.cin_maxsize - 0x10
-
 
332
        
359
        
333
      blocklen = (blocklen & 0xFFFFFFF0) +  (offset & 0xF)
-
 
334
      
-
 
335
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 4, offset, blocklen, 0))
-
 
336
      response = self.__getbulk(self.handle, self.__cinep, 0x10 + blocklen)
-
 
337
      self.__checkstatus(response)
-
 
338
      
-
 
339
      data += response[0x10:]
-
 
340
      
-
 
341
      offset += blocklen
360
        self.connect()
342
      size -= blocklen
-
 
343
 
-
 
344
    # read data with DMA, if it makes sense (-> much data) and isn't forbidden
-
 
345
    if (usedma) and (size > 2 * (self.cin_maxsize - 16)):
-
 
346
      if (freezesched):
-
 
347
        self.freezescheduler(1, 0)
361
        self.findEndpoints()
348
 
-
 
349
      while (size > (self.cin_maxsize - 16)):
-
 
350
        blocklen = size
-
 
351
      
-
 
352
        if (blocklen > self.din_maxsize):
-
 
353
          blocklen = self.din_maxsize
-
 
354
          
-
 
355
        self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 6, offset, blocklen, 0))
-
 
356
        response = self.__getbulk(self.handle, self.__cinep, 0x10)
-
 
357
        self.__checkstatus(response)
-
 
358
      
-
 
359
        data += self.__getbulk(self.handle, self.__doutep, blocklen)
-
 
360
      
-
 
361
        offset += blocklen
-
 
362
        size -= blocklen
-
 
363
        
362
        
364
      if (freezesched):
363
        self.packetsizelimit = {}
365
        self.freezescheduler(0, 0)
364
        self.packetsizelimit['cout'] = None
366
        
365
        self.packetsizelimit['cin'] = None
367
    # read rest of data
366
        self.packetsizelimit['dout'] = None
368
    while (size > 0):
367
        self.packetsizelimit['din'] = None
369
      blocklen = size
368
    
370
      
369
    def __del__(self):
371
      if (blocklen > self.cin_maxsize - 0x10):
370
        self.disconnect()
372
        blocklen = self.cin_maxsize - 0x10
371
    
373
    
372
    def findEndpoints(self):
374
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 4, offset, blocklen, 0))
373
        epcounter = 0
375
      response = self.__getbulk(self.handle, self.__cinep, 0x10 + blocklen)
374
        self.endpoint = {}
376
      self.__checkstatus(response)
375
        for cfg in self.dev:
377
      
376
            for intf in cfg:
378
      data += response[0x10:]
377
                for ep in intf:
379
      
378
                    if epcounter == 0:
380
      offset += blocklen
379
                        self.endpoint['cout'] = ep.bEndpointAddress
381
      size -= blocklen
380
                    elif epcounter == 1:
382
      
381
                        self.endpoint['cin'] = ep.bEndpointAddress
383
    return data
382
                    elif epcounter == 2:
384
 
383
                        self.endpoint['dout'] = ep.bEndpointAddress
385
 
384
                    elif epcounter == 3:
386
  def uploadfile(self, offset, file, usedma = 1, freezesched = 0, silent = 0):
385
                        self.endpoint['din'] = ep.bEndpointAddress
387
    self.__myprint("Uploading %s to 0x%08x..." % (file, offset), silent)
386
                    epcounter += 1
388
    f = open(file, "rb")
387
        if epcounter <= 3:
389
 
388
            raise DeviceError("Not all endpoints found in the descriptor. Only "+str(epcounter)+" found, we need 4")
390
    while True:
389
    
391
      data = f.read(262144)
390
    def connect(self):
392
      if data == "": break
391
        self.dev = usb.core.find(idVendor=self.idVendor, idProduct=self.idProduct)
393
      self.write(offset, data, usedma, freezesched)
392
        if self.dev is None:
394
      offset += len(data)
393
            raise DeviceNotFoundError()
395
      self.__myprint(".")
394
        self.dev.set_configuration()
396
 
395
    
397
    self.__myprint(" done\n", silent) 
396
    def disconnect(self):
398
    
397
        pass
399
  
398
    
400
  def downloadfile(self, offset, size, file, usedma = 1, freezesched = 0, silent = 0):
399
    def send(self, endpoint, data):
401
    self.__myprint("Downloading 0x%x bytes from 0x%08x to %s..." % (size, offset, file), silent)
400
        size = self.dev.write(endpoint, data, self.interface, self.timeout)
402
    f = open(file, "wb")
401
        if size != len(data):
403
 
402
            raise SendError
404
    while True:
403
        return len
405
      blocklen = size
404
    
406
      if blocklen == 0: break
405
    def receive(self, endpoint, size):
407
      if blocklen > 262144: blocklen = 262144
406
        read = self.dev.read(endpoint, size, self.interface, self.timeout)
408
      f.write(self.read(offset, blocklen, usedma, freezesched))
407
        if len(read) != size:
409
      offset += blocklen
408
            raise ReceiveError
410
      size -= blocklen
409
        return read
411
      self.__myprint(".")
410
    
412
 
411
    def cout(self, data):
413
    self.__myprint(" done\n", silent)
412
        if self.packetsizelimit['cout'] and len(data) > self.packetsizelimit['cout']:
414
    
413
            raise SendError("Packet too big")
415
    
414
        return self.send(self.endpoint['cout'], data)
416
  def uploadint(self, offset, data, silent = 0):
415
    
417
    self.__myprint("Uploading 0x%08x to 0x%08x..." % (data, offset), silent)
416
    def cin(self, size):
418
    data = struct.pack('<I', data)
417
        if self.packetsizelimit['cin'] and size > self.packetsizelimit['cin']:
419
    self.write(offset, data, 0, 0)
418
            raise ReceiveError("Packet too big")
420
    self.__myprint(" done\n", silent)
419
        return self.receive(self.endpoint['cin'], size)
421
 
420
    
422
 
421
    def dout(self, data):
423
  def downloadint(self, offset, silent = 0):
422
        if self.packetsizelimit['dout'] and len(data) > self.packetsizelimit['dout']:
424
    self.__myprint("Downloading an integer from 0x%08x..." % (offset), silent)
423
            raise SendError("Packet too big")
425
    data = self.read(offset, 4, 0, 0)
424
        return self.send(self.endpoint['dout'], data)
426
    number = struct.unpack('<I', data)
425
    
427
    self.__myprint(" done\nValue was: 0x%08x\n" % (number), silent)
426
    def din(self, size):
428
    
427
        if self.packetsizelimit['din'] and size > self.packetsizelimit['din']:
429
    return data
428
            raise ReceiveError("Packet too big")
430
    
429
        return self.receive(self.endpoint['din'], size)
431
    
430
 
432
#=====================================================================================  
431
 
433
    
432
if __name__ == "__main__":
434
    
433
    # Some tests
435
  def i2crecv(self, bus, slave, addr, size, silent = 0):
434
    import sys
436
    if (size > self.cin_maxsize - 0x10) or (size > 0xFF):
435
    embios = Embios()
437
      raise Exception ("The data exceeds the maximum amount that can be received with this instruction.")
436
    resp = embios.getversioninfo()
438
  
437
    sys.stdout.write("Embios device version information: " + libembiosdata.swtypes[resp.swtypeid] + " v" + str(resp.majorv) + "." + str(resp.minorv) + 
439
    self.__myprint("Reading 0x%2x bytes from 0x%2x at I2C device at bus 0x%2x, slave adress 0x%2x ..." % (size, addr, bus, slave), silent)
438
                     "." + str(resp.patchv) + " r" + str(resp.revision) + " running on " + libembiosdata.hwtypes[resp.hwtypeid] + "\n")
440
    
439
    resp = embios.getusermemrange()
441
    self.handle.bulkWrite(self.__coutep, struct.pack("<IBBBBII", 8, bus, slave, addr, size, 0, 0))
440
    sys.stdout.write("Usermemrange: "+hex(resp.lower)+" - "+hex(resp.upper)+"\n")
442
    data = self.__getbulk(self.handle, self.__cinep, 0x10 + size)
441
    memaddr = resp.lower
443
    self.__checkstatus(response)
442
    maxlen = resp.upper - resp.lower
444
    
443
    f = open("./embios.py", "rb")
445
    self.__myprint(" done\n data was:\n%s\n" % (self.__gethexviewprintout(data[16:])), silent)
444
    sys.stdout.write("Loading test file (embios.py) to send over USB...\n")
446
    
445
    datastr = f.read()[:maxlen]
447
    return data[16:]
446
    sys.stdout.write("Sending data...\n")
448
 
447
    embios.write(memaddr, datastr)
449
 
448
    sys.stdout.write("Encrypting data with the hardware key...\n")
450
  def i2csend(self, bus, slave, addr, data, silent = 0):
449
    embios.aesencrypt(memaddr, len(datastr), 0)
451
    size = len(data)
450
    sys.stdout.write("Reading data back and saving it to 'libembios-test-encrypted.bin'...\n")
452
    if (size > self.cout_maxsize - 0x10) or (size > 0xFF):
451
    f = open("./libembios-test-encrypted.bin", "wb")
453
      raise Exception ("The data exceeds the maximum amount that can be send with this instruction.")
452
    f.write(embios.read(memaddr, len(datastr)))
454
  
453
    sys.stdout.write("Decrypting the data again...\n")
455
    self.__myprint("Writing 0x%2x bytes to 0x%2x at I2C device at bus 0x%2x, slave adress 0x%2x ..." % (size, addr, bus, slave), silent)
454
    embios.aesdecrypt(memaddr, len(datastr), 0)
456
  
455
    sys.stdout.write("Reading data back from device...\n")
457
    self.handle.bulkWrite(self.__coutep, struct.pack("<IBBBBII", 9, bus, slave, addr, size, 0, 0) + data)
456
    readdata = embios.read(memaddr, len(datastr))
458
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
457
    if readdata == datastr:
459
    self.__checkstatus(response)
458
        sys.stdout.write("Data matches!")
460
    
-
 
461
    self.__myprint(" done\n", silent)
-
 
462
    
-
 
463
    
-
 
464
#=====================================================================================      
-
 
465
 
-
 
466
  def readusbcon(self, size, outtype = "", file = "", silent = 0):
-
 
467
    """ reads from USB console
-
 
468
      <size>: number of bytes to be read, if its length exceeds the Command In endpoint packet size - 0x10, it will be read in several steps
-
 
469
      <outtype>: how the data will be put out
-
 
470
        "file" => writes data to file <file>
-
 
471
        "printstring" => prints data as a string to the console window
-
 
472
        "printhex" => prints a hexview view of the data to the console window
-
 
473
        "" => only returns the data
-
 
474
      <silent>: if 0, nothing will be written to the console window (even if <outtype> defines something else)
-
 
475
      
-
 
476
      in every case, the data will be returned in an array with additional information
-
 
477
        [len, buffersize, datainbuffer, data]
-
 
478
          where len is the length of the data actually read,
-
 
479
                buffersize is the on-device read buffer size,
-
 
480
                datainbuffer is the number of bytes still left in the on device buffer,
-
 
481
                data is the actual data
-
 
482
      
-
 
483
      in case that within 5 secs, it's not possible to read <size> bytes, a timeout will occur
-
 
484
    """
-
 
485
    out_data = ""
-
 
486
    readbytes = 0
-
 
487
    buffersize = 0
-
 
488
    bytesleft = 0
-
 
489
    timeoutcounter = 0
-
 
490
    
-
 
491
    self.__myprint("Reading 0x%x bytes from USB console..." % (size), silent)
-
 
492
    
-
 
493
    while size > 0 and timoutcounter < 50:
-
 
494
      blocklen = size
-
 
495
      
-
 
496
      if size > self.cin_maxsize - 0x10:
-
 
497
        blocklen = self.cin_maxsize - 0x10
-
 
498
      
-
 
499
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 10, blocklen, 0, 0))
-
 
500
      response = self.__getbulk(self.handle, self.__cinep, blocklen + 0x10)
-
 
501
      self.__checkstatus(response)
-
 
502
      
-
 
503
      readbytes, buffersize, bytesleft = struct.unpack("<III", response[4:])
-
 
504
      out_data += response[0x10:0x10+readbytes]
-
 
505
      size -= blocklen
-
 
506
      
-
 
507
      if not bytesleft > 0:   # no data left to read => wait a bit and prevent an infinite loop trying to read data when there is none
-
 
508
        timeoutcounter += 1
-
 
509
        time.sleep(0.1)
-
 
510
      else:
-
 
511
        timeoutcounter -= 3
-
 
512
        if timeoutcounter < 0:
-
 
513
          timeoutcounter = 0
-
 
514
          
-
 
515
    self.__myprint(" done\n", silent)
-
 
516
    self.__myprint("\nBytes read: 0x%x\nOn-device buffersize: 0x%x\nBytes still in device's buffer: 0x%x\n\n"\
-
 
517
                    % (len(out_data), buffersize, bytesleft)                      
-
 
518
                    , silent)
-
 
519
    
-
 
520
    if (outtype == "file"):
-
 
521
      f = open(file, "wb")
-
 
522
      f.write(out_data)
-
 
523
      
-
 
524
    elif (outtype == "printstring"):
-
 
525
      self.__myprint(out_data, silent)
-
 
526
      self.__myprint("\n\n", silent)
-
 
527
      
-
 
528
    elif (outtype == "printhex"):
-
 
529
      self.__myprint(self.__gethexviewprintout(out_data, "", 1), silent)
-
 
530
      self.__myprint("\n\n", silent)
-
 
531
    
-
 
532
    elif (outtype == ""):
-
 
533
      pass    # return only
-
 
534
      
-
 
535
    else:
459
    else:
536
      raise Exception ("Invalid argument for <outtype>: '%s'." % (outtype))
-
 
537
    
-
 
538
    return [len(out_data), buffersize, bytesleft, out_data]
-
 
539
    
-
 
540
    
-
 
541
  def writeusbcon(self, data, silent = 0, *range):
-
 
542
    """ writes to USB console
-
 
543
      <data>: the data to be written
-
 
544
      <range>: the range in <data> that should be written, in the from [offset, length]
-
 
545
      <silent>: if 0, nothing will be written to the console window
-
 
546
      
-
 
547
      if the data to be written exceeds the Command Out endpoint packet size - 0x10, it will be written in several steps
-
 
548
    """
-
 
549
    size = len(data)
-
 
550
    boffset = 0
-
 
551
    
-
 
552
    if len(range) > 0:
-
 
553
      boffset = range[0]
-
 
554
    if len(range) > 1:
-
 
555
      size = range[1]
-
 
556
    
-
 
557
    self.__myprint("Writing 0x%x bytes to USB console..." % (size), silent)
-
 
558
    
-
 
559
    timeoutcounter = 0
-
 
560
    
-
 
561
    while (size > 0) and (timeoutcounter < 50):
-
 
562
      blocklen = size
-
 
563
      if blocklen > self.cout_maxsize - 0x10:
-
 
564
        blocklen = self.cout_maxsize - 0x10
-
 
565
    
-
 
566
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 11, size, 0, 0) + data[boffset:boffset+blocklen])
-
 
567
      response = self.__getbulk(self.handle, self.__cinep, 0x10)
-
 
568
      self.__checkstatus(response)
-
 
569
      
-
 
570
      sendbytes = struct.unpack("<I", response[4:])[0]
-
 
571
      if sendbytes < blocklen:   # not everything has been written, need to resent some stuff but wait a bit before doing so
-
 
572
        time.sleep(0.1)
-
 
573
        timeoutcounter += 1
-
 
574
      elif timeoutcounter > 0:    # lower timeoutcounter again
-
 
575
        timeoutcounter -= 3
-
 
576
        if timeoutcounter < 0:
-
 
577
          timeoutcounter = 0
-
 
578
      
-
 
579
      size -= sendbytes
-
 
580
      boffset += sendbytes
-
 
581
 
-
 
582
      
-
 
583
    if (timeoutcounter >=50):
-
 
584
      raise Exception("Timeout, 0x%x bytes couldn't be send." % size)
-
 
585
    
-
 
586
    self.__myprint(" done\n", silent)
-
 
587
    
-
 
588
    return size   # number of bytes that have not been sent
-
 
589
    
-
 
590
 
-
 
591
  def readdevcon(self, bitmask, size, outtype = "", file = "", silent = 0):
-
 
592
    """ reads from one or more of the device's consoles
-
 
593
      <bitmask>: bitmask of consoles to be read from
-
 
594
      <size>: number of bytes to be read, if its length exceeds the Command In endpoint packet size - 0x10, it will be read in several steps
-
 
595
      <outtype>: how the data will be put out
-
 
596
        "file" => writes data to file <file>
-
 
597
        "printstring" => prints data as a string to the console window
460
        sys.stdout.write("Data does NOT match. Something got wrong")
598
        "printhex" => prints a hexview view of the data to the console window
-
 
599
        "" => only returns the data
-
 
600
      <silent>: if 0, nothing will be written to the console window (even if <outtype> defines something else)
-
 
601
      
-
 
602
      in every case, the data will be returned
-
 
603
      
-
 
604
      in case that within 5 secs, it's not possible to read <size> bytes, a timeout will occur
-
 
605
    """
-
 
606
    out_data = ""
-
 
607
    readbytes = 0
-
 
608
    timeoutcounter = 0
-
 
609
    
-
 
610
    self.__myprint("Reading 0x%x bytes from device's console(s)..." % (size), silent)
-
 
611
    
-
 
612
    while size > 0 and timoutcounter < 50:
-
 
613
      blocklen = size
-
 
614
      
-
 
615
      if size > self.cin_maxsize - 0x10:
-
 
616
        blocklen = self.cin_maxsize - 0x10
-
 
617
      
-
 
618
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 13, bitmask, blocklen, 0))
-
 
619
      response = self.__getbulk(self.handle, self.__cinep, blocklen + 0x10)
-
 
620
      self.__checkstatus(response)
-
 
621
      
-
 
622
      readbytes = struct.unpack("<III", response[4:])[0]
-
 
623
      out_data += response[0x10:0x10+readbytes]
-
 
624
      size -= blocklen
-
 
625
      
-
 
626
      if not readbytes > 0:   # no data read => wait a bit and prevent an infinite loop trying to read data when there is none
-
 
627
        timeoutcounter += 1
-
 
628
        time.sleep(0.1)
-
 
629
      else:
-
 
630
        timeoutcounter -= 3
-
 
631
        if timeoutcounter < 0:
-
 
632
          timeoutcounter = 0
-
 
633
          
-
 
634
    self.__myprint(" done\n", silent)
-
 
635
    self.__myprint("\nBytes read: 0x%x\n\n" % (len(out_data)), silent)
-
 
636
    
-
 
637
    if (outtype == "file"):
-
 
638
      f = open(file, "wb")
-
 
639
      f.write(out_data)
-
 
640
      
-
 
641
    elif (outtype == "printstring"):
-
 
642
      self.__myprint(out_data, silent)
-
 
643
      self.__myprint("\n\n", silent)
-
 
644
      
-
 
645
    elif (outtype == "printhex"):
-
 
646
      self.__myprint(self.__gethexviewprintout(out_data, "", 1), silent)
-
 
647
      self.__myprint("\n\n", silent)
-
 
648
    
-
 
649
    elif (outtype == ""):
-
 
650
      pass    # return only
-
 
651
      
-
 
652
    else:
-
 
653
      raise Exception ("Invalid argument for <outtype>: '%s'." % (outtype))
-
 
654
    
-
 
655
    return out_data
-
 
656
    
-
 
657
    
-
 
658
  def writedevcon(self, bitmask, data, silent = 0, *range):
-
 
659
    """ writes to USB console
-
 
660
      <bitmask>: bitmask of consoles to be written to
-
 
661
      <data>: the data to be written
-
 
662
      <range>: the range in <data> that should be written, in the from [offset, length]
-
 
663
      <silent>: if 0, nothing will be written to the console window
-
 
664
      
-
 
665
      if the data to be written exceeds the Command Out endpoint packet size - 0x10, it will be written in several steps
-
 
666
    """
-
 
667
    size = len(data)
-
 
668
    boffset = 0
-
 
669
    
-
 
670
    if len(range) > 0:
-
 
671
      boffset = range[0]
-
 
672
    if len(range) > 1:
-
 
673
      size = range[1]
-
 
674
    
-
 
675
    self.__myprint("Writing 0x%x bytes to device's console(s)..." % (size), silent)
-
 
676
    
-
 
677
    timeoutcounter = 0
-
 
678
    
-
 
679
    while size > 0:
-
 
680
      blocklen = size
-
 
681
      if blocklen > self.cout_maxsize - 0x10:
-
 
682
        blocklen = self.cout_maxsize - 0x10
-
 
683
    
-
 
684
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 12, bitmask, size, 0) + data[boffset:boffset+blocklen])
-
 
685
      response = self.__getbulk(self.handle, self.__cinep, 0x10)
-
 
686
      self.__checkstatus(response)
-
 
687
      
-
 
688
      size -= blocklen
-
 
689
      boffset += blocklen
-
 
690
    
-
 
691
    self.__myprint(" done\n", silent)
-
 
692
   
-
 
693
       
-
 
694
  def flushconsolebuffers(self, bitmask, silent = 0):
-
 
695
    self.__myprint("Flushing device console('s) buffer('s)...")
-
 
696
    
-
 
697
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 14, bitmask, 0, 0))
-
 
698
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
-
 
699
    self.__checkstatus(response)
-
 
700
    
-
 
701
    self.__myprint(" done\n") 
-
 
702
 
-
 
703
    
-
 
704
#===================================================================================== 
-
 
705
 
-
 
706
  
-
 
707
  def freezescheduler(self, freeze, silent = 0):
-
 
708
    if (freeze):
-
 
709
      self.__myprint("Freezing scheduler...", silent)
-
 
710
      freeze = 1
-
 
711
    else:
-
 
712
      self.__myprint("Unfreezing scheduler...", silent)
-
 
713
      freeze = 0
-
 
714
      
-
 
715
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 16, freeze, 0, 0))
-
 
716
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
-
 
717
    self.__checkstatus(response)
-
 
718
    
-
 
719
    self.__myprint(" done\n", silent)    
-
 
720
    
-
 
721
    
-
 
722
  def suspendthread(self, suspend, threadid, silent = 0):
-
 
723
    if (suspend):
-
 
724
      self.__myprint("Suspending thread 0x%08x..." % threadid, silent)
-
 
725
      suspend = 1
-
 
726
    else:
-
 
727
      self.__myprint("Unsuspending thread 0x%08x..." % threadid, silent)
-
 
728
      suspend = 0
-
 
729
      
-
 
730
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 17, suspend, threadid, 0))
-
 
731
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
-
 
732
    self.__checkstatus(response)
-
 
733
    
-
 
734
    self.__myprint(" done\n", silent) 
-
 
735
 
-
 
736
 
-
 
737
  def killthread(self, threadid, silent = 0):
-
 
738
    self.__myprint("Killing thread 0x%08x..." % threadid, silent)
-
 
739
      
-
 
740
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 18, threadid, 0, 0))
-
 
741
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
-
 
742
    self.__checkstatus(response)
-
 
743
    
-
 
744
    self.__myprint(" done\n", silent) 
-
 
745
    
-
 
746
    
-
 
747
  def createthread(self, namepointer, entrypoint, stackpointer, stacksize, type, priority, state, silent = 0):
-
 
748
    self.__myprint("Creating thread...", silent)
-
 
749
      
-
 
750
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIIIIIII", 19, namepointer, entrypoint, stackpointer, stacksize, type, priority, state))
-
 
751
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
-
 
752
    self.__checkstatus(response)
-
 
753
    
-
 
754
    if (struct.unpack("<i", response[4:8])[0] < 0):
-
 
755
      self.__myprint(" failed, error code: 0x%x" % (struct.unpack("<i", response[4:8])[0]), silent)
-
 
756
    else:
-
 
757
      self.__myprint(" done\n, thread ID: 0x%x" % (struct.unpack("<I", response[4:8])[0]), silent)     
-
 
758
    
-
 
759
    
-
 
760
  def getprocinfo(self, silent = 0):
-
 
761
    """
-
 
762
      printout on console window:
-
 
763
        <silent> = 0: Process information struct version, Process information table size
-
 
764
        <silent> = 1: nothing
-
 
765
    """
-
 
766
    # inline functions ----------------------------------------------
-
 
767
    def procinfotolist(processinfo, structver):
-
 
768
      if (structver == 1):   # Process information struct version == 1
-
 
769
        ptr = 0
-
 
770
        process_n = 0
-
 
771
        retval = []
-
 
772
        while ptr < len(processinfo):
-
 
773
          if struct.unpack("<I", processinfo[ptr + 68:ptr + 72])[0] == 0:    # THREAD_FREE
-
 
774
            ptr += 120
-
 
775
            process_n += 1
-
 
776
            continue
-
 
777
          
-
 
778
          retval.append({})
-
 
779
          
-
 
780
          retval[process_n]['regs'] = struct.unpack("<IIIIIIIIIIIIIIII", processinfo[ptr:ptr + 64])
-
 
781
          ptr += 16 * 0x4
-
 
782
          retval[process_n]['cpsr'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
-
 
783
          ptr += 1 * 0x4
-
 
784
          retval[process_n]['state'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
-
 
785
          ptr += 1 * 0x4
-
 
786
          retval[process_n]['name_ptr'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
-
 
787
          ptr += 1 * 0x4
-
 
788
          retval[process_n]['cputime_current'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
-
 
789
          ptr += 1 * 0x4
-
 
790
          retval[process_n]['cputime_total'] = struct.unpack("<Q", processinfo[ptr:ptr + 8])[0]
-
 
791
          ptr += 1 * 0x8
-
 
792
          retval[process_n]['startusec'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
-
 
793
          ptr += 1 * 0x4
-
 
794
          retval[process_n]['queue_next_ptr'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
-
 
795
          ptr += 1 * 0x4
-
 
796
          retval[process_n]['timeout'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
-
 
797
          ptr += 1 * 0x4
-
 
798
          retval[process_n]['blocked_since'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
-
 
799
          ptr += 1 * 0x4
-
 
800
          retval[process_n]['blocked_by_ptr'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
-
 
801
          ptr += 1 * 0x4
-
 
802
          retval[process_n]['stack_ptr'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
-
 
803
          ptr += 1 * 0x4
-
 
804
          retval[process_n]['err_no'] = struct.unpack("<I", processinfo[ptr:ptr + 4])[0]
-
 
805
          ptr += 1 * 0x4
-
 
806
          retval[process_n]['block_type'] = struct.unpack("<B", processinfo[ptr:ptr + 1])[0]
-
 
807
          ptr += 1 * 0x1
-
 
808
          retval[process_n]['thread_type'] = struct.unpack("<B", processinfo[ptr:ptr + 1])[0]
-
 
809
          ptr += 1 * 0x1
-
 
810
          retval[process_n]['priority'] = struct.unpack("<B", processinfo[ptr:ptr + 1])[0]
-
 
811
          ptr += 1 * 0x1
-
 
812
          retval[process_n]['cpuload'] = struct.unpack("<B", processinfo[ptr:ptr + 1])[0]
-
 
813
          ptr += 1 * 0x1
-
 
814
          
-
 
815
          process_n += 1
-
 
816
          
-
 
817
        return retval
-
 
818
      
-
 
819
      
-
 
820
    def state2name(state, structver):
-
 
821
      if structver == 1:
-
 
822
        if state == 0: return "THREAD_FREE"
-
 
823
        elif state == 1: return "THREAD_SUSPENDED"
-
 
824
        elif state == 2: return "THREAD_READY"
-
 
825
        elif state == 3: return "THREAD_RUNNING"
-
 
826
        elif state == 4: return "THREAD_BLOCKED"
-
 
827
        elif state == 5: return "THREAD_DEFUNCT"
-
 
828
        elif state == 6: return "THREAD_DEFUNCT_ACK"
-
 
829
        else: return "UNKNOWN"
-
 
830
      else: return "UNKNOWN"
-
 
831
      
-
 
832
    def blocktype2name(blocktype, structver):
-
 
833
      if structver == 1:
-
 
834
        if blocktype == 0: return "THREAD_NOT_BLOCKED"
-
 
835
        elif blocktype == 1: return "THREAD_BLOCK_SLEEP"
-
 
836
        elif blocktype == 2: return "THREAD_BLOCK_MUTEX"
-
 
837
        elif blocktype == 3: return "THREAD_BLOCK_WAKEUP"
-
 
838
        elif blocktype == 4: return "THREAD_DEFUNCT_STKOV"
-
 
839
        elif blocktype == 5: return "THREAD_DEFUNCT_PANIC"
-
 
840
        else: return "UNKNOWN"
-
 
841
      else: return "UNKNOWN"
-
 
842
      
-
 
843
    def threadtype2name (threadtype, structver):
-
 
844
      if structver == 1:
-
 
845
        if threadtype == 0: return "USER_THREAD"
-
 
846
        elif threadtype == 1: return "OS_THREAD"
-
 
847
        elif threadtype == 2: return "CORE_THREAD"
-
 
848
        else: return "UNKNOWN"
-
 
849
      else: return "UNKNOWN"
-
 
850
      
-
 
851
    def procinfotostring(procinfolist, structver):
-
 
852
      processinfoprint = ""
-
 
853
      ptr = 0
-
 
854
      while structver == 1 and ptr < len(procinfolist):      # Process information struct version == 1
-
 
855
        processinfoprint += "--------------------------------------------------------------------------------\n"
-
 
856
        processinfoprint += "R0: 0x%08x,  R1: 0x%08x,  R2: 0x%08x,  R3: 0x%08x,\n"\
-
 
857
                            % (procinfolist[ptr]['regs'][0], procinfolist[ptr]['regs'][1], procinfolist[ptr]['regs'][2], procinfolist[ptr]['regs'][3])\
-
 
858
                            + "R4: 0x%08x,  R5: 0x%08x,  R6: 0x%08x,  R7: 0x%08x,\n"\
-
 
859
                            % (procinfolist[ptr]['regs'][4], procinfolist[ptr]['regs'][5], procinfolist[ptr]['regs'][6], procinfolist[ptr]['regs'][7])\
-
 
860
                            + "R8: 0x%08x,  R9: 0x%08x,  R10: 0x%08x, R11: 0x%08x,\n"\
-
 
861
                            % (procinfolist[ptr]['regs'][8], procinfolist[ptr]['regs'][9], procinfolist[ptr]['regs'][10], procinfolist[ptr]['regs'][11])\
-
 
862
                            + "R12: 0x%08x, SP: 0x%08x,  LR: 0x%08x,  PC: 0x%08x\n" \
-
 
863
                            % (procinfolist[ptr]['regs'][12], procinfolist[ptr]['regs'][13], procinfolist[ptr]['regs'][14], procinfolist[ptr]['regs'][15])
-
 
864
        processinfoprint += "cpsr: 0x%08x      " %             (procinfolist[ptr]['cpsr'])
-
 
865
        processinfoprint += "state: %s      " %                 (state2name([procinfolist[ptr]['state']], structver))
-
 
866
        processinfoprint += "nameptr: 0x%08x\n" %               (procinfolist[ptr]['name_ptr'])
-
 
867
        processinfoprint += "current cpu time: 0x%08x      " %  (procinfolist[ptr]['cputime_current'])
-
 
868
        processinfoprint += "total cpu time: 0x%016x\n" %       (procinfolist[ptr]['cputime_total'])
-
 
869
        processinfoprint += "startusec: 0x%08x      " %         (procinfolist[ptr]['startusec'])
-
 
870
        processinfoprint += "queue next ptr: 0x%08x\n" %        (procinfolist[ptr]['queue_next_ptr'])
-
 
871
        processinfoprint += "timeout: 0x%08x\n" %               (procinfolist[ptr]['timeout'])
-
 
872
        processinfoprint += "blocked since: 0x%08x      " %     (procinfolist[ptr]['blocked_since'])
-
 
873
        processinfoprint += "blocked by ptr: 0x%08x\n" %        (procinfolist[ptr]['blocked_by_ptr'])
-
 
874
        processinfoprint += "err_no: 0x%08x      " %            (procinfolist[ptr]['err_no'])
-
 
875
        processinfoprint += "block type: %s\n" %                (blocktype2name([procinfolist[ptr]['block_type']], structver))
-
 
876
        processinfoprint += "thread type: %s\n" %               (threadtype2name([procinfolist[ptr]['thread_type']], structver))
-
 
877
        processinfoprint += "priority: 0x%02x      " %          (procinfolist[ptr]['priority'])
-
 
878
        processinfoprint += "cpu load: 0x%02x\n" %              (procinfolist[ptr]['cpuload'])
-
 
879
          
-
 
880
        ptr += 1
-
 
881
        
-
 
882
      processinfoprint += "--------------------------------------------------------------------------------\n"
-
 
883
        
-
 
884
      return processinfoprint
-
 
885
     
-
 
886
    # reading code --------------------------------------------------
-
 
887
    self.__myprint("Retrieving process information...", silent)
-
 
888
    
-
 
889
    offset = 0
-
 
890
    blocklen = tablesize = self.cin_maxsize - 0x10
-
 
891
    procinfo = ""
-
 
892
    structversion = 0
-
 
893
    
-
 
894
    # reading loop
-
 
895
    while (offset < tablesize):
-
 
896
      self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 15, offset, blocklen, 0))
-
 
897
      response = self.__getbulk(self.handle, self.__cinep, blocklen + 0x10)
-
 
898
      self.__checkstatus(response)
-
 
899
      
-
 
900
      tablesize = struct.unpack("<I", response[8:12])[0]
-
 
901
      
-
 
902
      if tablesize <= offset + blocklen:
-
 
903
        blocklen = tablesize - offset
-
 
904
        procinfo += response[0x10:0x10 + blocklen]
-
 
905
        structversion = struct.unpack("<I", response[4:8])[0]
-
 
906
        tablesize = struct.unpack("<I", response[8:12])[0]
-
 
907
      else:
-
 
908
        procinfo += response[0x10:0x10 + blocklen]
-
 
909
      
-
 
910
      offset += blocklen
-
 
911
      
-
 
912
      blocklen = self.cin_maxsize - 0x10
-
 
913
      if blocklen > tablesize - offset:
-
 
914
        blocklen = tablesize - offset
-
 
915
    
-
 
916
    
-
 
917
    out = (structversion, tablesize, procinfotolist(procinfo, structversion))
-
 
918
 
-
 
919
    self.__myprint(" done\n"\
-
 
920
                   + "Process information struct version: 0x%08x\n" % out[0]\
-
 
921
                   + "Total size of process information table: 0x%08x\n" % out[1]\
-
 
922
                   + procinfotostring(out[2], 1)\
-
 
923
                   + "\n\n")
-
 
924
    
-
 
925
    return out
-
 
926
  
-
 
927
    
-
 
928
  def execimage(self, offset, silent = 0):
-
 
929
    self.__myprint("Executing emBIOS executable image at 0x%08x..." % offset, silent)
-
 
930
      
-
 
931
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 21, offset, 0, 0))
-
 
932
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
-
 
933
    self.__checkstatus(response)
-
 
934
    
-
 
935
    self.__myprint(" done\n    execimage() return code: 0x%08x\n" % struct.unpack("<I", response[4:8])[0], silent)
-
 
936
    
-
 
937
    return struct.unpack("<I", response[4:8])[0]
-
 
938
    
-
 
939
    
-
 
940
  def execfirmware(self, offset, silent = 0):
-
 
941
    self.__myprint("Executing firmware image at 0x%08x..." % offset, silent)
-
 
942
      
-
 
943
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 24, offset, 0, 0))
-
 
944
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
-
 
945
    self.__checkstatus(response)
-
 
946
    
-
 
947
    self.__myprint(" done\n", silent)
-
 
948
    
-
 
949
    return
-
 
950
    
-
 
951
    
-
 
952
#===================================================================================== 
-
 
953
 
-
 
954
 
-
 
955
  def readrawbootflash(self, addr_bootflsh, addr_mem, size, silent = 0):
-
 
956
    self.__myprint("Reading 0x%x bytes from 0x%08x at bootflash to 0x%08x..." % (size, addr_bootflsh, addr_mem), silent)
-
 
957
      
-
 
958
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 22, addr_mem, addr_bootflsh, size))
-
 
959
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
-
 
960
    self.__checkstatus(response)
-
 
961
    
-
 
962
    self.__myprint(" done\n", silent)
-
 
963
 
-
 
964
 
-
 
965
  def writerawbootflash(self, addr_mem, addr_bootflsh, size, silent = 0):
-
 
966
    self.__myprint("Writing 0x%x bytes from 0x%08x to bootflash at 0x%08x..." % (size, addr_fmem, addr_bootflsh), silent)
-
 
967
      
-
 
968
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 23, addr_mem, addr_bootflsh, size))
-
 
969
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
-
 
970
    self.__checkstatus(response)
-
 
971
    
-
 
972
    self.__myprint(" done\n", silent)
-
 
973
    
-
 
974
 
-
 
975
#=====================================================================================
-
 
976
 
-
 
977
 
-
 
978
  def flushcaches(self, silent = 0):
-
 
979
    self.__myprint("Flushing caches...", silent)
-
 
980
    
-
 
981
    self.handle.bulkWrite(self.__coutep, struct.pack("<IIII", 20, 0, 0, 0))
-
 
982
    response = self.__getbulk(self.handle, self.__cinep, 0x10)
-
 
983
    self.__checkstatus(response)
-
 
984
    
-
 
985
    self.__myprint(" done\n", silent) 
-
 
986
    
-
 
987
  
-
 
988
#======================================================================================
-
 
989
# backlight control, remnant from libibugger adjusted to work with libembios ==========
-
 
990
 
-
 
991
 
-
 
992
  def backlighton(self, fade, brightness, silent = 0):
-
 
993
    self.__myprint("Turning on backlight...", silent)
-
 
994
    if self.devtype == 2:
-
 
995
      self.i2csend(0, 0xe6, 0x2b, struct.pack("<B", fade), 1)
-
 
996
      self.i2csend(0, 0xe6, 0x28, struct.pack("<B", int(brightness * 46)), 1)
-
 
997
      self.i2csend(0, 0xe6, 0x29, struct.pack("<B", 1), 1)
-
 
998
      self.__myprint(" done\n", silent)
-
 
999
    elif self.devtype == 4:
-
 
1000
      self.i2csend(0, 0xe6, 0x30, struct.pack("<B", int(brightness * 250)), 1)
-
 
1001
      self.i2csend(0, 0xe6, 0x31, struct.pack("<B", 3), 1)
-
 
1002
      self.__myprint(" done\n", silent)
-
 
1003
    else: self.__myprint(" unsupported (%s)\n" % self.devtype2name(self.devtype), silent)
-
 
1004
 
-
 
1005
 
-
 
1006
  def backlightoff(self, fade, silent = 0):
-
 
1007
    self.__myprint("Turning off backlight...", silent)
-
 
1008
    if self.devtype == 2:
-
 
1009
      self.i2csend(0, 0xe6, 0x2b, struct.pack("<B", fade), 1)
-
 
1010
      self.i2csend(0, 0xe6, 0x29, struct.pack("<B", 0), 1)
-
 
1011
      self.__myprint(" done\n", silent)
-
 
1012
    elif self.devtype == 4:
-
 
1013
      self.i2csend(0, 0xe6, 0x31, struct.pack("<B", 2), 1)
-
 
1014
      self.__myprint(" done\n", silent)
-
 
1015
    else: self.__myprint(" unsupported (%s)\n" % self.devtype2name(self.devtype), silent)
-
 
1016
  
-
 
1017
461