Class: HardsploitAPI

Inherits:
Object
  • Object
show all
Includes:
USB, USB_COMMAND, USB_STATE
Defined in:
lib/HardsploitAPI/HardsploitAPI_I2C.rb,
lib/HardsploitAPI/HardsploitAPI.rb,
lib/HardsploitAPI/HardsploitAPI_SPI.rb,
lib/HardsploitAPI/HardsploitAPI_ERROR.rb,
lib/HardsploitAPI/SWD/HardsploitAPI_SWD.rb,
lib/HardsploitAPI/HardsploitAPI_CONSTANT.rb,
lib/HardsploitAPI/HardsploitAPI_FIRMWARE.rb,
lib/HardsploitAPI/HardsploitAPI_PROGRESS.rb,
lib/HardsploitAPI/HardsploitAPI_TEST_INTERACT.rb,
lib/HardsploitAPI/HardsploitAPI_USB_COMMUNICATION.rb,
lib/HardsploitAPI/HardsploitAPI_NO_MUX_PARALLELE_MEMORY.rb

Overview

Hardsploit API - By Opale Security
www.opale-security.com || www.hardsploit.io
License: GNU General Public License v3
License URI: http://www.gnu.org/licenses/gpl.txt

Defined Under Namespace

Modules: Error, I2C, USB, USB_COMMAND, USB_STATE, VERSION Classes: HardsploitProgress

Constant Summary

Constants included from USB_COMMAND

USB_COMMAND::ERASE_FIRMWARE, USB_COMMAND::FPGA_COMMAND, USB_COMMAND::FPGA_DATA, USB_COMMAND::GET_SERIAL_NUMBER, USB_COMMAND::GET_VERSION_NUMBER, USB_COMMAND::GREEN_LED, USB_COMMAND::LOOPBACK, USB_COMMAND::READ_ID_FLASH, USB_COMMAND::READ_PAGE_FIRMWARE, USB_COMMAND::RED_LED, USB_COMMAND::START_FPGA, USB_COMMAND::START_FPGA_DATA, USB_COMMAND::STOP_FPGA, USB_COMMAND::STOP_FPGA_DATA, USB_COMMAND::VCP_ERROR, USB_COMMAND::WRITE_PAGE_FIRMWARE

Constants included from USB_STATE

USB_STATE::BUSY, USB_STATE::CONNECTED, USB_STATE::ERROR_SEND, USB_STATE::NOT_CONNECTED, USB_STATE::PACKET_IS_TOO_LARGE, USB_STATE::SUCCESSFUL_RECEIVE, USB_STATE::SUCCESSFUL_SEND, USB_STATE::TIMEOUT_RECEIVE, USB_STATE::UNKNOWN_CONNECTED, USB_STATE::UNKNOWN_STATE

Constants included from USB

USB::IN_ENDPOINT, USB::OUT_ENDPOINT, USB::USB_TRAME_SIZE

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ HardsploitAPI

  • callbackSpeedOfTransfert

    callback to get back information about speed



36
37
38
39
40
41
42
43
44
45
46
# File 'lib/HardsploitAPI/HardsploitAPI.rb', line 36

def initialize(*args)
	parametters = HardsploitAPI.checkParametters(["callbackData","callbackInfo","callbackProgress","callbackSpeedOfTransfert"],args)
	@callbackData = parametters[:callbackData]
	@callbackInfo = parametters[:callbackInfo]
	@callbackProgress = parametters[:callbackProgress]
	@callbackSpeedOfTransfert = parametters[:callbackSpeedOfTransfert]

	@packet_send = Array.new
	@usb = LIBUSB::Context.new
	@device = nil
end

Instance Attribute Details

#debugPortObject

Returns the value of attribute debugPort.



12
13
14
# File 'lib/HardsploitAPI/SWD/HardsploitAPI_SWD.rb', line 12

def debugPort
  @debugPort
end

#devObject

Returns the value of attribute dev.



25
26
27
# File 'lib/HardsploitAPI/HardsploitAPI.rb', line 25

def dev
  @dev
end

#stm32Object

Returns the value of attribute stm32.



13
14
15
# File 'lib/HardsploitAPI/SWD/HardsploitAPI_SWD.rb', line 13

def stm32
  @stm32
end

Class Method Details

.BytesToInt(*args) ⇒ Object

Obtain high byte of a word

  • lByte

    low byte

  • hByte

    high byte

Return 16 bits integer concatenate with low and high bytes



70
71
72
73
74
75
# File 'lib/HardsploitAPI/HardsploitAPI_USB_COMMUNICATION.rb', line 70

def self.BytesToInt(*args)
	parametters = HardsploitAPI.checkParametters(["lByte","hByte"],args)
	lByte = parametters[:lByte]
	hByte = parametters[:hByte]
	return (lByte + (hByte<<8))
end

.checkParametters(arr_parametters, *args) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/HardsploitAPI/HardsploitAPI.rb', line 96

def self.checkParametters(arr_parametters,*args)
	params = Hash.new
	if args[0][0].class == Hash then
		hash_args = args[0][0]
			arr_parametters.each  do |param|
				if hash_args[param.to_sym] == nil then
						raise "Wrong parametters, you need to specify #{param.to_sym}"
				else
						params[param.to_sym] = hash_args[param.to_sym]
				end
			end
	else
		if args[0].length == arr_parametters.size then
				args[0].each_with_index do |value,key|
					params[arr_parametters[key].to_sym] = value
				end
		else
			raise "Error : method need #{arr_parametters.size} parametters"
		end
	end
	return params
end

.highByte(*args) ⇒ Object

Obtain high byte of a word

  • word

    16 bit word

Return high byte of the word



60
61
62
63
64
# File 'lib/HardsploitAPI/HardsploitAPI_USB_COMMUNICATION.rb', line 60

def self.highByte(*args)
	parametters = HardsploitAPI.checkParametters(["word"],args)
	word = parametters[:word]
	return  (word & 0xFF00) >> 8
end

.lowByte(*args) ⇒ Object

Obtain low byte of a word

  • word

    16 bit word

Return low byte of the word



51
52
53
54
55
# File 'lib/HardsploitAPI/HardsploitAPI_USB_COMMUNICATION.rb', line 51

def self.lowByte(*args)
	parametters = HardsploitAPI.checkParametters(["word"],args)
	word = parametters[:word]
	return  word & 0xFF
end

.reverseBit(byte) ⇒ Object



92
93
94
# File 'lib/HardsploitAPI/HardsploitAPI.rb', line 92

def self.reverseBit(byte)
	return byte.to_s(2).rjust(8, "0").reverse.to_i(2)
end

Instance Method Details

#calcOpcode(ap, register, read) ⇒ Object



239
240
241
242
243
244
245
246
247
248
# File 'lib/HardsploitAPI/SWD/HardsploitAPI_SWD.rb', line 239

def calcOpcode (ap, register, read)
		opcode = 0x00
		(ap ? opcode |= 0x40 : opcode |= 0x00)
		(read ? opcode |= 0x20 : opcode |= 0x00)
		opcode = opcode | ((register & 0x01) << 4) | ((register & 0x02) << 2) #Addr AP DP  bit 2..3
		opcode = opcode | (((opcode & 0x78).to_s(2).count('1').odd? ? 1 : 0) << 2)  #0x78 mask to take only read ap and register to process parity bit
		opcode = opcode | 0x81 #Start and Park Bit
		#puts "OpCode #{opcode.to_s(16)}"
		return opcode
