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