Subversion Repositories freemyipod

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
15 theseven 1
//
2
//
3
//    Copyright 2010 TheSeven
4
//
5
//
6
//    This file is part of emBIOS.
7
//
8
//    emBIOS 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
//    emBIOS 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 emBIOS.  If not, see <http://www.gnu.org/licenses/>.
20
//
21
//
22
 
23
 
24
#include "global.h"
25
#include "panic.h"
26
#include "usb.h"
27
#include "usb_ch9.h"
28
#include "usbdrv.h"
29
#include "thread.h"
30
#include "console.h"
31
#include "util.h"
25 theseven 32
#include "contextswitch.h"
54 theseven 33
#include "power.h"
35 theseven 34
#include "mmu.h"
29 theseven 35
#include "shutdown.h"
92 theseven 36
#include "execimage.h"
85 theseven 37
#ifdef HAVE_I2C
38
#include "i2c.h"
39
#endif
95 theseven 40
#ifdef HAVE_BOOTFLASH
41
#include "bootflash.h"
42
#endif
157 theseven 43
#ifdef HAVE_HWKEYAES
44
#include "hwkeyaes.h"
45
#endif
46
#ifdef HAVE_HMACSHA1
47
#include "hmacsha1.h"
48
#endif
15 theseven 49
 
50
 
51
static uint8_t ctrlresp[2] CACHEALIGN_ATTR;
52
static uint32_t dbgrecvbuf[0x80] CACHEALIGN_ATTR;
53
static uint32_t dbgsendbuf[0x80] CACHEALIGN_ATTR;
54
static uint32_t dbgasyncsendbuf[0x80] CACHEALIGN_ATTR;
55
static char dbgendpoints[4] IBSS_ATTR;
56
 
57
enum dbgaction_t
58
{
59
    DBGACTION_IDLE = 0,
60
    DBGACTION_I2CSEND,
61
    DBGACTION_I2CRECV,
29 theseven 62
    DBGACTION_RESET,
63
    DBGACTION_POWEROFF,
64
    DBGACTION_CWRITE,
65
    DBGACTION_CREAD,
92 theseven 66
    DBGACTION_CFLUSH,
95 theseven 67
    DBGACTION_EXECIMAGE,
127 theseven 68
    DBGACTION_EXECFIRMWARE,
95 theseven 69
    DBGACTION_READBOOTFLASH,
157 theseven 70
    DBGACTION_WRITEBOOTFLASH,
71
    DBGACTION_HWKEYAES,
72
    DBGACTION_HMACSHA1
15 theseven 73
};
74
 
75
static uint32_t dbgstack[0x100] STACK_ATTR;
76
struct wakeup dbgwakeup IBSS_ATTR;
77
extern struct scheduler_thread* scheduler_threads;
78
static enum dbgaction_t dbgaction IBSS_ATTR;
29 theseven 79
static int dbgi2cbus;
80
static int dbgi2cslave;
81
static int dbgactionaddr;
95 theseven 82
static int dbgactionoffset;
29 theseven 83
static int dbgactionlength;
84
static int dbgactionconsoles;
85
static int dbgactiontype;
25 theseven 86
static char dbgconsendbuf[4096];
87
static char dbgconrecvbuf[1024];
88
static int dbgconsendreadidx IBSS_ATTR;
89
static int dbgconsendwriteidx IBSS_ATTR;
90
static int dbgconrecvreadidx IBSS_ATTR;
91
static int dbgconrecvwriteidx IBSS_ATTR;
92
static struct wakeup dbgconsendwakeup IBSS_ATTR;
93
static struct wakeup dbgconrecvwakeup IBSS_ATTR;
94
static bool dbgconsoleattached IBSS_ATTR;
15 theseven 95
 
25 theseven 96
static const char dbgconoverflowstr[] = "\n\n[overflowed]\n\n";
15 theseven 97
 
35 theseven 98
extern int _initstart;   // These aren't ints at all, but gcc complains about void types being
99
extern int _sdramstart;  // used here, and we only need the address, so forget about it...
25 theseven 100
 
35 theseven 101
 
15 theseven 102
static struct usb_device_descriptor CACHEALIGN_ATTR device_descriptor =
103
{
104
    .bLength            = sizeof(struct usb_device_descriptor),
105
    .bDescriptorType    = USB_DT_DEVICE,
106
    .bcdUSB             = 0x0200,
107
    .bDeviceClass       = USB_CLASS_VENDOR_SPEC,
108
    .bDeviceSubClass    = 0xff,
109
    .bDeviceProtocol    = 0xff,
110
    .bMaxPacketSize0    = 64,
111
    .idVendor           = 0xffff,
112
    .idProduct          = 0xe000,
113
    .bcdDevice          = 0x0001,
114
    .iManufacturer      = 1,
115
    .iProduct           = 2,
116
    .iSerialNumber      = 0,
117
    .bNumConfigurations = 1
118
};
119
 
