From: travisutk Date: Thu, 30 Aug 2012 02:01:27 +0000 (+0000) Subject: Mass storage emulation now works well enough to emulate a readable, mountable disk. X-Git-Url: http://git.rot13.org/?p=goodfet;a=commitdiff_plain;h=3a1dba16a3f6c27250e1e9566171abe48537cc89;hp=5c28c526177571d53654b2a1e47ab5584a399fdf Mass storage emulation now works well enough to emulate a readable, mountable disk. git-svn-id: https://svn.code.sf.net/p/goodfet/code/trunk@1247 12e2690d-a6be-4b82-a7b7-67c4a43b65c8 --- diff --git a/client/GoodFETMAXUSB.py b/client/GoodFETMAXUSB.py index af95558..b35ba51 100644 --- a/client/GoodFETMAXUSB.py +++ b/client/GoodFETMAXUSB.py @@ -203,6 +203,7 @@ bmHXFRDNIRQ =0x80 class GoodFETMAXUSB(GoodFET): MAXUSBAPP=0x40; + usbverbose=True; def service_irqs(self): """Handle USB interrupt events.""" @@ -231,7 +232,7 @@ class GoodFETMAXUSB(GoodFET): """Overload this.""" def do_OUT1(self): """Overload this.""" - print "Ignoring an OUT1 interrupt."; + if self.usbverbose: print "Ignoring an OUT1 interrupt."; def setup2str(self,SUD): """Converts the header of a setup packet to a string.""" return "bmRequestType=0x%02x, bRequest=0x%02x, wValue=0x%04x, wIndex=0x%04x, wLength=0x%04x" % ( @@ -286,7 +287,7 @@ class GoodFETMAXUSB(GoodFET): ashex=""; for foo in toret: ashex=ashex+(" %02x"%ord(foo)); - print "GET %02x==%s" % (reg,ashex); + if self.usbverbose: print "GET %02x==%s" % (reg,ashex); return toret; def readbytesAS(self,reg,length): """Peek some bytes from a register, acking prior transfer.""" @@ -296,7 +297,7 @@ class GoodFETMAXUSB(GoodFET): ashex=""; for foo in toret: ashex=ashex+(" %02x"%ord(foo)); - print "GETAS %02x==%s" % (reg,ashex); + if self.usbverbose: print "GETAS %02x==%s" % (reg,ashex); return toret; def ctl_write_nd(self,request): """Control Write with no data stage. Assumes PERADDR is set @@ -413,13 +414,13 @@ class GoodFETMAXUSB(GoodFET): data=""; if type(tosend)==str: data=chr((reg<<3)|3)+tosend; - print "PUT %02x:=%s (0x%02x bytes)" % (reg,tosend,len(data)) + if self.usbverbose: print "PUT %02x:=%s (0x%02x bytes)" % (reg,tosend,len(data)) else: data=[(reg<<3)|3]+tosend; ashex=""; for foo in tosend: ashex=ashex+(" %02x"%foo); - print "PUT %02x:=%s (0x%02x bytes)" % (reg,ashex,len(data)) + if self.usbverbose: print "PUT %02x:=%s (0x%02x bytes)" % (reg,ashex,len(data)) self.writecmd(self.MAXUSBAPP,0x00,len(data),data); def usb_connect(self): """Connect the USB port.""" diff --git a/client/goodfet.maxusbmass b/client/goodfet.maxusbmass index 66c2e81..0882642 100755 --- a/client/goodfet.maxusbmass +++ b/client/goodfet.maxusbmass @@ -14,6 +14,9 @@ from GoodFETMAXUSB import *; class GoodFETMAXUSBMass(GoodFETMAXUSBDevice): """This emulates a USB Mass Storage device.""" + #Too much data to watch everything. + usbverbose=False; + def getSectorData(self,lba): """Overload this to return data from a given 512-byte sector.""" print "You forgot to overload getSectorData(). Returning something neighborly."; @@ -54,9 +57,14 @@ class GoodFETMAXUSBMass(GoodFETMAXUSBDevice): return sector; def putSectorData(self,lba,block): """Overload this to write data to a given 512-byte sector.""" - + print "You forgot to overload putSectorData(). Ignoring sector write."; return; + def getSectorCount(self): + """Returns the number of viable Logical Block Addresses.""" + print "You forgot to overload getSectorCount(). Guessing 0x200."; + return 0x200; + def massinit(self): """Initialize a USB Mass Storage device.""" self.usb_disconnect(); @@ -66,8 +74,9 @@ class GoodFETMAXUSBMass(GoodFETMAXUSBDevice): def massrun(self): """Main loop of the USB Mass Storage emulator.""" - print "Starting a Mass Storage device. This doesn't work yet."; + print "Starting a Mass Storage device."; while 1: + sys.stdout.flush(); self.service_irqs(); def do_SETUP(self): """Handle USB Enumeration""" @@ -218,7 +227,6 @@ class GoodFETMAXUSBMass(GoodFETMAXUSBDevice): def do_OUT1(self): """Handle an OUT1 output event.""" - print "Got an output event, printing the result."; l=self.rreg(rEP1OUTBC); frame=self.readbytes(rEP1OUTFIFO,l); self.handleCBW(frame); @@ -247,8 +255,9 @@ class GoodFETMAXUSBMass(GoodFETMAXUSBDevice): def handleCB(self,cb,cblen,dtlen,dtdir): """Handles a command block, then replies with a CSW.""" - print "\nGot command block 0x%02x, requesting 0x%02x bytes" % ( - ord(cb[0]), dtlen); + if self.usbverbose: + print "Got command block, type 0x%02x requesting 0x%02x bytes" % ( + ord(cb[0]), dtlen); verb=ord(cb[0]); status=00; #good, set to 1 for bad. if verb==0x00: # Test Unit Ready @@ -317,8 +326,10 @@ class GoodFETMAXUSBMass(GoodFETMAXUSBDevice): self.wregAS(rEP3INBC, len(response)); elif verb==0x25: #Read Capacity + lastlba=self.getSectorCount(); response=[ - 0x00, 0,0x0f,0xFF, # Last LBA; might have endianness backward. + #0x00, 0, 0x0f, 0xFF, # Last LBA + (lastlba>>24)&0xFF, (lastlba>>16)&0xFF, (lastlba>>8)&0xFF, lastlba&0xFF, # Last LBA 0x00,0x00,0x02,0x00 # Block length of 512 bytes. ]; self.writebytes(rEP3INFIFO, @@ -335,10 +346,15 @@ class GoodFETMAXUSBMass(GoodFETMAXUSBDevice): ); count=dtlen/512; print "Fetching %i blocks starting at LBA %i." % (count,baselba); + if count>32: + count=0; + status=1; #Fail if we're asked to read more than 32 blocks. + #Now we need to stall EP3. It's not acceptable to just forget to transmit. + self.wreg(rEPSTALLS,0x10); for i in range(0,count): - data=self.getSectorData(baselba+count); + data=self.getSectorData(baselba+i); for j in range(0,8): - print "Sending block fragment %i,%i" % (i,j); + #print "Sending block fragment %i,%i" % (i,j); #Transmit each 64-byte block fragment, then wait for next. while not(self.rreg(rEPIRQ)&bmIN3BAVIRQ): pass; response=data[j*64:j*64+64]; @@ -374,10 +390,73 @@ class GoodFETMAXUSBMass(GoodFETMAXUSBDevice): return; + +class GoodFETMAXUSBMassFile(GoodFETMAXUSBMass): + """This emulates a USB Mass Storage Device, providing a file as + its image. Writes are not yet supported, and this is very slow. + Performance hacks will come after the code stabilizes.""" + + datafile=None; + datafilelen=None; + def openImage(self,filename): + """Opens an image for use. Call this *before* massinit().""" + self.datafile=open(filename,"rb"); + print "Opened an image with %i blocks." % self.getSectorCount(); + def putSectorData(self,lba,block): + """Writes a 512-byte sector to the lba address.""" + print "Writes aren't yet supported."; + return; + + def getSectorData(self,lba): + """Returns data from a 512-byte sector.""" + toret=""; + + #Seek to the appropraite block. + #print "Seeking to position %i"% (lba*512) + self.datafile.seek(lba*512,0); + pos=self.datafile.tell(); + if pos!=lba*512: + print "SEEK ERROR: Seeked to %i (lba=%i), but now I'm at %i (lba=%i)" % ( + lba*512,lba, + pos,pos/512); + #sys.exit(); + + #Dump the data out, assuming no blocking and filling with nonsense. + toret=self.datafile.read(512); + if len(toret)<512: + print "Holy hell, I only have %i bytes of 512." % len(toret); + + toretbytes=range(0,len(toret)); + for b in range(0,len(toret)): toretbytes[b]=ord(toret[b]); + return toretbytes; + + def getSectorCount(self): + """Returns the number of viable Logical Block Addresses.""" + + # Python must have a better way to read a file length, but for + # now we just read the whole damned thing and then throw it + # away. With present performance, we can't read anything + # large enough for this to be a problem. + if self.datafilelen==None: + self.datafile.seek(0); + self.datafilelen=len(self.datafile.read()); + if self.datafilelen%512!=0: + print "ERROR: Image does not have an integer number of blocks!" + print "%i \% 512 == %i" % (self.datafilelen, + self.datafilelen%512); + sys.exit(); + return self.datafilelen/512-1; +if(len(sys.argv)==1): + print "Usage: %s disk.img\n" % sys.argv[0]; + sys.exit(); + + #Initialize FET and set baud rate -client=GoodFETMAXUSBMass(); +client=GoodFETMAXUSBMassFile(); client.serInit() +client.openImage(sys.argv[1]); + client.MAXUSBsetup(); client.massinit(); diff --git a/firmware/apps/radios/ccspi.c b/firmware/apps/radios/ccspi.c index 7c72ddd..9c6b09c 100644 --- a/firmware/apps/radios/ccspi.c +++ b/firmware/apps/radios/ccspi.c @@ -249,9 +249,9 @@ void ccspi_handle_fn( uint8_t const app, SETSS; */ - //Only should transmit length of one more than the reported - // length of the frame, which holds the length byte: - txdata(app,verb,i&0x7F); + //Only should transmit a packet if the length is legal. + if(cmddata[0]&0x80) i=0; + txdata(app,verb,i); }else{ //No packet. txdata(app,verb,0);