TianoCore EDK2 master
Loading...
Searching...
No Matches
VirtioScsi.c
Go to the documentation of this file.
1
39#include <Library/DebugLib.h>
42#include <Library/UefiLib.h>
43#include <Library/VirtioLib.h>
44
45#include "VirtioScsi.h"
46
73#define VIRTIO_CFG_WRITE(Dev, Field, Value) ((Dev)->VirtIo->WriteDevice ( \
74 (Dev)->VirtIo, \
75 OFFSET_OF_VSCSI (Field), \
76 SIZE_OF_VSCSI (Field), \
77 (Value) \
78 ))
79
80#define VIRTIO_CFG_READ(Dev, Field, Pointer) ((Dev)->VirtIo->ReadDevice ( \
81 (Dev)->VirtIo, \
82 OFFSET_OF_VSCSI (Field), \
83 SIZE_OF_VSCSI (Field), \
84 sizeof *(Pointer), \
85 (Pointer) \
86 ))
87
88//
89// UEFI Spec 2.3.1 + Errata C, 14.7 Extended SCSI Pass Thru Protocol specifies
90// the PassThru() interface. Beside returning a status code, the function must
91// set some fields in the EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET in/out
92// parameter on return. The following is a full list of those fields, for
93// easier validation of PopulateRequest(), ParseResponse(), and
94// ReportHostAdapterError() below.
95//
96// - InTransferLength
97// - OutTransferLength
98// - HostAdapterStatus
99// - TargetStatus
100// - SenseDataLength
101// - SenseData
102//
103// On any return from the PassThru() interface, these fields must be set,
104// except if the returned status code is explicitly exempt. (Actually the
105// implementation here conservatively sets these fields even in case not all
106// of them would be required by the specification.)
107//
108
145STATIC
147EFIAPI
149 IN CONST VSCSI_DEV *Dev,
150 IN UINT16 Target,
151 IN UINT64 Lun,
153 OUT volatile VIRTIO_SCSI_REQ *Request
154 )
155{
156 UINTN Idx;
157
158 if (
159 //
160 // bidirectional transfer was requested, but the host doesn't support it
161 //
162 ((Packet->InTransferLength > 0) && (Packet->OutTransferLength > 0) &&
163 !Dev->InOutSupported) ||
164
165 //
166 // a target / LUN was addressed that's impossible to encode for the host
167 //
168 (Target > 0xFF) || (Lun >= 0x4000) ||
169
170 //
171 // Command Descriptor Block bigger than VIRTIO_SCSI_CDB_SIZE
172 //
173 (Packet->CdbLength > VIRTIO_SCSI_CDB_SIZE) ||
174
175 //
176 // From virtio-0.9.5, 2.3.2 Descriptor Table:
177 // "no descriptor chain may be more than 2^32 bytes long in total".
178 //
179 ((UINT64)Packet->InTransferLength + Packet->OutTransferLength > SIZE_1GB)
180 )
181 {
182 //
183 // this error code doesn't require updates to the Packet output fields
184 //
185 return EFI_UNSUPPORTED;
186 }
187
188 if (
189 //
190 // addressed invalid device
191 //
192 (Target > Dev->MaxTarget) || (Lun > Dev->MaxLun) ||
193
194 //
195 // invalid direction (there doesn't seem to be a macro for the "no data
196 // transferred" "direction", eg. for TEST UNIT READY)
197 //
198 (Packet->DataDirection > EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL) ||
199
200 //
201 // trying to receive, but destination pointer is NULL, or contradicting
202 // transfer direction
203 //
204 ((Packet->InTransferLength > 0) &&
205 ((Packet->InDataBuffer == NULL) ||
206 (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE)
207 )
208 ) ||
209
210 //
211 // trying to send, but source pointer is NULL, or contradicting transfer
212 // direction
213 //
214 ((Packet->OutTransferLength > 0) &&
215 ((Packet->OutDataBuffer == NULL) ||
216 (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ)
217 )
218 )
219 )
220 {
221 //
222 // this error code doesn't require updates to the Packet output fields
223 //
224 return EFI_INVALID_PARAMETER;
225 }
226
227 //
228 // Catch oversized requests eagerly. If this condition evaluates to false,
229 // then the combined size of a bidirectional request will not exceed the
230 // virtio-scsi device's transfer limit either.
231 //
232 if ((ALIGN_VALUE (Packet->OutTransferLength, 512) / 512
233 > Dev->MaxSectors / 2) ||
234 (ALIGN_VALUE (Packet->InTransferLength, 512) / 512
235 > Dev->MaxSectors / 2))
236 {
237 Packet->InTransferLength = (Dev->MaxSectors / 2) * 512;
238 Packet->OutTransferLength = (Dev->MaxSectors / 2) * 512;
239 Packet->HostAdapterStatus =
240 EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
241 Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
242 Packet->SenseDataLength = 0;
243 return EFI_BAD_BUFFER_SIZE;
244 }
245
246 //
247 // target & LUN encoding: see virtio-0.9.5, Appendix I: SCSI Host Device,
248 // Device Operation: request queues
249 //
250 Request->Lun[0] = 1;
251 Request->Lun[1] = (UINT8)Target;
252 Request->Lun[2] = (UINT8)(((UINT32)Lun >> 8) | 0x40);
253 Request->Lun[3] = (UINT8)Lun;
254
255 //
256 // CopyMem() would cast away the "volatile" qualifier before access, which is
257 // undefined behavior (ISO C99 6.7.3p5)
258 //
259 for (Idx = 0; Idx < Packet->CdbLength; ++Idx) {
260 Request->Cdb[Idx] = ((UINT8 *)Packet->Cdb)[Idx];
261 }
262
263 return EFI_SUCCESS;
264}
265
287STATIC
289EFIAPI
292 IN CONST volatile VIRTIO_SCSI_RESP *Response
293 )
294{
295 UINTN ResponseSenseLen;
296 UINTN Idx;
297
298 //
299 // return sense data (length and contents) in all cases, truncated if needed
300 //
301 ResponseSenseLen = MIN (Response->SenseLen, VIRTIO_SCSI_SENSE_SIZE);
302 if (Packet->SenseDataLength > ResponseSenseLen) {
303 Packet->SenseDataLength = (UINT8)ResponseSenseLen;
304 }
305
306 for (Idx = 0; Idx < Packet->SenseDataLength; ++Idx) {
307 ((UINT8 *)Packet->SenseData)[Idx] = Response->Sense[Idx];
308 }
309
310 //
311 // Report actual transfer lengths. The logic below covers all three
312 // DataDirections (read, write, bidirectional).
313 //
314 // -+- @ 0
315 // |
316 // | write ^ @ Residual (unprocessed)
317 // | |
318 // -+- @ OutTransferLength -+- @ InTransferLength
319 // | |
320 // | read |
321 // | |
322 // V @ OutTransferLength + InTransferLength -+- @ 0
323 //
324 if (Response->Residual <= Packet->InTransferLength) {
325 Packet->InTransferLength -= Response->Residual;
326 } else {
327 Packet->OutTransferLength -= Response->Residual - Packet->InTransferLength;
328 Packet->InTransferLength = 0;
329 }
330
331 //
332 // report target status in all cases
333 //
334 Packet->TargetStatus = Response->Status;
335
336 //
337 // host adapter status and function return value depend on virtio-scsi
338 // response code
339 //
340 switch (Response->Response) {
341 case VIRTIO_SCSI_S_OK:
342 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;
343 return EFI_SUCCESS;
344
345 case VIRTIO_SCSI_S_OVERRUN:
346 Packet->HostAdapterStatus =
347 EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
348 break;
349
350 case VIRTIO_SCSI_S_BAD_TARGET:
351 //
352 // This is non-intuitive but explicitly required by the
353 // EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru() specification for
354 // disconnected (but otherwise valid) target / LUN addresses.
355 //
356 Packet->HostAdapterStatus =
357 EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND;
358 return EFI_TIMEOUT;
359
360 case VIRTIO_SCSI_S_RESET:
361 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_RESET;
362 break;
363
364 case VIRTIO_SCSI_S_BUSY:
365 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;
366 return EFI_NOT_READY;
367
368 //
369 // Lump together the rest. The mapping for VIRTIO_SCSI_S_ABORTED is
370 // intentional as well, not an oversight.
371 //
372 case VIRTIO_SCSI_S_ABORTED:
373 case VIRTIO_SCSI_S_TRANSPORT_FAILURE:
374 case VIRTIO_SCSI_S_TARGET_FAILURE:
375 case VIRTIO_SCSI_S_NEXUS_FAILURE:
376 case VIRTIO_SCSI_S_FAILURE:
377 default:
378 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
379 }
380
381 return EFI_DEVICE_ERROR;
382}
383
400STATIC
404 )
405{
406 Packet->InTransferLength = 0;
407 Packet->OutTransferLength = 0;
408 Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
409 Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
410 Packet->SenseDataLength = 0;
411 return EFI_DEVICE_ERROR;
412}
413
414//
415// The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL
416// for the virtio-scsi HBA. Refer to UEFI Spec 2.3.1 + Errata C, sections
417// - 14.1 SCSI Driver Model Overview,
418// - 14.7 Extended SCSI Pass Thru Protocol.
419//
420
422EFIAPI
423VirtioScsiPassThru (
425 IN UINT8 *Target,
426 IN UINT64 Lun,
428 IN EFI_EVENT Event OPTIONAL
429 )
430{
431 VSCSI_DEV *Dev;
432 UINT16 TargetValue;
433 EFI_STATUS Status;
434 volatile VIRTIO_SCSI_REQ *Request;
435 volatile VIRTIO_SCSI_RESP *Response;
436 VOID *ResponseBuffer;
437 DESC_INDICES Indices;
438 VOID *RequestMapping;
439 VOID *ResponseMapping;
440 VOID *InDataMapping;
441 VOID *OutDataMapping;
442 EFI_PHYSICAL_ADDRESS RequestDeviceAddress;
443 EFI_PHYSICAL_ADDRESS ResponseDeviceAddress;
444 EFI_PHYSICAL_ADDRESS InDataDeviceAddress;
445 EFI_PHYSICAL_ADDRESS OutDataDeviceAddress;
446 VOID *InDataBuffer;
447 UINTN InDataNumPages;
448 BOOLEAN OutDataBufferIsMapped;
449
450 //
451 // Set InDataMapping,OutDataMapping,InDataDeviceAddress and OutDataDeviceAddress to
452 // suppress incorrect compiler/analyzer warnings.
453 //
454 InDataMapping = NULL;
455 OutDataMapping = NULL;
456 InDataDeviceAddress = 0;
457 OutDataDeviceAddress = 0;
458
459 Request = AllocateZeroPool (sizeof (*Request));
460 if (Request == NULL) {
461 return EFI_OUT_OF_RESOURCES;
462 }
463
464 Dev = VIRTIO_SCSI_FROM_PASS_THRU (This);
465 CopyMem (&TargetValue, Target, sizeof TargetValue);
466
467 InDataBuffer = NULL;
468 OutDataBufferIsMapped = FALSE;
469 InDataNumPages = 0;
470
471 Status = PopulateRequest (Dev, TargetValue, Lun, Packet, Request);
472 if (EFI_ERROR (Status)) {
473 goto FreeScsiRequest;
474 }
475
476 //
477 // Map the virtio-scsi Request header buffer
478 //
480 Dev->VirtIo,
481 VirtioOperationBusMasterRead,
482 (VOID *)Request,
483 sizeof (*Request),
484 &RequestDeviceAddress,
485 &RequestMapping
486 );
487 if (EFI_ERROR (Status)) {
488 Status = ReportHostAdapterError (Packet);
489 goto FreeScsiRequest;
490 }
491
492 //
493 // Map the input buffer
494 //
495 if (Packet->InTransferLength > 0) {
496 //
497 // Allocate a intermediate input buffer. This is mainly to handle the
498 // following case:
499 // * caller submits a bi-directional request
500 // * we perform the request fine
501 // * but we fail to unmap the "InDataMapping"
502 //
503 // In that case simply returning the EFI_DEVICE_ERROR is not sufficient. In
504 // addition to the error code we also need to update Packet fields
505 // accordingly so that we report the full loss of the incoming transfer.
506 //
507 // We allocate a temporary buffer and map it with BusMasterCommonBuffer. If
508 // the Virtio request is successful then we copy the data from temporary
509 // buffer into Packet->InDataBuffer.
510 //
511 InDataNumPages = EFI_SIZE_TO_PAGES ((UINTN)Packet->InTransferLength);
512 Status = Dev->VirtIo->AllocateSharedPages (
513 Dev->VirtIo,
514 InDataNumPages,
515 &InDataBuffer
516 );
517 if (EFI_ERROR (Status)) {
518 Status = ReportHostAdapterError (Packet);
519 goto UnmapRequestBuffer;
520 }
521
522 ZeroMem (InDataBuffer, Packet->InTransferLength);
523
525 Dev->VirtIo,
526 VirtioOperationBusMasterCommonBuffer,
527 InDataBuffer,
528 Packet->InTransferLength,
529 &InDataDeviceAddress,
530 &InDataMapping
531 );
532 if (EFI_ERROR (Status)) {
533 Status = ReportHostAdapterError (Packet);
534 goto FreeInDataBuffer;
535 }
536 }
537
538 //
539 // Map the output buffer
540 //
541 if (Packet->OutTransferLength > 0) {
543 Dev->VirtIo,
544 VirtioOperationBusMasterRead,
545 Packet->OutDataBuffer,
546 Packet->OutTransferLength,
547 &OutDataDeviceAddress,
548 &OutDataMapping
549 );
550 if (EFI_ERROR (Status)) {
551 Status = ReportHostAdapterError (Packet);
552 goto UnmapInDataBuffer;
553 }
554
555 OutDataBufferIsMapped = TRUE;
556 }
557
558 //
559 // Response header is bi-direction (we preset with host status and expect
560 // the device to update it). Allocate a response buffer which can be mapped
561 // to access equally by both processor and device.
562 //
563 Status = Dev->VirtIo->AllocateSharedPages (
564 Dev->VirtIo,
565 EFI_SIZE_TO_PAGES (sizeof *Response),
566 &ResponseBuffer
567 );
568 if (EFI_ERROR (Status)) {
569 Status = ReportHostAdapterError (Packet);
570 goto UnmapOutDataBuffer;
571 }
572
573 Response = ResponseBuffer;
574
575 ZeroMem ((VOID *)Response, sizeof (*Response));
576
577 //
578 // preset a host status for ourselves that we do not accept as success
579 //
580 Response->Response = VIRTIO_SCSI_S_FAILURE;
581
582 //
583 // Map the response buffer with BusMasterCommonBuffer so that response
584 // buffer can be accessed by both host and device.
585 //
587 Dev->VirtIo,
588 VirtioOperationBusMasterCommonBuffer,
589 ResponseBuffer,
590 sizeof (*Response),
591 &ResponseDeviceAddress,
592 &ResponseMapping
593 );
594 if (EFI_ERROR (Status)) {
595 Status = ReportHostAdapterError (Packet);
596 goto FreeResponseBuffer;
597 }
598
599 VirtioPrepare (&Dev->Ring, &Indices);
600
601 //
602 // ensured by VirtioScsiInit() -- this predicate, in combination with the
603 // lock-step progress, ensures we don't have to track free descriptors.
604 //
605 ASSERT (Dev->Ring.QueueSize >= 4);
606
607 //
608 // enqueue Request
609 //
611 &Dev->Ring,
612 RequestDeviceAddress,
613 sizeof (*Request),
614 VRING_DESC_F_NEXT,
615 &Indices
616 );
617
618 //
619 // enqueue "dataout" if any
620 //
621 if (Packet->OutTransferLength > 0) {
623 &Dev->Ring,
624 OutDataDeviceAddress,
625 Packet->OutTransferLength,
626 VRING_DESC_F_NEXT,
627 &Indices
628 );
629 }
630
631 //
632 // enqueue Response, to be written by the host
633 //
635 &Dev->Ring,
636 ResponseDeviceAddress,
637 sizeof *Response,
638 VRING_DESC_F_WRITE | (Packet->InTransferLength > 0 ? VRING_DESC_F_NEXT : 0),
639 &Indices
640 );
641
642 //
643 // enqueue "datain" if any, to be written by the host
644 //
645 if (Packet->InTransferLength > 0) {
647 &Dev->Ring,
648 InDataDeviceAddress,
649 Packet->InTransferLength,
650 VRING_DESC_F_WRITE,
651 &Indices
652 );
653 }
654
655 // If kicking the host fails, we must fake a host adapter error.
656 // EFI_NOT_READY would save us the effort, but it would also suggest that the
657 // caller retry.
658 //
659 if (VirtioFlush (
660 Dev->VirtIo,
661 VIRTIO_SCSI_REQUEST_QUEUE,
662 &Dev->Ring,
663 &Indices,
664 NULL
665 ) != EFI_SUCCESS)
666 {
667 Status = ReportHostAdapterError (Packet);
668 goto UnmapResponseBuffer;
669 }
670
671 Status = ParseResponse (Packet, Response);
672
673 //
674 // If virtio request was successful and it was a CPU read request then we
675 // have used an intermediate buffer. Copy the data from intermediate buffer
676 // to the final buffer.
677 //
678 if (InDataBuffer != NULL) {
679 CopyMem (Packet->InDataBuffer, InDataBuffer, Packet->InTransferLength);
680 }
681
682UnmapResponseBuffer:
683 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, ResponseMapping);
684
685FreeResponseBuffer:
686 Dev->VirtIo->FreeSharedPages (
687 Dev->VirtIo,
688 EFI_SIZE_TO_PAGES (sizeof *Response),
689 ResponseBuffer
690 );
691
692UnmapOutDataBuffer:
693 if (OutDataBufferIsMapped) {
694 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, OutDataMapping);
695 }
696
697UnmapInDataBuffer:
698 if (InDataBuffer != NULL) {
699 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, InDataMapping);
700 }
701
702FreeInDataBuffer:
703 if (InDataBuffer != NULL) {
704 Dev->VirtIo->FreeSharedPages (Dev->VirtIo, InDataNumPages, InDataBuffer);
705 }
706
707UnmapRequestBuffer:
708 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, RequestMapping);
709
710FreeScsiRequest:
711 FreePool ((VOID *)Request);
712
713 return Status;
714}
715
717EFIAPI
718VirtioScsiGetNextTargetLun (
720 IN OUT UINT8 **TargetPointer,
721 IN OUT UINT64 *Lun
722 )
723{
724 UINT8 *Target;
725 UINTN Idx;
726 UINT16 LastTarget;
727 VSCSI_DEV *Dev;
728
729 //
730 // the TargetPointer input parameter is unnecessarily a pointer-to-pointer
731 //
732 Target = *TargetPointer;
733
734 //
735 // Search for first non-0xFF byte. If not found, return first target & LUN.
736 //
737 for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx) {
738 }
739
740 if (Idx == TARGET_MAX_BYTES) {
741 SetMem (Target, TARGET_MAX_BYTES, 0x00);
742 *Lun = 0;
743 return EFI_SUCCESS;
744 }
745
746 //
747 // see the TARGET_MAX_BYTES check in "VirtioScsi.h"
748 //
749 CopyMem (&LastTarget, Target, sizeof LastTarget);
750
751 //
752 // increment (target, LUN) pair if valid on input
753 //
754 Dev = VIRTIO_SCSI_FROM_PASS_THRU (This);
755 if ((LastTarget > Dev->MaxTarget) || (*Lun > Dev->MaxLun)) {
756 return EFI_INVALID_PARAMETER;
757 }
758
759 if (*Lun < Dev->MaxLun) {
760 ++*Lun;
761 return EFI_SUCCESS;
762 }
763
764 if (LastTarget < Dev->MaxTarget) {
765 *Lun = 0;
766 ++LastTarget;
767 CopyMem (Target, &LastTarget, sizeof LastTarget);
768 return EFI_SUCCESS;
769 }
770
771 return EFI_NOT_FOUND;
772}
773
775EFIAPI
776VirtioScsiBuildDevicePath (
778 IN UINT8 *Target,
779 IN UINT64 Lun,
780 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
781 )
782{
783 UINT16 TargetValue;
784 VSCSI_DEV *Dev;
785 SCSI_DEVICE_PATH *ScsiDevicePath;
786
787 if (DevicePath == NULL) {
788 return EFI_INVALID_PARAMETER;
789 }
790
791 CopyMem (&TargetValue, Target, sizeof TargetValue);
792 Dev = VIRTIO_SCSI_FROM_PASS_THRU (This);
793 if ((TargetValue > Dev->MaxTarget) || (Lun > Dev->MaxLun) || (Lun > 0xFFFF)) {
794 return EFI_NOT_FOUND;
795 }
796
797 ScsiDevicePath = AllocatePool (sizeof *ScsiDevicePath);
798 if (ScsiDevicePath == NULL) {
799 return EFI_OUT_OF_RESOURCES;
800 }
801
802 ScsiDevicePath->Header.Type = MESSAGING_DEVICE_PATH;
803 ScsiDevicePath->Header.SubType = MSG_SCSI_DP;
804 ScsiDevicePath->Header.Length[0] = (UINT8)sizeof *ScsiDevicePath;
805 ScsiDevicePath->Header.Length[1] = (UINT8)(sizeof *ScsiDevicePath >> 8);
806 ScsiDevicePath->Pun = TargetValue;
807 ScsiDevicePath->Lun = (UINT16)Lun;
808
809 *DevicePath = &ScsiDevicePath->Header;
810 return EFI_SUCCESS;
811}
812
814EFIAPI
815VirtioScsiGetTargetLun (
817 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
818 OUT UINT8 **TargetPointer,
819 OUT UINT64 *Lun
820 )
821{
822 SCSI_DEVICE_PATH *ScsiDevicePath;
823 VSCSI_DEV *Dev;
824 UINT8 *Target;
825
826 if ((DevicePath == NULL) || (TargetPointer == NULL) || (*TargetPointer == NULL) ||
827 (Lun == NULL))
828 {
829 return EFI_INVALID_PARAMETER;
830 }
831
832 if ((DevicePath->Type != MESSAGING_DEVICE_PATH) ||
833 (DevicePath->SubType != MSG_SCSI_DP))
834 {
835 return EFI_UNSUPPORTED;
836 }
837
838 ScsiDevicePath = (SCSI_DEVICE_PATH *)DevicePath;
839 Dev = VIRTIO_SCSI_FROM_PASS_THRU (This);
840 if ((ScsiDevicePath->Pun > Dev->MaxTarget) ||
841 (ScsiDevicePath->Lun > Dev->MaxLun))
842 {
843 return EFI_NOT_FOUND;
844 }
845
846 //
847 // a) the TargetPointer input parameter is unnecessarily a pointer-to-pointer
848 // b) see the TARGET_MAX_BYTES check in "VirtioScsi.h"
849 // c) ScsiDevicePath->Pun is an UINT16
850 //
851 Target = *TargetPointer;
852 CopyMem (Target, &ScsiDevicePath->Pun, 2);
853 SetMem (Target + 2, TARGET_MAX_BYTES - 2, 0x00);
854
855 *Lun = ScsiDevicePath->Lun;
856 return EFI_SUCCESS;
857}
858
860EFIAPI
861VirtioScsiResetChannel (
863 )
864{
865 return EFI_UNSUPPORTED;
866}
867
869EFIAPI
870VirtioScsiResetTargetLun (
872 IN UINT8 *Target,
873 IN UINT64 Lun
874 )
875{
876 return EFI_UNSUPPORTED;
877}
878
880EFIAPI
881VirtioScsiGetNextTarget (
883 IN OUT UINT8 **TargetPointer
884 )
885{
886 UINT8 *Target;
887 UINTN Idx;
888 UINT16 LastTarget;
889 VSCSI_DEV *Dev;
890
891 //
892 // the TargetPointer input parameter is unnecessarily a pointer-to-pointer
893 //
894 Target = *TargetPointer;
895
896 //
897 // Search for first non-0xFF byte. If not found, return first target.
898 //
899 for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx) {
900 }
901
902 if (Idx == TARGET_MAX_BYTES) {
903 SetMem (Target, TARGET_MAX_BYTES, 0x00);
904 return EFI_SUCCESS;
905 }
906
907 //
908 // see the TARGET_MAX_BYTES check in "VirtioScsi.h"
909 //
910 CopyMem (&LastTarget, Target, sizeof LastTarget);
911
912 //
913 // increment target if valid on input
914 //
915 Dev = VIRTIO_SCSI_FROM_PASS_THRU (This);
916 if (LastTarget > Dev->MaxTarget) {
917 return EFI_INVALID_PARAMETER;
918 }
919
920 if (LastTarget < Dev->MaxTarget) {
921 ++LastTarget;
922 CopyMem (Target, &LastTarget, sizeof LastTarget);
923 return EFI_SUCCESS;
924 }
925
926 return EFI_NOT_FOUND;
927}
928
929STATIC
931EFIAPI
932VirtioScsiInit (
933 IN OUT VSCSI_DEV *Dev
934 )
935{
936 UINT8 NextDevStat;
937 EFI_STATUS Status;
938 UINT64 RingBaseShift;
939 UINT64 Features;
940 UINT16 MaxChannel; // for validation only
941 UINT32 NumQueues; // for validation only
942 UINT16 QueueSize;
943
944 //
945 // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
946 //
947 NextDevStat = 0; // step 1 -- reset device
948 Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
949 if (EFI_ERROR (Status)) {
950 goto Failed;
951 }
952
953 NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence
954 Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
955 if (EFI_ERROR (Status)) {
956 goto Failed;
957 }
958
959 NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it
960 Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
961 if (EFI_ERROR (Status)) {
962 goto Failed;
963 }
964
965 //
966 // Set Page Size - MMIO VirtIo Specific
967 //
968 Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE);
969 if (EFI_ERROR (Status)) {
970 goto Failed;
971 }
972
973 //
974 // step 4a -- retrieve and validate features
975 //
976 Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);
977 if (EFI_ERROR (Status)) {
978 goto Failed;
979 }
980
981 Dev->InOutSupported = (BOOLEAN)((Features & VIRTIO_SCSI_F_INOUT) != 0);
982
983 Status = VIRTIO_CFG_READ (Dev, MaxChannel, &MaxChannel);
984 if (EFI_ERROR (Status)) {
985 goto Failed;
986 }
987
988 if (MaxChannel != 0) {
989 //
990 // this driver is for a single-channel virtio-scsi HBA
991 //
992 Status = EFI_UNSUPPORTED;
993 goto Failed;
994 }
995
996 Status = VIRTIO_CFG_READ (Dev, NumQueues, &NumQueues);
997 if (EFI_ERROR (Status)) {
998 goto Failed;
999 }
1000
1001 if (NumQueues < 1) {
1002 Status = EFI_UNSUPPORTED;
1003 goto Failed;
1004 }
1005
1006 Status = VIRTIO_CFG_READ (Dev, MaxTarget, &Dev->MaxTarget);
1007 if (EFI_ERROR (Status)) {
1008 goto Failed;
1009 }
1010
1011 if (Dev->MaxTarget > PcdGet16 (PcdVirtioScsiMaxTargetLimit)) {
1012 Dev->MaxTarget = PcdGet16 (PcdVirtioScsiMaxTargetLimit);
1013 }
1014
1015 Status = VIRTIO_CFG_READ (Dev, MaxLun, &Dev->MaxLun);
1016 if (EFI_ERROR (Status)) {
1017 goto Failed;
1018 }
1019
1020 if (Dev->MaxLun > PcdGet32 (PcdVirtioScsiMaxLunLimit)) {
1021 Dev->MaxLun = PcdGet32 (PcdVirtioScsiMaxLunLimit);
1022 }
1023
1024 Status = VIRTIO_CFG_READ (Dev, MaxSectors, &Dev->MaxSectors);
1025 if (EFI_ERROR (Status)) {
1026 goto Failed;
1027 }
1028
1029 if (Dev->MaxSectors < 2) {
1030 //
1031 // We must be able to halve it for bidirectional transfers
1032 // (see EFI_BAD_BUFFER_SIZE in PopulateRequest()).
1033 //
1034 Status = EFI_UNSUPPORTED;
1035 goto Failed;
1036 }
1037
1038 Features &= VIRTIO_SCSI_F_INOUT | VIRTIO_F_VERSION_1 |
1039 VIRTIO_F_IOMMU_PLATFORM;
1040
1041 //
1042 // In virtio-1.0, feature negotiation is expected to complete before queue
1043 // discovery, and the device can also reject the selected set of features.
1044 //
1045 if (Dev->VirtIo->Revision >= VIRTIO_SPEC_REVISION (1, 0, 0)) {
1046 Status = Virtio10WriteFeatures (Dev->VirtIo, Features, &NextDevStat);
1047 if (EFI_ERROR (Status)) {
1048 goto Failed;
1049 }
1050 }
1051
1052 //
1053 // step 4b -- allocate request virtqueue
1054 //
1055 Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE);
1056 if (EFI_ERROR (Status)) {
1057 goto Failed;
1058 }
1059
1060 Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);
1061 if (EFI_ERROR (Status)) {
1062 goto Failed;
1063 }
1064
1065 //
1066 // VirtioScsiPassThru() uses at most four descriptors
1067 //
1068 if (QueueSize < 4) {
1069 Status = EFI_UNSUPPORTED;
1070 goto Failed;
1071 }
1072
1073 Status = VirtioRingInit (Dev->VirtIo, QueueSize, &Dev->Ring);
1074 if (EFI_ERROR (Status)) {
1075 goto Failed;
1076 }
1077
1078 //
1079 // If anything fails from here on, we must release the ring resources
1080 //
1081 Status = VirtioRingMap (
1082 Dev->VirtIo,
1083 &Dev->Ring,
1084 &RingBaseShift,
1085 &Dev->RingMap
1086 );
1087 if (EFI_ERROR (Status)) {
1088 goto ReleaseQueue;
1089 }
1090
1091 //
1092 // Additional steps for MMIO: align the queue appropriately, and set the
1093 // size. If anything fails from here on, we must unmap the ring resources.
1094 //
1095 Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);
1096 if (EFI_ERROR (Status)) {
1097 goto UnmapQueue;
1098 }
1099
1100 Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);
1101 if (EFI_ERROR (Status)) {
1102 goto UnmapQueue;
1103 }
1104
1105 //
1106 // step 4c -- Report GPFN (guest-physical frame number) of queue.
1107 //
1108 Status = Dev->VirtIo->SetQueueAddress (
1109 Dev->VirtIo,
1110 &Dev->Ring,
1111 RingBaseShift
1112 );
1113 if (EFI_ERROR (Status)) {
1114 goto UnmapQueue;
1115 }
1116
1117 //
1118 // step 5 -- Report understood features and guest-tuneables.
1119 //
1120 if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) {
1121 Features &= ~(UINT64)(VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM);
1122 Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);
1123 if (EFI_ERROR (Status)) {
1124 goto UnmapQueue;
1125 }
1126 }
1127
1128 //
1129 // We expect these maximum sizes from the host. Since they are
1130 // guest-negotiable, ask for them rather than just checking them.
1131 //
1132 Status = VIRTIO_CFG_WRITE (Dev, CdbSize, VIRTIO_SCSI_CDB_SIZE);
1133 if (EFI_ERROR (Status)) {
1134 goto UnmapQueue;
1135 }
1136
1137 Status = VIRTIO_CFG_WRITE (Dev, SenseSize, VIRTIO_SCSI_SENSE_SIZE);
1138 if (EFI_ERROR (Status)) {
1139 goto UnmapQueue;
1140 }
1141
1142 //
1143 // step 6 -- initialization complete
1144 //
1145 NextDevStat |= VSTAT_DRIVER_OK;
1146 Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
1147 if (EFI_ERROR (Status)) {
1148 goto UnmapQueue;
1149 }
1150
1151 //
1152 // populate the exported interface's attributes
1153 //
1154 Dev->PassThru.Mode = &Dev->PassThruMode;
1155 Dev->PassThru.PassThru = &VirtioScsiPassThru;
1156 Dev->PassThru.GetNextTargetLun = &VirtioScsiGetNextTargetLun;
1157 Dev->PassThru.BuildDevicePath = &VirtioScsiBuildDevicePath;
1158 Dev->PassThru.GetTargetLun = &VirtioScsiGetTargetLun;
1159 Dev->PassThru.ResetChannel = &VirtioScsiResetChannel;
1160 Dev->PassThru.ResetTargetLun = &VirtioScsiResetTargetLun;
1161 Dev->PassThru.GetNextTarget = &VirtioScsiGetNextTarget;
1162
1163 //
1164 // AdapterId is a target for which no handle will be created during bus scan.
1165 // Prevent any conflict with real devices.
1166 //
1167 Dev->PassThruMode.AdapterId = 0xFFFFFFFF;
1168
1169 //
1170 // Set both physical and logical attributes for non-RAID SCSI channel. See
1171 // Driver Writer's Guide for UEFI 2.3.1 v1.01, 20.1.5 Implementing Extended
1172 // SCSI Pass Thru Protocol.
1173 //
1174 Dev->PassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL |
1175 EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
1176
1177 //
1178 // no restriction on transfer buffer alignment
1179 //
1180 Dev->PassThruMode.IoAlign = 0;
1181
1182 return EFI_SUCCESS;
1183
1184UnmapQueue:
1185 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);
1186
1187ReleaseQueue:
1188 VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
1189
1190Failed:
1191 //
1192 // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device
1193 // Status. VirtIo access failure here should not mask the original error.
1194 //
1195 NextDevStat |= VSTAT_FAILED;
1196 Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
1197
1198 Dev->InOutSupported = FALSE;
1199 Dev->MaxTarget = 0;
1200 Dev->MaxLun = 0;
1201 Dev->MaxSectors = 0;
1202
1203 return Status; // reached only via Failed above
1204}
1205
1206STATIC
1207VOID
1208EFIAPI
1209VirtioScsiUninit (
1210 IN OUT VSCSI_DEV *Dev
1211 )
1212{
1213 //
1214 // Reset the virtual device -- see virtio-0.9.5, 2.2.2.1 Device Status. When
1215 // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
1216 // the old comms area.
1217 //
1218 Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
1219
1220 Dev->InOutSupported = FALSE;
1221 Dev->MaxTarget = 0;
1222 Dev->MaxLun = 0;
1223 Dev->MaxSectors = 0;
1224
1225 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);
1226 VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
1227
1228 SetMem (&Dev->PassThru, sizeof Dev->PassThru, 0x00);
1229 SetMem (&Dev->PassThruMode, sizeof Dev->PassThruMode, 0x00);
1230}
1231
1232//
1233// Event notification function enqueued by ExitBootServices().
1234//
1235
1236STATIC
1237VOID
1238EFIAPI
1239VirtioScsiExitBoot (
1240 IN EFI_EVENT Event,
1241 IN VOID *Context
1242 )
1243{
1244 VSCSI_DEV *Dev;
1245
1246 DEBUG ((DEBUG_VERBOSE, "%a: Context=0x%p\n", __func__, Context));
1247 //
1248 // Reset the device. This causes the hypervisor to forget about the virtio
1249 // ring.
1250 //
1251 // We allocated said ring in EfiBootServicesData type memory, and code
1252 // executing after ExitBootServices() is permitted to overwrite it.
1253 //
1254 Dev = Context;
1255 Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
1256}
1257
1258//
1259// Probe, start and stop functions of this driver, called by the DXE core for
1260// specific devices.
1261//
1262// The following specifications document these interfaces:
1263// - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
1264// - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
1265//
1266// The implementation follows:
1267// - Driver Writer's Guide for UEFI 2.3.1 v1.01
1268// - 5.1.3.4 OpenProtocol() and CloseProtocol()
1269// - UEFI Spec 2.3.1 + Errata C
1270// - 6.3 Protocol Handler Services
1271//
1272
1274EFIAPI
1275VirtioScsiDriverBindingSupported (
1277 IN EFI_HANDLE DeviceHandle,
1278 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1279 )
1280{
1281 EFI_STATUS Status;
1282 VIRTIO_DEVICE_PROTOCOL *VirtIo;
1283
1284 //
1285 // Attempt to open the device with the VirtIo set of interfaces. On success,
1286 // the protocol is "instantiated" for the VirtIo device. Covers duplicate open
1287 // attempts (EFI_ALREADY_STARTED).
1288 //
1289 Status = gBS->OpenProtocol (
1290 DeviceHandle, // candidate device
1291 &gVirtioDeviceProtocolGuid, // for generic VirtIo access
1292 (VOID **)&VirtIo, // handle to instantiate
1293 This->DriverBindingHandle, // requestor driver identity
1294 DeviceHandle, // ControllerHandle, according to
1295 // the UEFI Driver Model
1296 EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to
1297 // the device; to be released
1298 );
1299 if (EFI_ERROR (Status)) {
1300 return Status;
1301 }
1302
1303 if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_SCSI_HOST) {
1304 Status = EFI_UNSUPPORTED;
1305 }
1306
1307 //
1308 // We needed VirtIo access only transitorily, to see whether we support the
1309 // device or not.
1310 //
1311 gBS->CloseProtocol (
1312 DeviceHandle,
1313 &gVirtioDeviceProtocolGuid,
1314 This->DriverBindingHandle,
1315 DeviceHandle
1316 );
1317 return Status;
1318}
1319
1321EFIAPI
1322VirtioScsiDriverBindingStart (
1324 IN EFI_HANDLE DeviceHandle,
1325 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1326 )
1327{
1328 VSCSI_DEV *Dev;
1329 EFI_STATUS Status;
1330
1331 Dev = (VSCSI_DEV *)AllocateZeroPool (sizeof *Dev);
1332 if (Dev == NULL) {
1333 return EFI_OUT_OF_RESOURCES;
1334 }
1335
1336 Status = gBS->OpenProtocol (
1337 DeviceHandle,
1338 &gVirtioDeviceProtocolGuid,
1339 (VOID **)&Dev->VirtIo,
1340 This->DriverBindingHandle,
1341 DeviceHandle,
1342 EFI_OPEN_PROTOCOL_BY_DRIVER
1343 );
1344 if (EFI_ERROR (Status)) {
1345 goto FreeVirtioScsi;
1346 }
1347
1348 //
1349 // VirtIo access granted, configure virtio-scsi device.
1350 //
1351 Status = VirtioScsiInit (Dev);
1352 if (EFI_ERROR (Status)) {
1353 goto CloseVirtIo;
1354 }
1355
1356 Status = gBS->CreateEvent (
1357 EVT_SIGNAL_EXIT_BOOT_SERVICES,
1358 TPL_CALLBACK,
1359 &VirtioScsiExitBoot,
1360 Dev,
1361 &Dev->ExitBoot
1362 );
1363 if (EFI_ERROR (Status)) {
1364 goto UninitDev;
1365 }
1366
1367 //
1368 // Setup complete, attempt to export the driver instance's PassThru
1369 // interface.
1370 //
1371 Dev->Signature = VSCSI_SIG;
1372 Status = gBS->InstallProtocolInterface (
1373 &DeviceHandle,
1374 &gEfiExtScsiPassThruProtocolGuid,
1376 &Dev->PassThru
1377 );
1378 if (EFI_ERROR (Status)) {
1379 goto CloseExitBoot;
1380 }
1381
1382 return EFI_SUCCESS;
1383
1384CloseExitBoot:
1385 gBS->CloseEvent (Dev->ExitBoot);
1386
1387UninitDev:
1388 VirtioScsiUninit (Dev);
1389
1390CloseVirtIo:
1391 gBS->CloseProtocol (
1392 DeviceHandle,
1393 &gVirtioDeviceProtocolGuid,
1394 This->DriverBindingHandle,
1395 DeviceHandle
1396 );
1397
1398FreeVirtioScsi:
1399 FreePool (Dev);
1400
1401 return Status;
1402}
1403
1405EFIAPI
1406VirtioScsiDriverBindingStop (
1408 IN EFI_HANDLE DeviceHandle,
1409 IN UINTN NumberOfChildren,
1410 IN EFI_HANDLE *ChildHandleBuffer
1411 )
1412{
1413 EFI_STATUS Status;
1415 VSCSI_DEV *Dev;
1416
1417 Status = gBS->OpenProtocol (
1418 DeviceHandle, // candidate device
1419 &gEfiExtScsiPassThruProtocolGuid, // retrieve the SCSI iface
1420 (VOID **)&PassThru, // target pointer
1421 This->DriverBindingHandle, // requestor driver ident.
1422 DeviceHandle, // lookup req. for dev.
1423 EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no new ref.
1424 );
1425 if (EFI_ERROR (Status)) {
1426 return Status;
1427 }
1428
1429 Dev = VIRTIO_SCSI_FROM_PASS_THRU (PassThru);
1430
1431 //
1432 // Handle Stop() requests for in-use driver instances gracefully.
1433 //
1434 Status = gBS->UninstallProtocolInterface (
1435 DeviceHandle,
1436 &gEfiExtScsiPassThruProtocolGuid,
1437 &Dev->PassThru
1438 );
1439 if (EFI_ERROR (Status)) {
1440 return Status;
1441 }
1442
1443 gBS->CloseEvent (Dev->ExitBoot);
1444
1445 VirtioScsiUninit (Dev);
1446
1447 gBS->CloseProtocol (
1448 DeviceHandle,
1449 &gVirtioDeviceProtocolGuid,
1450 This->DriverBindingHandle,
1451 DeviceHandle
1452 );
1453
1454 FreePool (Dev);
1455
1456 return EFI_SUCCESS;
1457}
1458
1459//
1460// The static object that groups the Supported() (ie. probe), Start() and
1461// Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
1462// C, 10.1 EFI Driver Binding Protocol.
1463//
1464STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
1465 &VirtioScsiDriverBindingSupported,
1466 &VirtioScsiDriverBindingStart,
1467 &VirtioScsiDriverBindingStop,
1468 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
1469 NULL, // ImageHandle, to be overwritten by
1470 // EfiLibInstallDriverBindingComponentName2() in VirtioScsiEntryPoint()
1471 NULL // DriverBindingHandle, ditto
1472};
1473
1474//
1475// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
1476// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
1477// in English, for display on standard console devices. This is recommended for
1478// UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
1479// Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
1480//
1481// Device type names ("Virtio SCSI Host Device") are not formatted because the
1482// driver supports only that device type. Therefore the driver name suffices
1483// for unambiguous identification.
1484//
1485
1486STATIC
1487EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
1488 { "eng;en", L"Virtio SCSI Host Driver" },
1489 { NULL, NULL }
1490};
1491
1492STATIC
1493EFI_COMPONENT_NAME_PROTOCOL gComponentName;
1494
1496EFIAPI
1497VirtioScsiGetDriverName (
1499 IN CHAR8 *Language,
1500 OUT CHAR16 **DriverName
1501 )
1502{
1503 return LookupUnicodeString2 (
1504 Language,
1505 This->SupportedLanguages,
1506 mDriverNameTable,
1507 DriverName,
1508 (BOOLEAN)(This == &gComponentName) // Iso639Language
1509 );
1510}
1511
1513EFIAPI
1514VirtioScsiGetDeviceName (
1516 IN EFI_HANDLE DeviceHandle,
1517 IN EFI_HANDLE ChildHandle,
1518 IN CHAR8 *Language,
1519 OUT CHAR16 **ControllerName
1520 )
1521{
1522 return EFI_UNSUPPORTED;
1523}
1524
1525STATIC
1526EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
1527 &VirtioScsiGetDriverName,
1528 &VirtioScsiGetDeviceName,
1529 "eng" // SupportedLanguages, ISO 639-2 language codes
1530};
1531
1532STATIC
1533EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
1534 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)&VirtioScsiGetDriverName,
1535 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)&VirtioScsiGetDeviceName,
1536 "en" // SupportedLanguages, RFC 4646 language codes
1537};
1538
1539//
1540// Entry point of this driver.
1541//
1543EFIAPI
1544VirtioScsiEntryPoint (
1545 IN EFI_HANDLE ImageHandle,
1546 IN EFI_SYSTEM_TABLE *SystemTable
1547 )
1548{
1550 ImageHandle,
1551 SystemTable,
1552 &gDriverBinding,
1553 ImageHandle,
1554 &gComponentName,
1555 &gComponentName2
1556 );
1557}
UINT64 UINTN
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
Definition: SetMemWrapper.c:38
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_STATUS(EFIAPI * EFI_COMPONENT_NAME2_GET_DRIVER_NAME)(IN EFI_COMPONENT_NAME2_PROTOCOL *This, IN CHAR8 *Language, OUT CHAR16 **DriverName)
EFI_STATUS(EFIAPI * EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)(IN EFI_COMPONENT_NAME2_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN EFI_HANDLE ChildHandle OPTIONAL, IN CHAR8 *Language, OUT CHAR16 **ControllerName)
#define MSG_SCSI_DP
Definition: DevicePath.h:346
#define MESSAGING_DEVICE_PATH
Definition: DevicePath.h:321
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define MIN(a, b)
Definition: Base.h:1007
#define ALIGN_VALUE(Value, Alignment)
Definition: Base.h:948
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdGet16(TokenName)
Definition: PcdLib.h:349
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI LookupUnicodeString2(IN CONST CHAR8 *Language, IN CONST CHAR8 *SupportedLanguages, IN CONST EFI_UNICODE_STRING_TABLE *UnicodeStringTable, OUT CHAR16 **UnicodeString, IN BOOLEAN Iso639Language)
Definition: UefiLib.c:801
EFI_STATUS EFIAPI EfiLibInstallDriverBindingComponentName2(IN CONST EFI_HANDLE ImageHandle, IN CONST EFI_SYSTEM_TABLE *SystemTable, IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, IN EFI_HANDLE DriverBindingHandle, IN CONST EFI_COMPONENT_NAME_PROTOCOL *ComponentName OPTIONAL, IN CONST EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2 OPTIONAL)
@ EFI_NATIVE_INTERFACE
Definition: UefiSpec.h:1193
EFI_STATUS EFIAPI VirtioMapAllBytesInSharedBuffer(IN VIRTIO_DEVICE_PROTOCOL *VirtIo, IN VIRTIO_MAP_OPERATION Operation, IN VOID *HostAddress, IN UINTN NumberOfBytes, OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, OUT VOID **Mapping)
Definition: VirtioLib.c:469
VOID EFIAPI VirtioAppendDesc(IN OUT VRING *Ring, IN UINT64 BufferDeviceAddress, IN UINT32 BufferSize, IN UINT16 Flags, IN OUT DESC_INDICES *Indices)
Definition: VirtioLib.c:228
EFI_STATUS EFIAPI VirtioFlush(IN VIRTIO_DEVICE_PROTOCOL *VirtIo, IN UINT16 VirtQueueId, IN OUT VRING *Ring, IN DESC_INDICES *Indices, OUT UINT32 *UsedLen OPTIONAL)
Definition: VirtioLib.c:274
EFI_STATUS EFIAPI VirtioRingMap(IN VIRTIO_DEVICE_PROTOCOL *VirtIo, IN VRING *Ring, OUT UINT64 *RingBaseShift, OUT VOID **Mapping)
Definition: VirtioLib.c:529
EFI_STATUS EFIAPI Virtio10WriteFeatures(IN VIRTIO_DEVICE_PROTOCOL *VirtIo, IN UINT64 Features, IN OUT UINT8 *DeviceStatus)
Definition: VirtioLib.c:391
VOID EFIAPI VirtioPrepare(IN OUT VRING *Ring, OUT DESC_INDICES *Indices)
Definition: VirtioLib.c:167
EFI_STATUS EFIAPI VirtioRingInit(IN VIRTIO_DEVICE_PROTOCOL *VirtIo, IN UINT16 QueueSize, OUT VRING *Ring)
Definition: VirtioLib.c:49
VOID EFIAPI VirtioRingUninit(IN VIRTIO_DEVICE_PROTOCOL *VirtIo, IN OUT VRING *Ring)
Definition: VirtioLib.c:144
STATIC EFI_STATUS EFIAPI ParseResponse(IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet, IN CONST volatile VIRTIO_SCSI_RESP *Response)
Definition: VirtioScsi.c:290
STATIC EFI_STATUS ReportHostAdapterError(OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet)
Definition: VirtioScsi.c:402
STATIC EFI_STATUS EFIAPI PopulateRequest(IN CONST VSCSI_DEV *Dev, IN UINT16 Target, IN UINT64 Lun, IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet, OUT volatile VIRTIO_SCSI_REQ *Request)
Definition: VirtioScsi.c:148
#define VIRTIO_CFG_WRITE(Dev, Field, Value)
Definition: VirtioScsi.c:73