120
static struct usb_config_bundle
121
{
122
    struct usb_config_descriptor config_descriptor;
123
    struct usb_interface_descriptor interface_descriptor;
124
    struct usb_endpoint_descriptor endpoint1_descriptor;
125
    struct usb_endpoint_descriptor endpoint2_descriptor;
126
    struct usb_endpoint_descriptor endpoint3_descriptor;
127
    struct usb_endpoint_descriptor endpoint4_descriptor;
128
} __attribute__((packed)) CACHEALIGN_ATTR config_bundle = 
129
{
130
    .config_descriptor =
131
    {
132
        .bLength             = sizeof(struct usb_config_descriptor),
133
        .bDescriptorType     = USB_DT_CONFIG,
134
        .wTotalLength        = sizeof(struct usb_config_descriptor)
135
                             + sizeof(struct usb_interface_descriptor)
136
                             + sizeof(struct usb_endpoint_descriptor) * 4,
137
        .bNumInterfaces      = 1,
138
        .bConfigurationValue = 1,
139
        .iConfiguration      = 0,
140
        .bmAttributes        = USB_CONFIG_ATT_ONE,
141
        .bMaxPower           = 250
142
    },
143
    .interface_descriptor =
144
    {
145
        .bLength             = sizeof(struct usb_interface_descriptor),
146
        .bDescriptorType     = USB_DT_INTERFACE,
147
        .bInterfaceNumber    = 0,
148
        .bAlternateSetting   = 0,
149
        .bNumEndpoints       = 4,
150
        .bInterfaceClass     = USB_CLASS_VENDOR_SPEC,
151
        .bInterfaceSubClass  = 0xff,
152
        .bInterfaceProtocol  = 0xff,
153
        .iInterface          = 0
154
    },
155
    .endpoint1_descriptor =
156
    {
157
        .bLength             = sizeof(struct usb_endpoint_descriptor),
158
        .bDescriptorType     = USB_DT_ENDPOINT,
159
        .bEndpointAddress    = 0,
160
        .bmAttributes        = USB_ENDPOINT_XFER_BULK,
161
        .wMaxPacketSize      = 0,
162
        .bInterval           = 1
163
    },
164
    .endpoint2_descriptor =
165
    {
166
        .bLength             = sizeof(struct usb_endpoint_descriptor),
167
        .bDescriptorType     = USB_DT_ENDPOINT,
168
        .bEndpointAddress    = 0,
169
        .bmAttributes        = USB_ENDPOINT_XFER_BULK,
170
        .wMaxPacketSize      = 0,
171
        .bInterval           = 1
172
    },
173
    .endpoint3_descriptor =
174
    {
175
        .bLength             = sizeof(struct usb_endpoint_descriptor),
176
        .bDescriptorType     = USB_DT_ENDPOINT,
177
        .bEndpointAddress    = 0,
178
        .bmAttributes        = USB_ENDPOINT_XFER_BULK,
179
        .wMaxPacketSize      = 0,
180
        .bInterval           = 1
181
    },
182
    .endpoint4_descriptor =
183
    {
184
        .bLength             = sizeof(struct usb_endpoint_descriptor),
185
        .bDescriptorType     = USB_DT_ENDPOINT,
186
        .bEndpointAddress    = 0,
187
        .bmAttributes        = USB_ENDPOINT_XFER_BULK,
188
        .wMaxPacketSize      = 0,
189
        .bInterval           = 1
190
    }
191
};
192
 
193
static struct usb_string_descriptor CACHEALIGN_ATTR string_devicename =
194
{
195
    32,
196
    USB_DT_STRING,
197
    {'e', 'm', 'B', 'I', 'O', 'S', ' ', 'D', 'e', 'b', 'u', 'g', 'g', 'e', 'r'}
198
};
199
 
200
static const struct usb_string_descriptor CACHEALIGN_ATTR lang_descriptor =
201
{
202
    4,
203
    USB_DT_STRING,
204
    {0x0409}
205
};
206
 
207
 
208
void usb_setup_dbg_listener()
209
{
210
    usb_drv_recv(dbgendpoints[0], dbgrecvbuf, usb_drv_port_speed() ? 512 : 64);
211
}
212
 
