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