]> git.zerfleddert.de Git - proxmark3-svn/blob - winsrc/prox.cpp
Implement version information storage and retrieval for the bootrom and the osimage.
[proxmark3-svn] / winsrc / prox.cpp
1 #include <windows.h>
2 #include <setupapi.h>
3 #include <stdio.h>
4 #include <ctype.h>
5 #include <stdlib.h>
6 extern "C" {
7 #include "include/hidsdi.h"
8 #include "include/hidpi.h"
9 }
10
11 #include "prox.h"
12
13 #define OUR_VID 0x9ac4
14 #define OUR_PID 0x4b8f
15
16 int offline = 0;
17 HANDLE UsbHandle;
18
19 static void ShowError(void)
20 {
21 char buf[1024];
22 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
23 buf, sizeof(buf), NULL);
24 printf("ERROR: %s", buf);
25 }
26
27 static BOOL UsbConnect(void)
28 {
29 typedef void (__stdcall *GetGuidProc)(GUID *);
30 typedef BOOLEAN (__stdcall *GetAttrProc)(HANDLE, HIDD_ATTRIBUTES *);
31 typedef BOOLEAN (__stdcall *GetPreparsedProc)(HANDLE,
32 PHIDP_PREPARSED_DATA *);
33 typedef NTSTATUS (__stdcall *GetCapsProc)(PHIDP_PREPARSED_DATA, PHIDP_CAPS);
34 GetGuidProc getGuid;
35 GetAttrProc getAttr;
36 GetPreparsedProc getPreparsed;
37 GetCapsProc getCaps;
38
39 HMODULE h = LoadLibrary("hid.dll");
40 getGuid = (GetGuidProc)GetProcAddress(h, "HidD_GetHidGuid");
41 getAttr = (GetAttrProc)GetProcAddress(h, "HidD_GetAttributes");
42 getPreparsed = (GetPreparsedProc)GetProcAddress(h, "HidD_GetPreparsedData");
43 getCaps = (GetCapsProc)GetProcAddress(h, "HidP_GetCaps");
44
45 GUID hidGuid;
46 getGuid(&hidGuid);
47
48 HDEVINFO devInfo;
49 devInfo = SetupDiGetClassDevs(&hidGuid, NULL, NULL,
50 DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
51
52 SP_DEVICE_INTERFACE_DATA devInfoData;
53 devInfoData.cbSize = sizeof(devInfoData);
54
55 int i;
56 for(i = 0;; i++) {
57 if(!SetupDiEnumDeviceInterfaces(devInfo, 0, &hidGuid, i, &devInfoData))
58 {
59 if(GetLastError() != ERROR_NO_MORE_ITEMS) {
60 // printf("SetupDiEnumDeviceInterfaces failed\n");
61 }
62 // printf("done list\n");
63 SetupDiDestroyDeviceInfoList(devInfo);
64 return FALSE;
65 }
66
67 // printf("item %d:\n", i);
68
69 DWORD sizeReqd = 0;
70 if(!SetupDiGetDeviceInterfaceDetail(devInfo, &devInfoData,
71 NULL, 0, &sizeReqd, NULL))
72 {
73 if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
74 // printf("SetupDiGetDeviceInterfaceDetail (0) failed\n");
75 continue;
76 }
77 }
78
79 SP_DEVICE_INTERFACE_DETAIL_DATA *devInfoDetailData =
80 (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(sizeReqd);
81 devInfoDetailData->cbSize = sizeof(*devInfoDetailData);
82
83 if(!SetupDiGetDeviceInterfaceDetail(devInfo, &devInfoData,
84 devInfoDetailData, 87, NULL, NULL))
85 {
86 // printf("SetupDiGetDeviceInterfaceDetail (1) failed\n");
87 continue;
88 }
89
90 char *path = devInfoDetailData->DevicePath;
91
92 UsbHandle = CreateFile(path, /*GENERIC_READ |*/ GENERIC_WRITE,
93 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
94 FILE_FLAG_OVERLAPPED, NULL);
95
96 if(UsbHandle == INVALID_HANDLE_VALUE) {
97 ShowError();
98 // printf("CreateFile failed: for '%s'\n", path);
99 continue;
100 }
101
102 HIDD_ATTRIBUTES attr;
103 attr.Size = sizeof(attr);
104 if(!getAttr(UsbHandle, &attr)) {
105 ShowError();
106 // printf("HidD_GetAttributes failed\n");
107 continue;
108 }
109
110 // printf("VID: %04x PID %04x\n", attr.VendorID, attr.ProductID);
111
112 if(attr.VendorID != OUR_VID || attr.ProductID != OUR_PID) {
113 CloseHandle(UsbHandle);
114 // printf(" nope, not us\n");
115 continue;
116 }
117
118 // printf ("got it!\n");
119 CloseHandle(UsbHandle);
120
121 UsbHandle = CreateFile(path, GENERIC_READ | GENERIC_WRITE,
122 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
123 FILE_FLAG_OVERLAPPED, NULL);
124
125 if(UsbHandle == INVALID_HANDLE_VALUE) {
126 ShowError();
127 // printf("Error, couldn't open our own handle as desired.\n");
128 return FALSE;
129 }
130
131 PHIDP_PREPARSED_DATA pp;
132 getPreparsed(UsbHandle, &pp);
133 HIDP_CAPS caps;
134
135 if(getCaps(pp, &caps) != HIDP_STATUS_SUCCESS) {
136 // printf("getcaps failed\n");
137 return FALSE;
138 }
139
140 // printf("input/out report %d/%d\n", caps.InputReportByteLength,
141 // caps.OutputReportByteLength);
142
143
144 return TRUE;
145 }
146 return FALSE;
147 }
148
149 BOOL ReceiveCommandPoll(UsbCommand *c)
150 {
151 static BOOL ReadInProgress = FALSE;
152 static OVERLAPPED Ov;
153 static BYTE Buf[65];
154 static DWORD HaveRead;
155
156 if(!ReadInProgress) {
157 memset(&Ov, 0, sizeof(Ov));
158 ReadFile(UsbHandle, Buf, 65, &HaveRead, &Ov);
159 if(GetLastError() != ERROR_IO_PENDING) {
160 ShowError();
161 exit(-1);
162 }
163 ReadInProgress = TRUE;
164 }
165
166 if(HasOverlappedIoCompleted(&Ov)) {
167 ReadInProgress = FALSE;
168
169 if(!GetOverlappedResult(UsbHandle, &Ov, &HaveRead, FALSE)) {
170 ShowError();
171 exit(-1);
172 }
173
174 memcpy(c, Buf+1, 64);
175
176 return TRUE;
177 } else {
178 return FALSE;
179 }
180 }
181
182 void ReceiveCommand(UsbCommand *c)
183 {
184 while(!ReceiveCommandPoll(c)) {
185 Sleep(0);
186 }
187 }
188
189 void SendCommand(UsbCommand *c, BOOL wantAck)
190 {
191 BYTE buf[65];
192 buf[0] = 0;
193 memcpy(buf+1, c, 64);
194
195 DWORD written;
196 OVERLAPPED ov;
197
198 memset(&ov, 0, sizeof(ov));
199 WriteFile(UsbHandle, buf, 65, &written, &ov);
200 if(GetLastError() != ERROR_IO_PENDING) {
201 ShowError();
202 exit(-1);
203 }
204
205 while(!HasOverlappedIoCompleted(&ov)) {
206 Sleep(0);
207 }
208
209 if(!GetOverlappedResult(UsbHandle, &ov, &written, FALSE)) {
210 ShowError();
211 exit(-1);
212 }
213
214 if(wantAck) {
215 UsbCommand ack;
216 ReceiveCommand(&ack);
217 if(ack.cmd != CMD_ACK) {
218 printf("bad ACK\n");
219 exit(-1);
220 }
221 }
222 }
223
224 static DWORD ExpectedAddr;
225 static BYTE QueuedToSend[256];
226 static BOOL AllWritten;
227
228 static void FlushPrevious(void)
229 {
230 UsbCommand c;
231 memset(&c, 0, sizeof(c));
232
233 int i;
234 for(i = 0; i < 240; i += 48) {
235 c.cmd = CMD_SETUP_WRITE;
236 memcpy(c.d.asBytes, QueuedToSend+i, 48);
237 c.ext1 = (i/4);
238 SendCommand(&c, TRUE);
239 }
240
241 c.cmd = CMD_FINISH_WRITE;
242 c.ext1 = (ExpectedAddr-1) & (~255);
243 printf("Flashing address: %08x\r", c.ext1);
244 memcpy(c.d.asBytes, QueuedToSend+240, 16);
245 SendCommand(&c, TRUE);
246
247 AllWritten = TRUE;
248 }
249
250 static void GotByte(DWORD where, BYTE which)
251 {
252 AllWritten = FALSE;
253
254 if(where != ExpectedAddr) {
255 printf("bad: got at %08x, expected at %08x\n", where, ExpectedAddr);
256 exit(-1);
257 }
258 QueuedToSend[where & 255] = which;
259 ExpectedAddr++;
260
261 if((where & 255) == 255) {
262 // we have completed a full page
263 FlushPrevious();
264 }
265 }
266
267 static int HexVal(int c)
268 {
269 c = tolower(c);
270 if(c >= '0' && c <= '9') {
271 return c - '0';
272 } else if(c >= 'a' && c <= 'f') {
273 return (c - 'a') + 10;
274 } else {
275 printf("bad hex digit '%c'\n", c);
276 exit(-1);
277 }
278 }
279
280 static BYTE HexByte(char *s)
281 {
282 return (HexVal(s[0]) << 4) | HexVal(s[1]);
283 }
284
285 static void LoadFlashFromSRecords(char *file, int addr)
286 {
287 ExpectedAddr = addr;
288
289 FILE *f = fopen(file, "r");
290 if(!f) {
291 printf("couldn't open file\n");
292 exit(-1);
293 }
294
295 char line[512];
296 while(fgets(line, sizeof(line), f)) {
297 if(memcmp(line, "S3", 2)==0) {
298 char *s = line + 2;
299 int len = HexByte(s) - 5;
300 s += 2;
301
302 char addrStr[9];
303 memcpy(addrStr, s, 8);
304 addrStr[8] = '\0';
305 DWORD addr;
306 sscanf(addrStr, "%x", &addr);
307 s += 8;
308
309 int i;
310 for(i = 0; i < len; i++) {
311 while((addr+i) > ExpectedAddr) {
312 GotByte(ExpectedAddr, 0xff);
313 }
314 GotByte(addr+i, HexByte(s));
315 s += 2;
316 }
317 }
318 }
319
320 if(!AllWritten) FlushPrevious();
321
322 fclose(f);
323 printf("\ndone.\n");
324 }
325
326 int main(int argc, char **argv)
327 {
328 int i = 0;
329
330 if(argc < 2) {
331 printf("Usage: %s bootrom file.s19\n", argv[0]);
332 printf(" %s load osimage.s19\n", argv[0]);
333 printf(" %s fpga fpgaimg.s19\n", argv[0]);
334 printf(" %s gui\n", argv[0]);
335 printf(" %s offline\n", argv[0]);
336 return -1;
337 }
338
339 // Only do this if NOT in offline mode
340 if (strcmp(argv[1], "offline"))
341 {
342 for(;;) {
343 if(UsbConnect()) {
344 break;
345 }
346 if(i == 0) {
347 printf("...no device connected, polling for it now\n");
348 }
349 if(i > 50000) {
350 printf("Could not connect to USB device; exiting.\n");
351 return -1;
352 }
353 i++;
354 Sleep(5);
355 }
356 }
357
358 if(strcmp(argv[1], "bootrom")==0 || strcmp(argv[1], "load")==0 || strcmp(argv[1], "fpga")==0) {
359 if(argc != 3) {
360 printf("Need filename.\n");
361 return -1;
362 }
363 if(strcmp(argv[1], "bootrom")==0) {
364 LoadFlashFromSRecords(argv[2], 0);
365 } else if(strcmp(argv[1], "fpga")==0) {
366 LoadFlashFromSRecords(argv[2], 0x2000);
367 } else {
368 LoadFlashFromSRecords(argv[2], 0x10000);
369 }
370 } else if(strcmp(argv[1], "gui")==0) {
371 ShowGui();
372 } else if(strcmp(argv[1], "offline")==0) {
373 offline = 1;
374 ShowGui();
375 } else if(strcmp(argv[1], "cmd")==0) {
376 if(argc != 3) {
377 printf("Need command.\n");
378 return -1;
379 }
380 ExecCmd(argv[2]);
381 } else {
382 printf("Command '%s' not recognized.\n", argv[1]);
383 return -1;
384 }
385
386 return 0;
387 }
Impressum, Datenschutz