213
void usb_handle_control_request(struct usb_ctrlrequest* req)
214
{
215
    const void* addr;
216
    int size = -1;
217
    switch (req->bRequest)
218
    {
219
    case USB_REQ_GET_STATUS:
220
        if (req->bRequestType == USB_DIR_IN) ctrlresp[0] = 1;
221
        else ctrlresp[0] = 0;
222
        ctrlresp[1] = 0;
223
        addr = ctrlresp;
224
        size = 2;
225
        break;
226
    case USB_REQ_CLEAR_FEATURE:
227
        if (req->bRequestType == USB_RECIP_ENDPOINT && req->wValue == USB_ENDPOINT_HALT)
228
            usb_drv_stall(req->wIndex & 0xf, false, req->wIndex >> 7);
229
        size = 0;
230
        break;
231
    case USB_REQ_SET_FEATURE:
232
        size = 0;
233
        break;
234
    case USB_REQ_SET_ADDRESS:
235
        size = 0;
236
        usb_drv_cancel_all_transfers();
237
        usb_drv_set_address(req->wValue);
238
        usb_setup_dbg_listener();
239
        break;
240
    case USB_REQ_GET_DESCRIPTOR:
241
        switch (req->wValue >> 8)
242
        {
243
        case USB_DT_DEVICE:
244
            addr = &device_descriptor;
245
            size = sizeof(device_descriptor);
246
            break;
247
        case USB_DT_OTHER_SPEED_CONFIG:
248
        case USB_DT_CONFIG:
249
            if ((req->wValue >> 8) == USB_DT_CONFIG)
250
            {
251
                int maxpacket = usb_drv_port_speed() ? 512 : 64;
252
                config_bundle.endpoint1_descriptor.wMaxPacketSize = maxpacket;
253
                config_bundle.endpoint2_descriptor.wMaxPacketSize = maxpacket;
254
                config_bundle.endpoint3_descriptor.wMaxPacketSize = maxpacket;
255
                config_bundle.endpoint4_descriptor.wMaxPacketSize = maxpacket;
256
                config_bundle.config_descriptor.bDescriptorType = USB_DT_CONFIG;
257
            }
258
            else
259
            {
260
                int maxpacket = usb_drv_port_speed() ? 64 : 512;
261
                config_bundle.endpoint1_descriptor.wMaxPacketSize = maxpacket;
262
                config_bundle.endpoint2_descriptor.wMaxPacketSize = maxpacket;
263
                config_bundle.endpoint3_descriptor.wMaxPacketSize = maxpacket;
264
                config_bundle.endpoint4_descriptor.wMaxPacketSize = maxpacket;
265
                config_bundle.config_descriptor.bDescriptorType = USB_DT_OTHER_SPEED_CONFIG;
266
            }
267
            addr = &config_bundle;
268
            size = sizeof(config_bundle);
269
            break;
270
        case USB_DT_STRING:
271
            switch (req->wValue & 0xff)
272
            {
273
            case 0:
274
                addr = &lang_descriptor;
275
                size = sizeof(lang_descriptor);
276
                break;
277
            case 1:
278
                string_devicename.bLength = 14;
279
                addr = &string_devicename;
280
                size = 14;
281
            case 2:
282
                string_devicename.bLength = sizeof(string_devicename);
283
                addr = &string_devicename;
284
                size = sizeof(string_devicename);
285
                break;
286
            }
287
            break;
288
        }
289
        break;
290
    case USB_REQ_GET_CONFIGURATION:
291
        ctrlresp[0] = 1;
292
        addr = ctrlresp;
293
        size = 1;
294
        break;
295
    case USB_REQ_SET_CONFIGURATION:
296
        usb_drv_cancel_all_transfers();
297
        usb_setup_dbg_listener();
298
        size = 0;
299
        break;
300
    }
301
    if (!size) usb_drv_send_nonblocking(0, NULL, 0);
302
    else if (size == -1)
303
    {
304
        usb_drv_stall(0, true, true);
305
        usb_drv_stall(0, true, false);
306
    }
307
    else
308
    {
309
        usb_drv_recv(0, NULL, 0);
310
        usb_drv_send_nonblocking(0, addr, size > req->wLength ? req->wLength : size);
311
    }
312
}
313
 
29 theseven 314
bool set_dbgaction(enum dbgaction_t action, int addsize)
15 theseven 315
{
316
    if (dbgaction != DBGACTION_IDLE)
317
    {
318
        dbgsendbuf[0] = 3;
29 theseven 319
        usb_drv_send_nonblocking(dbgendpoints[1], dbgsendbuf, 16 + addsize);
15 theseven 320
        return true;
321
    }
322
    dbgaction = action;
323
    wakeup_signal(&dbgwakeup);
324
    return false;
325
}
326
 
327
void reset() __attribute__((noreturn));
328
 
