Subversion Repositories freemyipod

Rev

Rev 676 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
676 theseven 1
//
2
//
897 user890104 3
//    Copyright 2011 TheSeven, user890104
676 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);
897 user890104 78
    HANDLE dfu = CreateFile("\\\\?\\usb#vid_05ac&pid_1225#87200000000001#{b8085869-feb9-404b-8cb1-1e5c14fa8c54}\\0001",
676 theseven 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
}