end

#clearStatusRegisterOfMemoryObject



60
61
62
63
# File 'lib/HardsploitAPI/HardsploitAPI_NO_MUX_PARALLELE_MEMORY.rb', line 60

def clearStatusRegisterOfMemory
	#Clear Statut register
	write_command_Memory_WithoutMultiplexing(0x000000,0x50)
end

#connectObject

Connect board and get an instance to work with Return USB_STATE



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/HardsploitAPI/HardsploitAPI_USB_COMMUNICATION.rb', line 31

def connect
	@device = @usb.devices(:idVendor => 0x0483, :idProduct => 0xFFFF)
	if @device.size == 0   then
			@device_version = ""
			return USB_STATE::NOT_CONNECTED
		else
		@dev = @device.first.open
			if RUBY_PLATFORM=~/linux/i && @dev.kernel_driver_active?(0)
				@dev.detach_kernel_driver(0)
			end
		@dev.claim_interface(0)
		Thread.abort_on_exception = true
		setStatutLed(USB_COMMAND::GREEN_LED,true);
		return USB_STATE::CONNECTED
	end
end

#consoleData(value) ⇒ Object



122
123
124
# File 'lib/HardsploitAPI/HardsploitAPI.rb', line 122

def consoleData(value)
	@callbackData.call(value)
end

#consoleInfo(value) ⇒ Object



128
129
130
# File 'lib/HardsploitAPI/HardsploitAPI.rb', line 128

def consoleInfo(value)
	@callbackInfo.call(value)
end

#consoleProgress(percent:, startTime:, endTime:) ⇒ Object



119
120
121
# File 'lib/HardsploitAPI/HardsploitAPI.rb', line 119

def consoleProgress(percent:,startTime:,endTime:)
	@callbackProgress.call(percent:percent,startTime:startTime,endTime:endTime)
end

#consoleSpeed(value) ⇒ Object



125
126
127
# File 'lib/HardsploitAPI/HardsploitAPI.rb', line 125

def consoleSpeed(value)
	@callbackSpeedOfTransfert.call(value)
end

#dumpFlash(path) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/HardsploitAPI/SWD/HardsploitAPI_SWD.rb', line 63

def dumpFlash(path)
	resetSWD()
	#DUMP FLASH MEMORY TO A FILE
	@stm32.halt
  flash_size = (stm32.ahb.readWord(0x1ffff7e0) & 0xFFFF)
	puts "Flash size : #{(flash_size) } KB"
	puts "Dump flash"
  time = Time.new
	data = @stm32.flashRead(0x08000000,(flash_size*1024))
	time = Time.new - time
	puts "DUMP #{((data.size/time)).round(2)}Bytes/s #{(data.size)}Bytes in  #{time.round(4)} s"
	IO.binwrite(path, data.pack('C*'))
	puts "Finish dump"
end

#eraseBlockMemory(blockAddress) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/HardsploitAPI/HardsploitAPI_NO_MUX_PARALLELE_MEMORY.rb', line 35

def eraseBlockMemory(blockAddress)
	#Read Five Word
	write_command_Memory_WithoutMultiplexing(blockAddress,0x0020)   #Block erase command
	statut = write_command_Memory_WithoutMultiplexing(blockAddress,0x00D0)   #Confirm Block erase command

	 timeout = 10
	# while (statut != 128 ) && (timeout >= 0)
	#
	# 	puts "#{statut}  #{timeout}"
	# 		statut = readByteFromMemory(0) #read statut register
	# 	sleep(100)
	# 	if timeout == 0 then
	# 		return statut
	# 	else
	# 		timeout = timeout-1
	# 	end
	# end
	for ty in 0..4
		puts readByteFromMemory(0)
	end

	puts "Return timeout"
	return statut
end

#eraseFlashObject



58
59
60
61
# File 'lib/HardsploitAPI/SWD/HardsploitAPI_SWD.rb', line 58

def eraseFlash
	puts 'Erase'
	stm32.flashErase()
end

#getVersionNumberObject

Obtaint the version number of the board



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/HardsploitAPI/HardsploitAPI.rb', line 75

def getVersionNumber
	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(USB_COMMAND::GET_VERSION_NUMBER)
	packet.push HardsploitAPI.highByte(USB_COMMAND::GET_VERSION_NUMBER)

	#remove header
	version_number = sendAndReceiveDATA(packet,1000).drop(4)
	if version_number.size < 20 then #if size more thant 20 char error when reading version number
			return version_number.pack('U*')
	else
		return "BAD VERSION NUMBER"
	end

end

#i2c_Generic_Dump(*args) ⇒ Object

  • startAddress

    Start address (included)

  • stopAddress

    Stop address (included)

  • sizeMax

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



98
99
100
101
102
103
104
105
106
107
108
109
110
111
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
# File 'lib/HardsploitAPI/HardsploitAPI_I2C.rb', line 98