329
void usb_handle_transfer_complete(int endpoint, int dir, int status, int length)
330
{
331
    void* addr = dbgsendbuf;
332
    int size = 0;
333
    if (endpoint == dbgendpoints[0])
334
    {
335
        switch (dbgrecvbuf[0])
336
        {
28 theseven 337
        case 1:  // GET INFO
15 theseven 338
            dbgsendbuf[0] = 1;
339
            size = 16;
28 theseven 340
            switch (dbgrecvbuf[1])
341
            {
342
            case 0:  // GET VERSION INFO
85 theseven 343
                dbgsendbuf[1] = VERSION_SVN_INT;
344
                dbgsendbuf[2] = VERSION_MAJOR | (VERSION_MINOR << 8)
28 theseven 345
                              | (VERSION_PATCH << 16) | (1 << 24);
85 theseven 346
                dbgsendbuf[3] = PLATFORM_ID;
28 theseven 347
                break;
348
            case 1:  // GET PACKET SIZE INFO
349
                dbgsendbuf[1] = 0x02000200;
350
                dbgsendbuf[2] = usb_drv_get_max_out_size();
351
                dbgsendbuf[3] = usb_drv_get_max_in_size();
352
                break;
35 theseven 353
            case 2:  // GET USER MEMORY INFO
354
                dbgsendbuf[1] = (uint32_t)&_initstart;
355
                dbgsendbuf[2] = (uint32_t)&_sdramstart;
356
                break;
28 theseven 357
            default:
358
                dbgsendbuf[0] = 2;
359
            }
15 theseven 360
            break;
361
        case 2:  // RESET
29 theseven 362
            if (dbgrecvbuf[1])
363
            {
364
                if (set_dbgaction(DBGACTION_RESET, 0)) break;
365
                dbgsendbuf[0] = 1;
366
                size = 16;
367
            }
368
            else reset();
15 theseven 369
            break;
370
        case 3:  // POWER OFF
29 theseven 371
            if (set_dbgaction(DBGACTION_POWEROFF, 0)) break;
372
            dbgactiontype = dbgrecvbuf[1];
373
            dbgsendbuf[0] = 1;
374
            size = 16;
15 theseven 375
            break;
376
        case 4:  // READ MEMORY
377
            dbgsendbuf[0] = 1;
378
            memcpy(&dbgsendbuf[4], (const void*)dbgrecvbuf[1], dbgrecvbuf[2]);
379
            size = dbgrecvbuf[2] + 16;
380
            break;
381
        case 5:  // WRITE MEMORY
382
            dbgsendbuf[0] = 1;
383
            memcpy((void*)dbgrecvbuf[1], &dbgrecvbuf[4], dbgrecvbuf[2]);
384
            size = 16;
385
            break;
386
        case 6:  // READ DMA
387
            dbgsendbuf[0] = 1;
388
            usb_drv_send_nonblocking(dbgendpoints[1], dbgsendbuf, 16);
389
            usb_drv_send_nonblocking(dbgendpoints[3], (const void*)dbgrecvbuf[1], dbgrecvbuf[2]);
390
            break;
391
        case 7:  // WRITE DMA
392
            dbgsendbuf[0] = 1;
393
            size = 16;
394
            usb_drv_recv(dbgendpoints[2], (void*)dbgrecvbuf[1], dbgrecvbuf[2]);
395
            break;
85 theseven 396
#ifdef HAVE_I2C
15 theseven 397
        case 8:  // READ I2C
29 theseven 398
            if (set_dbgaction(DBGACTION_I2CRECV, dbgrecvbuf[1] >> 24)) break;
15 theseven 399
            dbgi2cbus = dbgrecvbuf[1] & 0xff;
400
            dbgi2cslave = (dbgrecvbuf[1] >> 8) & 0xff;
29 theseven 401
            dbgactionaddr = (dbgrecvbuf[1] >> 16) & 0xff;
402
            dbgactionlength = dbgrecvbuf[1] >> 24;
175 theseven 403
            if (!dbgactionlength) dbgactionlength = 256;
15 theseven 404
            break;
405
        case 9:  // WRITE I2C
29 theseven 406
            if (set_dbgaction(DBGACTION_I2CSEND, 0)) break;
15 theseven 407
            dbgi2cbus = dbgrecvbuf[1] & 0xff;
408
            dbgi2cslave = (dbgrecvbuf[1] >> 8) & 0xff;
29 theseven 409
            dbgactionaddr = (dbgrecvbuf[1] >> 16) & 0xff;
410
            dbgactionlength = dbgrecvbuf[1] >> 24;
175 theseven 411
            if (!dbgactionlength) dbgactionlength = 256;
29 theseven 412
            memcpy(dbgasyncsendbuf, &dbgsendbuf[4], dbgactionlength);
15 theseven 413
            break;
85 theseven 414
#endif
25 theseven 415
        case 10:  // READ CONSOLE
416
            dbgconsoleattached = true;
417
            int bytes = dbgconsendwriteidx - dbgconsendreadidx;
418
            if (bytes >= sizeof(dbgconsendbuf)) bytes -= sizeof(dbgconsendbuf);
419
            if (bytes)
420
            {
421
                if (bytes < 0) bytes += sizeof(dbgconsendbuf);
422
                if (bytes > dbgrecvbuf[1]) bytes = dbgrecvbuf[1];
423
                int readbytes = bytes;
424
                char* outptr = (char*)&dbgsendbuf[4];
425
                if (dbgconsendreadidx + bytes >= sizeof(dbgconsendbuf))
426
                {
427
                    readbytes = sizeof(dbgconsendbuf) - dbgconsendreadidx;
428
                    memcpy(outptr, &dbgconsendbuf[dbgconsendreadidx], readbytes);
429
                    dbgconsendreadidx = 0;
430
                    outptr = &outptr[readbytes];
431
                    readbytes = bytes - readbytes;
432
                }
433
                if (readbytes) memcpy(outptr, &dbgconsendbuf[dbgconsendreadidx], readbytes);
434
                dbgconsendreadidx += readbytes;
26 theseven 435
                wakeup_signal(&dbgconsendwakeup);
25 theseven 436
            }
437
            dbgsendbuf[0] = 1;
438
            dbgsendbuf[1] = bytes;
439
            dbgsendbuf[2] = sizeof(dbgconsendbuf);
440
            dbgsendbuf[3] = dbgconsendwriteidx - dbgconsendreadidx;
441
            size = 16 + dbgrecvbuf[1];
442
            break;
26 theseven 443
        case 11:  // WRITE CONSOLE
444
            bytes = dbgconrecvreadidx - dbgconrecvwriteidx - 1;
445
            if (bytes < 0) bytes += sizeof(dbgconrecvbuf);
446
            if (bytes)
447
            {
448
                if (bytes > dbgrecvbuf[1]) bytes = dbgrecvbuf[1];
449
                int writebytes = bytes;
450
                char* readptr = (char*)&dbgrecvbuf[4];
451
                if (dbgconrecvwriteidx + bytes >= sizeof(dbgconrecvbuf))
452
                {
453
                    writebytes = sizeof(dbgconrecvbuf) - dbgconrecvwriteidx;
454
                    memcpy(&dbgconrecvbuf[dbgconrecvwriteidx], readptr, writebytes);
455
                    dbgconrecvwriteidx = 0;
456
                    readptr = &readptr[writebytes];
457
                    writebytes = bytes - writebytes;
458
                }
459
                if (writebytes) memcpy(&dbgconrecvbuf[dbgconrecvwriteidx], readptr, writebytes);
460
                dbgconrecvwriteidx += writebytes;
461
                wakeup_signal(&dbgconrecvwakeup);
462
            }
463
            dbgsendbuf[0] = 1;
464
            dbgsendbuf[1] = bytes;
465
            dbgsendbuf[2] = sizeof(dbgconrecvbuf);
466
            dbgsendbuf[3] = dbgconrecvreadidx - dbgconrecvwriteidx - 1;
467
            size = 16;
468
            break;
29 theseven 469
        case 12:  // CWRITE
470
            if (set_dbgaction(DBGACTION_CWRITE, 0)) break;
471
            dbgactionconsoles = dbgrecvbuf[1];
472
            dbgactionlength = dbgrecvbuf[2];
473
            memcpy(dbgasyncsendbuf, &dbgrecvbuf[4], dbgactionlength);
474
            break;
475
        case 13:  // CREAD
476
            if (set_dbgaction(DBGACTION_CREAD, dbgrecvbuf[2])) break;
477
            dbgactionconsoles = dbgrecvbuf[1];
478
            dbgactionlength = dbgrecvbuf[2];
479
            break;
480
        case 14:  // CFLUSH
481
            if (set_dbgaction(DBGACTION_CFLUSH, 0)) break;
482
            dbgactionconsoles = dbgrecvbuf[1];
483
            break;
31 theseven 484
        case 15:  // GET PROCESS INFO
485
            dbgsendbuf[0] = 1;
486
            dbgsendbuf[1] = SCHEDULER_THREAD_INFO_VERSION;
487
            dbgsendbuf[2] = MAX_THREADS * sizeof(struct scheduler_thread);
136 theseven 488
            memcpy(&dbgsendbuf[4], (void*)(((uint32_t)&scheduler_threads) + dbgrecvbuf[1]),
57 theseven 489
                   dbgrecvbuf[2]);
490
            size = dbgrecvbuf[2] + 16;
31 theseven 491
            break;
34 theseven 492
        case 16:  // FREEZE SCHEDULER
54 theseven 493
            dbgsendbuf[1] = scheduler_freeze(dbgrecvbuf[1]);
34 theseven 494
            dbgsendbuf[0] = 1;
495
            size = 16;
496
            break;
35 theseven 497
        case 17:  // SUSPEND THREAD
54 theseven 498
            if (dbgrecvbuf[1])
499
            {
500
                if (thread_suspend(dbgrecvbuf[2]) == -4) dbgsendbuf[1] = 1;
501
                else dbgsendbuf[1] = 0;
502
            }
503
            else
504
            {
505
                if (thread_resume(dbgrecvbuf[2]) == -5) dbgsendbuf[1] = 0;
506
                else dbgsendbuf[1] = 1;
507
            }
35 theseven 508
            dbgsendbuf[0] = 1;
509
            size = 16;
510
            break;
511
        case 18:  // KILL THREAD
512
            thread_terminate(dbgrecvbuf[1]);
513
            dbgsendbuf[0] = 1;
514
            size = 16;
515
            break;
57 theseven 516
        case 19:  // KILL THREAD
35 theseven 517
            dbgsendbuf[0] = 1;
518
            dbgsendbuf[1] = thread_create((const char*)dbgsendbuf[1], (const void*)dbgsendbuf[2],
519
                                          (char*)dbgsendbuf[3], dbgsendbuf[4], dbgsendbuf[5],
520
                                          dbgsendbuf[6], dbgsendbuf[7]);
521
            size = 16;
522
            break;
523
        case 20:  // FLUSH CACHE
524
            clean_dcache();
525
            invalidate_icache();
526
            dbgsendbuf[0] = 1;
527
            size = 16;
528
            break;
92 theseven 529
        case 21:  // EXECIMAGE
530
            if (set_dbgaction(DBGACTION_EXECIMAGE, 0)) break;
531
            dbgactionaddr = dbgrecvbuf[1];
532
            break;
95 theseven 533
#ifdef HAVE_BOOTFLASH
534
        case 22:  // READ BOOT FLASH
535
            if (set_dbgaction(DBGACTION_READBOOTFLASH, 0)) break;
536
            dbgactionaddr = dbgrecvbuf[1];
537
            dbgactionoffset = dbgrecvbuf[2];
538
            dbgactionlength = dbgrecvbuf[3];
539
            break;
540
        case 23:  // WRITE BOOT FLASH
541
            if (set_dbgaction(DBGACTION_WRITEBOOTFLASH, 0)) break;
542
            dbgactionaddr = dbgrecvbuf[1];
543
            dbgactionoffset = dbgrecvbuf[2];
544
            dbgactionlength = dbgrecvbuf[3];
545
            break;
546
#endif
127 theseven 547
        case 24:  // EXECFIRMWARE
548
            if (set_dbgaction(DBGACTION_EXECFIRMWARE, 0)) break;
549
            dbgactionaddr = dbgrecvbuf[1];
550
            break;
157 theseven 551
#ifdef HAVE_HWKEYAES
552
        case 25:  // HWKEYAES
553
            if (set_dbgaction(DBGACTION_HWKEYAES, 0)) break;
554
            dbgactiontype = ((uint8_t*)dbgrecvbuf)[4];
555
            dbgactionoffset = ((uint16_t*)dbgrecvbuf)[3];
556
            dbgactionaddr = dbgrecvbuf[2];
557
            dbgactionlength = dbgrecvbuf[3];
179 theseven 558
            break;
157 theseven 559
#endif
560
#ifdef HAVE_HMACSHA1
561
        case 26:  // HMACSHA1
562
            if (set_dbgaction(DBGACTION_HMACSHA1, 0)) break;
563
            dbgactionaddr = dbgrecvbuf[1];
564
            dbgactionlength = dbgrecvbuf[2];
565
            dbgactionoffset = dbgrecvbuf[3];
179 theseven 566
            break;
157 theseven 567
#endif
15 theseven 568
        default:
569
            dbgsendbuf[0] = 2;
570
            size = 16;
571
        }
572
        usb_setup_dbg_listener();
573
        if (size) usb_drv_send_nonblocking(dbgendpoints[1], addr, size);
574
    }
575
}
576
 
