| 676 |
theseven |
1 |
//
|
|
|
2 |
//
|
|
|
3 |
// Copyright 2011 TheSeven
|
|
|
4 |
//
|
|
|
5 |
//
|
|
|
6 |
// This file is part of emCORE.
|
|
|
7 |
//
|
|
|
8 |
// emCORE is free software: you can redistribute it and/or
|
|
|
9 |
// modify it under the terms of the GNU General Public License as
|
|
|
10 |
// published by the Free Software Foundation, either version 2 of the
|
|
|
11 |
// License, or (at your option) any later version.
|
|
|
12 |
//
|
|
|
13 |
// emCORE is distributed in the hope that it will be useful,
|
|
|
14 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
15 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
16 |
// See the GNU General Public License for more details.
|
|
|
17 |
//
|
|
|
18 |
// You should have received a copy of the GNU General Public License along
|
|
|
19 |
// with emCORE. If not, see <http://www.gnu.org/licenses/>.
|
|
|
20 |
//
|
|
|
21 |
//
|
|
|
22 |
|
|
|
23 |
|
|
|
24 |
#define WIN32_LEAN_AND_MEAN
|
|
|
25 |
#include <windows.h>
|
|
|
26 |
#include <stdbool.h>
|
|
|
27 |
#include <inttypes.h>
|
|
|
28 |
|
|
|
29 |
|
|
|
30 |
struct controlreq {
|
|
|
31 |
uint8_t bmRequestType;
|
|
|
32 |
uint8_t bRequest;
|
|
|
33 |
uint16_t wValue;
|
|
|
34 |
uint16_t wIndex;
|
|
|
35 |
uint16_t wLength;
|
|
|
36 |
unsigned char data[];
|
|
|
37 |
};
|
|
|
38 |
|
|
|
39 |
|
|
|
40 |
extern char dfuimage[];
|
|
|
41 |
extern uint32_t dfuimage_size;
|
|
|
42 |
|
|
|
43 |
|
|
|
44 |
void print_last_error(char* text, bool force)
|
|
|
45 |
{
|
|
|
46 |
DWORD dw = GetLastError();
|
|
|
47 |
if (!dw && !force) return;
|
|
|
48 |
LPVOID lpMsgBuf;
|
|
|
49 |
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
|
50 |
NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL);
|
|
|
51 |
printf("%s: Error %d: %s\n", text, dw, lpMsgBuf);
|
|
|
52 |
}
|
|
|
53 |
|
|
|
54 |
int control(HANDLE dfu, struct controlreq* req, int size, bool silent)
|
|
|
55 |
{
|
|
|
56 |
DWORD count;
|
|
|
57 |
OVERLAPPED overlapped;
|
|
|
58 |
memset(&overlapped, 0, sizeof(overlapped));
|
|
|
59 |
SetLastError(0);
|
|
|
60 |
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
|
61 |
DeviceIoControl(dfu, 0x2200A0, req, size, req, size, NULL, &overlapped);
|
|
|
62 |
WaitForSingleObject(overlapped.hEvent, 1000);
|
|
|
63 |
DWORD rc = GetOverlappedResult(dfu, &overlapped, &count, FALSE);
|
|
|
64 |
CloseHandle(overlapped.hEvent);
|
|
|
65 |
if (rc <= 0)
|
|
|
66 |
{
|
|
|
67 |
print_last_error("DeviceIoControl", true);
|
|
|
68 |
count = -1;
|
|
|
69 |
CancelIo(dfu);
|
|
|
70 |
if (!silent) MessageBox(0, "DFU transfer failed!", "Error", MB_OK);
|
|
|
71 |
}
|
|
|
72 |
return count;
|
|
|
73 |
}
|
|
|
74 |
|
|
|
75 |
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
|
|
76 |
{
|
|
|
77 |
SetLastError(0);
|
|
|
78 |
HANDLE dfu = CreateFile("\\\\?\\usb#vid_05ac&pid_1223#87020000000001#{b8085869-feb9-404b-8cb1-1e5c14fa8c54}\\0001",
|
|
|
79 |
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
|
|
80 |
if (!dfu || dfu == (HANDLE)-1)
|
|
|
81 |
{
|
|
|
82 |
print_last_error("CreateFile", true);
|
|
|
83 |
MessageBox(0, "Could not open DFU device!", "Error", MB_OK);
|
|
|
84 |
return 1;
|
|
|
85 |
}
|
|
|
86 |
unsigned int buf[514];
|
|
|
87 |
struct controlreq* req = (struct controlreq*)buf;
|
|
|
88 |
int i, j;
|
|
|
89 |
for (i = 0; i < 256; i++)
|
|
|
90 |
{
|
|
|
91 |
buf[i] = i;
|
|
|
92 |
for (j = 0; j < 8; j++)
|
|
|
93 |
{
|
|
|
94 |
if (buf[i] & 1) buf[i] = (buf[i] >> 1) ^ 0xedb88320;
|
|
|
95 |
else buf[i] >>= 1;
|
|
|
96 |
}
|
|
|
97 |
}
|
|
|
98 |
unsigned char* ptr = dfuimage;
|
|
|
99 |
int left = dfuimage_size + 4;
|
|
|
100 |
int packet = 0;
|
|
|
101 |
dfuimage_size = 0xffffffff;
|
|
|
102 |
for (i = 0; i < left - 4; i++)
|
|
|
103 |
dfuimage_size = (dfuimage_size >> 8) ^ buf[(dfuimage_size ^ ptr[i]) & 0xff];
|
|
|
104 |
while (left)
|
|
|
105 |
{
|
|
|
106 |
int size = left > 2048 ? 2048 : left;
|
|
|
107 |
req->bmRequestType = 0x21;
|
|
|
108 |
req->bRequest = 1;
|
|
|
109 |
req->wValue = packet;
|
|
|
110 |
req->wIndex = 0;
|
|
|
111 |
req->wLength = size;
|
|
|
112 |
memcpy(req->data, ptr, size);
|
|
|
113 |
if (control(dfu, req, size + 8, false) != size + 8) return 2;
|
|
|
114 |
req->data[4] = 0;
|
|
|
115 |
while (req->data[4] != 5)
|
|
|
116 |
{
|
|
|
117 |
req->bmRequestType = 0xa1;
|
|
|
118 |
req->bRequest = 3;
|
|
|
119 |
req->wValue = 0;
|
|
|
120 |
req->wIndex = 0;
|
|
|
121 |
req->wLength = 6;
|
|
|
122 |
req->data[4] = 0;
|
|
|
123 |
if (control(dfu, req, 14, false) != 14) return 3;
|
|
|
124 |
}
|
|
|
125 |
ptr += size;
|
|
|
126 |
left -= size;
|
|
|
127 |
packet++;
|
|
|
128 |
}
|
|
|
129 |
req->bmRequestType = 0x21;
|
|
|
130 |
req->bRequest = 1;
|
|
|
131 |
req->wValue = packet;
|
|
|
132 |
req->wIndex = 0;
|
|
|
133 |
req->wLength = 0;
|
|
|
134 |
if (control(dfu, req, 8, false) != 8) return 4;
|
|
|
135 |
int timeout = 20;
|
|
|
136 |
req->data[4] = 0;
|
|
|
137 |
while (req->data[4] != 2 && timeout-- > 0)
|
|
|
138 |
{
|
|
|
139 |
Sleep(100);
|
|
|
140 |
req->bmRequestType = 0xa1;
|
|
|
141 |
req->bRequest = 3;
|
|
|
142 |
req->wValue = 0;
|
|
|
143 |
req->wIndex = 0;
|
|
|
144 |
req->wLength = 6;
|
|
|
145 |
req->data[4] = 0;
|
|
|
146 |
if (control(dfu, req, 14, true) != 14) break;
|
|
|
147 |
}
|
|
|
148 |
if (req->data[4] == 2)
|
|
|
149 |
{
|
|
|
150 |
printf("DFU payload was rejected with code: %02X %02X\n", req->data[4], req->data[0]);
|
|
|
151 |
MessageBox(0, "DFU payload was rejected!", "Error", MB_OK);
|
|
|
152 |
}
|
|
|
153 |
else MessageBox(0, "UMSboot has been launched!", "Success", MB_OK);
|
|
|
154 |
return 0;
|
|
|
155 |
}
|