Subversion Repositories freemyipod

Rev

Rev 914 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
893 theseven 1
//
2
//
3
//    Copyright 2013 TheSeven
914 user890104 4
//    Copyright 2014 user890104
893 theseven 5
//
6
//
7
//    This file is part of emCORE.
8
//
9
//    emCORE is free software: you can redistribute it and/or
10
//    modify it under the terms of the GNU General Public License as
11
//    published by the Free Software Foundation, either version 2 of the
12
//    License, or (at your option) any later version.
13
//
14
//    emCORE is distributed in the hope that it will be useful,
15
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
16
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
//    See the GNU General Public License for more details.
18
//
19
//    You should have received a copy of the GNU General Public License along
20
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
21
//
22
//
23
 
24
 
25
#define LITTLE_ENDIAN
26
 
27
 
28
#include "emcoreapp.h"
918 user890104 29
#include "libboot.h"
893 theseven 30
 
31
 
32
#define SCSI_TEST_UNIT_READY        0x00
33
#define SCSI_INQUIRY                0x12
34
#define SCSI_MODE_SENSE_6           0x1a
35
#define SCSI_MODE_SENSE_10          0x5a
36
#define SCSI_REQUEST_SENSE          0x03
37
#define SCSI_ALLOW_MEDIUM_REMOVAL   0x1e
38
#define SCSI_READ_CAPACITY          0x25
39
#define SCSI_READ_FORMAT_CAPACITY   0x23
40
#define SCSI_READ_10                0x28
41
#define SCSI_WRITE_10               0x2a
42
#define SCSI_START_STOP_UNIT        0x1b
43
#define SCSI_REPORT_LUNS            0xa0
44
#define SCSI_WRITE_BUFFER           0x3b
45
 
46
#define SENSE_NOT_READY             0x02
47
#define SENSE_MEDIUM_ERROR          0x03
48
#define SENSE_ILLEGAL_REQUEST       0x05
49
#define SENSE_UNIT_ATTENTION        0x06
50
 
51
#define ASC_MEDIUM_NOT_PRESENT      0x3a
52
#define ASC_INVALID_FIELD_IN_CBD    0x24
53
#define ASC_LBA_OUT_OF_RANGE        0x21
54
#define ASC_WRITE_ERROR             0x0C
55
#define ASC_READ_ERROR              0x11
56
#define ASC_NOT_READY               0x04
57
#define ASC_INVALID_COMMAND         0x20
58
 
59
#define ASCQ_BECOMING_READY         0x01
60
 
61
#define DIRECT_ACCESS_DEVICE        0x00
62
#define DEVICE_REMOVABLE            0x80
63
 
64
#define SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA 0x02000000
65
 
66
 
914 user890104 67
struct storage_info storage_info;
893 theseven 68
 
914 user890104 69
enum storage_operation {
70
    OP_READ,
71
    OP_WRITE
72
} pending_op;
893 theseven 73
 
914 user890104 74
unsigned long pending_op_start;
75
int pending_op_count;
76
 
77
struct wakeup pending_op_wakeup;
78
 
893 theseven 79
static const struct usb_devicedescriptor usb_devicedescriptor =
80
{
81
    .bLength = sizeof(struct usb_devicedescriptor),
82
    .bDescriptorType = USB_DESCRIPTOR_TYPE_DEVICE,
83
    .bcdUSB = 0x0200,
84
    .bDeviceClass = 0,
85
    .bDeviceSubClass = 0,
86
    .bDeviceProtocol = 0,
87
    .bMaxPacketSize0 = 64,
88
    .idVendor = 0xffff,
913 user890104 89
    .idProduct = 0xe001,
893 theseven 90
    .bcdDevice = 2,
91
    .iManufacturer = 1,
92
    .iProduct = 2,
93
    .iSerialNumber = 0,
94
    .bNumConfigurations = 1,
95
};
96
 
97
static struct __attribute__((packed)) _usb_config1_descriptors
98
{
99
    struct usb_configurationdescriptor c1;
100
    struct usb_interfacedescriptor c1_i0_a0;
101
    struct usb_endpointdescriptor c1_i0_a0_e1out;
102
    struct usb_endpointdescriptor c1_i0_a0_e1in;
103
} usb_config1_descriptors =
104
{
105
    .c1 =
106
    {
107
        .bLength = sizeof(struct usb_configurationdescriptor),
108
        .bDescriptorType = USB_DESCRIPTOR_TYPE_CONFIGURATION,
109
        .wTotalLength = sizeof(struct _usb_config1_descriptors),
110
        .bNumInterfaces = 1,
111
        .bConfigurationValue = 1,
112
        .iConfiguration = 0,
113
        .bmAttributes = { .buspowered = 1, .selfpowered = 1 },
114
        .bMaxPower = 100 / 2,
115
    },
116
    .c1_i0_a0 =
117
    {
118
        .bLength = sizeof(struct usb_interfacedescriptor),
119
        .bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE,
120
        .bInterfaceNumber = 0,
121
        .bAlternateSetting = 0,
122
        .bNumEndpoints = 2,
123
        .bInterfaceClass = 0x08,
124
        .bInterfaceSubClass = 0x06,
125
        .bInterfaceProtocol = 0x50,
126
        .iInterface = 0,
127
    },
128
    .c1_i0_a0_e1out =
129
    {
130
        .bLength = sizeof(struct usb_endpointdescriptor),
131
        .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT,
132
        .bEndpointAddress = { .number = 0, .direction = USB_ENDPOINT_DIRECTION_OUT },
133
        .bmAttributes = { .type = USB_ENDPOINT_ATTRIBUTE_TYPE_BULK },
134
        .wMaxPacketSize = 512,
135
        .bInterval = 1,
136
    },
137
    .c1_i0_a0_e1in =
138
    {
139
        .bLength = sizeof(struct usb_endpointdescriptor),
140
        .bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT,
141
        .bEndpointAddress = { .number = 0, .direction = USB_ENDPOINT_DIRECTION_IN },
142
        .bmAttributes = { .type = USB_ENDPOINT_ATTRIBUTE_TYPE_BULK },
143
        .wMaxPacketSize = 512,
144
        .bInterval = 1,
145
    },
146
};
147
 
