Class: HardsploitAPI_SPI

Inherits:
Object
  • Object
show all
Defined in:
lib/HardsploitAPI/Modules/SPI/HardsploitAPI_SPI.rb

Instance Method Summary collapse

Constructor Details

#initialize(speed:, mode:) ⇒ HardsploitAPI_SPI

Returns a new instance of HardsploitAPI_SPI.



13
14
15
16
17
18
19
# File 'lib/HardsploitAPI/Modules/SPI/HardsploitAPI_SPI.rb', line 13

def initialize(speed:,mode:)
  #to be sure the singleton was initialize
  HardsploitAPI.instance.connect
  self.speed=speed
  self.mode=mode
  @pulse = 0
end

Instance Method Details

#modeObject



46
47
48
# File 'lib/HardsploitAPI/Modules/SPI/HardsploitAPI_SPI.rb', line 46

def mode
  return @mode
end

#mode=(mode) ⇒ Object



50
51
52
53
54
55
56
# File 'lib/HardsploitAPI/Modules/SPI/HardsploitAPI_SPI.rb', line 50

def mode=(mode)
  if ( mode < 0 ) or ( mode > 3 ) then
    raise HardsploitAPI::ERROR::SPIWrongMode
  else
    @mode = mode
  end
end

#pulseObject



21
22
23
# File 'lib/HardsploitAPI/Modules/SPI/HardsploitAPI_SPI.rb', line 21

def pulse
  return @pulse
end

#pulse=(pulse) ⇒ Object



25
26
27
28
29
30
31
32
# File 'lib/HardsploitAPI/Modules/SPI/HardsploitAPI_SPI.rb', line 25

def pulse=(pulse)
  if (pulse == 0) or (pulse == 1) then
    @pulse = pulse
    spi_SetSettings #Send an Empty array to validate the value of pulse
  else
    raise HardsploitAPI::ERROR::SPIWrongPulse
  end
end

#speedObject



34
35
36
# File 'lib/HardsploitAPI/Modules/SPI/HardsploitAPI_SPI.rb', line 34

def speed
  return @speed
end

#speed=(speed) ⇒ Object



38
39
40
41
42
43
44
# File 'lib/HardsploitAPI/Modules/SPI/HardsploitAPI_SPI.rb', line 38

def speed=(speed)
  if (speed <=2) or (speed >256) then
    raise HardsploitAPI::ERROR::SPIWrongSpeed
  else
    @speed = speed
  end
end

#spi_Generic_Dump(readSpiCommand:, startAddress:, stopAddress:, sizeMax:) ⇒ Object

Spi generic dump

  • readSpiCommand

    The read command

  • startAddress

    Start address (included)

  • stopAddress

    Stop address (included)

  • sizeMax

    Size max of memory (important to calculate automaticly the number of byte to set address)



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/HardsploitAPI/Modules/SPI/HardsploitAPI_SPI.rb', line 206

