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