148
static const struct usb_stringdescriptor usb_string_language =
149
{
150
    .bLength = sizeof(usb_string_language) + sizeof(*usb_string_language.wString),
151
    .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
152
    .wString = { 0x0409 },
153
};
154
 
155
static const struct usb_stringdescriptor usb_string_vendor =
156
{
157
    .bLength = sizeof(usb_string_vendor) + sizeof(*usb_string_vendor.wString) * 14,
158
    .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
159
    .wString = { 'f', 'r', 'e', 'e', 'm', 'y', 'i', 'p', 'o', 'd', '.', 'o', 'r', 'g' },
160
};
161
 
162
static const struct usb_stringdescriptor usb_string_product =
163
{
914 user890104 164
    .bLength = sizeof(usb_string_product) + sizeof(*usb_string_product.wString) * 16,
893 theseven 165
    .bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
914 user890104 166
    .wString = { 'e', 'm', 'C', 'O', 'R', 'E', ' ', 'D', 'i', 's', 'k', ' ', 'm', 'o', 'd', 'e' },
893 theseven 167
};
168
 
169
static const struct usb_stringdescriptor* usb_stringdescriptors[] =
170
{
171
    &usb_string_language,
172
    &usb_string_vendor,
173
    &usb_string_product,
174
};
175
 
176
struct __attribute__((packed,aligned(32))) command_block_wrapper
177
{
178
    unsigned int signature;
179
    unsigned int tag;
180
    unsigned int data_transfer_length;
181
    unsigned char flags;
182
    unsigned char lun;
183
    unsigned char command_length;
184
    unsigned char command_block[16];
185
};
186
 
187
struct __attribute__((packed)) command_status_wrapper
188
{
189
    unsigned int signature;
190
    unsigned int tag;
191
    unsigned int data_residue;
192
    unsigned char status;
193
};
194
 
195
struct __attribute__((packed)) inquiry_data
196
{
197
    unsigned char DeviceType;
198
    unsigned char DeviceTypeModifier;
199
    unsigned char Versions;
200
    unsigned char Format;
201
    unsigned char AdditionalLength;
202
    unsigned char Reserved[2];
203
    unsigned char Capability;
204
    char VendorId[8];
205
    char ProductId[16];
206
    char ProductRevisionLevel[4];
207
};
208
 
209
struct __attribute__((packed)) report_lun_data
210
{
211
    unsigned int lun_list_length;
212
    unsigned int reserved1;
213
    unsigned char luns[1][8];
214
};
215
 
216
struct __attribute__((packed)) sense_data
217
{
218
    unsigned char ResponseCode;
219
    unsigned char Obsolete;
220
    unsigned char fei_sensekey;
221
    unsigned int Information;
222
    unsigned char AdditionalSenseLength;
223
    unsigned int  CommandSpecificInformation;
224
    unsigned char AdditionalSenseCode;
225
    unsigned char AdditionalSenseCodeQualifier;
226
    unsigned char FieldReplaceableUnitCode;
227
    unsigned char SKSV;
228
    unsigned short SenseKeySpecific;
229
};
230
 
231
struct __attribute__((packed)) mode_sense_bdesc_longlba
232
{
233
    unsigned char num_blocks[8];
234
    unsigned char reserved[4];
235
    unsigned char block_size[4];
236
};
237
 
238
struct __attribute__((packed)) mode_sense_bdesc_shortlba
239
{
240
    unsigned char density_code;
241
    unsigned char num_blocks[3];
242
    unsigned char reserved;
243
    unsigned char block_size[3];
244
};
245
 
246
struct __attribute__((packed)) mode_sense_data_10
247
{
248
    unsigned short mode_data_length;
249
    unsigned char medium_type;
250
    unsigned char device_specific;
251
    unsigned char longlba;
252
    unsigned char reserved;
253
    unsigned short block_descriptor_length;
254
    struct mode_sense_bdesc_longlba block_descriptor;
255
};
256
 