def spi_Generic_Dump (readSpiCommand:,startAddress:,stopAddress:,sizeMax:)
    if (( startAddress < 0 )  or ( startAddress > sizeMax - 1 )) then
      raise TypeError, "Start address can't be negative and not more than size max - 1"
    end

    if (( stopAddress < 0 )  or ( stopAddress > ( sizeMax - 1 ))) then
      raise TypeError, "Stop address can't be negative and not more than size max-1 because start at 0"
    end

    if ( stopAddress < startAddress ) then
      raise TypeError, "Stop address need to be greater than start address"
    end

    numberOfByteAddress = ((( Math.log( sizeMax - 1, 2 )).floor + 1) / 8.0 ).ceil
    if numberOfByteAddress > 4 then
      raise TypeError, "Size max must be less than 2^32 about 4Gb"
    end

    if numberOfByteAddress <= 0 then
      raise TypeError, "There is an issue with calculating of number of byte needed"
    end

    #Start time
    startTime = Time.now
    packet_size = 4000 - numberOfByteAddress - 1
    number_complet_packet = (( stopAddress - startAddress + 1 ) / packet_size ).floor
    size_last_packet =  ( stopAddress - startAddress + 1 ) % packet_size

    #SEND the first complete trame
    for i in 0..number_complet_packet - 1 do
      packet = generate_spi_read_command(
        numberOfByteAddress:  numberOfByteAddress,
        readSpiCommand:       readSpiCommand,
        startAddress:         i * packet_size + startAddress,
        size:                 packet_size
      )
      begin
        temp = spi_Interact( payload: packet )
      rescue
        raise HardsploitAPI::ERROR::USB_ERROR
      end
      #Remove header, result of read command and numberOfByte Address too
      #puts "receive real size #{temp.size}"
      HardsploitAPI.instance.consoleData temp.drop( numberOfByteAddress + 1 )
      HardsploitAPI.instance.consoleProgress(
        percent:    100 * ( i + 1 ) / ( number_complet_packet + ( size_last_packet.zero? ? 0 : 1 )),
        startTime:  startTime,
        endTime:    Time.new
      )
    end

  if( size_last_packet > 0 ) then
    packet = generate_spi_read_command(
      numberOfByteAddress: numberOfByteAddress,
      readSpiCommand:      readSpiCommand,
      startAddress:        number_complet_packet * packet_size + startAddress,
      size:                  size_last_packet
    )
    temp = spi_Interact( payload: packet )
    #Remove header, result of read command and numberOfByte Address too
    HardsploitAPI.instance.consoleData temp.drop( numberOfByteAddress + 1 )
    begin
      HardsploitAPI.instance.consoleProgress(
        percent:   100,
        startTime: startTime,
        endTime:   Time.now
      )
    rescue
      raise HardsploitAPI::ERROR::USB_ERROR
    end
  end
    delta = Time.now - startTime
    HardsploitAPI.instance.consoleSpeed "Write in #{delta.round(4)} sec"
end

#spi_Generic_Import(startAddress:, pageSize:, memorySize:, dataFile:, writeSpiCommand:, writePageLatency:, enableWriteSpiCommand:, clearSpiCommand:, clearChipTime:, isFLASH:) ⇒ Object

Spi generic Import

  • writeSpiCommand

    The write command most of the time 0x02

  • startAddress

    Start address (included)

  • pageSize

    Size of page

  • memorySize

    Size max of memory in byte (important, to calculate automatically the number of byte to set address)

  • saveFile

    File contain data

  • writePageLatency

    Time to wait after each pages written

  • enableWriteSpiCommand

    Enable write commad most of the time 0x06

  • clearSpiCommand

    Bulk erase command most of the time 0x60 chip eraseTime

  • clearChipTime

    Time to erase entire the memory (bulk erase) in case of flash memory, 240 seconds for a 512Mb spansion memory and 13 seconds for a 16Mb Micron memory, see the datasheet

  • isFLASH

    True if it is a Flash memory (add clear content)



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/HardsploitAPI/Modules/SPI/HardsploitAPI_SPI.rb', line 112