577
void usb_handle_bus_reset(void)
578
{
579
    dbgendpoints[0] = usb_drv_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_OUT);
580
    dbgendpoints[1] = usb_drv_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_IN);
581
    dbgendpoints[2] = usb_drv_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_OUT);
582
    dbgendpoints[3] = usb_drv_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_IN);
583
    config_bundle.endpoint1_descriptor.bEndpointAddress = dbgendpoints[0];
584
    config_bundle.endpoint2_descriptor.bEndpointAddress = dbgendpoints[1];
585
    config_bundle.endpoint3_descriptor.bEndpointAddress = dbgendpoints[2];
586
    config_bundle.endpoint4_descriptor.bEndpointAddress = dbgendpoints[3];
587
    usb_setup_dbg_listener();
588
}
589
 
590
void dbgthread(void)
591
{
592
    int i;
25 theseven 593
    int t;
15 theseven 594
    while (1)
595
    {
596
        wakeup_wait(&dbgwakeup, TIMEOUT_BLOCK);
597
        for (i = 0; i < MAX_THREADS; i++)
598
            if (scheduler_threads[i].state == THREAD_DEFUNCT)
599
            {
600
                if (scheduler_threads[i].block_type == THREAD_DEFUNCT_STKOV)
35 theseven 601
                {
602
                    if (scheduler_threads[i].name)
603
                        cprintf(1, "\n*PANIC*\nStack overflow! (%s)\n",
604
                                scheduler_threads[i].name);
605
                    else cprintf(1, "\n*PANIC*\nStack overflow! (ID %d)\n", i);
606
                }
15 theseven 607
                scheduler_threads[i].state = THREAD_DEFUNCT_ACK;
608
            }
609
        if (dbgaction != DBGACTION_IDLE)
610
        {
611
            switch (dbgaction)
612
            {
85 theseven 613
#ifdef HAVE_I2C
15 theseven 614
            case DBGACTION_I2CSEND:
29 theseven 615
                i2c_send(dbgi2cbus, dbgi2cslave, dbgactionaddr,
616
                         (uint8_t*)dbgasyncsendbuf, dbgactionlength);
15 theseven 617
                dbgasyncsendbuf[0] = 1;
618
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
619
                break;
620
            case DBGACTION_I2CRECV:
29 theseven 621
                i2c_recv(dbgi2cbus, dbgi2cslave, dbgactionaddr,
622
                         (uint8_t*)(&dbgasyncsendbuf[4]), dbgactionlength);
15 theseven 623
                dbgasyncsendbuf[0] = 1;
29 theseven 624
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16 + dbgactionlength);
15 theseven 625
                break;
85 theseven 626
#endif
15 theseven 627
            case DBGACTION_POWEROFF:
127 theseven 628
                if (dbgactiontype) shutdown(true);
54 theseven 629
                power_off();
15 theseven 630
                break;
29 theseven 631
            case DBGACTION_RESET:
127 theseven 632
                shutdown(false);
29 theseven 633
                reset();
634
                break;
635
            case DBGACTION_CWRITE:
636
                cwrite(dbgactionconsoles, (const char*)dbgasyncsendbuf, dbgactionlength);
637
                dbgasyncsendbuf[0] = 1;
638
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
639
                break;
640
            case DBGACTION_CREAD:
641
                dbgasyncsendbuf[0] = 1;
30 theseven 642
                dbgasyncsendbuf[1] = cread(dbgactionconsoles, (char*)&dbgasyncsendbuf[4],
643
                                           dbgactionlength, 0);
29 theseven 644
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
645
                break;
646
            case DBGACTION_CFLUSH:
647
                cflush(dbgactionconsoles);
648
                dbgasyncsendbuf[0] = 1;
649
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
650
                break;
92 theseven 651
            case DBGACTION_EXECIMAGE:
652
                dbgasyncsendbuf[0] = 1;
653
                dbgasyncsendbuf[1] = execimage((void*)dbgactionaddr);
654
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
655
                break;
127 theseven 656
            case DBGACTION_EXECFIRMWARE:
657
                shutdown(false);
658
                dbgasyncsendbuf[0] = 1;
659
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
660
                execfirmware((void*)dbgactionaddr);
95 theseven 661
#ifdef HAVE_BOOTFLASH
662
            case DBGACTION_READBOOTFLASH:
663
                bootflash_readraw((void*)dbgactionaddr, dbgactionoffset, dbgactionlength);
664
                dbgasyncsendbuf[0] = 1;
665
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
666
                break;
667
            case DBGACTION_WRITEBOOTFLASH:
668
                bootflash_writeraw((void*)dbgactionaddr, dbgactionoffset, dbgactionlength);
669
                dbgasyncsendbuf[0] = 1;
670
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
671
                break;
672
#endif
157 theseven 673
#ifdef HAVE_HWKEYAES
674
            case DBGACTION_HWKEYAES:
675
                hwkeyaes((enum hwkeyaes_direction) dbgactiontype, dbgactionoffset,
676
                         (void*)dbgactionaddr, dbgactionlength);
677
                dbgasyncsendbuf[0] = 1;
678
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
679
                break;
680
#endif
681
#ifdef HAVE_HMACSHA1
682
            case DBGACTION_HMACSHA1:
683
                hmacsha1((void*)dbgactionaddr, dbgactionlength, (void*)dbgactionoffset);
684
                dbgasyncsendbuf[0] = 1;
685
                usb_drv_send_nonblocking(dbgendpoints[1], dbgasyncsendbuf, 16);
686
                break;
687
#endif
15 theseven 688
            }
689
            dbgaction = DBGACTION_IDLE;
690
        }
691
    }