257
struct __attribute__((packed)) mode_sense_data_6
258
{
259
    unsigned char mode_data_length;
260
    unsigned char medium_type;
261
    unsigned char device_specific;
262
    unsigned char block_descriptor_length;
263
    struct mode_sense_bdesc_shortlba block_descriptor;
264
};
265
 
266
struct __attribute__((packed)) capacity
267
{
268
    unsigned int block_count;
269
    unsigned int block_size;
270
};
271
 
272
struct __attribute__((packed)) format_capacity
273
{
274
    unsigned int following_length;
275
    unsigned int block_count;
276
    unsigned int block_size;
277
};
278
 
279
union __attribute__((aligned(32)))
280
{
281
    struct inquiry_data inquiry;
282
    struct capacity capacity_data;
283
    struct format_capacity format_capacity_data;
284
    struct sense_data sense_data;
285
    struct mode_sense_data_6 ms_data_6;
286
    struct mode_sense_data_10 ms_data_10;
287
    struct report_lun_data lun_data;
288
    struct command_status_wrapper csw;
289
} tb;
290
 
291
static enum
292
{
293
    WAITING_FOR_COMMAND,
294
    SENDING_BLOCKS,
295
    SENDING_RESULT,
296
    SENDING_FAILED_RESULT,
297
    RECEIVING_BLOCKS,
298
    WAITING_FOR_CSW_COMPLETION
299
} state = WAITING_FOR_COMMAND;
300
 
301
static struct
302
{
303
    unsigned int sector;
304
    unsigned int count;
305
    unsigned int orig_count;
306
    unsigned int cur_cmd;
307
    unsigned int tag;
308
    unsigned int lun;
309
    unsigned int last_result;
310
} cur_cmd;
311
 
312
static struct
313
{
314
    unsigned char sense_key;
315
    unsigned char information;
316
    unsigned char asc;
317
    unsigned char ascq;
318
} cur_sense_data;
319
 
320
static union usb_endpoint_number outep = { .number = 0, .direction = USB_ENDPOINT_DIRECTION_OUT };
321
static union usb_endpoint_number inep = { .number = 0, .direction = USB_ENDPOINT_DIRECTION_IN };
322
 
323
static struct command_block_wrapper cbw;
324
static int maxpacket = 512;
325
static int maxlen;
326
static int length;
327
static bool locked;
328
static const struct usb_instance* usb;
329
static volatile bool ejected = false;
914 user890104 330
static uint8_t __attribute__((aligned(32))) storage_buffer[0x10000];
893 theseven 331
 
918 user890104 332
struct bootinfo_t
333
{
334
    bool valid;
335
    void* firmware;
336
    int size;
337
    void* app;
338
    int argc;
339
    const char** argv;
340
};
341
 
893 theseven 342
static void listen()
343
{
344
    usb_start_rx(usb, outep, &cbw, sizeof(cbw));
345
}
346
 
347
static void send_csw(int status)
348
{
349
    tb.csw.signature = 0x53425355;
350
    tb.csw.tag = cur_cmd.tag;
351
    tb.csw.data_residue = 0;
352
    tb.csw.status = status;
353
 
354
    state = WAITING_FOR_CSW_COMPLETION;
355
    usb_start_tx(usb, inep, &tb.csw, sizeof(tb.csw));
356
 
357
    if (!status)
358
    {
359
        cur_sense_data.sense_key = 0;
360
        cur_sense_data.information = 0;
361
        cur_sense_data.asc = 0;
362
        cur_sense_data.ascq = 0;
363
    }
364
}
365
 
366
static void receive_block_data(void* data, int size)
367
{
368
    length = size;
369
    usb_start_rx(usb, outep, data, size);
370
    state = RECEIVING_BLOCKS;
371
}
372
 
373
static void send_block_data(void* data, int size)
374
{
375
    length = size;
376
    usb_start_tx(usb, inep, data, size);
377
    state = SENDING_BLOCKS;
378
}
379
 
380
static void send_command_result(void* data, int size)
381
{
382
    length = size;
383
    usb_start_tx(usb, inep, data, size);
384
    state = SENDING_RESULT;
385
}
386
 
387
static void send_command_failed_result()
388
{
389
    usb_start_tx(usb, inep, NULL, 0);
390
    state = SENDING_FAILED_RESULT;
391
}
392
 
393
static void send_and_read_next()
394
{
395
    if (cur_cmd.last_result)
396
    {
397
        send_csw(1);
398
        cur_sense_data.sense_key = SENSE_MEDIUM_ERROR;
399
        cur_sense_data.asc = ASC_READ_ERROR;
400
        cur_sense_data.ascq = 0;
401
        return;
402
    }
914 user890104 403
 
404
    pending_op_start = cur_cmd.sector;
405
    pending_op_count = cur_cmd.count;
406
    pending_op = OP_READ;
407
    wakeup_signal(&pending_op_wakeup);
893 theseven 408
}
409
 
410
static void copy_padded(char* dest, char* src, int len)
411
{
412
   int i = 0;
413
   while (src[i] && i < len)
414
   {
415
      dest[i] = src[i];
416
      i++;
417
   }
418
   while(i < len) dest[i++] = ' ';
419
}
420
 
