turn ftdi driver into echo server
[goodfet] / client / goodfet.maxusbmass
1 #!/usr/bin/env python
2
3 #USB Mass Storage Emulator
4 #by Travis Goodspeed
5 #with thanks to Brandon Wilson and his Linky project.
6
7 import sys;
8 import binascii;
9 import array;
10 import time;
11 import warnings
12
13 from GoodFETMAXUSB import *;
14
15 warnings.warn(
16 """The libraries upon which this program depends will soon be deprecated in
17 favor of the USB*.py libraries.  See facedancer-umass.py (forthcoming) for an
18 example of this program written using the new libraries."""
19 )
20
21 # This constant is kinda complicated and very ugly.  The idea is that
22 # if we take too long in any given transaction, the host will abort.
23 # How many blocks we can send depends upon timeouts on both sides,
24 # with (at least in Linux) the behavior that aborting early causes the
25 # disk to reset with only warning and no real errors.  Somewhere
26 # there's a way to provide this constant to the host, in which case
27 # stalling and waiting for a reset will no longer be necessary.
28
29 MAXBLOCKSPERTRANSFER=128
30
31 def zeros(length):
32     """Returns a list of zeroes of the specified length."""
33     l=range(0,length);
34     for foo in l:
35         l[foo]=0;
36     return l;
37
38 class GoodFETMAXUSBMass(GoodFETMAXUSBDevice):
39     """This emulates a USB Mass Storage device."""
40     
41     #Too much data to watch everything.
42     usbverbose=False;
43
44     def getSectorData(self,lba):
45         """Overload this to return data from a given 512-byte sector."""
46         print "You forgot to overload getSectorData().  Returning something neighborly.";
47         sector=[
48             0xE9, 0x86, 0x00, 0x0A, 0x47, 0x6F, 0x6F, 0x64, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x30, 0x2E, 0x30,
49             0x31, 0x0A, 0x0D, 0x62, 0x79, 0x20, 0x54, 0x72, 0x61, 0x76, 0x69, 0x73, 0x20, 0x47, 0x6F, 0x6F,
50             0x64, 0x73, 0x70, 0x65, 0x65, 0x64, 0x0A, 0x0A, 0x0D, 0x00, 0x59, 0x6F, 0x75, 0x20, 0x68, 0x61,
51             0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6E, 0x20, 0x65, 0x61, 0x74, 0x65, 0x6E, 0x20, 0x62, 0x79,
52             0x20, 0x61, 0x20, 0x67, 0x72, 0x75, 0x65, 0x2E, 0x20, 0x20, 0x53, 0x6F, 0x72, 0x72, 0x79, 0x2E,
53             0x0A, 0x0D, 0x00, 0x31, 0x29, 0x20, 0x52, 0x65, 0x61, 0x64, 0x69, 0x6E, 0x67, 0x20, 0x6B, 0x65,
54             0x72, 0x6E, 0x65, 0x6C, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x64, 0x69, 0x73, 0x6B, 0x2E, 0x0A,
55             0x0D, 0x00, 0x32, 0x29, 0x20, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x6B,
56             0x65, 0x72, 0x6E, 0x65, 0x6C, 0x2E, 0x0A, 0x0D, 0x00, 0xBE, 0x03, 0x7C, 0xE8, 0x41, 0x00, 0xE8,
57             0x7B, 0x00, 0x31, 0xC0, 0x30, 0xD2, 0xCD, 0x13, 0x0F, 0x82, 0xE8, 0x00, 0xBE, 0x53, 0x7C, 0xE8,
58             0x2E, 0x00, 0xB8, 0xE0, 0x07, 0x8E, 0xC0, 0x31, 0xDB, 0xB8, 0x10, 0x02, 0xB5, 0x00, 0xB1, 0x02,
59             0xB6, 0x00, 0xB2, 0x00, 0xCD, 0x13, 0x0F, 0x82, 0xCA, 0x00, 0xB8, 0x00, 0x7E, 0x89, 0xC6, 0xE8,
60             0x7C, 0x00, 0xBE, 0x72, 0x7C, 0xE8, 0x08, 0x00, 0xEA, 0x00, 0x00, 0xE0, 0x07, 0xE8, 0xB4, 0x00,
61             0xAC, 0x3C, 0x00, 0x74, 0x06, 0xB4, 0x0E, 0xCD, 0x10, 0xEB, 0xF5, 0xC3, 0x30, 0x78, 0x00, 0x20,
62             0x62, 0x79, 0x74, 0x65, 0x73, 0x20, 0x6F, 0x66, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x20,
63             0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x2E, 0x0A, 0x0D, 0x00, 0x53, 0x65, 0x67, 0x6D,
64             0x65, 0x6E, 0x74, 0x73, 0x3A, 0x20, 0x00, 0x2C, 0x20, 0x00, 0x0A, 0x0D, 0x00, 0xBE, 0xDC, 0x7C,
65             0xE8, 0xBD, 0xFF, 0xE8, 0x63, 0x00, 0xE8, 0x07, 0x00, 0xBE, 0xDF, 0x7C, 0xE8, 0xB1, 0xFF, 0xC3,
66             0x89, 0xC3, 0xC1, 0xE8, 0x0C, 0xE8, 0x39, 0x00, 0x89, 0xD8, 0xC1, 0xE8, 0x08, 0xE8, 0x31, 0x00,
67             0x89, 0xD8, 0xC1, 0xE8, 0x04, 0xE8, 0x29, 0x00, 0x89, 0xD8, 0xE8, 0x24, 0x00, 0xC3, 0x31, 0xC9,
68             0xAD, 0xE8, 0xDC, 0xFF, 0xE8, 0x2C, 0x00, 0x83, 0xC1, 0x02, 0x81, 0xF9, 0x00, 0x02, 0x75, 0xF0,
69             0xC3, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45,
70             0x46, 0x50, 0x56, 0x83, 0xE0, 0x0F, 0x05, 0x51, 0x7D, 0x89, 0xC6, 0xAC, 0xB4, 0x0E, 0xCD, 0x10,
71             0x5E, 0x58, 0xC3, 0xB8, 0x20, 0x0E, 0xCD, 0x10, 0xC3, 0x31, 0xC0, 0xCD, 0x12, 0x72, 0x05, 0x85,
72             0xC0, 0x74, 0x01, 0xC3, 0xBE, 0x2A, 0x7C, 0xE8, 0x46, 0xFF, 0xEB, 0xFE, 0xEA, 0x00, 0x00, 0xFF,
73             0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA
80             ];
81         return sector;
82     def putSectorData(self,lba,block):
83         """Overload this to write data to a given 512-byte sector."""
84         print "You forgot to overload putSectorData().  Ignoring sector write.";
85         return;
86     
87     def getSectorCount(self):
88         """Returns the number of viable Logical Block Addresses."""
89         print "You forgot to overload getSectorCount().  Guessing 0x200.";
90         return 0x200;
91     
92     def massinit(self):
93         """Initialize a USB Mass Storage device."""
94         self.usb_disconnect();
95         time.sleep(1);
96         self.usb_connect();
97         self.massrun();
98         
99     def massrun(self):
100         """Main loop of the USB Mass Storage emulator."""
101         print "Starting a Mass Storage device.";
102         while 1:
103             sys.stdout.flush();
104             self.service_irqs();
105     def do_SETUP(self):
106         """Handle USB Enumeration"""
107         
108         #Grab the SETUP packet from the buffer.
109         SUD=self.readbytes(rSUDFIFO,8);
110         
111         #Parse the SETUP packet
112         print "Handling a setup packet of %s" % self.setup2str(SUD);
113         setuptype=(ord(SUD[bmRequestType])&0x60);
114         if setuptype==0x00:
115             self.std_request(SUD);
116         elif setuptype==0x20:
117             self.class_request(SUD);
118         elif setuptype==0x40:
119             self.vendor_request(SUD);
120         else:
121             print "Unknown bmRequestType=0x%02x." % ord(SUD[bmRequestType])
122             self.STALL_EP0(SUD);
123     def class_request(self,SUD):
124         """Handle a class request."""
125         requesttype=ord(SUD[bmRequestType]);
126         request=ord(SUD[bRequest]);
127         if requesttype==0xA1 and request==0xFE:
128             print "Reporting 0 as the maximum LUN.";
129             #This is a Get Max LUN request.
130             #Return 1-byte maximum Logical Unit Number
131             self.wreg(rEP0FIFO,0x00); # Just one LUN.
132             self.wregAS(rEP0BC,1); # ARM and fire!
133             return; #Don't stall.
134         if requesttype==0x21 and request==0xff:
135             print "Received BBB reset."
136             self.wregAS(rEP0BC,0); # ARM and fire!
137             return; #Don't stall.
138         print "Stalling an unknown class request: %s" % self.setup2str(SUD);
139         self.STALL_EP0(SUD);
140     def vendor_request(self,SUD):
141         """Handle a vendor request."""
142         request=ord(SUD[bRequest]);
143         print "Why the hell is there a vendor request?";
144         #self.wreg(rEP0FIFO,0);
145         self.wregAS(rEP0BC,0);
146     def std_request(self,SUD):
147         """Handles a standard setup request."""
148         setuptype=ord(SUD[bRequest]);
149         if setuptype==SR_GET_DESCRIPTOR: self.send_descriptor(SUD);
150         #elif setuptype==SR_SET_FEATURE: self.feature(1);
151         elif setuptype==SR_SET_CONFIGURATION: self.set_configuration(SUD);
152         elif setuptype==SR_GET_STATUS: self.get_status(SUD);
153         elif setuptype==SR_SET_ADDRESS: self.rregAS(rFNADDR);
154         elif setuptype==SR_GET_INTERFACE: self.get_interface(SUD);
155         else:
156             #print "Stalling Unknown standard setup request type %02x" % setuptype;
157             #self.STALL_EP0(SUD);
158             print "Accepting unknown standard setup request type %02x" % setuptype;
159             self.wregAS(rEP0BC,0);
160             
161     def get_interface(self,SUD):
162         """Handles a setup request for SR_GET_INTERFACE."""
163         if ord(SUD[wIndexL]==0):
164             self.wreg(rEP0FIFO,0);
165             self.wregAS(rEP0BC,1);
166         else:
167             self.STALL_EP0(SUD);
168     
169
170
171 #Device Descriptor
172     DD=[ 
173         
174     0x12, #length
175     0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
176     0x81, 0x07, #Sandisk 
177     0x50, 0x51, #SDCZ2 Cruzer Mini Flash Drive (thin)
178     0x00, 0x03,
179     0x01, 0x02, 0x03, #Strings
180     0x01
181     
182     ];
183
184 #Configuration Descriptor
185     CD=[
186
187   0x09, #Length
188   0x02, #Type
189   0x20, #Total Length
190   0x00, 0x01, 0x01, 0x00, 0xE0, 0x00, 0x09, 0x04, 0x00, 0x00,
191   0x02, #Num Endpoints
192   0x08, #Mass Storage Bulk Only
193   0x06, #SCSI
194   0x50, 0x00,
195   
196   #OUT EP1
197   0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00,
198   #IN EP3
199   0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00,
200
201 ];
202     strDesc=[
203 # STRING descriptor 0--Language string
204 "\x04\x03\x09\x04",
205 # [
206 #         0x04,                 # bLength
207 #       0x03,                   # bDescriptorType = string
208 #       0x09,0x04               # wLANGID(L/H) = English-United Sates
209 # ],
210 # STRING descriptor 1--Manufacturer ID
211 "\x10\x03G\x00o\x00o\x00d\x00F\x00E\x00T\x00",
212 # STRING descriptor 2 - Product ID
213 "\x1C\x03M\x00A\x00S\x00S\x00 \x00E\x00m\x00u\x00l\x00a\x00t\x00o\x00r\x00",
214 # STRING descriptor 3 - Serial Number ID
215 "\x14\x03S\x00/\x00N\x00 \x003\x004\x002\x000\x00E\x00"
216 ];
217
218     def get_status(self,SUD):
219         """Get the USB Setup Status."""
220         testbyte=ord(SUD[bmRequestType])
221         
222         #Toward Device
223         if testbyte==0x80:
224             self.wreg(rEP0FIFO,0x03); #Enable RWU and self-powered
225             self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
226             self.wregAS(rEP0BC,2);    #Load byte count, arm transfer, and ack CTL.
227         #Toward Interface
228         elif testbyte==0x81:
229             self.wreg(rEP0FIFO,0x00);
230             self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
231             self.wregAS(rEP0BC,2);
232         #Toward Endpoint
233         elif testbyte==0x82:
234             if(ord(SUD[wIndexL])==0x83):
235                 print "This code almost certainly doesn't work.";
236                 self.wreg(rEP0FIFO,0x01); #Stall EP3
237                 self.wreg(rEP0FIFO,0x00); #Second byte is always zero.
238                 self.wregAS(rEP0BC,2);
239             else:
240                 print "Stalling unknown status.";
241                 self.STALL_EP0(SUD);
242         else:
243             print "Stalling unknown status.";
244             self.STALL_EP0(SUD);
245     
246     def do_IN3(self):
247         """Handle IN3 input event."""
248         # Do nothing here, as it'll be taken care of elsewhere.  The
249         # interrupt just means that the buffer is empty, not that we
250         # are expected to fill it.
251         
252     def do_OUT1(self):
253         """Handle an OUT1 output event."""
254         l=self.rreg(rEP1OUTBC);
255         frame=self.readbytes(rEP1OUTFIFO,l);
256         self.handleCBW(frame);
257         
258     lastCBW="";
259     def handleCBW(self,cbw):
260         """Handles an incoming Command Block Wrapper.  See USB Mass
261         Storage Class for details."""
262         
263         if len(cbw)!=31:
264             print "Invalid CBW length of %i bytes.  Aborting." % len(cbw);
265             return;
266         sig=cbw[0:4];
267         if sig!="USBC":
268             print "Invalid CBW signature: %s.  Should be USBC; aborting." % sig;
269             return;
270         self.lastCBW=cbw;
271         
272         dtlen=ord(cbw[8])+(ord(cbw[9])<<8)+(ord(cbw[10])<<16)+(ord(cbw[11])<<24);
273         flags=ord(cbw[12]);
274         dtdir=flags&0x80; # 0x80 for dev->host, 0x00 for host->dev
275         lun=ord(cbw[13])&0x0F; # Should be zero, as we only reported one LUN.
276         cblen=ord(cbw[14])&0x1F;
277         cb=cbw[15:31];
278         self.handleCB(cb,cblen,dtlen,dtdir);
279         
280     def handleCB(self,cb,cblen,dtlen,dtdir):
281         """Handles a command block, then replies with a CSW."""
282         if self.usbverbose:
283             print "Got command block, type 0x%02x requesting 0x%02x bytes" % (
284                 ord(cb[0]), dtlen);
285         verb=ord(cb[0]);
286         status=00; #good, set to 1 for bad.
287         if verb==0x00: # Test Unit Ready
288             # Send nothing, just the success code.
289             status=0;
290         elif verb==0x03: # Request Sense
291             print "Responding to Request Sense.  Needed for Macs.";
292             response=[0x70, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0A,
293                       0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
294                       0x00, 0x00,
295                       0,0,0,0,0];
296             #status=1;
297             self.writebytes(rEP3INFIFO,
298                             response);
299             self.wreg(rEP3INBC,len(response));
300         elif verb==0x12: #Inquiry
301             #print "Responding to CB inquiry.";
302             response=[
303                 0x00, # 00 for Direct, 1F for "no floppy"
304                 0x80, # make 0x80 for removable media, 0x00 for fixed
305                 0x00, # Version
306                 0x01, # Response Data Format
307                 0x1f, #Additional length.
308                 0x00, 0x00, 0x00,
309                 #Manufacturer
310                 ord('G'),ord('o'),ord('o'),ord('d'),ord('F'),ord('E'),ord('T'),0x20,
311                 #Device name
312                 ord('G'),ord('o'),ord('o'),ord('d'),ord('F'),ord('E'),ord('T'),0x20,
313                 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
314                 ord('0'),ord('.'),ord('0'),ord('1')]
315             #print "Sending %i byte reply to %i byte query." % (
316             #        len(response),dtlen);
317             while len(response)<dtlen:
318                 response=response+[0];
319             #while not(self.rreg(rEPIRQ)&bmIN3BAVIRQ):
320             #    #Wait for the packet to complete before sending the next.
321             #    print "Waiting to complete inquiry."
322             #    pass;
323             self.writebytes(rEP3INFIFO,
324                             response);
325             self.wregAS(rEP3INBC,
326                         dtlen);
327                         #len(response));
328             #self.wreg(rEPIRQ,bmIN3BAVIRQ); #Clear the bit
329             #while not(self.rreg(rEPIRQ)&bmIN3BAVIRQ):
330             #    #Wait for the packet to complete before sending the next.
331             #    print "Waiting to complete inquiry."
332             #    pass;
333         elif verb==0x1e: #Prevent/Allow Removal
334             # Give a good status to pretend we understand.
335             status=0x00;
336         elif verb==0x1A or verb==0x5A: #Mode Sense (6 or 10)
337             # I should probably send six bytes here.
338             page=ord(cb[2])&0x3F;
339             print "Mode Sense (6) requesting %i byte Page Code %02x" % (
340                 dtlen,page);
341             #This is completely wrong.
342             response=[0x07,0,0,0, 0,0,0,0x1C];
343             # response=[0x37,0x00,0x00,0x08,0x00,0x00,0x00,0x00, 0x00,0x00,0x02,0x00,0x01,0x0a,0x80,0x00,
344             #           0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x08,0x12,0x04,0x00,0x00,0x00,0x00,0x00,
345             #           0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x0a,0x0a,0x02,0x00,
346             #           0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x1e];
347             if page!=0x3f:
348                 print "Unknown page, returning empty page.";
349                 response=[0x07,0,0,0, 0,0,0,0];
350             self.fifo_ep3in_tx(response);
351         elif verb==0x23: #Read Format Capacity
352             response=[
353                 0x00, 0,0x00,0x08,    # Capacity list length.
354                 0,0x00,0x10,0x00,     # Number of sectors, implying 10MB.  Should come from image.
355                 0x01,0x00,            # reserved/desciptor code.
356                 0x02,0x00             # 512 bytes/sector.  Why is this twice?
357                 ];
358             self.writebytes(rEP3INFIFO,
359                             response);
360             self.wregAS(rEP3INBC,
361                         len(response));
362         elif verb==0x25: #Read Capacity
363             lastlba=self.getSectorCount();
364             response=[
365                 #0x00, 0, 0x0f, 0xFF, # Last LBA
366                 (lastlba>>24)&0xFF, (lastlba>>16)&0xFF, (lastlba>>8)&0xFF, lastlba&0xFF, # Last LBA
367                 0x00,0x00,0x02,0x00   # Block length of 512 bytes.
368                 ];
369             self.writebytes(rEP3INFIFO,
370                             response);
371             self.wregAS(rEP3INBC,
372                         len(response));
373         elif verb==0x28: #READ SECTOR
374             cbw=self.lastCBW;
375             baselba=(
376                 ord(cbw[20]) |
377                 (ord(cbw[19])<<8) |
378                 (ord(cbw[18])<<16) |
379                 (ord(cbw[17])<<24)
380                 );
381             count=dtlen/512;
382             print "Fetching %i blocks starting at  LBA %i." % (count,baselba);
383             if count>MAXBLOCKSPERTRANSFER:
384                 count=0;
385                 #status=1; #Fail if we're asked to read more than 32 blocks.
386                 #Now we need to stall EP3.  It's not acceptable to just forget to transmit.
387                 self.wreg(rEPSTALLS,0x10);
388                 return;
389             for i in range(0,count):
390                 data=self.getSectorData(baselba+i);
391                 self.fifo_ep3in_tx(data);
392                 
393                 # for j in range(0,8):
394                 #     #print "Sending block fragment %i,%i" % (i,j);
395                 #     #Transmit each 64-byte block fragment, then wait for next.
396                 #     while not(self.rreg(rEPIRQ)&bmIN3BAVIRQ): pass;
397                 #     response=data[j*64:j*64+64];
398                 #     self.writebytes(rEP3INFIFO,
399                 #                     response);
400                 #     self.wregAS(rEP3INBC,
401                 #                 64);
402             #sys.exit();
403         elif verb==0x2A: #WRITE SECTOR
404             print "Haven't implemented WRITE SECTOR.  This will end badly.";
405             #sys.exit();
406         elif verb==0x1B: #EJECT/RETRACT DISK
407             print "Haven't implemented SCSI Start Stop Unit Command (1B)";
408             print "https://en.wikipedia.org/wiki/SCSI_Start_Stop_Unit_Command";
409             #sys.exit();
410         else:
411             print "ERROR: Unknown SCSI command block verb %02x." % verb;
412             status=0x02; #Command Failed
413             if dtlen>0:
414                 print "Sending %i bytes of dummy data here." % dtlen;
415                 self.fifo_ep3in_tx(zeros(dtlen));
416             #sys.exit(1);
417         cbw=self.lastCBW;
418         
419         #Now we need to send the CSW.
420         csw=[
421             #Standard prefix.
422             ord('U'),ord('S'),ord('B'),ord('S'),
423             #CBW key; must be the same as the one we're replying to.
424             ord(cbw[4]),ord(cbw[5]),ord(cbw[6]),ord(cbw[7]),
425             #CSW Data Residue, probably oughtn't be zeroed.
426             0,0,0,0,
427             #Status byte: 00 for good, 01 for bad.
428             status];
429         self.writebytes(rEP3INFIFO,
430                         csw);
431         self.wregAS(rEP3INBC,len(csw));
432         
433         
434         return;
435
436 class GoodFETMAXUSBMassFile(GoodFETMAXUSBMass):
437     """This emulates a USB Mass Storage Device, providing a file as
438     its image.  Writes are not yet supported, and this is very slow.
439     Performance hacks will come after the code stabilizes."""
440     
441     datafile=None;
442     datafilelen=None;
443     def openImage(self,filename):
444         """Opens an image for use.  Call this *before* massinit()."""
445         self.datafile=open(filename,"rb");
446         print "Opened an image with %i blocks." % self.getSectorCount();
447     def putSectorData(self,lba,block):
448         """Writes a 512-byte sector to the lba address."""
449         print "Writes aren't yet supported.";
450         return;
451     
452     def getSectorData(self,lba):
453         """Returns data from a 512-byte sector."""
454         toret="";
455         
456         #Seek to the appropraite block.
457         #print "Seeking to position %i"% (lba*512)
458         self.datafile.seek(lba*512,0);
459         pos=self.datafile.tell();
460         if pos!=lba*512:
461             print "SEEK ERROR: Seeked to %i (lba=%i), but now I'm at %i (lba=%i)" % (
462                 lba*512,lba,
463                 pos,pos/512);
464             #sys.exit();
465         
466         #Dump the data out, assuming no blocking and filling with nonsense.
467         toret=self.datafile.read(512);
468         if len(toret)<512:
469             print "Holy hell, I only have %i bytes of 512." % len(toret);
470         
471         toretbytes=range(0,len(toret));
472         for b in range(0,len(toret)): toretbytes[b]=ord(toret[b]);
473         return toretbytes;
474         
475     def getSectorCount(self):
476         """Returns the number of viable Logical Block Addresses."""
477         
478         # Python must have a better way to read a file length, but for
479         # now we just read the whole damned thing and then throw it
480         # away.  With present performance, we can't read anything
481         # large enough for this to be a problem.
482         if self.datafilelen==None:
483             self.datafile.seek(0);
484             self.datafilelen=len(self.datafile.read());
485         if self.datafilelen%512!=0:
486             print "ERROR: Image does not have an integer number of blocks!"
487             print "%i \% 512 == %i" % (self.datafilelen,
488                                        self.datafilelen%512);
489             sys.exit();
490         return self.datafilelen/512-1;
491
492 if(len(sys.argv)==1):
493     print "Usage: %s disk.img\n" % sys.argv[0];
494     sys.exit();
495
496
497 #Initialize FET and set baud rate
498 client=GoodFETMAXUSBMassFile();
499 client.serInit()
500
501 client.openImage(sys.argv[1]);
502
503 client.MAXUSBsetup();
504 client.massinit();
505