]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/VirtioScsiDxe/VirtioScsi.c
c2f6f412ff408f2f602948a59ffbda930bc41f14
[mirror_edk2.git] / OvmfPkg / VirtioScsiDxe / VirtioScsi.c
1 /** @file
2
3 This driver produces Extended SCSI Pass Thru Protocol instances for
4 virtio-scsi devices.
5
6 The implementation is basic:
7
8 - No hotplug / hot-unplug.
9
10 - Although EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru() could be a good match
11 for multiple in-flight virtio-scsi requests, we stick to synchronous
12 requests for now.
13
14 - Timeouts are not supported for EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru().
15
16 - Only one channel is supported. (At the time of this writing, host-side
17 virtio-scsi supports a single channel too.)
18
19 - Only one request queue is used (for the one synchronous request).
20
21 - The ResetChannel() and ResetTargetLun() functions of
22 EFI_EXT_SCSI_PASS_THRU_PROTOCOL are not supported (which is allowed by the
23 UEFI 2.3.1 Errata C specification), although
24 VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET could be a good match. That would
25 however require client code for the control queue, which is deemed
26 unreasonable for now.
27
28 Copyright (C) 2012, Red Hat, Inc.
29 Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.<BR>
30 Copyright (c) 2017, AMD Inc, All rights reserved.<BR>
31
32 This program and the accompanying materials are licensed and made available
33 under the terms and conditions of the BSD License which accompanies this
34 distribution. The full text of the license may be found at
35 http://opensource.org/licenses/bsd-license.php
36
37 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
38 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
39
40 **/
41
42 #include <IndustryStandard/VirtioScsi.h>
43 #include <Library/BaseMemoryLib.h>
44 #include <Library/DebugLib.h>
45 #include <Library/MemoryAllocationLib.h>
46 #include <Library/UefiBootServicesTableLib.h>
47 #include <Library/UefiLib.h>
48 #include <Library/VirtioLib.h>
49
50 #include "VirtioScsi.h"
51
52 /**
53
54 Convenience macros to read and write configuration elements of the
55 virtio-scsi VirtIo device.
56
57 The following macros make it possible to specify only the "core parameters"
58 for such accesses and to derive the rest. By the time VIRTIO_CFG_WRITE()
59 returns, the transaction will have been completed.
60
61 @param[in] Dev Pointer to the VSCSI_DEV structure.
62
63 @param[in] Field A field name from VSCSI_HDR, identifying the virtio-scsi
64 configuration item to access.
65
66 @param[in] Value (VIRTIO_CFG_WRITE() only.) The value to write to the
67 selected configuration item.
68
69 @param[out] Pointer (VIRTIO_CFG_READ() only.) The object to receive the
70 value read from the configuration item. Its type must be
71 one of UINT8, UINT16, UINT32, UINT64.
72
73
74 @return Status codes returned by Virtio->WriteDevice() / Virtio->ReadDevice().
75
76 **/
77
78 #define VIRTIO_CFG_WRITE(Dev, Field, Value) ((Dev)->VirtIo->WriteDevice ( \
79 (Dev)->VirtIo, \
80 OFFSET_OF_VSCSI (Field), \
81 SIZE_OF_VSCSI (Field), \
82 (Value) \
83 ))
84
85 #define VIRTIO_CFG_READ(Dev, Field, Pointer) ((Dev)->VirtIo->ReadDevice ( \
86 (Dev)->VirtIo, \
87 OFFSET_OF_VSCSI (Field), \
88 SIZE_OF_VSCSI (Field), \
89 sizeof *(Pointer), \
90 (Pointer) \
91 ))
92
93
94 //
95 // UEFI Spec 2.3.1 + Errata C, 14.7 Extended SCSI Pass Thru Protocol specifies
96 // the PassThru() interface. Beside returning a status code, the function must
97 // set some fields in the EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET in/out
98 // parameter on return. The following is a full list of those fields, for
99 // easier validation of PopulateRequest(), ParseResponse(), and
100 // VirtioScsiPassThru() below.
101 //
102 // - InTransferLength
103 // - OutTransferLength
104 // - HostAdapterStatus
105 // - TargetStatus
106 // - SenseDataLength
107 // - SenseData
108 //
109 // On any return from the PassThru() interface, these fields must be set,
110 // except if the returned status code is explicitly exempt. (Actually the
111 // implementation here conservatively sets these fields even in case not all
112 // of them would be required by the specification.)
113 //
114
115 /**
116
117 Populate a virtio-scsi request from the Extended SCSI Pass Thru Protocol
118 packet.
119
120 The caller is responsible for pre-zeroing the virtio-scsi request. The
121 Extended SCSI Pass Thru Protocol packet is modified, to be forwarded outwards
122 by VirtioScsiPassThru(), if invalid or unsupported parameters are detected.
123
124 @param[in] Dev The virtio-scsi host device the packet targets.
125
126 @param[in] Target The SCSI target controlled by the virtio-scsi host
127 device.
128
129 @param[in] Lun The Logical Unit Number under the SCSI target.
130
131 @param[in out] Packet The Extended SCSI Pass Thru Protocol packet the
132 function translates to a virtio-scsi request. On
133 failure this parameter relays error contents.
134
135 @param[out] Request The pre-zeroed virtio-scsi request to populate. This
136 parameter is volatile-qualified because we expect the
137 caller to append it to a virtio ring, thus
138 assignments to Request must be visible when the
139 function returns.
140
141
142 @retval EFI_SUCCESS The Extended SCSI Pass Thru Protocol packet was valid,
143 Request has been populated.
144
145 @return Otherwise, invalid or unsupported parameters were
146 detected. Status codes are meant for direct forwarding
147 by the EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru()
148 implementation.
149
150 **/
151 STATIC
152 EFI_STATUS
153 EFIAPI
154 PopulateRequest (
155 IN CONST VSCSI_DEV *Dev,
156 IN UINT16 Target,
157 IN UINT64 Lun,
158 IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
159 OUT volatile VIRTIO_SCSI_REQ *Request
160 )
161 {
162 UINTN Idx;
163
164 if (
165 //
166 // bidirectional transfer was requested, but the host doesn't support it
167 //
168 (Packet->InTransferLength > 0 && Packet->OutTransferLength > 0 &&
169 !Dev->InOutSupported) ||
170
171 //
172 // a target / LUN was addressed that's impossible to encode for the host
173 //
174 Target > 0xFF || Lun >= 0x4000 ||
175
176 //
177 // Command Descriptor Block bigger than VIRTIO_SCSI_CDB_SIZE
178 //
179 Packet->CdbLength > VIRTIO_SCSI_CDB_SIZE ||
180
181 //
182 // From virtio-0.9.5, 2.3.2 Descriptor Table:
183 // "no descriptor chain may be more than 2^32 bytes long in total".
184 //
185 (UINT64) Packet->InTransferLength + Packet->OutTransferLength > SIZE_1GB
186 ) {
187
188 //
189 // this error code doesn't require updates to the Packet output fields
190 //
191 return EFI_UNSUPPORTED;
192 }
193
194 if (
195 //
196 // addressed invalid device
197 //
198 Target > Dev->MaxTarget || Lun > Dev->MaxLun ||
199
200 //
201 // invalid direction (there doesn't seem to be a macro for the "no data
202 // transferred" "direction", eg. for TEST UNIT READY)
203 //
204 Packet->DataDirection > EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL ||
205
206 //
207 // trying to receive, but destination pointer is NULL, or contradicting
208 // transfer direction
209 //
210 (Packet->InTransferLength > 0 &&
211 (Packet->InDataBuffer == NULL ||
212 Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE
213 )
214 ) ||
215
216 //
217 // trying to send, but source pointer is NULL, or contradicting transfer
218 // direction
219 //
220 (Packet->OutTransferLength > 0 &&
221 (Packet->OutDataBuffer == NULL ||
222 Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ
223 )
224 )
225 ) {
226
227 //
228 // this error code doesn't require updates to the Packet output fields
229 //
230 return EFI_INVALID_PARAMETER;
231 }
232
233 //
234 // Catch oversized requests eagerly. If this condition evaluates to false,
235 // then the combined size of a bidirectional request will not exceed the
236 // virtio-scsi device's transfer limit either.
237 //
238 if (ALIGN_VALUE (Packet->OutTransferLength, 512) / 512
239 > Dev->MaxSectors / 2 ||
240 ALIGN_VALUE (Packet->InTransferLength, 512) / 512
241 > Dev->MaxSectors / 2) {
242 Packet->InTransferLength = (Dev->MaxSectors / 2) * 512;
243 Packet->OutTransferLength = (Dev->MaxSectors / 2) * 512;
244 Packet->HostAdapterStatus =
245 EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
246 Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
247 Packet->SenseDataLength = 0;
248 return EFI_BAD_BUFFER_SIZE;
249 }
250
251 //
252 // target & LUN encoding: see virtio-0.9.5, Appendix I: SCSI Host Device,
253 // Device Operation: request queues
254 //
255 Request->Lun[0] = 1;
256 Request->Lun[1] = (UINT8) Target;
257 Request->Lun[2] = (UINT8) (((UINT32)Lun >> 8) | 0x40);
258 Request->Lun[3] = (UINT8) Lun;
259
260 //
261 // CopyMem() would cast away the "volatile" qualifier before access, which is
262 // undefined behavior (ISO C99 6.7.3p5)
263 //
264 for (Idx = 0; Idx < Packet->CdbLength; ++Idx) {
265 Request->Cdb[Idx] = ((UINT8 *) Packet->Cdb)[Idx];
266 }
267
268 return EFI_SUCCESS;
269 }
270
271
272 /**
273
274 Parse the virtio-scsi device's response, translate it to an EFI status code,
275 and update the Extended SCSI Pass Thru Protocol packet, to be returned by
276 the EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru() implementation.
277
278 @param[in out] Packet The Extended SCSI Pass Thru Protocol packet that has
279 been translated to a virtio-scsi request with
280 PopulateRequest(), and processed by the host. On
281 output this parameter is updated with response or
282 error contents.
283
284 @param[in] Response The virtio-scsi response structure to parse. We expect
285 it to come from a virtio ring, thus it is qualified
286 volatile.
287
288
289 @return PassThru() status codes mandated by UEFI Spec 2.3.1 + Errata C, 14.7
290 Extended SCSI Pass Thru Protocol.
291
292 **/
293 STATIC
294 EFI_STATUS
295 EFIAPI
296 ParseResponse (
297 IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
298 IN CONST volatile VIRTIO_SCSI_RESP *Response
299 )
300 {
301 UINTN ResponseSenseLen;
302 UINTN Idx;
303
304 //
305 // return sense data (length and contents) in all cases, truncated if needed
306 //
307 ResponseSenseLen = MIN (Response->SenseLen, VIRTIO_SCSI_SENSE_SIZE);
308 if (Packet->SenseDataLength > ResponseSenseLen) {
309 Packet->SenseDataLength = (UINT8) ResponseSenseLen;
310 }
311 for (Idx = 0; Idx < Packet->SenseDataLength; ++Idx) {
312 ((UINT8 *) Packet->SenseData)[Idx] = Response->Sense[Idx];
313 }
314
315 //
316 // Report actual transfer lengths. The logic below covers all three
317 // DataDirections (read, write, bidirectional).
318 //
319 // -+- @ 0
320 // |
321 // | write ^ @ Residual (unprocessed)
322 // | |
323 // -+- @ OutTransferLength -+- @ InTransferLength
324 // | |
325 // | read |
326 // | |
327 // V @ OutTransferLength + InTransferLength -+- @ 0
328 //
329 if (Response->Residual <= Packet->InTransferLength) {
330 Packet->InTransferLength -= Response->Residual;
331 }
332 else {
333 Packet->OutTransferLength -= Response->Residual - Packet->InTransferLength;
334 Packet->InTransferLength = 0;
335 }
336
337 //
338 // report target status in all cases
339 //
340 Packet->TargetStatus = Response->Status;
341
342 //
343 // host adapter status and function return value depend on virtio-scsi
344 // response code
345 //
346 switch (Response->Response) {
347 case VIRTIO_SCSI_S_OK:
348 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;
349 return EFI_SUCCESS;
350
351 case VIRTIO_SCSI_S_OVERRUN:
352 Packet->HostAdapterStatus =
353 EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
354 break;
355
356 case VIRTIO_SCSI_S_BAD_TARGET:
357 //
358 // This is non-intuitive but explicitly required by the
359 // EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru() specification for
360 // disconnected (but otherwise valid) target / LUN addresses.
361 //
362 Packet->HostAdapterStatus =
363 EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND;
364 return EFI_TIMEOUT;
365
366 case VIRTIO_SCSI_S_RESET:
367 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_RESET;
368 break;
369
370 case VIRTIO_SCSI_S_BUSY:
371 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;
372 return EFI_NOT_READY;
373
374 //
375 // Lump together the rest. The mapping for VIRTIO_SCSI_S_ABORTED is
376 // intentional as well, not an oversight.
377 //
378 case VIRTIO_SCSI_S_ABORTED:
379 case VIRTIO_SCSI_S_TRANSPORT_FAILURE:
380 case VIRTIO_SCSI_S_TARGET_FAILURE:
381 case VIRTIO_SCSI_S_NEXUS_FAILURE:
382 case VIRTIO_SCSI_S_FAILURE:
383 default:
384 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
385 }
386
387 return EFI_DEVICE_ERROR;
388 }
389
390
391 //
392 // The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL
393 // for the virtio-scsi HBA. Refer to UEFI Spec 2.3.1 + Errata C, sections
394 // - 14.1 SCSI Driver Model Overview,
395 // - 14.7 Extended SCSI Pass Thru Protocol.
396 //
397
398 EFI_STATUS
399 EFIAPI
400 VirtioScsiPassThru (
401 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
402 IN UINT8 *Target,
403 IN UINT64 Lun,
404 IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
405 IN EFI_EVENT Event OPTIONAL
406 )
407 {
408 VSCSI_DEV *Dev;
409 UINT16 TargetValue;
410 EFI_STATUS Status;
411 volatile VIRTIO_SCSI_REQ Request;
412 volatile VIRTIO_SCSI_RESP Response;
413 DESC_INDICES Indices;
414
415 ZeroMem ((VOID*) &Request, sizeof (Request));
416 ZeroMem ((VOID*) &Response, sizeof (Response));
417
418 Dev = VIRTIO_SCSI_FROM_PASS_THRU (This);
419 CopyMem (&TargetValue, Target, sizeof TargetValue);
420
421 Status = PopulateRequest (Dev, TargetValue, Lun, Packet, &Request);
422 if (EFI_ERROR (Status)) {
423 return Status;
424 }
425
426 VirtioPrepare (&Dev->Ring, &Indices);
427
428 //
429 // preset a host status for ourselves that we do not accept as success
430 //
431 Response.Response = VIRTIO_SCSI_S_FAILURE;
432
433 //
434 // ensured by VirtioScsiInit() -- this predicate, in combination with the
435 // lock-step progress, ensures we don't have to track free descriptors.
436 //
437 ASSERT (Dev->Ring.QueueSize >= 4);
438
439 //
440 // enqueue Request
441 //
442 VirtioAppendDesc (&Dev->Ring, (UINTN) &Request, sizeof Request,
443 VRING_DESC_F_NEXT, &Indices);
444
445 //
446 // enqueue "dataout" if any
447 //
448 if (Packet->OutTransferLength > 0) {
449 VirtioAppendDesc (&Dev->Ring, (UINTN) Packet->OutDataBuffer,
450 Packet->OutTransferLength, VRING_DESC_F_NEXT, &Indices);
451 }
452
453 //
454 // enqueue Response, to be written by the host
455 //
456 VirtioAppendDesc (&Dev->Ring, (UINTN) &Response, sizeof Response,
457 VRING_DESC_F_WRITE | (Packet->InTransferLength > 0 ?
458 VRING_DESC_F_NEXT : 0),
459 &Indices);
460
461 //
462 // enqueue "datain" if any, to be written by the host
463 //
464 if (Packet->InTransferLength > 0) {
465 VirtioAppendDesc (&Dev->Ring, (UINTN) Packet->InDataBuffer,
466 Packet->InTransferLength, VRING_DESC_F_WRITE, &Indices);
467 }
468
469 // If kicking the host fails, we must fake a host adapter error.
470 // EFI_NOT_READY would save us the effort, but it would also suggest that the
471 // caller retry.
472 //
473 if (VirtioFlush (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE, &Dev->Ring,
474 &Indices, NULL) != EFI_SUCCESS) {
475 Packet->InTransferLength = 0;
476 Packet->OutTransferLength = 0;
477 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
478 Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
479 Packet->SenseDataLength = 0;
480 return EFI_DEVICE_ERROR;
481 }
482
483 return ParseResponse (Packet, &Response);
484 }
485
486
487 EFI_STATUS
488 EFIAPI
489 VirtioScsiGetNextTargetLun (
490 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
491 IN OUT UINT8 **TargetPointer,
492 IN OUT UINT64 *Lun
493 )
494 {
495 UINT8 *Target;
496 UINTN Idx;
497 UINT16 LastTarget;
498 VSCSI_DEV *Dev;
499
500 //
501 // the TargetPointer input parameter is unnecessarily a pointer-to-pointer
502 //
503 Target = *TargetPointer;
504
505 //
506 // Search for first non-0xFF byte. If not found, return first target & LUN.
507 //
508 for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx)
509 ;
510 if (Idx == TARGET_MAX_BYTES) {
511 SetMem (Target, TARGET_MAX_BYTES, 0x00);
512 *Lun = 0;
513 return EFI_SUCCESS;
514 }
515
516 //
517 // see the TARGET_MAX_BYTES check in "VirtioScsi.h"
518 //
519 CopyMem (&LastTarget, Target, sizeof LastTarget);
520
521 //
522 // increment (target, LUN) pair if valid on input
523 //
524 Dev = VIRTIO_SCSI_FROM_PASS_THRU (This);
525 if (LastTarget > Dev->MaxTarget || *Lun > Dev->MaxLun) {
526 return EFI_INVALID_PARAMETER;
527 }
528
529 if (*Lun < Dev->MaxLun) {
530 ++*Lun;
531 return EFI_SUCCESS;
532 }
533
534 if (LastTarget < Dev->MaxTarget) {
535 *Lun = 0;
536 ++LastTarget;
537 CopyMem (Target, &LastTarget, sizeof LastTarget);
538 return EFI_SUCCESS;
539 }
540
541 return EFI_NOT_FOUND;
542 }
543
544
545 EFI_STATUS
546 EFIAPI
547 VirtioScsiBuildDevicePath (
548 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
549 IN UINT8 *Target,
550 IN UINT64 Lun,
551 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
552 )
553 {
554 UINT16 TargetValue;
555 VSCSI_DEV *Dev;
556 SCSI_DEVICE_PATH *ScsiDevicePath;
557
558 if (DevicePath == NULL) {
559 return EFI_INVALID_PARAMETER;
560 }
561
562 CopyMem (&TargetValue, Target, sizeof TargetValue);
563 Dev = VIRTIO_SCSI_FROM_PASS_THRU (This);
564 if (TargetValue > Dev->MaxTarget || Lun > Dev->MaxLun || Lun > 0xFFFF) {
565 return EFI_NOT_FOUND;
566 }
567
568 ScsiDevicePath = AllocatePool (sizeof *ScsiDevicePath);
569 if (ScsiDevicePath == NULL) {
570 return EFI_OUT_OF_RESOURCES;
571 }
572
573 ScsiDevicePath->Header.Type = MESSAGING_DEVICE_PATH;
574 ScsiDevicePath->Header.SubType = MSG_SCSI_DP;
575 ScsiDevicePath->Header.Length[0] = (UINT8) sizeof *ScsiDevicePath;
576 ScsiDevicePath->Header.Length[1] = (UINT8) (sizeof *ScsiDevicePath >> 8);
577 ScsiDevicePath->Pun = TargetValue;
578 ScsiDevicePath->Lun = (UINT16) Lun;
579
580 *DevicePath = &ScsiDevicePath->Header;
581 return EFI_SUCCESS;
582 }
583
584
585 EFI_STATUS
586 EFIAPI
587 VirtioScsiGetTargetLun (
588 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
589 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
590 OUT UINT8 **TargetPointer,
591 OUT UINT64 *Lun
592 )
593 {
594 SCSI_DEVICE_PATH *ScsiDevicePath;
595 VSCSI_DEV *Dev;
596 UINT8 *Target;
597
598 if (DevicePath == NULL || TargetPointer == NULL || *TargetPointer == NULL ||
599 Lun == NULL) {
600 return EFI_INVALID_PARAMETER;
601 }
602
603 if (DevicePath->Type != MESSAGING_DEVICE_PATH ||
604 DevicePath->SubType != MSG_SCSI_DP) {
605 return EFI_UNSUPPORTED;
606 }
607
608 ScsiDevicePath = (SCSI_DEVICE_PATH *) DevicePath;
609 Dev = VIRTIO_SCSI_FROM_PASS_THRU (This);
610 if (ScsiDevicePath->Pun > Dev->MaxTarget ||
611 ScsiDevicePath->Lun > Dev->MaxLun) {
612 return EFI_NOT_FOUND;
613 }
614
615 //
616 // a) the TargetPointer input parameter is unnecessarily a pointer-to-pointer
617 // b) see the TARGET_MAX_BYTES check in "VirtioScsi.h"
618 // c) ScsiDevicePath->Pun is an UINT16
619 //
620 Target = *TargetPointer;
621 CopyMem (Target, &ScsiDevicePath->Pun, 2);
622 SetMem (Target + 2, TARGET_MAX_BYTES - 2, 0x00);
623
624 *Lun = ScsiDevicePath->Lun;
625 return EFI_SUCCESS;
626 }
627
628
629 EFI_STATUS
630 EFIAPI
631 VirtioScsiResetChannel (
632 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This
633 )
634 {
635 return EFI_UNSUPPORTED;
636 }
637
638
639 EFI_STATUS
640 EFIAPI
641 VirtioScsiResetTargetLun (
642 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
643 IN UINT8 *Target,
644 IN UINT64 Lun
645 )
646 {
647 return EFI_UNSUPPORTED;
648 }
649
650
651 EFI_STATUS
652 EFIAPI
653 VirtioScsiGetNextTarget (
654 IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
655 IN OUT UINT8 **TargetPointer
656 )
657 {
658 UINT8 *Target;
659 UINTN Idx;
660 UINT16 LastTarget;
661 VSCSI_DEV *Dev;
662
663 //
664 // the TargetPointer input parameter is unnecessarily a pointer-to-pointer
665 //
666 Target = *TargetPointer;
667
668 //
669 // Search for first non-0xFF byte. If not found, return first target.
670 //
671 for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx)
672 ;
673 if (Idx == TARGET_MAX_BYTES) {
674 SetMem (Target, TARGET_MAX_BYTES, 0x00);
675 return EFI_SUCCESS;
676 }
677
678 //
679 // see the TARGET_MAX_BYTES check in "VirtioScsi.h"
680 //
681 CopyMem (&LastTarget, Target, sizeof LastTarget);
682
683 //
684 // increment target if valid on input
685 //
686 Dev = VIRTIO_SCSI_FROM_PASS_THRU (This);
687 if (LastTarget > Dev->MaxTarget) {
688 return EFI_INVALID_PARAMETER;
689 }
690
691 if (LastTarget < Dev->MaxTarget) {
692 ++LastTarget;
693 CopyMem (Target, &LastTarget, sizeof LastTarget);
694 return EFI_SUCCESS;
695 }
696
697 return EFI_NOT_FOUND;
698 }
699
700
701 STATIC
702 EFI_STATUS
703 EFIAPI
704 VirtioScsiInit (
705 IN OUT VSCSI_DEV *Dev
706 )
707 {
708 UINT8 NextDevStat;
709 EFI_STATUS Status;
710
711 UINT64 Features;
712 UINT16 MaxChannel; // for validation only
713 UINT32 NumQueues; // for validation only
714 UINT16 QueueSize;
715
716 //
717 // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
718 //
719 NextDevStat = 0; // step 1 -- reset device
720 Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
721 if (EFI_ERROR (Status)) {
722 goto Failed;
723 }
724
725 NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence
726 Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
727 if (EFI_ERROR (Status)) {
728 goto Failed;
729 }
730
731 NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it
732 Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
733 if (EFI_ERROR (Status)) {
734 goto Failed;
735 }
736
737 //
738 // Set Page Size - MMIO VirtIo Specific
739 //
740 Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE);
741 if (EFI_ERROR (Status)) {
742 goto Failed;
743 }
744
745 //
746 // step 4a -- retrieve and validate features
747 //
748 Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);
749 if (EFI_ERROR (Status)) {
750 goto Failed;
751 }
752 Dev->InOutSupported = (BOOLEAN) ((Features & VIRTIO_SCSI_F_INOUT) != 0);
753
754 Status = VIRTIO_CFG_READ (Dev, MaxChannel, &MaxChannel);
755 if (EFI_ERROR (Status)) {
756 goto Failed;
757 }
758 if (MaxChannel != 0) {
759 //
760 // this driver is for a single-channel virtio-scsi HBA
761 //
762 Status = EFI_UNSUPPORTED;
763 goto Failed;
764 }
765
766 Status = VIRTIO_CFG_READ (Dev, NumQueues, &NumQueues);
767 if (EFI_ERROR (Status)) {
768 goto Failed;
769 }
770 if (NumQueues < 1) {
771 Status = EFI_UNSUPPORTED;
772 goto Failed;
773 }
774
775 Status = VIRTIO_CFG_READ (Dev, MaxTarget, &Dev->MaxTarget);
776 if (EFI_ERROR (Status)) {
777 goto Failed;
778 }
779 if (Dev->MaxTarget > PcdGet16 (PcdVirtioScsiMaxTargetLimit)) {
780 Dev->MaxTarget = PcdGet16 (PcdVirtioScsiMaxTargetLimit);
781 }
782
783 Status = VIRTIO_CFG_READ (Dev, MaxLun, &Dev->MaxLun);
784 if (EFI_ERROR (Status)) {
785 goto Failed;
786 }
787 if (Dev->MaxLun > PcdGet32 (PcdVirtioScsiMaxLunLimit)) {
788 Dev->MaxLun = PcdGet32 (PcdVirtioScsiMaxLunLimit);
789 }
790
791 Status = VIRTIO_CFG_READ (Dev, MaxSectors, &Dev->MaxSectors);
792 if (EFI_ERROR (Status)) {
793 goto Failed;
794 }
795 if (Dev->MaxSectors < 2) {
796 //
797 // We must be able to halve it for bidirectional transfers
798 // (see EFI_BAD_BUFFER_SIZE in PopulateRequest()).
799 //
800 Status = EFI_UNSUPPORTED;
801 goto Failed;
802 }
803
804 Features &= VIRTIO_SCSI_F_INOUT | VIRTIO_F_VERSION_1;
805
806 //
807 // In virtio-1.0, feature negotiation is expected to complete before queue
808 // discovery, and the device can also reject the selected set of features.
809 //
810 if (Dev->VirtIo->Revision >= VIRTIO_SPEC_REVISION (1, 0, 0)) {
811 Status = Virtio10WriteFeatures (Dev->VirtIo, Features, &NextDevStat);
812 if (EFI_ERROR (Status)) {
813 goto Failed;
814 }
815 }
816
817 //
818 // step 4b -- allocate request virtqueue
819 //
820 Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE);
821 if (EFI_ERROR (Status)) {
822 goto Failed;
823 }
824 Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);
825 if (EFI_ERROR (Status)) {
826 goto Failed;
827 }
828 //
829 // VirtioScsiPassThru() uses at most four descriptors
830 //
831 if (QueueSize < 4) {
832 Status = EFI_UNSUPPORTED;
833 goto Failed;
834 }
835
836 Status = VirtioRingInit (Dev->VirtIo, QueueSize, &Dev->Ring);
837 if (EFI_ERROR (Status)) {
838 goto Failed;
839 }
840
841 //
842 // Additional steps for MMIO: align the queue appropriately, and set the
843 // size. If anything fails from here on, we must release the ring resources.
844 //
845 Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);
846 if (EFI_ERROR (Status)) {
847 goto ReleaseQueue;
848 }
849
850 Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);
851 if (EFI_ERROR (Status)) {
852 goto ReleaseQueue;
853 }
854
855 //
856 // step 4c -- Report GPFN (guest-physical frame number) of queue.
857 //
858 Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring);
859 if (EFI_ERROR (Status)) {
860 goto ReleaseQueue;
861 }
862
863 //
864 // step 5 -- Report understood features and guest-tuneables.
865 //
866 if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) {
867 Features &= ~(UINT64)VIRTIO_F_VERSION_1;
868 Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);
869 if (EFI_ERROR (Status)) {
870 goto ReleaseQueue;
871 }
872 }
873
874 //
875 // We expect these maximum sizes from the host. Since they are
876 // guest-negotiable, ask for them rather than just checking them.
877 //
878 Status = VIRTIO_CFG_WRITE (Dev, CdbSize, VIRTIO_SCSI_CDB_SIZE);
879 if (EFI_ERROR (Status)) {
880 goto ReleaseQueue;
881 }
882 Status = VIRTIO_CFG_WRITE (Dev, SenseSize, VIRTIO_SCSI_SENSE_SIZE);
883 if (EFI_ERROR (Status)) {
884 goto ReleaseQueue;
885 }
886
887 //
888 // step 6 -- initialization complete
889 //
890 NextDevStat |= VSTAT_DRIVER_OK;
891 Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
892 if (EFI_ERROR (Status)) {
893 goto ReleaseQueue;
894 }
895
896 //
897 // populate the exported interface's attributes
898 //
899 Dev->PassThru.Mode = &Dev->PassThruMode;
900 Dev->PassThru.PassThru = &VirtioScsiPassThru;
901 Dev->PassThru.GetNextTargetLun = &VirtioScsiGetNextTargetLun;
902 Dev->PassThru.BuildDevicePath = &VirtioScsiBuildDevicePath;
903 Dev->PassThru.GetTargetLun = &VirtioScsiGetTargetLun;
904 Dev->PassThru.ResetChannel = &VirtioScsiResetChannel;
905 Dev->PassThru.ResetTargetLun = &VirtioScsiResetTargetLun;
906 Dev->PassThru.GetNextTarget = &VirtioScsiGetNextTarget;
907
908 //
909 // AdapterId is a target for which no handle will be created during bus scan.
910 // Prevent any conflict with real devices.
911 //
912 Dev->PassThruMode.AdapterId = 0xFFFFFFFF;
913
914 //
915 // Set both physical and logical attributes for non-RAID SCSI channel. See
916 // Driver Writer's Guide for UEFI 2.3.1 v1.01, 20.1.5 Implementing Extended
917 // SCSI Pass Thru Protocol.
918 //
919 Dev->PassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL |
920 EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
921
922 //
923 // no restriction on transfer buffer alignment
924 //
925 Dev->PassThruMode.IoAlign = 0;
926
927 return EFI_SUCCESS;
928
929 ReleaseQueue:
930 VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
931
932 Failed:
933 //
934 // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device
935 // Status. VirtIo access failure here should not mask the original error.
936 //
937 NextDevStat |= VSTAT_FAILED;
938 Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
939
940 Dev->InOutSupported = FALSE;
941 Dev->MaxTarget = 0;
942 Dev->MaxLun = 0;
943 Dev->MaxSectors = 0;
944
945 return Status; // reached only via Failed above
946 }
947
948
949 STATIC
950 VOID
951 EFIAPI
952 VirtioScsiUninit (
953 IN OUT VSCSI_DEV *Dev
954 )
955 {
956 //
957 // Reset the virtual device -- see virtio-0.9.5, 2.2.2.1 Device Status. When
958 // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
959 // the old comms area.
960 //
961 Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
962
963 Dev->InOutSupported = FALSE;
964 Dev->MaxTarget = 0;
965 Dev->MaxLun = 0;
966 Dev->MaxSectors = 0;
967
968 VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
969
970 SetMem (&Dev->PassThru, sizeof Dev->PassThru, 0x00);
971 SetMem (&Dev->PassThruMode, sizeof Dev->PassThruMode, 0x00);
972 }
973
974
975 //
976 // Event notification function enqueued by ExitBootServices().
977 //
978
979 STATIC
980 VOID
981 EFIAPI
982 VirtioScsiExitBoot (
983 IN EFI_EVENT Event,
984 IN VOID *Context
985 )
986 {
987 VSCSI_DEV *Dev;
988
989 //
990 // Reset the device. This causes the hypervisor to forget about the virtio
991 // ring.
992 //
993 // We allocated said ring in EfiBootServicesData type memory, and code
994 // executing after ExitBootServices() is permitted to overwrite it.
995 //
996 Dev = Context;
997 Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
998 }
999
1000
1001 //
1002 // Probe, start and stop functions of this driver, called by the DXE core for
1003 // specific devices.
1004 //
1005 // The following specifications document these interfaces:
1006 // - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
1007 // - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
1008 //
1009 // The implementation follows:
1010 // - Driver Writer's Guide for UEFI 2.3.1 v1.01
1011 // - 5.1.3.4 OpenProtocol() and CloseProtocol()
1012 // - UEFI Spec 2.3.1 + Errata C
1013 // - 6.3 Protocol Handler Services
1014 //
1015
1016 EFI_STATUS
1017 EFIAPI
1018 VirtioScsiDriverBindingSupported (
1019 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1020 IN EFI_HANDLE DeviceHandle,
1021 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1022 )
1023 {
1024 EFI_STATUS Status;
1025 VIRTIO_DEVICE_PROTOCOL *VirtIo;
1026
1027 //
1028 // Attempt to open the device with the VirtIo set of interfaces. On success,
1029 // the protocol is "instantiated" for the VirtIo device. Covers duplicate open
1030 // attempts (EFI_ALREADY_STARTED).
1031 //
1032 Status = gBS->OpenProtocol (
1033 DeviceHandle, // candidate device
1034 &gVirtioDeviceProtocolGuid, // for generic VirtIo access
1035 (VOID **)&VirtIo, // handle to instantiate
1036 This->DriverBindingHandle, // requestor driver identity
1037 DeviceHandle, // ControllerHandle, according to
1038 // the UEFI Driver Model
1039 EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to
1040 // the device; to be released
1041 );
1042 if (EFI_ERROR (Status)) {
1043 return Status;
1044 }
1045
1046 if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_SCSI_HOST) {
1047 Status = EFI_UNSUPPORTED;
1048 }
1049
1050 //
1051 // We needed VirtIo access only transitorily, to see whether we support the
1052 // device or not.
1053 //
1054 gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
1055 This->DriverBindingHandle, DeviceHandle);
1056 return Status;
1057 }
1058
1059
1060 EFI_STATUS
1061 EFIAPI
1062 VirtioScsiDriverBindingStart (
1063 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1064 IN EFI_HANDLE DeviceHandle,
1065 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1066 )
1067 {
1068 VSCSI_DEV *Dev;
1069 EFI_STATUS Status;
1070
1071 Dev = (VSCSI_DEV *) AllocateZeroPool (sizeof *Dev);
1072 if (Dev == NULL) {
1073 return EFI_OUT_OF_RESOURCES;
1074 }
1075
1076 Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
1077 (VOID **)&Dev->VirtIo, This->DriverBindingHandle,
1078 DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
1079 if (EFI_ERROR (Status)) {
1080 goto FreeVirtioScsi;
1081 }
1082
1083 //
1084 // VirtIo access granted, configure virtio-scsi device.
1085 //
1086 Status = VirtioScsiInit (Dev);
1087 if (EFI_ERROR (Status)) {
1088 goto CloseVirtIo;
1089 }
1090
1091 Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
1092 &VirtioScsiExitBoot, Dev, &Dev->ExitBoot);
1093 if (EFI_ERROR (Status)) {
1094 goto UninitDev;
1095 }
1096
1097 //
1098 // Setup complete, attempt to export the driver instance's PassThru
1099 // interface.
1100 //
1101 Dev->Signature = VSCSI_SIG;
1102 Status = gBS->InstallProtocolInterface (&DeviceHandle,
1103 &gEfiExtScsiPassThruProtocolGuid, EFI_NATIVE_INTERFACE,
1104 &Dev->PassThru);
1105 if (EFI_ERROR (Status)) {
1106 goto CloseExitBoot;
1107 }
1108
1109 return EFI_SUCCESS;
1110
1111 CloseExitBoot:
1112 gBS->CloseEvent (Dev->ExitBoot);
1113
1114 UninitDev:
1115 VirtioScsiUninit (Dev);
1116
1117 CloseVirtIo:
1118 gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
1119 This->DriverBindingHandle, DeviceHandle);
1120
1121 FreeVirtioScsi:
1122 FreePool (Dev);
1123
1124 return Status;
1125 }
1126
1127
1128 EFI_STATUS
1129 EFIAPI
1130 VirtioScsiDriverBindingStop (
1131 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1132 IN EFI_HANDLE DeviceHandle,
1133 IN UINTN NumberOfChildren,
1134 IN EFI_HANDLE *ChildHandleBuffer
1135 )
1136 {
1137 EFI_STATUS Status;
1138 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;
1139 VSCSI_DEV *Dev;
1140
1141 Status = gBS->OpenProtocol (
1142 DeviceHandle, // candidate device
1143 &gEfiExtScsiPassThruProtocolGuid, // retrieve the SCSI iface
1144 (VOID **)&PassThru, // target pointer
1145 This->DriverBindingHandle, // requestor driver ident.
1146 DeviceHandle, // lookup req. for dev.
1147 EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no new ref.
1148 );
1149 if (EFI_ERROR (Status)) {
1150 return Status;
1151 }
1152
1153 Dev = VIRTIO_SCSI_FROM_PASS_THRU (PassThru);
1154
1155 //
1156 // Handle Stop() requests for in-use driver instances gracefully.
1157 //
1158 Status = gBS->UninstallProtocolInterface (DeviceHandle,
1159 &gEfiExtScsiPassThruProtocolGuid, &Dev->PassThru);
1160 if (EFI_ERROR (Status)) {
1161 return Status;
1162 }
1163
1164 gBS->CloseEvent (Dev->ExitBoot);
1165
1166 VirtioScsiUninit (Dev);
1167
1168 gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
1169 This->DriverBindingHandle, DeviceHandle);
1170
1171 FreePool (Dev);
1172
1173 return EFI_SUCCESS;
1174 }
1175
1176
1177 //
1178 // The static object that groups the Supported() (ie. probe), Start() and
1179 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
1180 // C, 10.1 EFI Driver Binding Protocol.
1181 //
1182 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
1183 &VirtioScsiDriverBindingSupported,
1184 &VirtioScsiDriverBindingStart,
1185 &VirtioScsiDriverBindingStop,
1186 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
1187 NULL, // ImageHandle, to be overwritten by
1188 // EfiLibInstallDriverBindingComponentName2() in VirtioScsiEntryPoint()
1189 NULL // DriverBindingHandle, ditto
1190 };
1191
1192
1193 //
1194 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
1195 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
1196 // in English, for display on standard console devices. This is recommended for
1197 // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
1198 // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
1199 //
1200 // Device type names ("Virtio SCSI Host Device") are not formatted because the
1201 // driver supports only that device type. Therefore the driver name suffices
1202 // for unambiguous identification.
1203 //
1204
1205 STATIC
1206 EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
1207 { "eng;en", L"Virtio SCSI Host Driver" },
1208 { NULL, NULL }
1209 };
1210
1211 STATIC
1212 EFI_COMPONENT_NAME_PROTOCOL gComponentName;
1213
1214 EFI_STATUS
1215 EFIAPI
1216 VirtioScsiGetDriverName (
1217 IN EFI_COMPONENT_NAME_PROTOCOL *This,
1218 IN CHAR8 *Language,
1219 OUT CHAR16 **DriverName
1220 )
1221 {
1222 return LookupUnicodeString2 (
1223 Language,
1224 This->SupportedLanguages,
1225 mDriverNameTable,
1226 DriverName,
1227 (BOOLEAN)(This == &gComponentName) // Iso639Language
1228 );
1229 }
1230
1231 EFI_STATUS
1232 EFIAPI
1233 VirtioScsiGetDeviceName (
1234 IN EFI_COMPONENT_NAME_PROTOCOL *This,
1235 IN EFI_HANDLE DeviceHandle,
1236 IN EFI_HANDLE ChildHandle,
1237 IN CHAR8 *Language,
1238 OUT CHAR16 **ControllerName
1239 )
1240 {
1241 return EFI_UNSUPPORTED;
1242 }
1243
1244 STATIC
1245 EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
1246 &VirtioScsiGetDriverName,
1247 &VirtioScsiGetDeviceName,
1248 "eng" // SupportedLanguages, ISO 639-2 language codes
1249 };
1250
1251 STATIC
1252 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
1253 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) &VirtioScsiGetDriverName,
1254 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &VirtioScsiGetDeviceName,
1255 "en" // SupportedLanguages, RFC 4646 language codes
1256 };
1257
1258
1259 //
1260 // Entry point of this driver.
1261 //
1262 EFI_STATUS
1263 EFIAPI
1264 VirtioScsiEntryPoint (
1265 IN EFI_HANDLE ImageHandle,
1266 IN EFI_SYSTEM_TABLE *SystemTable
1267 )
1268 {
1269 return EfiLibInstallDriverBindingComponentName2 (
1270 ImageHandle,
1271 SystemTable,
1272 &gDriverBinding,
1273 ImageHandle,
1274 &gComponentName,
1275 &gComponentName2
1276 );
1277 }