def i2c_Generic_Dump (*args)
		parametters = HardsploitAPI.checkParametters(["speed","i2cBaseAddress","startAddress","stopAddress","sizeMax"],args)
		speed = parametters[:speed]
		i2cBaseAddress = parametters[:i2cBaseAddress]
		startAddress = parametters[:startAddress]
		stopAddress = parametters[:stopAddress]
		sizeMax = parametters[: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
		startTime = Time.now
		packet_size = 2000 - 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_i2c_read_command i2cBaseAddress,numberOfByteAddress+startAddress,i*packet_size,packet_size
			temp = i2c_Interact(speed,packet)
			case temp
				when HardsploitAPI::USB_STATE::PACKET_IS_TOO_LARGE
					puts "PACKET_IS_TOO_LARGE max: #{HardsploitAPI::USB::USB_TRAME_SIZE}"
				when HardsploitAPI::USB_STATE::ERROR_SEND
					puts "ERROR_SEND\n"
				when HardsploitAPI::USB_STATE::BUSY
					puts "BUSY"
				when HardsploitAPI::USB_STATE::TIMEOUT_RECEIVE
					puts "TIMEOUT_RECEIVE\n"
				else
					#Remove header, result of read command and numberOfByte Address too
					consoleData ( process_dump_i2c_result( temp ) )
			end

			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_i2c_read_command i2cBaseAddress,numberOfByteAddress,number_complet_packet*packet_size+startAddress,size_last_packet
		temp = i2c_Interact(speed,packet)
		case temp
			when HardsploitAPI::USB_STATE::PACKET_IS_TOO_LARGE
				puts "PACKET_IS_TOO_LARGE max: #{HardsploitAPI::USB::USB_TRAME_SIZE}"
			when HardsploitAPI::USB_STATE::ERROR_SEND
				puts "ERROR_SEND\n"
			when HardsploitAPI::USB_STATE::BUSY
				puts "BUSY"
			when HardsploitAPI::USB_STATE::TIMEOUT_RECEIVE
				puts "TIMEOUT_RECEIVE\n"
			else
				#Remove header, result of read command and numberOfByte Address too
				consoleData ( process_dump_i2c_result ( temp ) )
		 end
		 consoleProgress(percent:100,startTime:startTime,endTime:Time.new)
	end

	delta = Time.now - startTime
	consoleSpeed "Write in #{delta.round(4)} sec"
end

#i2c_Generic_Import(*args) ⇒ Object

For the moment only with EEPROM (not need to erase or activate write)



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
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
# File 'lib/HardsploitAPI/HardsploitAPI_I2C.rb', line 175

def i2c_Generic_Import (*args)
	parametters = HardsploitAPI.checkParametters(["speed","i2cBaseAddress","startAddress","pageSize","memorySize","dataFile","writePageLatency"],args)
	speed = parametters[:speed]
	i2cBaseAddress = parametters[:i2cBaseAddress]
	startAddress = parametters[:startAddress]
	pageSize = parametters[:pageSize]
	memorySize = parametters[:memorySize]
	dataFile = parametters[:dataFile]
	writePageLatency = parametters[:writePageLatency]

	startTime = Time.now
	begin
		file =	File.open(dataFile, 'rb')
		sizeFile = file.size
	rescue Exception => e
		raise Error::FileIssue, e.message
	end

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

	if ((pageSize <= 0) and (pageSize >1024)) then
		raise TypeError, "pageSize need to be greater than 0 and less than 1024"
	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

	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
		packet = generate_i2c_write_command i2cBaseAddress,numberOfByteAddress,i*packet_size,file.read(packet_size).unpack("C*")
		temp = i2c_Interact(speed,packet)
		case temp
			when HardsploitAPI::USB_STATE::PACKET_IS_TOO_LARGE
				puts "PACKET_IS_TOO_LARGE max: #{HardsploitAPI::USB::USB_TRAME_SIZE}"
			when HardsploitAPI::USB_STATE::ERROR_SEND
				puts "ERROR_SEND\n"
			when HardsploitAPI::USB_STATE::BUSY
				puts "BUSY"
			when HardsploitAPI::USB_STATE::TIMEOUT_RECEIVE
				puts "TIMEOUT_RECEIVE\n"
			else
				#Remove header, result of read command and numberOfByte Address too
				process_import_i2c_result( temp )
		end

		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
		packet = generate_i2c_write_command(i2cBaseAddress,numberOfByteAddress,number_complet_packet*packet_size+startAddress,file.read(size_last_packet).unpack("C*"))
		temp = i2c_Interact(speed,packet)
		case temp
			when HardsploitAPI::USB_STATE::PACKET_IS_TOO_LARGE
				puts "PACKET_IS_TOO_LARGE max: #{HardsploitAPI::USB::USB_TRAME_SIZE}"
			when HardsploitAPI::USB_STATE::ERROR_SEND
				puts "ERROR_SEND\n"
			when HardsploitAPI::USB_STATE::BUSY
				puts "BUSY"
			when HardsploitAPI::USB_STATE::TIMEOUT_RECEIVE
				puts "TIMEOUT_RECEIVE\n"
			else
				#Remove header, result of read command and numberOfByte Address too
				process_import_i2c_result ( temp )
		end
			consoleProgress(percent:100,startTime:startTime,endTime:Time.new)
	end

	delta = Time.now - startTime
	consoleSpeed "Write in #{delta.round(4)} sec"
end

#i2c_Interact(*args) ⇒ Object

  • payload

    payload to send



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/HardsploitAPI/HardsploitAPI_I2C.rb', line 14

def i2c_Interact(*args)
	parametters = HardsploitAPI.checkParametters(["speed","payload"],args)
	speed = parametters[:speed]
	payload = parametters[:payload]

	if (speed < 0)  and (speed >3) then
		raise TypeError, 'Speed must be between 0 and 3'
	end

	if (payload.size > 4000) then
		raise TypeError, 'Size of the data need to be less than 4000'
	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(USB_COMMAND::FPGA_COMMAND)
	packet.push HardsploitAPI.highByte(USB_COMMAND::FPGA_COMMAND)

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

	packet.push speed #Add speed
	packet.concat payload #Add data

	sendPacket packet

	tmp= receiveDATA(2000)
	case tmp
		when HardsploitAPI::USB_STATE::BUSY
			return USB_STATE::BUSY
		when HardsploitAPI::USB_STATE::TIMEOUT_RECEIVE
			return USB_STATE::TIMEOUT_RECEIVE
		else
			#remove header (4 bytes   2 for size 2 for type of command)
			return tmp.bytes.drop(4)
	end
end

#i2c_Scan(*args) ⇒ Object

  • Return An array 256 value for each addresse if 0 not present if 1 present



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/HardsploitAPI/HardsploitAPI_I2C.rb', line 55

def i2c_Scan(*args)
	parametters = HardsploitAPI.checkParametters(["speed"],args)
	speed = parametters[:speed]

	if (speed < 0)  and (speed >3) then
		raise TypeError, 'Speed must be between 0 and 3'
	end

	array_i2c_scan = Array.new
	result_scan = Array.new
	return_scan = Array.new

	#we want scan just read address it is a partial scan (fastest)
	for i in (1..255).step(2) do
		array_i2c_scan.push HardsploitAPI.lowByte(1)  #Count Low  Byte
		array_i2c_scan.push HardsploitAPI.highByte(1)   #Count High Byte
		array_i2c_scan.push i
	end

	result_scan = i2c_Interact(speed,array_i2c_scan)
	if result_scan.size != 256 then
		raise TypeError, "FPGA send a wrong I2C scan result, try again , check power jumper, fix wiring , power on ? (reboot the board if needed)"
	end

	for i in (0..result_scan.size-1).step(2) do
		#Check if ACK_ERROR
		if result_scan[i] == 1 then
			return_scan.push 1 #For write
			return_scan.push 1 #For read
		else
			return_scan.push 0 #For write
			return_scan.push 0 #For read
		end
	end
	return return_scan
end

#obtainCodesObject



24
25
26
27
28
29
30
31
32
33
# File 'lib/HardsploitAPI/SWD/HardsploitAPI_SWD.rb', line 24

def obtainCodes
	resetSWD()
	code = {
	  :DebugPortId => debugPort.idcode(),
	  :AccessPortId => stm32.ahb.idcode(),
	  :CpuId => stm32.ahb.readWord(0xE000ED00),
		:DeviceId => stm32.ahb.readWord(0x1FFFF7E8)
	}
	return code
end

#read_Memory_WithoutMultiplexing(*args) ⇒ Object

Read parallele memory in asynchronous mode (blocking function) but callBack data is used to receive packet

  • addressStart

    32 bits address

  • addressStop

    32 bits address

  • bits8_or_bits16_DataSize

    0 for 8 bits operation & 1 for 16 bits operation

  • latency

    latency in ns range 7ns to 1600ns=1,6ms

Return USB_STATE End with TIMEOUT_RECEIVE but need to check if received the right number of bytes to ensure all is correct



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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/HardsploitAPI/HardsploitAPI_NO_MUX_PARALLELE_MEMORY.rb', line 152

def read_Memory_WithoutMultiplexing(*args)
parametters = HardsploitAPI.checkParametters(["addressStart","addressStop","bits8_or_bits16_DataSize","latency"],args)
 	addressStart = parametters[:addressStart]
addressStop = parametters[:addressStop]
bits8_or_bits16_DataSize = parametters[:bits8_or_bits16_DataSize]
latency = parametters[:latency]


numberOfByteReaded = 0
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(USB_COMMAND::FPGA_COMMAND)
packet.push HardsploitAPI.highByte(USB_COMMAND::FPGA_COMMAND)

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

#Chek if 8bits or 16 bits
if bits8_or_bits16_DataSize == true then
	packet.push 1
else
	packet.push	0
end

#Check latency value
if ((latency >= 7)  and (latency <= 1600)) then
	packet.push (latency/6.66).floor
else
	raise TypeError, 'Latency value must be from 7 to 1695'
end

#Check address
if (addressStop <= addressStart  ) then
	raise TypeError, 'Stop address is less than start address'
end

packet.push  ((addressStart & 0xFF000000) >> 24 ) #AddStart3
packet.push  ((addressStart & 0x00FF0000) >> 16 ) #AddStart2
packet.push  ((addressStart & 0x0000FF00) >> 8 )  #AddStart1
packet.push  ((addressStart & 0x000000FF) >> 0)   #AddStart0

packet.push 0x10 #Memory read command
packet.push  ((addressStop & 0xFF000000) >> 24 ) #AddStart3
packet.push  ((addressStop & 0x00FF0000) >> 16 ) #AddStop2
packet.push  ((addressStop & 0x0000FF00) >> 8 )  #AddStop1
packet.push  ((addressStop & 0x000000FF) >> 0)   #AddStop0

sendPacket(packet)

if bits8_or_bits16_DataSize then
	sizeCalculated = (addressStop-addressStart+1)
else
	sizeCalculated = (addressStop-addressStart+1)*2
end

numberOfByteReaded = 0
while true
	tmp= receiveDATA(2000)
	case tmp
		when HardsploitAPI::USB_STATE::BUSY
			raise  "USB_STATE::BUSY"
		when HardsploitAPI::USB_STATE::TIMEOUT_RECEIVE
			raise "Timeout"
		else
			#remove header (4 bytes   2 for size 2 for type of command)
			tmp = tmp.bytes.drop(4)
			numberOfByteReaded = numberOfByteReaded + tmp.size
			consoleData(tmp)

			puts "Receive #{numberOfByteReaded} of #{sizeCalculated}"
				if numberOfByteReaded >= sizeCalculated then
			 	#Exit because we received all data
			 	return
			end
		end
	end
end

#readBlockAP(size) ⇒ Object



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/HardsploitAPI/SWD/HardsploitAPI_SWD.rb', line 156

def readBlockAP(size)
	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(HardsploitAPI::USB_COMMAND::FPGA_COMMAND)
	packet.push HardsploitAPI.highByte(HardsploitAPI::USB_COMMAND::FPGA_COMMAND)

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

	packet.push 0xAA #Read mode
	packet.push HardsploitAPI.lowByte(size)
	packet.push HardsploitAPI.highByte(size)

	result = sendAndReceiveDATA(packet,1000)
	 if result.class == Array then
	 		if result.size >= 4   then #Receive read + 4bytes for header
	 			return result.drop(4)
			else
				raise "Receive just Header where is the data ? "
	 		end
	 else # Receive and error
	 		raise "Error during reading  timeout or ACK issue "
	 end
end

#readByteFromMemory(address) ⇒ Object



103
104
105
106
107
108
109
110
111
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
# File 'lib/HardsploitAPI/HardsploitAPI_NO_MUX_PARALLELE_MEMORY.rb', line 103

def readByteFromMemory(address)
	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(USB_COMMAND::FPGA_COMMAND)
	packet.push HardsploitAPI.highByte(USB_COMMAND::FPGA_COMMAND)

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


	#16 bits
	packet.push	0
	packet.push (1500/6.66).floor


	packet.push  ((address & 0xFF000000) >> 24 ) #AddStart3
	packet.push  ((address & 0x00FF0000) >> 16 ) #AddStart2
	packet.push  ((address & 0x0000FF00) >> 8 )  #AddStart1
	packet.push  ((address & 0x000000FF) >> 0)   #AddStart0

	packet.push 0x10 #Memory read command
	packet.push  ((address & 0xFF000000) >> 24 ) #AddStart3
	packet.push  ((address & 0x00FF0000) >> 16 ) #AddStop2
	packet.push  ((address & 0x0000FF00) >> 8 )  #AddStop1
	packet.push  ((address & 0x000000FF) >> 0)   #AddStop0

	result = sendAndReceiveDATA(packet,1000)

	if result == USB_STATE::TIMEOUT_RECEIVE then
		return "TIMEOUT"
	else
		if result.size == 6 then
				return HardsploitAPI.BytesToInt(result[4] , result[5])
		else
			raise "BAD RESPONSE"
		end
	end
end

#readDeviceIdMemoryObject



18
19
20
21
# File 'lib/HardsploitAPI/HardsploitAPI_NO_MUX_PARALLELE_MEMORY.rb', line 18

def readDeviceIdMemory
	write_command_Memory_WithoutMultiplexing(0x00000000,0x90) #ReadDeviceIdentifierCommand
	return readByteFromMemory(0)#Read  0
end

#readManufactuerCodeMemoryObject



13
14
15
16
# File 'lib/HardsploitAPI/HardsploitAPI_NO_MUX_PARALLELE_MEMORY.rb', line 13

def readManufactuerCodeMemory
	write_command_Memory_WithoutMultiplexing(0x00000000,0x90) #ReadDeviceIdentifierCommand
	return readByteFromMemory(1) #Read from 1 to 1 = read 1 byte at 1
end

#readModeObject



30
31
32
33
# File 'lib/HardsploitAPI/HardsploitAPI_NO_MUX_PARALLELE_MEMORY.rb', line 30

def readMode
	#go in read mode
	write_command_Memory_WithoutMultiplexing(0x000000,0x00FF)
end

#readSWD(ap, register) ⇒ Object



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/HardsploitAPI/SWD/HardsploitAPI_SWD.rb', line 181

def readSWD(ap,register)
	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(HardsploitAPI::USB_COMMAND::FPGA_COMMAND)
	packet.push HardsploitAPI.highByte(HardsploitAPI::USB_COMMAND::FPGA_COMMAND)

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

	packet.push 0x11 #Read mode
	packet.push(calcOpcode(ap,register, true)) #Send Request

	result = sendAndReceiveDATA(packet,1000)
	 if result.class == Array then
	 		if result.size == 4 + 4  then #Receive read + 4bytes for header
	 			convert = (result[7]  << 24)  + (result[6]  << 16) + (result[5]  << 8 ) + result[4]
	 			return convert
	 		elsif result.size == 4+1 then #receive ACK
				raise "Read error  ACK : #{result[4]}"
	 		else
	 			raise "Error during reading"
	 		end
	 else # Receive and error
	 	raise "Error during reading  timeout "
	 end
end

#receiveDATA(timeout) ⇒ Object

Wait to receive data

  • timeout

    timeout to read response (ms)

Return USB_STATE or array with response (improve soon with exception)



108
109
110
111
112
113
114
115
116
117
118
# File 'lib/HardsploitAPI/HardsploitAPI_USB_COMMUNICATION.rb', line 108

def receiveDATA(timeout)
	begin
		received_data =  dev.bulk_transfer(:endpoint=>IN_ENDPOINT, :dataIn=>USB::USB_TRAME_SIZE, :timeout=>timeout)
	rescue LIBUSB::ERROR_BUSY
		return USB_STATE::BUSY
	rescue LIBUSB::ERROR_TIMEOUT
		return USB_STATE::TIMEOUT_RECEIVE
	else
		return received_data
	end
end

#resetSWDObject

Return array with 1 byte for ACK Return 32bits integer for data read here is Core ID Raise if error



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
# File 'lib/HardsploitAPI/SWD/HardsploitAPI_SWD.rb', line 212

def resetSWD
	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(HardsploitAPI::USB_COMMAND::FPGA_COMMAND)
	packet.push HardsploitAPI.highByte(HardsploitAPI::USB_COMMAND::FPGA_COMMAND)

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

	packet.push 0x00 #Reset mode

	result = sendAndReceiveDATA(packet,1000)
	if result.class == Array then
			if result.size == 4 + 4  then #Receive read + 4bytes for header
				convert = (result[7]  << 24)  + (result[6]  << 16) + (result[5]  << 8 ) + result[4]
				return convert
			elsif result.size == 4 +1 then #reveice ACK
				raise "ERROR ACK #{result[4]}"
			else
				raise "Error during reading ICCODE result != 4"
			end
	else # Receive and error
		raise "Error during reading ICCODE timeout "
	end
end

#runSWDObject



15
16
17
18
19
20
21
22
# File 'lib/HardsploitAPI/SWD/HardsploitAPI_SWD.rb', line 15

def runSWD
	@debugPort = SWD_DEBUG_PORT.new(self)
	@stm32     = SWD_STM32.new(debugPort)

	resetSWD()
	#  Cortex M4 0x410FC241
	#  Cortex M3 0x411FC231
end

#sendAndReceiveDATA(packet_send, timeout) ⇒ Object

Send data and wait to receive response

  • packet_send

    array of byte

  • timeout

    timeout to read response (ms)

Return USB_STATE or array with response (improve soon with exception)



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/HardsploitAPI/HardsploitAPI_USB_COMMUNICATION.rb', line 82

def sendAndReceiveDATA(packet_send,timeout)
	time = Time.new
	case sendPacket(packet_send)
		when USB_STATE::SUCCESSFUL_SEND
			received_data = receiveDATA(timeout)
			case received_data
				when USB_STATE::BUSY
					return  USB_STATE::BUSY
				when USB_STATE::TIMEOUT_RECEIVE
					return USB_STATE::TIMEOUT_RECEIVE
				else
					consoleSpeed "RECEIVE #{((received_data.bytes.to_a.size/(Time.new-time))).round(2)}Bytes/s  #{(received_data.bytes.to_a.size)}Bytes in  #{(Time.new-time).round(4)} s"
					return received_data.bytes.to_a
			end
		when USB_STATE::PACKET_IS_TOO_LARGE
			return  USB_STATE::PACKET_IS_TOO_LARGE
		when USB_STATE::ERROR_SEND
			return  USB_STATE::ERROR_SEND
		else
			return  USB_STATE::UNKNOWN_STATE
	end
end

#sendPacket(packet_send) ⇒ Object

Send USB packet

  • packet

    array with bytes

Return USB_STATE or array with response (improve soon with exception)



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
# File 'lib/HardsploitAPI/HardsploitAPI_USB_COMMUNICATION.rb', line 123

def sendPacket(packet_send)
	if packet_send.size <= 8191 then

		packet_send[0] = HardsploitAPI.lowByte(packet_send.size)
		packet_send[1] = HardsploitAPI.highByte(packet_send.size)

		#if a multiple of packet size add a value to explicit the end of trame
		if packet_send.size % 64 ==0 then
			packet_send.push 0
		end

		number_of_data_send = 0
		time = Benchmark.realtime  do
			number_of_data_send =  @dev.bulk_transfer(:endpoint=>OUT_ENDPOINT, :dataOut=>packet_send.pack('c*'),:timeout=>3000)
		end
		consoleSpeed "SEND #{((number_of_data_send/time)).round(2)}Bytes/s  SEND #{(number_of_data_send)}Bytes in  #{time.round(4)} s"
		if number_of_data_send ==  packet_send.size then
			return USB_STATE::SUCCESSFUL_SEND
		else
			return USB_STATE::ERROR_SEND
		end
	else
		return USB_STATE::PACKET_IS_TOO_LARGE
	end
end

#setStatutLed(*args) ⇒ Object

Set the leds of uC returning nothing

  • led

    USB_COMMAND::GREEN_LED or USB_COMMAND::RED_LED

  • state

    callback to return data for dump function



15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/HardsploitAPI/HardsploitAPI_USB_COMMUNICATION.rb', line 15

def setStatutLed(*args)
	parametters = HardsploitAPI.checkParametters(["led","state"],args)
	led = parametters[:led]
	state = parametters[:state]

	packet_send = Array.new
	packet_send.push 0 #size set before send automatic
	packet_send.push 0	#size set before send automatic
	packet_send.push HardsploitAPI.lowByte(led)
	packet_send.push HardsploitAPI.highByte(led)
	packet_send.push (state ? 1 : 0)
	return sendPacket(packet_send)
end

#setWiringLeds(*args) ⇒ Object

  • value

    64 bits (8x8 Bytes) values to represent led (PortH PortG PortF PortE PortD PortC PortB PortA)



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/HardsploitAPI/HardsploitAPI.rb', line 50

def setWiringLeds(*args)
	parametters = HardsploitAPI.checkParametters(["value"],args)
	val = parametters[:value]

	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(USB_COMMAND::FPGA_COMMAND)
	packet.push HardsploitAPI.highByte(USB_COMMAND::FPGA_COMMAND)

	packet.push 0x23 #Command SPI write wiring led

	packet.push  HardsploitAPI.reverseBit((val & 0x00000000000000FF) >> 0)
	packet.push  HardsploitAPI.reverseBit((val & 0x000000000000FF00) >> 8 )
	packet.push  HardsploitAPI.reverseBit((val & 0x0000000000FF0000) >> 16 )
	packet.push  HardsploitAPI.reverseBit((val & 0x00000000FF000000) >> 24 )
	packet.push  HardsploitAPI.reverseBit((val & 0x000000FF00000000) >> 32 )
	packet.push  HardsploitAPI.reverseBit((val & 0x0000FF0000000000) >> 40 )
	packet.push  HardsploitAPI.reverseBit((val & 0x00FF000000000000) >> 48 )
	packet.push  HardsploitAPI.reverseBit((val & 0xFF00000000000000) >> 56 )

	return  self.sendPacket(packet)
end

#signalHelpingWiring(*args) ⇒ Object

Power on the led for each signal specified Params:

signal

Name of signal you want visual help (set the led)



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/HardsploitAPI/HardsploitAPI_CONSTANT.rb', line 15

def signalHelpingWiring(*args)
	parametters = HardsploitAPI.checkParametters(["signal"],args)
	signal = parametters[:signal]

	wires = Hash.new

	#Parallel module
	wires["A0"] = 0
	wires["A1"] = 1
	wires["A2"] = 2
	wires["A3"] = 3
	wires["A4"] = 4
	wires["A5"] = 5
	wires["A6"] = 6
	wires["A7"] = 7
	wires["A8"] = 8
	wires["A9"] = 9
	wires["A10"] = 10
	wires["A11"] = 11
	wires["A12"] = 12
	wires["A13"] = 13
	wires["A14"] = 14
	wires["A15"] = 15
	wires["A16"] = 16
	wires["A17"] = 17
	wires["A18"] = 18
	wires["A19"] = 19
	wires["A20"] = 20
	wires["A21"] = 21
	wires["A22"] = 22
	wires["A23"] = 23
	wires["A24"] = 24
	wires["A25"] = 25
	wires["A26"] = 26
	wires["A27"] = 27
	wires["A28"] = 28
	wires["A29"] = 29
	wires["A30"] = 30
	wires["A31"] = 31

	wires["D0"] = 32
	wires["D1"] = 33
	wires["D2"] = 34
	wires["D3"] = 35
	wires["D4"] = 36
	wires["D5"] = 37
	wires["D6"] = 38
	wires["D7"] = 39
	wires["D8"] = 40
	wires["D9"] = 41
	wires["D10"] = 42
	wires["D11"] = 43
	wires["D12"] = 44
	wires["D13"] = 45
	wires["D14"] = 46
	wires["D15"] = 47

	wires["RST"] = 48
	wires["CE"] = 49
	wires["OE"] = 50
	wires["WE"] = 51
	wires["CLK"] = 52
	wires["WP"] = 53
	wires["ADV"] = 54


	#SPI module
	wires["CS"] = 0
	wires["SPI_CLK"] = 1
	wires["MOSI"] = 2
	wires["MISO"] = 3

	#I2C module
	wires["I2C_CLK"] = 0
	wires["SDA"] = 1

	begin
		setWiringLeds(2**wires[signal])
	rescue Exception => e
	   raise 'UNKNOWN SIGNAL'
	end
end

#spi_Generic_Dump(*args) ⇒ Object

Spi generic dump

  • mode

    SPI mode 0,1,2,3

  • speed

    Range 1-255 SPI clock = 150Mhz / (2*speed) tested from 3 to 255 (25Mhz to about 0.3Khz)

  • 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)



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
280
281
282
283
284
285
286
287
288
289
290
291
292
293
# File 'lib/HardsploitAPI/HardsploitAPI_SPI.rb', line 208