421
static void fill_inquiry()
422
{
423
    memset(&tb.inquiry, 0, sizeof(tb.inquiry));
914 user890104 424
    copy_padded(tb.inquiry.VendorId, storage_info.vendor, sizeof(tb.inquiry.VendorId));
425
    copy_padded(tb.inquiry.ProductId, storage_info.product, sizeof(tb.inquiry.ProductId));
426
    copy_padded(tb.inquiry.ProductRevisionLevel, storage_info.revision, sizeof(tb.inquiry.ProductRevisionLevel));
893 theseven 427
 
428
    tb.inquiry.DeviceType = DIRECT_ACCESS_DEVICE;
429
    tb.inquiry.AdditionalLength = 0x1f;
430
    tb.inquiry.Versions = 4;  // SPC-2
431
    tb.inquiry.Format = 2;  // SPC-2/3 inquiry format
432
    tb.inquiry.DeviceTypeModifier = DEVICE_REMOVABLE;
433
}
434
 
435
static void handle_scsi(struct command_block_wrapper* cbw)
436
{
437
    unsigned int length = cbw->data_transfer_length;
438
 
439
    if (cbw->signature != 0x43425355)
440
    {
441
        usb_set_stall(usb, outep, true);
442
        usb_set_stall(usb, inep, true);
443
        return;
444
    }
445
    cur_cmd.tag = cbw->tag;
446
    cur_cmd.lun = cbw->lun;
447
    cur_cmd.cur_cmd = cbw->command_block[0];
448
 
449
    switch (cbw->command_block[0])
450
    {
451
        case SCSI_TEST_UNIT_READY:
452
            if (!ejected) send_csw(0);
453
            else
454
            {
455
                send_csw(1);
456
                cur_sense_data.sense_key = SENSE_NOT_READY;
457
                cur_sense_data.asc = ASC_MEDIUM_NOT_PRESENT;
458
                cur_sense_data.ascq = 0;
459
            }
460
            break;
461
 
462
        case SCSI_REPORT_LUNS:
463
        {
464
            memset(&tb.lun_data, 0, sizeof(struct report_lun_data));
465
            tb.lun_data.lun_list_length = 0x08000000;
466
            send_command_result(&tb.lun_data, MIN(16, length));
467
            break;
468
        }
469
 
470
        case SCSI_INQUIRY:
471
            fill_inquiry();
472
            length = MIN(length, cbw->command_block[4]);
473
            send_command_result(&tb.inquiry, MIN(sizeof(tb.inquiry), length));
474
            break;
475
 
476
        case SCSI_REQUEST_SENSE:
477
        {
478
            tb.sense_data.ResponseCode = 0x70;
479
            tb.sense_data.Obsolete = 0;
480
            tb.sense_data.fei_sensekey = cur_sense_data.sense_key & 0x0f;
481
            tb.sense_data.Information = cur_sense_data.information;
482
            tb.sense_data.AdditionalSenseLength = 10;
483
            tb.sense_data.CommandSpecificInformation = 0;
484
            tb.sense_data.AdditionalSenseCode = cur_sense_data.asc;
485
            tb.sense_data.AdditionalSenseCodeQualifier = cur_sense_data.ascq;
486
            tb.sense_data.FieldReplaceableUnitCode = 0;
487
            tb.sense_data.SKSV = 0;
488
            tb.sense_data.SenseKeySpecific = 0;
489
            send_command_result(&tb.sense_data, MIN(sizeof(tb.sense_data), length));
490
            break;
491
        }
492
 
493
        case SCSI_MODE_SENSE_10:
494
        {
495
            if (ejected)
496
            {
497
                send_command_failed_result();
498
                cur_sense_data.sense_key = SENSE_NOT_READY;
499
                cur_sense_data.asc = ASC_MEDIUM_NOT_PRESENT;
500
                cur_sense_data.ascq = 0;
501
                break;
502
            }
503
            unsigned char page_code = cbw->command_block[2] & 0x3f;
504
            switch (page_code)
505
            {
506
                case 0x3f:
507
                    tb.ms_data_10.mode_data_length = htobe16(sizeof(tb.ms_data_10) - 2);
508
                    tb.ms_data_10.medium_type = 0;
509
                    tb.ms_data_10.device_specific = 0;
510
                    tb.ms_data_10.reserved = 0;
511
                    tb.ms_data_10.longlba = 1;
512
                    tb.ms_data_10.block_descriptor_length = htobe16(sizeof(tb.ms_data_10.block_descriptor));
513
 
514
                    memset(tb.ms_data_10.block_descriptor.reserved, 0, 4);
515
                    memset(tb.ms_data_10.block_descriptor.num_blocks, 0, 8);
516
 
914 user890104 517
                    tb.ms_data_10.block_descriptor.num_blocks[4] = (storage_info.num_sectors & 0xff000000) >> 24;
518
                    tb.ms_data_10.block_descriptor.num_blocks[5] = (storage_info.num_sectors & 0x00ff0000) >> 16;
519
                    tb.ms_data_10.block_descriptor.num_blocks[6] = (storage_info.num_sectors & 0x0000ff00) >> 8;
520
                    tb.ms_data_10.block_descriptor.num_blocks[7] = (storage_info.num_sectors & 0x000000ff);
893 theseven 521
 
914 user890104 522
                    tb.ms_data_10.block_descriptor.block_size[0] = (storage_info.sector_size & 0xff000000) >> 24;
523
                    tb.ms_data_10.block_descriptor.block_size[1] = (storage_info.sector_size & 0x00ff0000) >> 16;
524
                    tb.ms_data_10.block_descriptor.block_size[2] = (storage_info.sector_size & 0x0000ff00) >> 8;
525
                    tb.ms_data_10.block_descriptor.block_size[3] = (storage_info.sector_size & 0x000000ff);
893 theseven 526
                    send_command_result(&tb.ms_data_10, MIN(sizeof(tb.ms_data_10), length));
527
                    break;
528
                default:
529
                    send_command_failed_result();
530
                    cur_sense_data.sense_key = SENSE_ILLEGAL_REQUEST;
531
                    cur_sense_data.asc = ASC_INVALID_FIELD_IN_CBD;
532
                    cur_sense_data.ascq = 0;
533
                    break;
534
            }
535
            break;
536
        }
537
 
538
        case SCSI_MODE_SENSE_6:
539
        {
540
            if (ejected)
541
            {
542
                send_command_failed_result();
543
                cur_sense_data.sense_key = SENSE_NOT_READY;
544
                cur_sense_data.asc = ASC_MEDIUM_NOT_PRESENT;
545
                cur_sense_data.ascq = 0;
546
                break;
547
            }
548
            unsigned char page_code = cbw->command_block[2] & 0x3f;
549
            switch (page_code)
550
            {
551
                case 0x3f:
552
                    tb.ms_data_6.mode_data_length = sizeof(tb.ms_data_6) - 1;
553
                    tb.ms_data_6.medium_type = 0;
554
                    tb.ms_data_6.device_specific = 0;
555
                    tb.ms_data_6.block_descriptor_length = sizeof(tb.ms_data_6.block_descriptor);
556
                    tb.ms_data_6.block_descriptor.density_code = 0;
557
                    tb.ms_data_6.block_descriptor.reserved = 0;
914 user890104 558
                    if (storage_info.num_sectors > 0xffffff)
893 theseven 559
                    {
560
                        tb.ms_data_6.block_descriptor.num_blocks[0] = 0xff;
561
                        tb.ms_data_6.block_descriptor.num_blocks[1] = 0xff;
562
                        tb.ms_data_6.block_descriptor.num_blocks[2] = 0xff;
563
                    }
564
                    else
565
                    {
914 user890104 566
                        tb.ms_data_6.block_descriptor.num_blocks[0] = (storage_info.num_sectors & 0xff0000) >> 16;
567
                        tb.ms_data_6.block_descriptor.num_blocks[1] = (storage_info.num_sectors & 0x00ff00) >> 8;
568
                        tb.ms_data_6.block_descriptor.num_blocks[2] = (storage_info.num_sectors & 0x0000ff);
893 theseven 569
                    }
914 user890104 570
                    tb.ms_data_6.block_descriptor.block_size[0] = (storage_info.sector_size & 0xff0000) >> 16;
571
                    tb.ms_data_6.block_descriptor.block_size[1] = (storage_info.sector_size & 0x00ff00) >> 8;
572
                    tb.ms_data_6.block_descriptor.block_size[2] = (storage_info.sector_size & 0x0000ff);
893 theseven 573
                    send_command_result(&tb.ms_data_6, MIN(sizeof(tb.ms_data_6), length));
574
                    break;
575
                default:
576
                    send_command_failed_result();
577
                    cur_sense_data.sense_key = SENSE_ILLEGAL_REQUEST;
578
                    cur_sense_data.asc = ASC_INVALID_FIELD_IN_CBD;
579
                    cur_sense_data.ascq = 0;
580
                    break;
581
            }
582
            break;
583
        }
584
 
585
        case SCSI_START_STOP_UNIT:
586
            if ((cbw->command_block[4] & 0xf3) == 2) ejected = true;
587
            send_csw(0);
588
            break;
589
 
590
        case SCSI_ALLOW_MEDIUM_REMOVAL:
591
            if ((cbw->command_block[4] & 0x03) == 0) locked = false;
592
            else locked = true;
593
            send_csw(0);
594
            break;
595
 
596
        case SCSI_READ_FORMAT_CAPACITY:
597
        {
598
            if (!ejected)
599
            {
600
                tb.format_capacity_data.following_length = 0x08000000;
914 user890104 601
                tb.format_capacity_data.block_count = htobe32(storage_info.num_sectors - 1);
602
                tb.format_capacity_data.block_size = htobe32(storage_info.sector_size);
893 theseven 603
                tb.format_capacity_data.block_size |= htobe32(SCSI_FORMAT_CAPACITY_FORMATTED_MEDIA);
604
                send_command_result(&tb.format_capacity_data, MIN(sizeof(tb.format_capacity_data), length));
605
           }
606
           else
607
           {
608
               send_command_failed_result();
609
               cur_sense_data.sense_key = SENSE_NOT_READY;
610
               cur_sense_data.asc = ASC_MEDIUM_NOT_PRESENT;
611
               cur_sense_data.ascq = 0;
612
           }
613
           break;
614
        }
615
 
616
        case SCSI_READ_CAPACITY:
617
        {
618
            if (!ejected)
619
            {
914 user890104 620
                tb.capacity_data.block_count = htobe32(storage_info.num_sectors - 1);
621
                tb.capacity_data.block_size = htobe32(storage_info.sector_size);
893 theseven 622
                send_command_result(&tb.capacity_data, MIN(sizeof(tb.capacity_data), length));
623
            }
624
            else
625
            {
626
                send_command_failed_result();
627
                cur_sense_data.sense_key = SENSE_NOT_READY;
628
                cur_sense_data.asc = ASC_MEDIUM_NOT_PRESENT;
629
                cur_sense_data.ascq = 0;
630
            }
631
            break;
632
        }
633
 
634
        case SCSI_READ_10:
635
            if (ejected)
636
            {
637
                send_command_failed_result();
638
                cur_sense_data.sense_key = SENSE_NOT_READY;
639
                cur_sense_data.asc = ASC_MEDIUM_NOT_PRESENT;
640
                cur_sense_data.ascq = 0;
641
                break;
642
            }
643
            cur_cmd.sector = (cbw->command_block[2] << 24 | cbw->command_block[3] << 16
644
                            | cbw->command_block[4] << 8 | cbw->command_block[5]);
645
            cur_cmd.count = (cbw->command_block[7] << 8 | cbw->command_block[8]);
646
            cur_cmd.orig_count = cur_cmd.count;
647
 
914 user890104 648
            if ((cur_cmd.sector + cur_cmd.count) > storage_info.num_sectors)
893 theseven 649
            {
650
                send_csw(1);
651
                cur_sense_data.sense_key = SENSE_ILLEGAL_REQUEST;
652
                cur_sense_data.asc = ASC_LBA_OUT_OF_RANGE;
653
                cur_sense_data.ascq = 0;
654
            }
655
            else send_and_read_next();
656
            break;
657
 
658
        case SCSI_WRITE_10:
659
            if (ejected)
660
            {
661
                send_command_failed_result();
662
                cur_sense_data.sense_key = SENSE_NOT_READY;
663
                cur_sense_data.asc = ASC_MEDIUM_NOT_PRESENT;
664
                cur_sense_data.ascq = 0;
665
                break;
666
            }
667
            cur_cmd.sector = (cbw->command_block[2] << 24 | cbw->command_block[3] << 16
668
                            | cbw->command_block[4] << 8 | cbw->command_block[5]);
669
            cur_cmd.count = (cbw->command_block[7] << 8 | cbw->command_block[8]);
670
            cur_cmd.orig_count = cur_cmd.count;
671
 
914 user890104 672
            if ((cur_cmd.sector + cur_cmd.count) > storage_info.num_sectors)
893 theseven 673
            {
674
                send_csw(1);
675
                cur_sense_data.sense_key = SENSE_ILLEGAL_REQUEST;
676
                cur_sense_data.asc = ASC_LBA_OUT_OF_RANGE;
677
                cur_sense_data.ascq = 0;
678
            }
914 user890104 679
            else {
680
                receive_block_data(storage_buffer, MIN(maxlen, cur_cmd.count * storage_info.sector_size));
681
            }
893 theseven 682
            break;
683
 
684
        case SCSI_WRITE_BUFFER:
685
            break;
686
 
687
        default:
688
            send_csw(1);
689
            cur_sense_data.sense_key = SENSE_ILLEGAL_REQUEST;
690
            cur_sense_data.asc = ASC_INVALID_COMMAND;
691
            cur_sense_data.ascq = 0;
692
            break;
693
    }
694
}
695
 
