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