def spi_Generic_Dump (*args)
		parametters = HardsploitAPI.checkParametters(["mode","speed","readSpiCommand","startAddress","stopAddress","sizeMax"],args)
		mode = parametters[:mode]
		speed = parametters[:speed]
		readSpiCommand = parametters[:readSpiCommand]
		startAddress = parametters[:startAddress]
		stopAddress = parametters[:stopAddress]
		sizeMax = parametters[:sizeMax]


		if (mode < 0)  and (mode >3) then
			raise TypeError, 'Mode must be between 0 and 3'
		end
		if (speed <= 2)  and (speed >256) then
			raise TypeError, 'Speed must be between 3 and 255'
		end

		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,readSpiCommand,i*packet_size+startAddress,packet_size
			temp = spi_Interact(mode,speed,packet)
			case temp
				when HardsploitAPI::USB_STATE::PACKET_IS_TOO_LARGE
					puts "PACKET_IS_TOO_LARGE max: #{HardsploitAPI::USB::USB_TRAME_SIZE}"
				when HardsploitAPI::USB_STATE::ERROR_SEND
					puts "ERROR_SEND\n"
				when HardsploitAPI::USB_STATE::BUSY
					puts "BUSY"
				when HardsploitAPI::USB_STATE::TIMEOUT_RECEIVE
					puts "TIMEOUT_RECEIVE\n"
				else
					#Remove header, result of read command and numberOfByte Address too
					#puts "receive real size #{temp.size}"
					consoleData temp.drop(numberOfByteAddress+1)
			end
			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,readSpiCommand,number_complet_packet*packet_size+startAddress,size_last_packet
			temp = spi_Interact(mode,speed,packet)
			case temp
				when HardsploitAPI::USB_STATE::PACKET_IS_TOO_LARGE
					puts "PACKET_IS_TOO_LARGE max: #{HardsploitAPI::USB::USB_TRAME_SIZE}"
				when HardsploitAPI::USB_STATE::ERROR_SEND
					puts "ERROR_SEND\n"
				when HardsploitAPI::USB_STATE::BUSY
					puts "BUSY"
				when HardsploitAPI::USB_STATE::TIMEOUT_RECEIVE
					puts "TIMEOUT_RECEIVE\n"
				else
					#Remove header, result of read command and numberOfByte Address too
					#puts "receive real size #{temp.size}"
					consoleData temp.drop(numberOfByteAddress+1)
					consoleProgress(percent:100,startTime:startTime,endTime:Time.now)
				end
		end
		delta = Time.now - startTime
		consoleSpeed "Write in #{delta.round(4)} sec"