696
int handle_ctrl_request(const struct usb_instance* data, int interface, union usb_ep0_buffer* request, const void** response)
697
{
698
    int size = -1;
699
    switch (request->setup.bmRequestType.type)
700
    {
701
    case USB_SETUP_BMREQUESTTYPE_TYPE_CLASS:
702
        switch (request->setup.bRequest.raw)
703
        {
704
        case 0xfe:  // GET_MAX_LUN
705
            data->buffer->raw[0] = 0;
706
            size = 1;
707
            break;
708
        case 0xff:  // STORAGE_RESET
709
            size = 0;
710
            break;
711
        default: break;
712
        }
713
        break;
714
        default: break;
715
    }
716
    return size;
717
}
718
 
719
void handle_set_altsetting(const struct usb_instance* data, int interface, int altsetting)
720
{
721
    usb = data;
722
    state = WAITING_FOR_COMMAND;
723
    maxlen = maxpacket * MIN(usb_get_max_transfer_size(usb, outep), usb_get_max_transfer_size(usb, inep));
724
    usb_configure_ep(usb, outep, USB_ENDPOINT_TYPE_BULK, maxpacket);
725
    usb_configure_ep(usb, inep, USB_ENDPOINT_TYPE_BULK, maxpacket);
726
    listen();
727
}
728
 