692
}
693
 
694
void usb_init(void)
695
{
696
    dbgaction = DBGACTION_IDLE;
697
    wakeup_init(&dbgwakeup);
25 theseven 698
    dbgconsendreadidx = 0;
699
    dbgconsendwriteidx = 0;
700
    dbgconrecvreadidx = 0;
701
    dbgconrecvwriteidx = 0;
702
    wakeup_init(&dbgconsendwakeup);
703
    wakeup_init(&dbgconrecvwakeup);
85 theseven 704
    dbgconsoleattached = false;
167 theseven 705
    thread_create("monitor worker", dbgthread, dbgstack, sizeof(dbgstack), CORE_THREAD, 255, true);
15 theseven 706
    usb_drv_init();
707
}
25 theseven 708
 
709
int dbgconsole_getfree() ICODE_ATTR;
710
int dbgconsole_getfree()
711
{
712
    int free = dbgconsendreadidx - dbgconsendwriteidx - 1;
713
    if (free < 0) free += sizeof(dbgconsendbuf);
714
    return free;
715
}
716
 
717
int dbgconsole_makespace(int length) ICODE_ATTR;
718
int dbgconsole_makespace(int length)
719
{
720
    int free = dbgconsole_getfree();
721
    while (!free && dbgconsoleattached)
722
    {
723
        if (wakeup_wait(&dbgconsendwakeup, 2000000) == THREAD_TIMEOUT)
724
            dbgconsoleattached = false;
725
        free = dbgconsole_getfree();
726
    }
727
    if (free) return free > length ? length : free;
728
    if (length > sizeof(dbgconsendbuf) - 17) length = sizeof(dbgconsendbuf) - 17;
729
    uint32_t mode = enter_critical_section();
730
    dbgconsendreadidx += length;
731
    if (dbgconsendreadidx >= sizeof(dbgconsendbuf))
732
        dbgconsendreadidx -= sizeof(dbgconsendbuf);
733
    int offset = 0;
734
    int idx = dbgconsendreadidx;
735
    if (idx + 16 >= sizeof(dbgconsendbuf))
736
    {
737
        offset = sizeof(dbgconsendbuf) - dbgconsendreadidx;
738
        memcpy(&dbgconsendbuf[dbgconsendreadidx], dbgconoverflowstr, offset);
739
        idx = 0;
740
    }
741
    if (offset != 16) memcpy(&dbgconsendbuf[idx], &dbgconoverflowstr[offset], 16 - offset);
742
    leave_critical_section(mode);
743
    return length;
744
}
745
 
