Subversion Repositories freemyipod

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
207 theseven 1
#!/usr/bin/env python
2
#
3
#
4
#    Copyright 2010 TheSeven
5
#
6
#
427 farthen 7
#    This file is part of emCORE.
207 theseven 8
#
427 farthen 9
#    emCORE is free software: you can redistribute it and/or
207 theseven 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
12
#    License, or (at your option) any later version.
13
#
427 farthen 14
#    emCORE is distributed in the hope that it will be useful,
207 theseven 15
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
16
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
#    See the GNU General Public License for more details.
18
#
19
#    You should have received a copy of the GNU General Public License along
427 farthen 20
#    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
207 theseven 21
#
22
#
23
 
24
 
25
import sys
26
import math
27
import struct
28
import time
29
import usb
30
 
31
 
427 farthen 32
class emcoreldr:
207 theseven 33
  def __init__(self, generation = 0):
34
    busses = usb.busses()
35
 
36
    for bus in busses:
37
      devices = bus.devices
38
      for dev in devices:
39
        if dev.idVendor == 0xffff and dev.idProduct == 0xe112:
40
          handle = dev.open()
41
          handle.setConfiguration(1)
42
          handle.claimInterface(0)
43
          if generation in [0, 2]:
44
            self.devtype = 2;
45
            self.maxin = 528;
46
            self.maxout = 528
47
            self.handle = handle
427 farthen 48
            print("Connected to emCORE Loader Recovery Mode on iPod Nano 2G, USB version %s" % dev.deviceVersion)
207 theseven 49
            return
50
          handle.releaseInterface()
51
 
52
    raise Exception("Could not find specified device (generation = %d)" % generation)
53
 
54
 
55
  @staticmethod
56
  def __myprint(data):
57
    sys.stdout.write(data)
58
    sys.stdout.flush()
59
 
60
 
61
  @staticmethod
62
  def __getbulk(handle, endpoint, size):
63
    data = handle.bulkRead(endpoint, size, 1000)
64
    return struct.pack("%dB" % len(data), *data)
65
 
66
 
67
  @staticmethod
68
  def __checkstatus(data):
69
    errorcode = struct.unpack("<I", data[:4])[0]
70
    if errorcode == 1:
71
      # everything went fine
72
      return
73
    elif errorcode == 2:
74
      print("\nError: Device doesn't support this function!")
75
      raise Exception("Device doesn't support this function!")
76
    else:
77
      print("\nUnknown error %d" % errorcode)
78
      raise Exception("Unknown error %d" % errorcode)
79
 
80
 
81
  def __readstatus(self):
82
    return self.__getbulk(self.handle, 0x83, 0x10)
83
 
84
 
85
  @staticmethod
86
  def devtype2name(devtype):
87
    if devtype == 2: return "iPod Nano 2G"
88
    else: return "UNKNOWN (%8x)" % devtype
89
 
90
 
91
  def write(self, offset, data, *range):
92
    if offset & 3 != 0 or len(data) & 3 != 0:
93
      raise Exception("Unaligned data write!")
94
 
95
    boffset = 0
96
    size = len(data)
97
    if len(range) > 0:
98
      boffset = range[0]
99
    if len(range) > 1:
100
      size = range[1]
101
 
102
    maxblk = self.maxout - 0x10
103
 
104
    while True:
105
      blocklen = size
106
      if blocklen == 0: break
107
      if blocklen > maxblk: blocklen = maxblk
108
      self.handle.bulkWrite(4, struct.pack("<IIII", 2, offset, int(blocklen / 4), 0) \
109
                             + data[boffset:boffset+blocklen])
110
      self.__checkstatus(self.__readstatus())
111
      offset += blocklen
112
      boffset += blocklen
113
      size -= blocklen
114
 
115
 
116
  def read(self, offset, size):
117
    if offset & 3 != 0 or size & 3 != 0:
118
      raise Exception("Unaligned data read!")
119
 
120
    maxblk = self.maxin - 0x10
121
 
122
    data = ""
123
 
124
    while True:
125
      blocklen = size
126
      if blocklen == 0: break
127
      if blocklen > maxblk: blocklen = maxblk
128
      self.handle.bulkWrite(4, struct.pack("<IIII", 1, offset, int(blocklen / 4), 0))
129
      block = self.__getbulk(self.handle, 0x83, 0x10 + blocklen)
130
      self.__checkstatus(block)
131
      offset += blocklen
132
      data += block[0x10:]
133
      size -= blocklen
134
 
135
    return data
136
 
137
 
138
  def execute(self, addr, stack):
139
    self.__myprint("Passing control to code at 0x%8x..." % addr)
140
    self.handle.bulkWrite(4, struct.pack("<IIII", 0, addr, stack, 0))
141
    self.__myprint(" done\n")
142
 
143
 
144
  def upload(self, offset, file):
145
    self.__myprint("Uploading %s to 0x%8x..." % (file, offset))
146
    f = open(file, "rb")
147
 
148
    while True:
149
      data = f.read(65536)
854 theseven 150
      if data == b"": break
207 theseven 151
      self.write(offset, data)
152
      offset += len(data)
153
      self.__myprint(".")
154
 
155
    self.__myprint(" done\n")
156
 
157
 
158
  def download(self, offset, size, file):
159
    self.__myprint("Downloading 0x%x bytes from 0x%8x to %s..." % (size, offset, file))
160
    f = open(file, "wb")
161
 
162
    while True:
163
      blocklen = size
164
      if blocklen == 0: break
165
      if blocklen > 65536: blocklen = 65536
166
      f.write(self.read(offset, blocklen))
167
      offset += blocklen
168
      size -= blocklen
169
      self.__myprint(".")
170
 
171
    self.__myprint(" done\n")
172
 
173
 
174
  def run(self, file):
175
    self.upload(0x08000000, file)
176
    self.execute(0x08000000, 0x0a000000)
177