729
void handle_unset_altsetting(const struct usb_instance* data, int interface, int altsetting)
730
{
731
    usb_unconfigure_ep(usb, outep);
732
    usb_unconfigure_ep(usb, inep);
733
}
734
 
735
int handle_ep_ctrl_request(const struct usb_instance* data, int interface, int endpoint, union usb_ep0_buffer* request, const void** response)
736
{
737
    int size = -1;
738
    switch (request->setup.bmRequestType.type)
739
    {
740
    case USB_SETUP_BMREQUESTTYPE_TYPE_STANDARD:
741
        switch (request->setup.bRequest.req)
742
        {
743
        case USB_SETUP_BREQUEST_CLEAR_FEATURE:
744
            if (request->setup.wLength || request->setup.wValue) break;
745
            listen();
746
            break;
747
        default: break;
748
        }
749
        break;
750
        default: break;
751
    }
752
    return size;
753
}
754
 
755
void handle_xfer_complete(const struct usb_instance* data, int ifnum, int epnum, int bytesleft)
756
{
757
    length -= bytesleft;
758
    switch (state)
759
    {
760
        case RECEIVING_BLOCKS:
914 user890104 761
            if (length != storage_info.sector_size * cur_cmd.count && length != maxlen) break;
893 theseven 762
 
914 user890104 763
            pending_op_start = cur_cmd.sector;
764
            pending_op_count = cur_cmd.count;
765
            pending_op = OP_WRITE;
766
            wakeup_signal(&pending_op_wakeup);
893 theseven 767
            break;
768
        case WAITING_FOR_CSW_COMPLETION:
769
            state = WAITING_FOR_COMMAND;
770
            listen();
771
            break;
772
        case WAITING_FOR_COMMAND:
773
            handle_scsi(&cbw);
774
            break;
775
        case SENDING_RESULT:
776
            send_csw(0);
777
            break;
778
        case SENDING_FAILED_RESULT:
779
            send_csw(1);
780
            break;
781
        case SENDING_BLOCKS:
782
            if (!cur_cmd.count) send_csw(0);
783
            else send_and_read_next();
784
            break;
785
    }
786
}
787
 
