1 /*
2 * Copyright (c) 2023 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/storage/disk_access.h>
9 #include <zephyr/sys/byteorder.h>
10
11 #include "usbd_msc_scsi.h"
12
13 #include <zephyr/logging/log.h>
14 LOG_MODULE_DECLARE(usbd_msc, CONFIG_USBD_MSC_LOG_LEVEL);
15
16 #define INQUIRY_VERSION_SPC_2 0x04
17 #define INQUIRY_VERSION_SPC_3 0x05
18 #define INQUIRY_VERSION_SPC_4 0x06
19 #define INQUIRY_VERSION_SPC_5 0x07
20
21 /* Claim conformance to SPC-2 because this allows us to implement less commands
22 * and do not care about multiple reserved bits that became actual options
23 * later on. DO NOT change unless you make sure that all mandatory commands are
24 * implemented and all options (e.g. vpd pages) that are mandatory at given
25 * version are also implemented.
26 */
27 #define CLAIMED_CONFORMANCE_VERSION INQUIRY_VERSION_SPC_2
28
29 #define T10_VENDOR_LENGTH 8
30 #define T10_PRODUCT_LENGTH 16
31 #define T10_REVISION_LENGTH 4
32
33 /* Optional, however Windows insists on reading Unit Serial Number.
34 * There doesn't seem to be requirement on minimum product serial number length,
35 * however when the number is not available the device shall return ASCII spaces
36 * in the field.
37 */
38 #define UNIT_SERIAL_NUMBER " "
39
40 /* Every SCSI command has to abide to the general handling rules. Use macros
41 * to allow generating boilerplate handling code.
42 */
43 #define SCSI_CMD_STRUCT(opcode) struct scsi_##opcode##_cmd
44 #define SCSI_CMD_HANDLER(opcode) \
45 static int scsi_##opcode(struct scsi_ctx *ctx, \
46 struct scsi_##opcode##_cmd *cmd, \
47 uint8_t data_in_buf[static CONFIG_USBD_MSC_SCSI_BUFFER_SIZE])
48
49 /* SAM-6 5.2 Command descriptor block (CDB)
50 * Table 43 – CONTROL byte
51 */
52 #define GET_CONTROL_NACA(cmd) (cmd->control & BIT(2))
53
54 /* SPC-5 4.3.3 Variable type data field requirements
55 * Table 25 — Code set enumeration
56 */
57 enum code_set {
58 CODE_SET_BINARY = 0x1,
59 CODE_SET_ASCII = 0x2,
60 CODE_SET_UTF8 = 0x3,
61 };
62
63 /* SPC-5 F.3.1 Operation codes Table F.2 — Operation codes */
64 enum scsi_opcode {
65 TEST_UNIT_READY = 0x00,
66 REQUEST_SENSE = 0x03,
67 INQUIRY = 0x12,
68 MODE_SENSE_6 = 0x1A,
69 START_STOP_UNIT = 0x1B,
70 PREVENT_ALLOW_MEDIUM_REMOVAL = 0x1E,
71 READ_FORMAT_CAPACITIES = 0x23,
72 READ_CAPACITY_10 = 0x25,
73 READ_10 = 0x28,
74 WRITE_10 = 0x2A,
75 MODE_SENSE_10 = 0x5A,
76 };
77
SCSI_CMD_STRUCT(TEST_UNIT_READY)78 SCSI_CMD_STRUCT(TEST_UNIT_READY) {
79 uint8_t opcode;
80 uint32_t reserved;
81 uint8_t control;
82 } __packed;
83
84 /* DESC bit was reserved in SPC-2 and is optional since SPC-3 */
85 #define GET_REQUEST_SENSE_DESC(cmd) (cmd->desc & BIT(0))
86
SCSI_CMD_STRUCT(REQUEST_SENSE)87 SCSI_CMD_STRUCT(REQUEST_SENSE) {
88 uint8_t opcode;
89 uint8_t desc;
90 uint8_t reserved2;
91 uint8_t reserved3;
92 uint8_t allocation_length;
93 uint8_t control;
94 } __packed;
95
96 #define SENSE_VALID BIT(7)
97 #define SENSE_CODE_CURRENT_ERRORS 0x70
98 #define SENSE_CODE_DEFERRED_ERRORS 0x71
99
100 #define SENSE_FILEMARK BIT(7)
101 #define SENSE_EOM BIT(6)
102 #define SENSE_ILI BIT(5)
103 #define SENSE_KEY_MASK BIT_MASK(4)
104
105 #define SENSE_SKSV BIT(7)
106
107 struct scsi_request_sense_response {
108 uint8_t valid_code;
109 uint8_t obsolete;
110 uint8_t filemark_eom_ili_sense_key;
111 uint32_t information;
112 uint8_t additional_sense_length;
113 uint32_t command_specific_information;
114 uint16_t additional_sense_with_qualifier;
115 uint8_t field_replaceable_unit_code;
116 uint8_t sksv;
117 uint16_t sense_key_specific;
118 } __packed;
119
120 #define INQUIRY_EVPD BIT(0)
121 /* CMDDT in SPC-2, but obsolete since SPC-3 */
122 #define INQUIRY_CMDDT_OBSOLETE BIT(1)
123
124 enum vpd_page_code {
125 VPD_SUPPORTED_VPD_PAGES = 0x00,
126 VPD_UNIT_SERIAL_NUMBER = 0x80,
127 VPD_DEVICE_IDENTIFICATION = 0x83,
128 };
129
130 /* SPC-5 Table 517 — DESIGNATOR TYPE field */
131 enum designator_type {
132 DESIGNATOR_VENDOR = 0x0,
133 DESIGNATOR_T10_VENDOR_ID_BASED = 0x1,
134 DESIGNATOR_EUI_64_BASED = 0x2,
135 DESIGNATOR_NAA = 0x3,
136 DESIGNATOR_RELATIVE_TARGET_PORT_IDENTIFIER = 0x4,
137 DESIGNATOR_TARGET_PORT_GROUP = 0x5,
138 DESIGNATOR_MD5_LOGICAL_UNIT_IDENTIFIER = 0x6,
139 DESIGNATOR_SCSI_NAME_STRING = 0x8,
140 DESIGNATOR_PROTOCOL_SPECIFIC_PORT_IDENTIFIER = 0x9,
141 DESIGNATOR_UUID_IDENTIFIER = 0xA,
142 };
143
SCSI_CMD_STRUCT(INQUIRY)144 SCSI_CMD_STRUCT(INQUIRY) {
145 uint8_t opcode;
146 uint8_t cmddt_evpd;
147 uint8_t page_code;
148 /* Allocation length was 8-bit (LSB only) in SPC-2. MSB was reserved
149 * and hence SPC-2 compliant initiators should set it to 0.
150 */
151 uint16_t allocation_length;
152 uint8_t control;
153 } __packed;
154
155 struct scsi_inquiry_response {
156 uint8_t peripheral;
157 uint8_t rmb;
158 uint8_t version;
159 uint8_t format;
160 uint8_t additional_length;
161 uint8_t sccs;
162 uint8_t encserv;
163 uint8_t cmdque;
164 char scsi_vendor[T10_VENDOR_LENGTH];
165 char product[T10_PRODUCT_LENGTH];
166 char revision[T10_REVISION_LENGTH];
167 /* SPC-5 states the standard INQUIRY should contain at least 36 bytes.
168 * We do the minimum required (and thus end the inquiry response here),
169 * as there is no real use in Zephyr for vendor specific data and/or
170 * parameters and we don't claim conformance to specific versions.
171 */
172 } __packed;
173
174 #define MODE_SENSE_PAGE_CODE_ALL_PAGES 0x3F
175
SCSI_CMD_STRUCT(MODE_SENSE_6)176 SCSI_CMD_STRUCT(MODE_SENSE_6) {
177 uint8_t opcode;
178 uint8_t dbd;
179 uint8_t page;
180 uint8_t subpage;
181 uint8_t allocation_length;
182 uint8_t control;
183 } __packed;
184
185 /* SPC-5 7.5.6 Mode parameter header formats
186 * Table 443 — Mode parameter header(6)
187 */
188 struct scsi_mode_sense_6_response {
189 uint8_t mode_data_length;
190 uint8_t medium_type;
191 uint8_t device_specific_parameter;
192 uint8_t block_descriptor_length;
193 } __packed;
194
195 #define GET_IMMED(cmd) (cmd->immed & BIT(0))
196 #define GET_POWER_CONDITION_MODIFIER(cmd) (cmd->condition & BIT_MASK(4))
197 #define GET_POWER_CONDITION(cmd) ((cmd->start & 0xF0) >> 4)
198 #define GET_NO_FLUSH(cmd) (cmd->start & BIT(2))
199 #define GET_LOEJ(cmd) (cmd->start & BIT(1))
200 #define GET_START(cmd) (cmd->start & BIT(0))
201 /* SBC-4 Table 114 — POWER CONDITION and POWER CONDITION MODIFIER field */
202 enum power_condition {
203 POWER_COND_START_VALID = 0x0,
204 POWER_COND_ACTIVE = 0x1,
205 POWER_COND_IDLE = 0x2,
206 POWER_COND_STANDBY = 0x3,
207 POWER_COND_LU_CONTROL = 0x7,
208 POWER_COND_FORCE_IDLE_0 = 0xA,
209 POWER_COND_FORCE_STANDBY_0 = 0xB,
210 };
211
SCSI_CMD_STRUCT(START_STOP_UNIT)212 SCSI_CMD_STRUCT(START_STOP_UNIT) {
213 uint8_t opcode;
214 uint8_t immed;
215 uint8_t reserved;
216 uint8_t condition;
217 uint8_t start;
218 uint8_t control;
219 } __packed;
220
221 #define GET_PREVENT(cmd) (cmd->prevent & BIT_MASK(2))
222 /* SBC-4 Table 77 — PREVENT field */
223 enum prevent_field {
224 MEDIUM_REMOVAL_ALLOWED = 0,
225 MEDIUM_REMOVAL_SHALL_BE_PREVENTED = 1,
226 PREVENT_OBSOLETE_2 = 2,
227 PREVENT_OBSOLETE_3 = 3,
228 };
229
SCSI_CMD_STRUCT(PREVENT_ALLOW_MEDIUM_REMOVAL)230 SCSI_CMD_STRUCT(PREVENT_ALLOW_MEDIUM_REMOVAL) {
231 uint8_t opcode;
232 uint8_t reserved1;
233 uint8_t reserved2;
234 uint8_t reserved3;
235 uint8_t prevent;
236 uint8_t control;
237 } __packed;
238
SCSI_CMD_STRUCT(READ_FORMAT_CAPACITIES)239 SCSI_CMD_STRUCT(READ_FORMAT_CAPACITIES) {
240 uint8_t opcode;
241 uint8_t reserved1;
242 uint8_t reserved2;
243 uint8_t reserved3;
244 uint8_t reserved4;
245 uint8_t reserved5;
246 uint8_t reserved6;
247 uint16_t allocation_length;
248 uint8_t control;
249 } __packed;
250
251 struct capacity_list_header {
252 uint8_t reserved1;
253 uint8_t reserved2;
254 uint8_t reserved3;
255 uint8_t capacity_list_length;
256 } __packed;
257
258 enum descriptor_types {
259 UNFORMATTED_OR_BLANK_MEDIA = 1,
260 FORMATTED_MEDIA = 2,
261 NO_MEDIA_PRESENT_OR_UNKNOWN_CAPACITY = 3,
262 };
263
264 struct current_maximum_capacity_descriptor {
265 uint32_t number_of_blocks;
266 uint8_t type;
267 uint32_t block_length : 24;
268 } __packed;
269
270 struct scsi_read_format_capacities_response {
271 struct capacity_list_header header;
272 struct current_maximum_capacity_descriptor desc;
273 } __packed;
274
SCSI_CMD_STRUCT(READ_CAPACITY_10)275 SCSI_CMD_STRUCT(READ_CAPACITY_10) {
276 uint8_t opcode;
277 uint8_t reserved_or_obsolete[8];
278 uint8_t control;
279 } __packed;
280
281 struct scsi_read_capacity_10_response {
282 uint32_t last_lba;
283 uint32_t block_length;
284 } __packed;
285
SCSI_CMD_STRUCT(READ_10)286 SCSI_CMD_STRUCT(READ_10) {
287 uint8_t opcode;
288 uint8_t rdprotect;
289 uint32_t lba;
290 uint8_t group_number;
291 uint16_t transfer_length;
292 uint8_t control;
293 } __packed;
294
SCSI_CMD_STRUCT(WRITE_10)295 SCSI_CMD_STRUCT(WRITE_10) {
296 uint8_t opcode;
297 uint8_t wrprotect;
298 uint32_t lba;
299 uint8_t group_number;
300 uint16_t transfer_length;
301 uint8_t control;
302 } __packed;
303
SCSI_CMD_STRUCT(MODE_SENSE_10)304 SCSI_CMD_STRUCT(MODE_SENSE_10) {
305 uint8_t opcode;
306 uint8_t llbaa_dbd;
307 uint8_t page;
308 uint8_t subpage;
309 uint8_t reserved4;
310 uint8_t reserved5;
311 uint8_t reserved6;
312 uint16_t allocation_length;
313 uint8_t control;
314 } __packed;
315
316 /* SPC-5 7.5.6 Mode parameter header formats
317 * Table 444 — Mode parameter header(10)
318 */
319 struct scsi_mode_sense_10_response {
320 uint16_t mode_data_length;
321 uint8_t medium_type;
322 uint8_t device_specific_parameter;
323 uint8_t longlba;
324 uint8_t reserved5;
325 uint16_t block_descriptor_length;
326 } __packed;
327
update_disk_info(struct scsi_ctx * const ctx)328 static int update_disk_info(struct scsi_ctx *const ctx)
329 {
330 int status = disk_access_status(ctx->disk);
331
332 if (disk_access_ioctl(ctx->disk, DISK_IOCTL_GET_SECTOR_COUNT, &ctx->sector_count) != 0) {
333 ctx->sector_count = 0;
334 status = -EIO;
335 }
336
337 if (disk_access_ioctl(ctx->disk, DISK_IOCTL_GET_SECTOR_SIZE, &ctx->sector_size) != 0) {
338 ctx->sector_size = 0;
339 status = -EIO;
340 }
341
342 if (ctx->sector_size > CONFIG_USBD_MSC_SCSI_BUFFER_SIZE) {
343 status = -ENOMEM;
344 }
345
346 return status;
347 }
348
good(struct scsi_ctx * ctx,size_t data_in_bytes)349 static size_t good(struct scsi_ctx *ctx, size_t data_in_bytes)
350 {
351 ctx->status = GOOD;
352 ctx->sense_key = NO_SENSE;
353 ctx->asc = NO_ADDITIONAL_SENSE_INFORMATION;
354
355 return data_in_bytes;
356 }
357
illegal_request(struct scsi_ctx * ctx,enum scsi_additional_sense_code asc)358 static size_t illegal_request(struct scsi_ctx *ctx, enum scsi_additional_sense_code asc)
359 {
360 ctx->status = CHECK_CONDITION;
361 ctx->sense_key = ILLEGAL_REQUEST;
362 ctx->asc = asc;
363
364 return 0;
365 }
366
not_ready(struct scsi_ctx * ctx,enum scsi_additional_sense_code asc)367 static size_t not_ready(struct scsi_ctx *ctx, enum scsi_additional_sense_code asc)
368 {
369 ctx->status = CHECK_CONDITION;
370 ctx->sense_key = NOT_READY;
371 ctx->asc = asc;
372
373 return 0;
374 }
375
medium_error(struct scsi_ctx * ctx,enum scsi_additional_sense_code asc)376 static size_t medium_error(struct scsi_ctx *ctx, enum scsi_additional_sense_code asc)
377 {
378 ctx->status = CHECK_CONDITION;
379 ctx->sense_key = MEDIUM_ERROR;
380 ctx->asc = asc;
381
382 return 0;
383 }
384
scsi_init(struct scsi_ctx * ctx,const char * disk,const char * vendor,const char * product,const char * revision)385 void scsi_init(struct scsi_ctx *ctx, const char *disk, const char *vendor,
386 const char *product, const char *revision)
387 {
388 memset(ctx, 0, sizeof(struct scsi_ctx));
389 ctx->disk = disk;
390 ctx->vendor = vendor;
391 ctx->product = product;
392 ctx->revision = revision;
393
394 scsi_reset(ctx);
395 }
396
scsi_reset(struct scsi_ctx * ctx)397 void scsi_reset(struct scsi_ctx *ctx)
398 {
399 ctx->prevent_removal = false;
400 ctx->medium_loaded = true;
401 }
402
403 /* SPC-5 TEST UNIT READY command */
SCSI_CMD_HANDLER(TEST_UNIT_READY)404 SCSI_CMD_HANDLER(TEST_UNIT_READY)
405 {
406 if (!ctx->medium_loaded || update_disk_info(ctx) != DISK_STATUS_OK) {
407 return not_ready(ctx, MEDIUM_NOT_PRESENT);
408 } else {
409 return good(ctx, 0);
410 }
411 }
412
413 /* SPC-5 REQUEST SENSE command */
SCSI_CMD_HANDLER(REQUEST_SENSE)414 SCSI_CMD_HANDLER(REQUEST_SENSE)
415 {
416 struct scsi_request_sense_response r;
417 int length;
418
419 ctx->cmd_is_data_read = true;
420
421 /* SPC-2 should ignore DESC (it was reserved)
422 * SPC-3 can ignore DESC if not supported
423 * SPC-4 and later shall error out if DESC is not supported
424 */
425 if ((CLAIMED_CONFORMANCE_VERSION >= INQUIRY_VERSION_SPC_4) &&
426 (GET_REQUEST_SENSE_DESC(cmd))) {
427 return illegal_request(ctx, INVALID_FIELD_IN_CDB);
428 }
429
430 r.valid_code = SENSE_CODE_CURRENT_ERRORS;
431 r.obsolete = 0;
432 r.filemark_eom_ili_sense_key = ctx->sense_key & SENSE_KEY_MASK;
433 r.information = sys_cpu_to_be32(0);
434 r.additional_sense_length = sizeof(struct scsi_request_sense_response) - 1 -
435 offsetof(struct scsi_request_sense_response, additional_sense_length);
436 r.command_specific_information = sys_cpu_to_be32(0);
437 r.additional_sense_with_qualifier = sys_cpu_to_be16(ctx->asc);
438 r.field_replaceable_unit_code = 0;
439 r.sksv = 0;
440 r.sense_key_specific = sys_cpu_to_be16(0);
441
442 BUILD_ASSERT(sizeof(r) <= CONFIG_USBD_MSC_SCSI_BUFFER_SIZE);
443 length = MIN(cmd->allocation_length, sizeof(r));
444 memcpy(data_in_buf, &r, length);
445
446 /* REQUEST SENSE completed successfully, old sense information is
447 * cleared according to SPC-5.
448 */
449 return good(ctx, length);
450 }
451
fill_inquiry(struct scsi_ctx * ctx,uint8_t buf[static CONFIG_USBD_MSC_SCSI_BUFFER_SIZE])452 static int fill_inquiry(struct scsi_ctx *ctx,
453 uint8_t buf[static CONFIG_USBD_MSC_SCSI_BUFFER_SIZE])
454 {
455 /* For simplicity prepare whole response on stack and then copy
456 * requested length.
457 */
458 struct scsi_inquiry_response r;
459
460 memset(&r, 0, sizeof(struct scsi_inquiry_response));
461
462 /* Accessible; Direct access block device (SBC) */
463 r.peripheral = 0x00;
464 /* Removable; not a part of conglomerate. Note that when device is
465 * accessible via USB Mass Storage, it should always be marked as
466 * removable to allow Safely Remove Hardware.
467 */
468 r.rmb = 0x80;
469 r.version = CLAIMED_CONFORMANCE_VERSION;
470 /* ACA not supported; No SAM-5 LUNs; Complies to SPC */
471 r.format = 0x02;
472 r.additional_length = sizeof(struct scsi_inquiry_response) - 1 -
473 offsetof(struct scsi_inquiry_response, additional_length);
474 /* No embedded storage array controller available */
475 r.sccs = 0x00;
476 /* No embedded enclosure services */
477 r.encserv = 0x00;
478 /* Does not support SAM-5 command management model */
479 r.cmdque = 0x00;
480
481 strncpy(r.scsi_vendor, ctx->vendor, sizeof(r.scsi_vendor));
482 strncpy(r.product, ctx->product, sizeof(r.product));
483 strncpy(r.revision, ctx->revision, sizeof(r.revision));
484
485 BUILD_ASSERT(sizeof(r) <= CONFIG_USBD_MSC_SCSI_BUFFER_SIZE);
486 memcpy(buf, &r, sizeof(r));
487 return sizeof(r);
488 }
489
fill_vpd_page(struct scsi_ctx * ctx,enum vpd_page_code page,uint8_t buf[static CONFIG_USBD_MSC_SCSI_BUFFER_SIZE])490 static int fill_vpd_page(struct scsi_ctx *ctx, enum vpd_page_code page,
491 uint8_t buf[static CONFIG_USBD_MSC_SCSI_BUFFER_SIZE])
492 {
493 uint16_t offset = 0;
494 uint8_t *page_start = &buf[4];
495
496 switch (page) {
497 case VPD_SUPPORTED_VPD_PAGES:
498 /* Page Codes must appear in ascending order */
499 page_start[offset++] = VPD_SUPPORTED_VPD_PAGES;
500 page_start[offset++] = VPD_UNIT_SERIAL_NUMBER;
501 page_start[offset++] = VPD_DEVICE_IDENTIFICATION;
502 break;
503 case VPD_DEVICE_IDENTIFICATION:
504 /* Absolute minimum is one vendor based descriptor formed by
505 * concatenating Vendor ID and Unit Serial Number
506 *
507 * Other descriptors (EUI-64 or NAA) should be there but should
508 * is equivalent to "it is strongly recommended" and adding them
509 * is pretty much problematic because these descriptors involve
510 * (additional) unique identifiers.
511 */
512 page_start[offset++] = CODE_SET_ASCII;
513 page_start[offset++] = DESIGNATOR_T10_VENDOR_ID_BASED;
514 page_start[offset++] = 0x00;
515 page_start[offset++] = T10_VENDOR_LENGTH + sizeof(UNIT_SERIAL_NUMBER) - 1;
516 strncpy(&page_start[offset], ctx->vendor, T10_VENDOR_LENGTH);
517 offset += T10_VENDOR_LENGTH;
518 memcpy(&page_start[offset], UNIT_SERIAL_NUMBER, sizeof(UNIT_SERIAL_NUMBER) - 1);
519 offset += sizeof(UNIT_SERIAL_NUMBER) - 1;
520 break;
521 case VPD_UNIT_SERIAL_NUMBER:
522 memcpy(page_start, UNIT_SERIAL_NUMBER, sizeof(UNIT_SERIAL_NUMBER) - 1);
523 offset += sizeof(UNIT_SERIAL_NUMBER) - 1;
524 break;
525 default:
526 return -ENOTSUP;
527 }
528
529 /* Accessible; Direct access block device (SBC) */
530 buf[0] = 0x00;
531 buf[1] = page;
532 sys_put_be16(offset, &buf[2]);
533 return offset + 4;
534 }
535
536 /* SPC-5 6.7 INQUIRY command */
SCSI_CMD_HANDLER(INQUIRY)537 SCSI_CMD_HANDLER(INQUIRY)
538 {
539 int ret;
540
541 ctx->cmd_is_data_read = true;
542
543 if (cmd->cmddt_evpd & INQUIRY_CMDDT_OBSOLETE) {
544 /* Optional in SPC-2 and later obsoleted, do not support it */
545 ret = -EINVAL;
546 } else if (cmd->cmddt_evpd & INQUIRY_EVPD) {
547 /* Linux won't ask for VPD unless enabled with
548 * echo "Zephyr:Disk:0x10000000" > /proc/scsi/device_info
549 */
550 ret = MIN(sys_be16_to_cpu(cmd->allocation_length),
551 fill_vpd_page(ctx, cmd->page_code, data_in_buf));
552 } else if (cmd->page_code != 0) {
553 LOG_WRN("Page Code is %d but EVPD set", cmd->page_code);
554 ret = -EINVAL;
555 } else {
556 /* Standard inquiry */
557 ret = MIN(sys_be16_to_cpu(cmd->allocation_length),
558 fill_inquiry(ctx, data_in_buf));
559 }
560
561 if (ret < 0) {
562 return illegal_request(ctx, INVALID_FIELD_IN_CDB);
563 }
564 return good(ctx, ret);
565 }
566
567 /* SPC-5 6.14 MODE SENSE(6) command */
SCSI_CMD_HANDLER(MODE_SENSE_6)568 SCSI_CMD_HANDLER(MODE_SENSE_6)
569 {
570 struct scsi_mode_sense_6_response r;
571 int length;
572
573 ctx->cmd_is_data_read = true;
574
575 if (cmd->page != MODE_SENSE_PAGE_CODE_ALL_PAGES || cmd->subpage != 0) {
576 return illegal_request(ctx, INVALID_FIELD_IN_CDB);
577 }
578
579 r.mode_data_length = 3;
580 r.medium_type = 0x00;
581 r.device_specific_parameter = 0x00;
582 r.block_descriptor_length = 0x00;
583
584 BUILD_ASSERT(sizeof(r) <= CONFIG_USBD_MSC_SCSI_BUFFER_SIZE);
585 length = MIN(cmd->allocation_length, sizeof(r));
586 memcpy(data_in_buf, &r, length);
587 return good(ctx, length);
588 }
589
590 /* SBC-4 5.31 START STOP UNIT command */
SCSI_CMD_HANDLER(START_STOP_UNIT)591 SCSI_CMD_HANDLER(START_STOP_UNIT)
592 {
593 bool medium_loaded = ctx->medium_loaded;
594
595 /* Safe Hardware Removal is essentially START STOP UNIT command that
596 * asks to eject the media. Disk is shown as safely removed when
597 * device (SCSI target) responds with NOT READY/MEDIUM NOT PRESENT to
598 * TEST UNIT READY command
599 */
600 if (GET_POWER_CONDITION(cmd) == POWER_COND_START_VALID) {
601 if (GET_LOEJ(cmd)) {
602 if (GET_START(cmd)) {
603 medium_loaded = true;
604 } else {
605 medium_loaded = false;
606 }
607 }
608 }
609
610 if (!medium_loaded && ctx->medium_loaded && ctx->prevent_removal) {
611 return illegal_request(ctx, MEDIUM_REMOVAL_PREVENTED);
612 }
613
614 ctx->medium_loaded = medium_loaded;
615 return good(ctx, 0);
616 }
617
618 /* SBC-4 5.15 PREVENT ALLOW MEDIUM REMOVAL command */
SCSI_CMD_HANDLER(PREVENT_ALLOW_MEDIUM_REMOVAL)619 SCSI_CMD_HANDLER(PREVENT_ALLOW_MEDIUM_REMOVAL)
620 {
621 switch (GET_PREVENT(cmd)) {
622 case MEDIUM_REMOVAL_ALLOWED:
623 ctx->prevent_removal = false;
624 break;
625 case MEDIUM_REMOVAL_SHALL_BE_PREVENTED:
626 ctx->prevent_removal = true;
627 break;
628 case PREVENT_OBSOLETE_2:
629 case PREVENT_OBSOLETE_3:
630 break;
631 }
632
633 return good(ctx, 0);
634 }
635
636 /* MMC-6 6.23 READ FORMAT CAPACITIES command
637 * Microsoft Windows issues this command for all USB drives (no idea why)
638 */
SCSI_CMD_HANDLER(READ_FORMAT_CAPACITIES)639 SCSI_CMD_HANDLER(READ_FORMAT_CAPACITIES)
640 {
641 struct scsi_read_format_capacities_response r;
642 int length;
643
644 ctx->cmd_is_data_read = true;
645
646 memset(&r, 0, sizeof(r));
647 r.header.capacity_list_length = sizeof(r) - sizeof(r.header);
648
649 if (update_disk_info(ctx) < 0) {
650 r.desc.number_of_blocks = sys_cpu_to_be32(UINT32_MAX);
651 r.desc.type = NO_MEDIA_PRESENT_OR_UNKNOWN_CAPACITY;
652 } else {
653 r.desc.number_of_blocks = sys_cpu_to_be32(ctx->sector_count);
654 r.desc.type = FORMATTED_MEDIA;
655 }
656 r.desc.block_length = sys_cpu_to_be32(ctx->sector_size);
657
658 ctx->cmd_is_data_read = true;
659
660 BUILD_ASSERT(sizeof(r) <= CONFIG_USBD_MSC_SCSI_BUFFER_SIZE);
661 length = MIN(sys_be16_to_cpu(cmd->allocation_length), sizeof(r));
662 memcpy(data_in_buf, &r, length);
663 return good(ctx, length);
664 }
665
666 /* SBC-4 5.20 READ CAPACITY (10) command */
SCSI_CMD_HANDLER(READ_CAPACITY_10)667 SCSI_CMD_HANDLER(READ_CAPACITY_10)
668 {
669 struct scsi_read_capacity_10_response r;
670
671 ctx->cmd_is_data_read = true;
672
673 if (!ctx->medium_loaded || update_disk_info(ctx) != DISK_STATUS_OK) {
674 return not_ready(ctx, MEDIUM_NOT_PRESENT);
675 }
676
677 r.last_lba = sys_cpu_to_be32(ctx->sector_count ? ctx->sector_count - 1 : 0);
678 r.block_length = sys_cpu_to_be32(ctx->sector_size);
679
680 ctx->cmd_is_data_read = true;
681
682 BUILD_ASSERT(sizeof(r) <= CONFIG_USBD_MSC_SCSI_BUFFER_SIZE);
683 memcpy(data_in_buf, &r, sizeof(r));
684 return good(ctx, sizeof(r));
685 }
686
687 static int
validate_transfer_length(struct scsi_ctx * ctx,uint32_t lba,uint16_t length)688 validate_transfer_length(struct scsi_ctx *ctx, uint32_t lba, uint16_t length)
689 {
690 uint32_t last_lba = lba + length - 1;
691
692 if (lba >= ctx->sector_count) {
693 LOG_WRN("LBA %d is out of range", lba);
694 return -EINVAL;
695 }
696
697 /* SBC-4 explicitly mentions that transfer length 0 is OK */
698 if (length == 0) {
699 return 0;
700 }
701
702 if ((last_lba >= ctx->sector_count) || (last_lba < lba)) {
703 LOG_WRN("%d blocks starting at %d go out of bounds", length, lba);
704 return -EINVAL;
705 }
706
707 return 0;
708 }
709
fill_read_10(struct scsi_ctx * ctx,uint8_t buf[static CONFIG_USBD_MSC_SCSI_BUFFER_SIZE])710 static size_t fill_read_10(struct scsi_ctx *ctx,
711 uint8_t buf[static CONFIG_USBD_MSC_SCSI_BUFFER_SIZE])
712 {
713 uint32_t sectors;
714
715 sectors = MIN(CONFIG_USBD_MSC_SCSI_BUFFER_SIZE, ctx->remaining_data) / ctx->sector_size;
716 if (disk_access_read(ctx->disk, buf, ctx->lba, sectors) != 0) {
717 /* Terminate transfer */
718 sectors = 0;
719 }
720 ctx->lba += sectors;
721 return sectors * ctx->sector_size;
722 }
723
SCSI_CMD_HANDLER(READ_10)724 SCSI_CMD_HANDLER(READ_10)
725 {
726 uint32_t lba = sys_be32_to_cpu(cmd->lba);
727 uint16_t transfer_length = sys_be16_to_cpu(cmd->transfer_length);
728
729 ctx->cmd_is_data_read = true;
730
731 if (!ctx->medium_loaded || update_disk_info(ctx) != DISK_STATUS_OK) {
732 return not_ready(ctx, MEDIUM_NOT_PRESENT);
733 }
734
735 if (validate_transfer_length(ctx, lba, transfer_length)) {
736 return illegal_request(ctx, LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE);
737 }
738
739 ctx->read_cb = fill_read_10;
740 ctx->lba = lba;
741 ctx->remaining_data = ctx->sector_size * transfer_length;
742
743 return good(ctx, 0);
744 }
745
store_write_10(struct scsi_ctx * ctx,const uint8_t * buf,size_t length)746 static size_t store_write_10(struct scsi_ctx *ctx, const uint8_t *buf, size_t length)
747 {
748 uint32_t remaining_sectors;
749 uint32_t sectors;
750 bool error = false;
751
752 remaining_sectors = ctx->remaining_data / ctx->sector_size;
753 sectors = MIN(length, ctx->remaining_data) / ctx->sector_size;
754 if (disk_access_write(ctx->disk, buf, ctx->lba, sectors) != 0) {
755 /* Flush cache and terminate transfer */
756 sectors = 0;
757 remaining_sectors = 0;
758 error = true;
759 }
760
761 /* Flush cache if this is the last sector in transfer */
762 if (remaining_sectors - sectors == 0) {
763 if (disk_access_ioctl(ctx->disk, DISK_IOCTL_CTRL_SYNC, NULL)) {
764 LOG_ERR("Disk cache sync failed");
765 error = true;
766 }
767 }
768
769 ctx->lba += sectors;
770
771 if (error) {
772 return medium_error(ctx, WRITE_ERROR);
773 } else {
774 return sectors * ctx->sector_size;
775 }
776 }
777
SCSI_CMD_HANDLER(WRITE_10)778 SCSI_CMD_HANDLER(WRITE_10)
779 {
780 uint32_t lba = sys_be32_to_cpu(cmd->lba);
781 uint16_t transfer_length = sys_be16_to_cpu(cmd->transfer_length);
782
783 ctx->cmd_is_data_write = true;
784
785 if (!ctx->medium_loaded || update_disk_info(ctx) != DISK_STATUS_OK) {
786 return not_ready(ctx, MEDIUM_NOT_PRESENT);
787 }
788
789 if (validate_transfer_length(ctx, lba, transfer_length)) {
790 return illegal_request(ctx, LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE);
791 }
792
793 ctx->write_cb = store_write_10;
794 ctx->lba = lba;
795 ctx->remaining_data = ctx->sector_size * transfer_length;
796
797 return good(ctx, 0);
798 }
799
800 /* SPC-5 6.15 MODE SENSE(10) command */
SCSI_CMD_HANDLER(MODE_SENSE_10)801 SCSI_CMD_HANDLER(MODE_SENSE_10)
802 {
803 struct scsi_mode_sense_10_response r;
804 int length;
805
806 ctx->cmd_is_data_read = true;
807
808 if (cmd->page != MODE_SENSE_PAGE_CODE_ALL_PAGES || cmd->subpage != 0) {
809 return illegal_request(ctx, INVALID_FIELD_IN_CDB);
810 }
811
812 r.mode_data_length = sys_cpu_to_be16(6);
813 r.medium_type = 0x00;
814 r.device_specific_parameter = 0x00;
815 r.longlba = 0x00;
816 r.reserved5 = 0x00;
817 r.block_descriptor_length = sys_cpu_to_be16(0);
818
819 BUILD_ASSERT(sizeof(r) <= CONFIG_USBD_MSC_SCSI_BUFFER_SIZE);
820 length = MIN(sys_be16_to_cpu(cmd->allocation_length), sizeof(r));
821 memcpy(data_in_buf, &r, length);
822
823 return good(ctx, length);
824 }
825
scsi_usb_boot_cmd_len(const uint8_t * cb,int len)826 int scsi_usb_boot_cmd_len(const uint8_t *cb, int len)
827 {
828 /* Universal Serial Bus Mass Storage Specification For Bootability
829 * requires device to accept CBW padded to 12 bytes for commands
830 * documented in Bootability specification. Windows 11 uses padding
831 * for REQUEST SENSE command.
832 */
833 if (len != 12) {
834 return len;
835 }
836
837 switch (cb[0]) {
838 case TEST_UNIT_READY: return sizeof(SCSI_CMD_STRUCT(TEST_UNIT_READY));
839 case REQUEST_SENSE: return sizeof(SCSI_CMD_STRUCT(REQUEST_SENSE));
840 case INQUIRY: return sizeof(SCSI_CMD_STRUCT(INQUIRY));
841 case READ_CAPACITY_10: return sizeof(SCSI_CMD_STRUCT(READ_CAPACITY_10));
842 case READ_10: return sizeof(SCSI_CMD_STRUCT(READ_10));
843 case WRITE_10: return sizeof(SCSI_CMD_STRUCT(WRITE_10));
844 case MODE_SENSE_10: return sizeof(SCSI_CMD_STRUCT(MODE_SENSE_10));
845 default: return len;
846 }
847 }
848
scsi_cmd(struct scsi_ctx * ctx,const uint8_t * cb,int len,uint8_t data_in_buf[static CONFIG_USBD_MSC_SCSI_BUFFER_SIZE])849 size_t scsi_cmd(struct scsi_ctx *ctx, const uint8_t *cb, int len,
850 uint8_t data_in_buf[static CONFIG_USBD_MSC_SCSI_BUFFER_SIZE])
851 {
852 ctx->cmd_is_data_read = false;
853 ctx->cmd_is_data_write = false;
854 ctx->remaining_data = 0;
855 ctx->read_cb = NULL;
856 ctx->write_cb = NULL;
857
858 #define SCSI_CMD(opcode) do { \
859 if (len == sizeof(SCSI_CMD_STRUCT(opcode)) && cb[0] == opcode) { \
860 LOG_DBG("SCSI " #opcode); \
861 if (GET_CONTROL_NACA(((SCSI_CMD_STRUCT(opcode)*)cb))) { \
862 return illegal_request(ctx, INVALID_FIELD_IN_CDB); \
863 } \
864 return scsi_##opcode(ctx, (SCSI_CMD_STRUCT(opcode)*)cb, \
865 data_in_buf); \
866 } \
867 } while (0)
868
869 SCSI_CMD(TEST_UNIT_READY);
870 SCSI_CMD(REQUEST_SENSE);
871 SCSI_CMD(INQUIRY);
872 SCSI_CMD(MODE_SENSE_6);
873 SCSI_CMD(START_STOP_UNIT);
874 SCSI_CMD(PREVENT_ALLOW_MEDIUM_REMOVAL);
875 SCSI_CMD(READ_FORMAT_CAPACITIES);
876 SCSI_CMD(READ_CAPACITY_10);
877 SCSI_CMD(READ_10);
878 SCSI_CMD(WRITE_10);
879 SCSI_CMD(MODE_SENSE_10);
880
881 LOG_ERR("Unknown SCSI opcode 0x%02x", cb[0]);
882 return illegal_request(ctx, INVALID_FIELD_IN_CDB);
883 }
884
scsi_cmd_is_data_read(struct scsi_ctx * ctx)885 bool scsi_cmd_is_data_read(struct scsi_ctx *ctx)
886 {
887 return ctx->cmd_is_data_read;
888 }
889
scsi_cmd_is_data_write(struct scsi_ctx * ctx)890 bool scsi_cmd_is_data_write(struct scsi_ctx *ctx)
891 {
892 return ctx->cmd_is_data_write;
893 }
894
scsi_cmd_remaining_data_len(struct scsi_ctx * ctx)895 size_t scsi_cmd_remaining_data_len(struct scsi_ctx *ctx)
896 {
897 return ctx->remaining_data;
898 }
899
scsi_read_data(struct scsi_ctx * ctx,uint8_t buf[static CONFIG_USBD_MSC_SCSI_BUFFER_SIZE])900 size_t scsi_read_data(struct scsi_ctx *ctx,
901 uint8_t buf[static CONFIG_USBD_MSC_SCSI_BUFFER_SIZE])
902 {
903 size_t retrieved = 0;
904
905 __ASSERT_NO_MSG(ctx->cmd_is_data_read);
906
907 if ((ctx->remaining_data > 0) && ctx->read_cb) {
908 retrieved = ctx->read_cb(ctx, buf);
909 }
910 ctx->remaining_data -= retrieved;
911 if (retrieved == 0) {
912 /* Terminate transfer. Host will notice data residue. */
913 ctx->remaining_data = 0;
914 }
915 return retrieved;
916 }
917
scsi_write_data(struct scsi_ctx * ctx,const uint8_t * buf,size_t length)918 size_t scsi_write_data(struct scsi_ctx *ctx, const uint8_t *buf, size_t length)
919 {
920 size_t processed = 0;
921
922 __ASSERT_NO_MSG(ctx->cmd_is_data_write);
923
924 length = MIN(length, ctx->remaining_data);
925 if ((length > 0) && ctx->write_cb) {
926 processed = ctx->write_cb(ctx, buf, length);
927 }
928 ctx->remaining_data -= processed;
929 if (processed == 0) {
930 /* Terminate transfer. Host will notice data residue. */
931 ctx->remaining_data = 0;
932 }
933 return processed;
934 }
935
scsi_cmd_get_status(struct scsi_ctx * ctx)936 enum scsi_status_code scsi_cmd_get_status(struct scsi_ctx *ctx)
937 {
938 return ctx->status;
939 }
940