def spi_Generic_Import (startAddress:,pageSize:,memorySize:,dataFile:,writeSpiCommand:,writePageLatency:,enableWriteSpiCommand:,clearSpiCommand:,clearChipTime:,isFLASH:)
    #Start time
    startTime = Time.now

    file =  File.open(dataFile, 'rb')
    sizeFile = file.size

    if (( startAddress < 0 )  or ( startAddress > memorySize - 1 )) then
      raise Error::WrongStartAddress
    end

    if (( pageSize <= 0 ) and ( pageSize > 2048 )) then
      raise TypeError, "pageSize need to be greater than 0 and less than 2048"
    end

    numberOfByteAddress = ((( Math.log( memorySize - 1, 2 )).floor + 1 ) / 8.0 ).ceil
    if numberOfByteAddress > 4 then
      raise TypeError, "Size max must be less than 2^32 about 4Gb"
    end

    if numberOfByteAddress <= 0 then
      raise TypeError, "There is an issue with calculating of number of byte needed"
    end

    #if flash memory we need to erase it before and wait enought
    #time (erase cycle time in datasheet) or polling status register
    if isFLASH then
      spi_Interact(payload: [clearSpiCommand])
      sleep(clearChipTime)
    end

    startTime = Time.now
    packet_size = pageSize
    number_complet_packet = (sizeFile / packet_size).floor
    size_last_packet =  sizeFile % packet_size

    #SEND the first complete trame
    for i in 0..number_complet_packet - 1 do
      #Enable write latch
      spi_Interact(payload:  [enableWriteSpiCommand])
      packet = generate_spi_write_command(
        numberOfByteAddress:  numberOfByteAddress,
        writeSpiCommand:      writeSpiCommand,
        startAddress:         i * packet_size + startAddress,
        data:                 file.read(packet_size).unpack("C*")
      )

      temp = spi_Interact( payload:  packet )
      #Remove header, result of read command and numberOfByte Address too
      unless packet.size == temp.size then
        raise HardsploitAPI::SpiError
      end

      HardsploitAPI.instance.consoleProgress(
        percent:  100 * ( i + 1 ) / ( number_complet_packet + ( size_last_packet.zero? ? 0 : 1 ) ),
        startTime:startTime,
        endTime:  Time.new
      )
      #if too many error when write increase because we need to wait to write a full page
      sleep(writePageLatency)
    end

    if( size_last_packet > 0 )then
      #Enable write latch
      spi_Interact( payload: [enableWriteSpiCommand] )
      packet = generate_spi_write_command(
        numberOfByteAddress:  numberOfByteAddress,
        writeSpiCommand:      writeSpiCommand,
        startAddress:         number_complet_packet * packet_size + startAddress,
        data:                 file.read(size_last_packet).unpack("C*")
      )
      temp = spi_Interact( payload:  packet )
      #Remove header, result of write command and numberOfByte Address too
      unless packet.size == temp.size then
        raise HardsploitAPI::SpiError
      end

      #Send 100% in case of last packet
      HardsploitAPI.instance.consoleProgress(
        percent:    100,
        startTime:  startTime,
        endTime:    Time.now
      )
    end
    delta = Time.now - startTime
    HardsploitAPI.instance.consoleSpeed "Write in #{delta.round(4)} sec"
end

#spi_Interact(payload:) ⇒ Object

SPI interact

  • payload

    Byte array want to send

  • Return SPI data received



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/HardsploitAPI/Modules/SPI/HardsploitAPI_SPI.rb', line 79

def spi_Interact(payload:)
  if ( payload.size > 4000 ) then
    raise SPIWrongPayloadSize
  end

  packet = Array.new
  packet.push 0  #low byte of lenght of trame refresh automaticly before send by usb
  packet.push 0  #high byte of lenght of trame refresh automaticly before send by usb
  packet.push HardsploitAPI.lowByte(word:HardsploitAPI::USB_COMMAND::FPGA_COMMAND)
  packet.push HardsploitAPI.highByte(word:HardsploitAPI::USB_COMMAND::FPGA_COMMAND)

  packet.push 0x50 #Command RAW COMMUNICATION TO FPGA FIFO
  packet.push (( @pulse & 1 ) << 2 ) || ( @mode & 3 ) #Add mode and the value of pin pulse
  packet.push @speed #Add speed
  packet.concat payload #Add data
  #puts "Payload : #{payload}"

  #remove header (4 bytes   2 for size 2 for type of command)
  return HardsploitAPI.instance.sendAndReceiveDATA(packet, 1000).drop(4)
end

#spi_SetSettingsObject



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/HardsploitAPI/Modules/SPI/HardsploitAPI_SPI.rb', line 58

def spi_SetSettings()
  packet = Array.new
  packet.push 0  #low byte of lenght of trame refresh automaticly before send by usb
  packet.push 0  #high byte of lenght of trame refresh automaticly before send by usb
  packet.push HardsploitAPI.lowByte(word:HardsploitAPI::USB_COMMAND::FPGA_COMMAND)
  packet.push HardsploitAPI.highByte(word:HardsploitAPI::USB_COMMAND::FPGA_COMMAND)

  packet.push 0x50 #Command RAW COMMUNICATION TO FPGA FIFO

  packet.push (( @pulse & 1 ) << 2 ) || ( @mode & 3 ) #Add mode and the value of pin pulse
  packet.push @speed #Add speed
  begin
    HardsploitAPI.instance.sendPacket packet
    rescue
    raise HardsploitAPI::ERROR::USB_ERROR
  end
end