746
void dbgconsole_putc(char string)
747
{
748
    dbgconsole_makespace(1);
749
    dbgconsendbuf[dbgconsendwriteidx++] = string;
750
    if (dbgconsendwriteidx >= sizeof(dbgconsendbuf))
751
        dbgconsendwriteidx -= sizeof(dbgconsendbuf);
752
}
753
 
754
void dbgconsole_write(const char* string, size_t length)
755
{
756
    while (length)
757
    {
758
        int space = dbgconsole_makespace(length);
759
        if (dbgconsendwriteidx + space >= sizeof(dbgconsendbuf))
760
        {
761
            int bytes = sizeof(dbgconsendbuf) - dbgconsendwriteidx;
762
            memcpy(&dbgconsendbuf[dbgconsendwriteidx], string, bytes);
763
            dbgconsendwriteidx = 0;
764
            string = &string[bytes];
765
            space -= bytes;
766
            length -= bytes;
767
        }
768
        if (space) memcpy(&dbgconsendbuf[dbgconsendwriteidx], string, space);
769
        dbgconsendwriteidx += space;
770
        string = &string[space];
771
        length -= space;
772
    }
773
}
774
 
775
void dbgconsole_puts(const char* string)
776
{
777
    dbgconsole_write(string, strlen(string));
778
}
26 theseven 779
 
