]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/VirtioScsiDxe/VirtioScsi.c
OvmfPkg/VirtioScsiDxe: map VRING using VirtioRingMap()
[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 UINT64 RingBaseShift;
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 // If anything fails from here on, we must release the ring resources
843 //
844 Status = VirtioRingMap (
845 Dev->VirtIo,
846 &Dev->Ring,
847 &RingBaseShift,
848 &Dev->RingMap
849 );
850 if (EFI_ERROR (Status)) {
851 goto ReleaseQueue;
852 }
853
854 //
855 // Additional steps for MMIO: align the queue appropriately, and set the
856 // size. If anything fails from here on, we must unmap the ring resources.
857 //
858 Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);
859 if (EFI_ERROR (Status)) {
860 goto UnmapQueue;
861 }
862
863 Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);
864 if (EFI_ERROR (Status)) {
865 goto UnmapQueue;
866 }
867
868 //
869 // step 4c -- Report GPFN (guest-physical frame number) of queue.
870 //
871 Status = Dev->VirtIo->SetQueueAddress (
872 Dev->VirtIo,
873 &Dev->Ring,
874 RingBaseShift
875 );
876 if (EFI_ERROR (Status)) {
877 goto UnmapQueue;
878 }
879
880 //
881 // step 5 -- Report understood features and guest-tuneables.
882 //
883 if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) {
884 Features &= ~(UINT64)VIRTIO_F_VERSION_1;
885 Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);
886 if (EFI_ERROR (Status)) {
887 goto UnmapQueue;
888 }
889 }
890
891 //
892 // We expect these maximum sizes from the host. Since they are
893 // guest-negotiable, ask for them rather than just checking them.
894 //
895 Status = VIRTIO_CFG_WRITE (Dev, CdbSize, VIRTIO_SCSI_CDB_SIZE);
896 if (EFI_ERROR (Status)) {
897 goto UnmapQueue;
898 }
899 Status = VIRTIO_CFG_WRITE (Dev, SenseSize, VIRTIO_SCSI_SENSE_SIZE);
900 if (EFI_ERROR (Status)) {
901 goto UnmapQueue;
902 }
903
904 //
905 // step 6 -- initialization complete
906 //
907 NextDevStat |= VSTAT_DRIVER_OK;
908 Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
909 if (EFI_ERROR (Status)) {
910 goto UnmapQueue;
911 }
912
913 //
914 // populate the exported interface's attributes
915 //
916 Dev->PassThru.Mode = &Dev->PassThruMode;
917 Dev->PassThru.PassThru = &VirtioScsiPassThru;
918 Dev->PassThru.GetNextTargetLun = &VirtioScsiGetNextTargetLun;
919 Dev->PassThru.BuildDevicePath = &VirtioScsiBuildDevicePath;
920 Dev->PassThru.GetTargetLun = &VirtioScsiGetTargetLun;
921 Dev->PassThru.ResetChannel = &VirtioScsiResetChannel;
922 Dev->PassThru.ResetTargetLun = &VirtioScsiResetTargetLun;
923 Dev->PassThru.GetNextTarget = &VirtioScsiGetNextTarget;
924
925 //
926 // AdapterId is a target for which no handle will be created during bus scan.
927 // Prevent any conflict with real devices.
928 //
929 Dev->PassThruMode.AdapterId = 0xFFFFFFFF;
930
931 //
932 // Set both physical and logical attributes for non-RAID SCSI channel. See
933 // Driver Writer's Guide for UEFI 2.3.1 v1.01, 20.1.5 Implementing Extended
934 // SCSI Pass Thru Protocol.
935 //
936 Dev->PassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL |
937 EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
938
939 //
940 // no restriction on transfer buffer alignment
941 //
942 Dev->PassThruMode.IoAlign = 0;
943
944 return EFI_SUCCESS;
945
946 UnmapQueue:
947 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);
948
949 ReleaseQueue:
950 VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
951
952 Failed:
953 //
954 // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device
955 // Status. VirtIo access failure here should not mask the original error.
956 //
957 NextDevStat |= VSTAT_FAILED;
958 Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
959
960 Dev->InOutSupported = FALSE;
961 Dev->MaxTarget = 0;
962 Dev->MaxLun = 0;
963 Dev->MaxSectors = 0;
964
965 return Status; // reached only via Failed above
966 }
967
968
969 STATIC
970 VOID
971 EFIAPI
972 VirtioScsiUninit (
973 IN OUT VSCSI_DEV *Dev
974 )
975 {
976 //
977 // Reset the virtual device -- see virtio-0.9.5, 2.2.2.1 Device Status. When
978 // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
979 // the old comms area.
980 //
981 Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
982
983 Dev->InOutSupported = FALSE;
984 Dev->MaxTarget = 0;
985 Dev->MaxLun = 0;
986 Dev->MaxSectors = 0;
987
988 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);
989 VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
990
991 SetMem (&Dev->PassThru, sizeof Dev->PassThru, 0x00);
992 SetMem (&Dev->PassThruMode, sizeof Dev->PassThruMode, 0x00);
993 }
994
995
996 //
997 // Event notification function enqueued by ExitBootServices().
998 //
999
1000 STATIC
1001 VOID
1002 EFIAPI
1003 VirtioScsiExitBoot (
1004 IN EFI_EVENT Event,
1005 IN VOID *Context
1006 )
1007 {
1008 VSCSI_DEV *Dev;
1009
1010 //
1011 // Reset the device. This causes the hypervisor to forget about the virtio
1012 // ring.
1013 //
1014 // We allocated said ring in EfiBootServicesData type memory, and code
1015 // executing after ExitBootServices() is permitted to overwrite it.
1016 //
1017 Dev = Context;
1018 Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
1019
1020 //
1021 // Unmap the ring buffer so that hypervisor will not be able to get
1022 // readable data after device reset.
1023 //
1024 Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);
1025 }
1026
1027
1028 //
1029 // Probe, start and stop functions of this driver, called by the DXE core for
1030 // specific devices.
1031 //
1032 // The following specifications document these interfaces:
1033 // - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
1034 // - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
1035 //
1036 // The implementation follows:
1037 // - Driver Writer's Guide for UEFI 2.3.1 v1.01
1038 // - 5.1.3.4 OpenProtocol() and CloseProtocol()
1039 // - UEFI Spec 2.3.1 + Errata C
1040 // - 6.3 Protocol Handler Services
1041 //
1042
1043 EFI_STATUS
1044 EFIAPI
1045 VirtioScsiDriverBindingSupported (
1046 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1047 IN EFI_HANDLE DeviceHandle,
1048 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1049 )
1050 {
1051 EFI_STATUS Status;
1052 VIRTIO_DEVICE_PROTOCOL *VirtIo;
1053
1054 //
1055 // Attempt to open the device with the VirtIo set of interfaces. On success,
1056 // the protocol is "instantiated" for the VirtIo device. Covers duplicate open
1057 // attempts (EFI_ALREADY_STARTED).
1058 //
1059 Status = gBS->OpenProtocol (
1060 DeviceHandle, // candidate device
1061 &gVirtioDeviceProtocolGuid, // for generic VirtIo access
1062 (VOID **)&VirtIo, // handle to instantiate
1063 This->DriverBindingHandle, // requestor driver identity
1064 DeviceHandle, // ControllerHandle, according to
1065 // the UEFI Driver Model
1066 EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to
1067 // the device; to be released
1068 );
1069 if (EFI_ERROR (Status)) {
1070 return Status;
1071 }
1072
1073 if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_SCSI_HOST) {
1074 Status = EFI_UNSUPPORTED;
1075 }
1076
1077 //
1078 // We needed VirtIo access only transitorily, to see whether we support the
1079 // device or not.
1080 //
1081 gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
1082 This->DriverBindingHandle, DeviceHandle);
1083 return Status;
1084 }
1085
1086
1087 EFI_STATUS
1088 EFIAPI
1089 VirtioScsiDriverBindingStart (
1090 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1091 IN EFI_HANDLE DeviceHandle,
1092 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
1093 )
1094 {
1095 VSCSI_DEV *Dev;
1096 EFI_STATUS Status;
1097
1098 Dev = (VSCSI_DEV *) AllocateZeroPool (sizeof *Dev);
1099 if (Dev == NULL) {
1100 return EFI_OUT_OF_RESOURCES;
1101 }
1102
1103 Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
1104 (VOID **)&Dev->VirtIo, This->DriverBindingHandle,
1105 DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
1106 if (EFI_ERROR (Status)) {
1107 goto FreeVirtioScsi;
1108 }
1109
1110 //
1111 // VirtIo access granted, configure virtio-scsi device.
1112 //
1113 Status = VirtioScsiInit (Dev);
1114 if (EFI_ERROR (Status)) {
1115 goto CloseVirtIo;
1116 }
1117
1118 Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
1119 &VirtioScsiExitBoot, Dev, &Dev->ExitBoot);
1120 if (EFI_ERROR (Status)) {
1121 goto UninitDev;
1122 }
1123
1124 //
1125 // Setup complete, attempt to export the driver instance's PassThru
1126 // interface.
1127 //
1128 Dev->Signature = VSCSI_SIG;
1129 Status = gBS->InstallProtocolInterface (&DeviceHandle,
1130 &gEfiExtScsiPassThruProtocolGuid, EFI_NATIVE_INTERFACE,
1131 &Dev->PassThru);
1132 if (EFI_ERROR (Status)) {
1133 goto CloseExitBoot;
1134 }
1135
1136 return EFI_SUCCESS;
1137
1138 CloseExitBoot:
1139 gBS->CloseEvent (Dev->ExitBoot);
1140
1141 UninitDev:
1142 VirtioScsiUninit (Dev);
1143
1144 CloseVirtIo:
1145 gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
1146 This->DriverBindingHandle, DeviceHandle);
1147
1148 FreeVirtioScsi:
1149 FreePool (Dev);
1150
1151 return Status;
1152 }
1153
1154
1155 EFI_STATUS
1156 EFIAPI
1157 VirtioScsiDriverBindingStop (
1158 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1159 IN EFI_HANDLE DeviceHandle,
1160 IN UINTN NumberOfChildren,
1161 IN EFI_HANDLE *ChildHandleBuffer
1162 )
1163 {
1164 EFI_STATUS Status;
1165 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;
1166 VSCSI_DEV *Dev;
1167
1168 Status = gBS->OpenProtocol (
1169 DeviceHandle, // candidate device
1170 &gEfiExtScsiPassThruProtocolGuid, // retrieve the SCSI iface
1171 (VOID **)&PassThru, // target pointer
1172 This->DriverBindingHandle, // requestor driver ident.
1173 DeviceHandle, // lookup req. for dev.
1174 EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no new ref.
1175 );
1176 if (EFI_ERROR (Status)) {
1177 return Status;
1178 }
1179
1180 Dev = VIRTIO_SCSI_FROM_PASS_THRU (PassThru);
1181
1182 //
1183 // Handle Stop() requests for in-use driver instances gracefully.
1184 //
1185 Status = gBS->UninstallProtocolInterface (DeviceHandle,
1186 &gEfiExtScsiPassThruProtocolGuid, &Dev->PassThru);
1187 if (EFI_ERROR (Status)) {
1188 return Status;
1189 }
1190
1191 gBS->CloseEvent (Dev->ExitBoot);
1192
1193 VirtioScsiUninit (Dev);
1194
1195 gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
1196 This->DriverBindingHandle, DeviceHandle);
1197
1198 FreePool (Dev);
1199
1200 return EFI_SUCCESS;
1201 }
1202
1203
1204 //
1205 // The static object that groups the Supported() (ie. probe), Start() and
1206 // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
1207 // C, 10.1 EFI Driver Binding Protocol.
1208 //
1209 STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
1210 &VirtioScsiDriverBindingSupported,
1211 &VirtioScsiDriverBindingStart,
1212 &VirtioScsiDriverBindingStop,
1213 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
1214 NULL, // ImageHandle, to be overwritten by
1215 // EfiLibInstallDriverBindingComponentName2() in VirtioScsiEntryPoint()
1216 NULL // DriverBindingHandle, ditto
1217 };
1218
1219
1220 //
1221 // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
1222 // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
1223 // in English, for display on standard console devices. This is recommended for
1224 // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
1225 // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
1226 //
1227 // Device type names ("Virtio SCSI Host Device") are not formatted because the
1228 // driver supports only that device type. Therefore the driver name suffices
1229 // for unambiguous identification.
1230 //
1231
1232 STATIC
1233 EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
1234 { "eng;en", L"Virtio SCSI Host Driver" },
1235 { NULL, NULL }
1236 };
1237
1238 STATIC
1239 EFI_COMPONENT_NAME_PROTOCOL gComponentName;
1240
1241 EFI_STATUS
1242 EFIAPI
1243 VirtioScsiGetDriverName (
1244 IN EFI_COMPONENT_NAME_PROTOCOL *This,
1245 IN CHAR8 *Language,
1246 OUT CHAR16 **DriverName
1247 )
1248 {
1249 return LookupUnicodeString2 (
1250 Language,
1251 This->SupportedLanguages,
1252 mDriverNameTable,
1253 DriverName,
1254 (BOOLEAN)(This == &gComponentName) // Iso639Language
1255 );
1256 }
1257
1258 EFI_STATUS
1259 EFIAPI
1260 VirtioScsiGetDeviceName (
1261 IN EFI_COMPONENT_NAME_PROTOCOL *This,
1262 IN EFI_HANDLE DeviceHandle,
1263 IN EFI_HANDLE ChildHandle,
1264 IN CHAR8 *Language,
1265 OUT CHAR16 **ControllerName
1266 )
1267 {
1268 return EFI_UNSUPPORTED;
1269 }
1270
1271 STATIC
1272 EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
1273 &VirtioScsiGetDriverName,
1274 &VirtioScsiGetDeviceName,
1275 "eng" // SupportedLanguages, ISO 639-2 language codes
1276 };
1277
1278 STATIC
1279 EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
1280 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) &VirtioScsiGetDriverName,
1281 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &VirtioScsiGetDeviceName,
1282 "en" // SupportedLanguages, RFC 4646 language codes
1283 };
1284
1285
1286 //
1287 // Entry point of this driver.
1288 //
1289 EFI_STATUS
1290 EFIAPI
1291 VirtioScsiEntryPoint (
1292 IN EFI_HANDLE ImageHandle,
1293 IN EFI_SYSTEM_TABLE *SystemTable
1294 )
1295 {
1296 return EfiLibInstallDriverBindingComponentName2 (
1297 ImageHandle,
1298 SystemTable,
1299 &gDriverBinding,
1300 ImageHandle,
1301 &gComponentName,
1302 &gComponentName2
1303 );
1304 }