788
void handle_timeout(const struct usb_instance* data, int interface, int endpoint, int bytesleft)
789
{
790
    usb_set_stall(usb, outep, true);
791
    usb_set_stall(usb, inep, true);
792
}
793
 
794
static void handle_bus_reset(const struct usb_instance* data, int configuration, int interface, int highspeed)
795
{
796
    maxpacket = highspeed ? 512 : 64;
797
    usb_config1_descriptors.c1_i0_a0_e1out.wMaxPacketSize = maxpacket;
798
    usb_config1_descriptors.c1_i0_a0_e1in.wMaxPacketSize = maxpacket;
799
}
800
 
801
static struct usb_endpoint usb_c1_i0_a0_ep1out =
802
{
803
    .number = { .number = 0, .direction = USB_ENDPOINT_DIRECTION_OUT },
804
    .ctrl_request = handle_ep_ctrl_request,
805
    .xfer_complete = handle_xfer_complete,
806
};
807
 
808
static struct usb_endpoint usb_c1_i0_a0_ep1in =
809
{
810
    .number = { .number = 0, .direction = USB_ENDPOINT_DIRECTION_IN },
811
    .ctrl_request = handle_ep_ctrl_request,
812
    .xfer_complete = handle_xfer_complete,
813
    .timeout = handle_timeout,
814
};
815
 
816
static const struct usb_altsetting usb_c1_i0_a0 =
817
{
818
    .set_altsetting = handle_set_altsetting,
819
    .unset_altsetting = handle_unset_altsetting,
820
    .endpoint_count = 2,
821
    .endpoints =
822
    {
823
        &usb_c1_i0_a0_ep1out,
824
        &usb_c1_i0_a0_ep1in,
825
    },
826
};
827
 
828
static const struct usb_interface usb_c1_i0 =
829
{
830
    .bus_reset = handle_bus_reset,
831
    .ctrl_request = handle_ctrl_request,
832
    .altsetting_count = 1,
833
    .altsettings =
834
    {
835
        &usb_c1_i0_a0,
836
    },
837
};
838
 
839
static const struct usb_configuration usb_c1 =
840
{
841
    .descriptor = &usb_config1_descriptors.c1,
842
    .set_configuration = NULL,
843
    .unset_configuration = NULL,
844
    .interface_count = 1,
845
    .interfaces =
846
    {
847
        &usb_c1_i0,
848
    },
849
};
850
 
851
static const struct usb_configuration* usb_configurations[] =
852
{
853
    &usb_c1,
854
};
855
 
918 user890104 856
struct emcorelib_header* loadlib(uint32_t identifier, uint32_t version, char* filename)
857
{
858
    struct emcorelib_header* lib = get_library(identifier, version, LIBSOURCE_BOOTFLASH, filename);
859
    if (!lib) panicf(PANIC_KILLTHREAD, "Could not load %s", filename);
860
    return lib;
861
}
862
 