780
int dbgconsole_getavailable() ICODE_ATTR;
781
int dbgconsole_getavailable()
782
{
783
    int available = dbgconrecvwriteidx - dbgconrecvreadidx;
784
    if (available < 0) available += sizeof(dbgconrecvbuf);
785
    return available;
786
}
787
 
788
int dbgconsole_getc(int timeout)
789
{
790
    if (!dbgconsole_getavailable())
791
    {
792
        wakeup_wait(&dbgconrecvwakeup, TIMEOUT_NONE);
793
        if (!dbgconsole_getavailable())
794
        {
795
            wakeup_wait(&dbgconrecvwakeup, timeout);
796
            if (!dbgconsole_getavailable()) return -1;
797
        }
798
    }
799
    int byte = dbgconrecvbuf[dbgconrecvreadidx++];
800
    if (dbgconrecvreadidx >= sizeof(dbgconrecvbuf))
801
        dbgconrecvreadidx -= sizeof(dbgconrecvbuf);
802
    return byte;
803
}
804
 
805
int dbgconsole_read(char* buffer, size_t length, int timeout)
806
{
807
    if (!length) return 0;
808
    int available = dbgconsole_getavailable();
809
    if (!available)
810
    {
811
        wakeup_wait(&dbgconrecvwakeup, TIMEOUT_NONE);
812
        int available = dbgconsole_getavailable();
813
        if (!available)
814
        {
815
            wakeup_wait(&dbgconrecvwakeup, timeout);
816
            int available = dbgconsole_getavailable();
817
            if (!available) return 0;
818
        }
819
    }
820
    if (available > length) available = length;
821
    int left = available;
822
    if (dbgconrecvreadidx + available >= sizeof(dbgconrecvbuf))
823
    {
824
        int bytes = sizeof(dbgconrecvbuf) - dbgconrecvreadidx;
825
        memcpy(buffer, &dbgconrecvbuf[dbgconrecvreadidx], bytes);
826
        dbgconrecvreadidx = 0;
827
        buffer = &buffer[bytes];
828
        left -= bytes;
829
    }
830
    if (left) memcpy(buffer, &dbgconrecvbuf[dbgconrecvreadidx], left);
831
    dbgconrecvreadidx += left;
832
    return available;
833
}