end

#spi_Generic_Import(*args) ⇒ Object

Spi generic Import

  • mode

    SPI mode 0,1,2,3

  • speed

    Range 1-255 SPI clock = 150Mhz / (2*speed) tested from 3 to 255 (25Mhz to about 0.3Khz)

  • writeSpiCommand

    The write command

  • 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

  • clearSpiCommand

    Bulk erase command

  • 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)



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
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/HardsploitAPI_SPI.rb', line 74

def spi_Generic_Import (*args)
		parametters = HardsploitAPI.checkParametters(["mode","speed","startAddress","pageSize","memorySize","dataFile","writeSpiCommand","writePageLatency","enableWriteSpiCommand","clearSpiCommand","clearChipTime","isFLASH"],args)
		mode = parametters[:mode]
		speed = parametters[:speed]
		startAddress = parametters[:startAddress]
		pageSize = parametters[:pageSize]
		memorySize = parametters[:memorySize]
		dataFile = parametters[:dataFile]
		writePageLatency = parametters[:writePageLatency]

		#most of the time 0x02
		writeSpiCommand = parametters[:writeSpiCommand]
		writeSpiCommand
		#most of the time 0x06
		enableWriteSpiCommand = parametters[:enableWriteSpiCommand]

		#most of the time 0x60  chip eraseTime
		clearSpiCommand = parametters[:clearWriteSpiCommand]

		# in second
		clearChipTime = parametters[:clearChipTime]

		#if flash memory
		isFLASH = parametters[:isEEPROM]

		#Start time
		startTime = Time.now
		begin
			file =	File.open(dataFile, 'rb')
			sizeFile = file.size
		rescue Exception => e
			raise Error::FileIssue, e.message
		end

		if (mode < 0)  and (mode >3) then
			raise TypeError, 'Mode must be between 0 and 3'
		end
		if (speed <= 2)  and (speed >256) then
			raise TypeError, 'Speed must be between 3 and 255'
		end

		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(mode:mode,speed:speed,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(mode:mode,speed:speed,payload:[enableWriteSpiCommand])
			packet = generate_spi_write_command numberOfByteAddress,writeSpiCommand,i*packet_size+startAddress,file.read(packet_size).unpack("C*")
		  temp = spi_Interact(mode,speed,packet)
			case temp
				when HardsploitAPI::USB_STATE::PACKET_IS_TOO_LARGE
					puts "PACKET_IS_TOO_LARGE max: #{HardsploitAPI::USB::USB_TRAME_SIZE}"
				when HardsploitAPI::USB_STATE::ERROR_SEND
					puts "ERROR_SEND\n"
				when HardsploitAPI::USB_STATE::BUSY
					puts "BUSY"
				when HardsploitAPI::USB_STATE::TIMEOUT_RECEIVE
					puts "TIMEOUT_RECEIVE\n"
				else
					#Remove header, result of read command and numberOfByte Address too
					#consoleData temp.drop(numberOfByteAddress+1)
					if packet.size != packet.size then
						raise HardsploitAPI::SpiError
					end
			end

			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(mode:mode,speed:speed,payload:[enableWriteSpiCommand])
			packet = generate_spi_write_command numberOfByteAddress,writeSpiCommand,number_complet_packet*packet_size+startAddress,file.read(size_last_packet).unpack("C*")
			temp = spi_Interact(mode,speed,packet)
			case temp
				when HardsploitAPI::USB_STATE::PACKET_IS_TOO_LARGE
					puts "PACKET_IS_TOO_LARGE max: #{HardsploitAPI::USB::USB_TRAME_SIZE}"
				when HardsploitAPI::USB_STATE::ERROR_SEND
					puts "ERROR_SEND\n"
				when HardsploitAPI::USB_STATE::BUSY
					puts "BUSY"
				when HardsploitAPI::USB_STATE::TIMEOUT_RECEIVE
					puts "TIMEOUT_RECEIVE\n"
				else
					#Remove header, result of write command and numberOfByte Address too
					#consoleData temp.drop(numberOfByteAddress+1)
					if packet.size != packet.size then
						raise HardsploitAPI::SpiError
					end
			end
			#Send 100% in case of last packet
			consoleProgress(percent:100,startTime:startTime,endTime:Time.now)
		end
		delta = Time.now - startTime
		consoleSpeed "Write in #{delta.round(4)} sec"
end

#spi_Interact(*args) ⇒ Object

SPI interact

  • mode

    SPI mode 0,1,2,3

  • speed

    Range 1-255 SPI clock = 150Mhz / (2*speed) tested from 3 to 255 (25Mhz to about 0.3Khz)

  • payload

    Byte array want to send

  • Return SPI data received



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/HardsploitAPI/HardsploitAPI_SPI.rb', line 17

def spi_Interact(*args)
	parametters = HardsploitAPI.checkParametters(["mode","speed","payload"],args)
	mode = parametters[:mode]
	speed = parametters[:speed]
	payload = parametters[:payload]

	if (mode < 0)  and (mode >3) then
		raise TypeError, 'Mode must be between 0 and 3'
	end
	if (speed <= 2)  and (speed >256) then
		raise TypeError, 'Speed must be between 3 and 255'
	end

	if (payload.size > 4000) then
		raise TypeError, 'Size of the data need to be less than 4000'
	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(USB_COMMAND::FPGA_COMMAND)
	packet.push HardsploitAPI.highByte(USB_COMMAND::FPGA_COMMAND)

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

	packet.push mode #Add mode
	packet.push speed #Add speed
	packet.concat payload #Add data

	sendPacket packet

	tmp= receiveDATA(1000)
	case tmp
		when HardsploitAPI::USB_STATE::BUSY
			return USB_STATE::BUSY
		when HardsploitAPI::USB_STATE::TIMEOUT_RECEIVE
			return USB_STATE::TIMEOUT_RECEIVE
		else
			#remove header (4 bytes   2 for size 2 for type of command)
			return tmp.bytes.drop(4)
	end
end

#startFPGAObject



34
35
36
37
38
39
40
41
# File 'lib/HardsploitAPI/HardsploitAPI_FIRMWARE.rb', line 34

def startFPGA
	packet = Array.new
	packet.push HardsploitAPI.lowByte(4)
	packet.push HardsploitAPI.highByte(4)
	packet.push HardsploitAPI.lowByte(USB_COMMAND::START_FPGA)
	packet.push HardsploitAPI.highByte(USB_COMMAND::START_FPGA)
	self.sendPacket(packet)
end

#stopFPGAObject



42
43
44
45
46
47
48
49
# File 'lib/HardsploitAPI/HardsploitAPI_FIRMWARE.rb', line 42

def stopFPGA
	packet = Array.new
	packet.push HardsploitAPI.lowByte(4)
	packet.push HardsploitAPI.highByte(4)
	packet.push HardsploitAPI.lowByte(USB_COMMAND::STOP_FPGA)
	packet.push HardsploitAPI.highByte(USB_COMMAND::STOP_FPGA)
	self.sendPacket(packet)
end

#test_InteractReadObject

return [Integer] 64bits



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/HardsploitAPI/HardsploitAPI_TEST_INTERACT.rb', line 60

def test_InteractRead
	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(USB_COMMAND::FPGA_COMMAND)
	packet.push HardsploitAPI.highByte(USB_COMMAND::FPGA_COMMAND)

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

	#Read mode
	packet.push 0xCD

 packet.push 0xA1
 packet.push 0xA2
 packet.push 0xA3
 packet.push 0xA4
 packet.push 0xA5
 packet.push 0xA6
 packet.push 0xA7
   packet.push 0xA8


	sendPacket packet

	tmp= receiveDATA(1000)
	case tmp
		when HardsploitAPI::USB_STATE::BUSY
			return USB_STATE::BUSY
		when HardsploitAPI::USB_STATE::TIMEOUT_RECEIVE
			puts "TIMEOUT"
		#	raise "test_InteractRead Timeout"
		else
			#remove header (4 bytes   2 for size 2 for type of command)
			tmp = tmp.bytes.drop(4)
			return  0 |  (tmp[0] << 0) |  (tmp[1] << 8) 	 |  (tmp[2] << 16)  |  (tmp[3] << 24) |  (tmp[4] << 32) |  (tmp[5] << 40)  |  (tmp[6] << 48)  | (tmp[7] << 56)
	end
end

#test_InteractWrite(*args) ⇒ Object

Write value of 64 IO for testing purpose

  • value

    64bits to write on all ports

return [Integer] Return the value sent (lookback) (64bits)



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/HardsploitAPI/HardsploitAPI_TEST_INTERACT.rb', line 15

def test_InteractWrite(*args)
	parametters = HardsploitAPI.checkParametters(["value"],args)
	val = parametters[:value]

	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(USB_COMMAND::FPGA_COMMAND)
	packet.push HardsploitAPI.highByte(USB_COMMAND::FPGA_COMMAND)

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

	#Write mode
	packet.push 0xEF

	packet.push  ((val & 0x00000000000000FF) >> 0)
	packet.push  ((val & 0x000000000000FF00) >> 8 )
	packet.push  ((val & 0x0000000000FF0000) >> 16 )
	packet.push  ((val & 0x00000000FF000000) >> 24 )
	packet.push  ((val & 0x000000FF00000000) >> 32 )
	packet.push  ((val & 0x0000FF0000000000) >> 40 )
	packet.push  ((val & 0x00FF000000000000) >> 48 )
	packet.push  ((val & 0xFF00000000000000) >> 56 )

	sendPacket packet

	tmp= receiveDATA(1000)
	case tmp
		when HardsploitAPI::USB_STATE::BUSY
			return USB_STATE::BUSY
		when HardsploitAPI::USB_STATE::TIMEOUT_RECEIVE
			return USB_STATE::TIMEOUT_RECEIVE
		else
			#remove header (4 bytes   2 for size 2 for type of command)
			tmp = tmp.bytes.drop(4)

			return  0 |  (tmp[0] << 0) |  (tmp[1] << 8) 	 |  (tmp[2] << 16)  |  (tmp[3] << 24) |  (tmp[4] << 32) |  (tmp[5] << 40)  |  (tmp[6] << 48)  | (tmp[7] << 56)
	end
end

#unlockBlock(blockAddress) ⇒ Object



65
66
67
68
69
# File 'lib/HardsploitAPI/HardsploitAPI_NO_MUX_PARALLELE_MEMORY.rb', line 65

def unlockBlock (blockAddress)
	write_command_Memory_WithoutMultiplexing(blockAddress,0x0060) #Lock Block Command
	write_command_Memory_WithoutMultiplexing(blockAddress,0x00D0) #UnLock  Command
	return readByteFromMemory(0x000000) #read statut register
end

#uploadFirmware(*args) ⇒ Object

Wait to receive data

  • pathFirmware

    path of rpd file (vhdl)

  • checkFirmware

    boolean if check is needed (recommended false, in case issue true to check)

Return true if firmware write == firmware read (slow because read the firmware for check)



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/HardsploitAPI/HardsploitAPI_FIRMWARE.rb', line 16

def uploadFirmware(*args)
	parametters = HardsploitAPI.checkParametters(["pathFirmware","checkFirmware"],args)
	pathFirmware = parametters[:pathFirmware]
	checkFirmware = parametters[:checkFirmware]

	stopFPGA
	eraseFirmware
	firmwarewrite = self.writeFirmware(pathFirmware)#return array of bytes write
	if checkFirmware == true then
		firmwareRead = self.readFirmware(firmwarewrite.length) #return array of bytes read
		startFPGA
		return (firmwarewrite == firmwareRead)
	else
		startFPGA
		return true
	end
end

#write_command_Memory_WithoutMultiplexing(address, data) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/HardsploitAPI/HardsploitAPI_NO_MUX_PARALLELE_MEMORY.rb', line 71

def write_command_Memory_WithoutMultiplexing(address,data)
	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(USB_COMMAND::FPGA_COMMAND)
	packet.push HardsploitAPI.highByte(USB_COMMAND::FPGA_COMMAND)

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

	packet.push	0 #16 bits
	packet.push (1500/6.66).floor  #latency at 1500ns

	packet.push  ((address & 0xFF000000) >> 24 ) #AddStart3
	packet.push  ((address & 0x00FF0000) >> 16 ) #AddStart2
	packet.push  ((address & 0x0000FF00) >> 8 )  #AddStart1
	packet.push  ((address & 0x000000FF) >> 0)   #AddStart0
	packet.push 0x20 #Memory write command
	packet.push  ((data & 0xFF00) >> 8 )  #Data HIGHT BYTE
	packet.push  ((data & 0xFF) >> 0)  #Data LOW BYTE


	result = sendAndReceiveDATA(packet,1000)
	 if result == USB_STATE::TIMEOUT_RECEIVE then
	 	raise "TIMEOUT"
	elsif result[4] == (data & 0xFF)

	 	return readByteFromMemory(0)
	else
	 	raise "ERROR BAD RESPONSE"
	 end
end

#writeBlockAP(data) ⇒ Object



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
# File 'lib/HardsploitAPI/SWD/HardsploitAPI_SWD.rb', line 119

def writeBlockAP(data)
	if data.size > 8000 then
		raise "data is too big > 8000"
	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(HardsploitAPI::USB_COMMAND::FPGA_COMMAND)
	packet.push HardsploitAPI.highByte(HardsploitAPI::USB_COMMAND::FPGA_COMMAND)

	packet.push 0x50 #Command RAW COMMUNICATION TO FPGA FIFO
	packet.push 0xBB #Write ap
	packet.push *data

	result = sendAndReceiveDATA(packet,1000)
	if result.class == Array then
			if result.size == 1 + 4 then #receive ACK
				if result[4] == 1 then
						return true
				elsif result[4] == 2 then
						raise "WAIT response"
				elsif result[4] == 4 then
					  raise "FAULT response"
				else
						raise "WRITE ERROR #{result[4]}"
				end
			else
				raise "Error during writing"
			end
	else # Receive and error
		raise "Error during writing, timeout "
	end
		return false
end

#writeByteToMemory(address, value) ⇒ Object



23
24
25
26
27
28
# File 'lib/HardsploitAPI/HardsploitAPI_NO_MUX_PARALLELE_MEMORY.rb', line 23

def writeByteToMemory(address,value)
	#Write data in word mode  and read Five status register
	write_command_Memory_WithoutMultiplexing(address,0x0040)
	write_command_Memory_WithoutMultiplexing(address,value)
	return readByteFromMemory(0)
end

#writeFlash(path) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/HardsploitAPI/SWD/HardsploitAPI_SWD.rb', line 36

def writeFlash(path)
	resetSWD()
	dataWrite = IO.binread(path)
  dataWrite = dataWrite.unpack("C*")
	puts "Halting Processor"
	stm32.halt()
	puts "Erasing Flash"
	stm32.flashUnlock()
	stm32.flashErase()
	puts "Programming Flash"
	stm32.flashProgram()
	time = Time.new
	stm32.flashWrite(0x08000000, dataWrite)
	time = Time.new - time
	puts "Write #{((dataWrite.size/time)).round(2)}Bytes/s #{(dataWrite.size)}Bytes in  #{time.round(4)} s"
	stm32.flashProgramEnd()
	puts "Resetting"
	stm32.sysReset()
	puts "Start"
	stm32.unhalt
end

#writeSWD(ap, register, data) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/HardsploitAPI/SWD/HardsploitAPI_SWD.rb', line 78

def writeSWD(ap,register,data)
	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(HardsploitAPI::USB_COMMAND::FPGA_COMMAND)
	packet.push HardsploitAPI.highByte(HardsploitAPI::USB_COMMAND::FPGA_COMMAND)

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

	packet.push 0x10 #Write mode

	packet.push (calcOpcode(ap, register, false)) #Send Request

	packet.push  ((data & 0xFF) >> 0)
	packet.push  ((data & 0xFF00) >> 8 )
	packet.push  ((data & 0xFF0000) >> 16 )
	packet.push  ((data & 0xFF000000) >> 24 )

	result = sendAndReceiveDATA(packet,1000)

	if result.class == Array then
			if result.size == 1 + 4 then #receive ACK
				if result[4] == 1 then
						return true
				elsif result[4] == 2 then
						raise "WAIT response"
				elsif result[4] == 4 then
					  raise "FAULT response"
				else
						raise "WRITE ERROR #{result[4]}"
				end
			else
				raise "Error during writing}"
			end
	else # Receive and error
		raise "Error during writing, timeout "
	end

	return false
end