893 theseven 863
static void main(int argc, const char** argv)
864
{
918 user890104 865
    cprintf(3, "Welcome to Disk mode! Please wait until your device is detected by your operating system. It should not take more than 1-2 minutes. In case of issues, please ask for support.\n\n");
866
    cprintf(3, "When you're done transferring files, please use your operating system's Eject/Unmount option before unplugging the device.\n\n");
867
 
914 user890104 868
    storage_get_info(0, &storage_info);
869
 
870
    if (!storage_info.sector_size) panicf(PANIC_KILLTHREAD, "Sector size is zero!\n");
871
    if (!storage_info.num_sectors) panicf(PANIC_KILLTHREAD, "Number of sectors is zero!\n");
872
 
873
    disk_unmount(0);
874
 
893 theseven 875
    int i;
876
    uint32_t eps = usbmanager_get_available_endpoints();
877
    int ep_out = 0;
878
    int ep_in = 0;
879
    for (i = 1; i < 16; i++)
880
        if (eps & (1 << i))
881
        {
882
            ep_out = i;
883
            break;
884
        }
885
    for (i = 1; i < 16; i++)
886
        if (eps & (1 << (16 + i)))
887
        {
888
            ep_in = i;
889
            break;
890
        }
891
    if (!ep_out || !ep_in) panicf(PANIC_KILLTHREAD, "Not enough USB endpoints available!\n");
892
    usb_config1_descriptors.c1_i0_a0_e1out.bEndpointAddress.number = ep_out;
893
    usb_config1_descriptors.c1_i0_a0_e1in.bEndpointAddress.number = ep_in;
894
    usb_c1_i0_a0_ep1out.number.number = ep_out;
895
    usb_c1_i0_a0_ep1in.number.number = ep_in;
896
    outep.number = ep_out;
897
    inep.number = ep_in;
898
    int rc = usbmanager_install_custom(&usb_devicedescriptor, ARRAYLEN(usb_configurations), usb_configurations,
899
                                       ARRAYLEN(usb_stringdescriptors), usb_stringdescriptors, true);
914 user890104 900
    if (IS_ERR(rc)) {
901
        disk_mount(0);
902
        panicf(PANIC_KILLTHREAD, "Failed to register USB handler: %08X\n", rc);
903
    }
904
 
905
    wakeup_init(&pending_op_wakeup);
906
 
907
    while (!ejected && usbmanager_get_connected()) {
908
        if (wakeup_wait(&pending_op_wakeup, 200000) == THREAD_OK) {
909
            if (pending_op == OP_READ) {
910
                //cprintf(3, "R(%u, %u)\n", pending_op_start, pending_op_count);
911
                storage_read_sectors_md(0, pending_op_start, pending_op_count, storage_buffer);
912
 
913
                send_block_data(storage_buffer, MIN(maxlen, cur_cmd.count * storage_info.sector_size));
914
            }
915
 
916
            if (pending_op == OP_WRITE) {
917
                //cprintf(3, "W(%u, %u)\n", pending_op_start, pending_op_count);
918
                storage_write_sectors_md(0, pending_op_start, pending_op_count, storage_buffer);
919
            }
920
 
921
            cur_cmd.sector += maxlen / storage_info.sector_size;
922
            cur_cmd.count -= MIN(cur_cmd.count, maxlen / storage_info.sector_size);
923
 
924
            if (pending_op == OP_WRITE) {
925
                if (cur_cmd.count) {
926
                    receive_block_data(storage_buffer, MIN(maxlen, cur_cmd.count * storage_info.sector_size));
927
                }
928
                else send_csw(0);
929
            }
930
        }
931
    }
932
 
893 theseven 933
    usbmanager_uninstall_custom();
914 user890104 934
 
918 user890104 935
    cprintf(3, "Disk mode completed successfully. Returning to the bootmenu...\n\n");
936
 
937
    struct bootinfo_t bootinfo =
938
    {
939
        .valid = false,
940
        .firmware = NULL,
941
        .size = 0,
942
        .app = NULL,
943
        .argc = 0,
944
        .argv = NULL
945
    };
946
 
947
    struct emcorelib_header* libboot = loadlib(LIBBOOT_IDENTIFIER,
948
                                               LIBBOOT_API_VERSION, "libboot ");
949
    struct libboot_api* boot = (struct libboot_api*)libboot->api;
950
 
951
    boot->load_from_flash(&bootinfo.app, &bootinfo.size, false, "bootmenu", 0);
952
 
953
    if (!bootinfo.app) {
954
        panicf(PANIC_KILLTHREAD, "Unable to start the bootmenu! Press MENU+SELECT to reboot your device.\n");
955
    }
956
 
914 user890104 957
    disk_mount(0);
918 user890104 958
    execimage(bootinfo.app, false, bootinfo.argc, bootinfo.argv);
893 theseven 959
}
960
 
961
 
914 user890104 962
EMCORE_APP_HEADER("Disk mode", main, 127)