]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBus.c
Code Scrub:
[mirror_edk2.git] / MdeModulePkg / Bus / Scsi / ScsiBusDxe / ScsiBus.c
1 /** @file
2 SCSI Bus driver that layers on every SCSI Pass Thru and
3 Extended SCSI Pass Thru protocol in the system.
4
5 Copyright (c) 2006 - 2008, Intel Corporation. <BR>
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16
17 #include "ScsiBus.h"
18
19
20 EFI_DRIVER_BINDING_PROTOCOL gSCSIBusDriverBinding = {
21 SCSIBusDriverBindingSupported,
22 SCSIBusDriverBindingStart,
23 SCSIBusDriverBindingStop,
24 0xa,
25 NULL,
26 NULL
27 };
28
29
30 //
31 // The ScsiBusProtocol is just used to locate ScsiBusDev
32 // structure in the SCSIBusDriverBindingStop(). Then we can
33 // Close all opened protocols and release this structure.
34 //
35 EFI_GUID mScsiBusProtocolGuid = EFI_SCSI_BUS_PROTOCOL_GUID;
36
37 VOID *mWorkingBuffer;
38
39 /**
40 Convert EFI_SCSI_IO_SCSI_REQUEST_PACKET packet to EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet.
41
42 @param Packet The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET
43 @param CommandPacket The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
44
45 **/
46 EFI_STATUS
47 EFIAPI
48 ScsiioToPassThruPacket (
49 IN EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet,
50 OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *CommandPacket
51 );
52
53 /**
54 Convert EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet to EFI_SCSI_IO_SCSI_REQUEST_PACKET packet.
55
56 @param ScsiPacket The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
57 @param Packet The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET
58
59 **/
60 EFI_STATUS
61 EFIAPI
62 PassThruToScsiioPacket (
63 IN EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ScsiPacket,
64 OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet
65 );
66
67 /**
68 Notify Function in which convert EFI1.0 PassThru Packet back to UEF2.0
69 SCSI IO Packet.
70
71 @param Event The instance of EFI_EVENT.
72 @param Context The parameter passed in.
73
74 **/
75 VOID
76 EFIAPI
77 NotifyFunction (
78 IN EFI_EVENT Event,
79 IN VOID *Context
80 );
81
82 /**
83 The user Entry Point for module ScsiBus. The user code starts with this function.
84
85 @param ImageHandle The firmware allocated handle for the EFI image.
86 @param SystemTable A pointer to the EFI System Table.
87
88 @retval EFI_SUCCESS The entry point is executed successfully.
89 @retval other Some error occurs when executing this entry point.
90
91 **/
92 EFI_STATUS
93 EFIAPI
94 InitializeScsiBus(
95 IN EFI_HANDLE ImageHandle,
96 IN EFI_SYSTEM_TABLE *SystemTable
97 )
98 {
99 EFI_STATUS Status;
100
101 //
102 // Install driver model protocol(s).
103 //
104 Status = EfiLibInstallDriverBindingComponentName2 (
105 ImageHandle,
106 SystemTable,
107 &gSCSIBusDriverBinding,
108 ImageHandle,
109 &gScsiBusComponentName,
110 &gScsiBusComponentName2
111 );
112 ASSERT_EFI_ERROR (Status);
113
114 return Status;
115 }
116
117
118 /**
119 Test to see if this driver supports ControllerHandle.
120
121 This service is called by the EFI boot service ConnectController(). In order
122 to make drivers as small as possible, there are a few calling restrictions for
123 this service. ConnectController() must follow these calling restrictions. If
124 any other agent wishes to call Supported() it must also follow these calling
125 restrictions.
126
127 @param This Protocol instance pointer.
128 @param ControllerHandle Handle of device to test
129 @param RemainingDevicePath Optional parameter use to pick a specific child
130 device to start.
131
132 @retval EFI_SUCCESS This driver supports this device
133 @retval EFI_ALREADY_STARTED This driver is already running on this device
134 @retval other This driver does not support this device
135
136 **/
137 EFI_STATUS
138 EFIAPI
139 SCSIBusDriverBindingSupported (
140 IN EFI_DRIVER_BINDING_PROTOCOL *This,
141 IN EFI_HANDLE Controller,
142 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
143 )
144 {
145 EFI_STATUS Status;
146 EFI_SCSI_PASS_THRU_PROTOCOL *PassThru;
147 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtPassThru;
148 //
149 // Check for the existence of Extended SCSI Pass Thru Protocol and SCSI Pass Thru Protocol
150 //
151 Status = gBS->OpenProtocol (
152 Controller,
153 &gEfiExtScsiPassThruProtocolGuid,
154 (VOID **)&ExtPassThru,
155 This->DriverBindingHandle,
156 Controller,
157 EFI_OPEN_PROTOCOL_BY_DRIVER
158 );
159
160 if (Status == EFI_ALREADY_STARTED) {
161 return EFI_SUCCESS;
162 }
163
164 if (EFI_ERROR (Status)) {
165 Status = gBS->OpenProtocol (
166 Controller,
167 &gEfiScsiPassThruProtocolGuid,
168 (VOID **)&PassThru,
169 This->DriverBindingHandle,
170 Controller,
171 EFI_OPEN_PROTOCOL_BY_DRIVER
172 );
173
174 if (Status == EFI_ALREADY_STARTED) {
175 return EFI_SUCCESS;
176 }
177
178 if (EFI_ERROR (Status)) {
179 return Status;
180 }
181
182 gBS->CloseProtocol (
183 Controller,
184 &gEfiScsiPassThruProtocolGuid,
185 This->DriverBindingHandle,
186 Controller
187 );
188 return EFI_SUCCESS;
189 }
190
191 gBS->CloseProtocol (
192 Controller,
193 &gEfiExtScsiPassThruProtocolGuid,
194 This->DriverBindingHandle,
195 Controller
196 );
197
198 return EFI_SUCCESS;
199 }
200
201
202 /**
203 Start this driver on ControllerHandle.
204
205 This service is called by the EFI boot service ConnectController(). In order
206 to make drivers as small as possible, there are a few calling restrictions for
207 this service. ConnectController() must follow these calling restrictions. If
208 any other agent wishes to call Start() it must also follow these calling
209 restrictions.
210
211 @param This Protocol instance pointer.
212 @param ControllerHandle Handle of device to bind driver to
213 @param RemainingDevicePath Optional parameter use to pick a specific child
214 device to start.
215
216 @retval EFI_SUCCESS This driver is added to ControllerHandle
217 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
218 @retval other This driver does not support this device
219
220 **/
221 EFI_STATUS
222 EFIAPI
223 SCSIBusDriverBindingStart (
224 IN EFI_DRIVER_BINDING_PROTOCOL *This,
225 IN EFI_HANDLE Controller,
226 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
227 )
228 {
229 UINT64 Lun;
230 UINT8 *TargetId;
231 BOOLEAN ScanOtherPuns;
232 BOOLEAN FromFirstTarget;
233 BOOLEAN ExtScsiSupport;
234 EFI_STATUS Status;
235 EFI_STATUS DevicePathStatus;
236 EFI_STATUS PassThruStatus;
237 SCSI_BUS_DEVICE *ScsiBusDev;
238 SCSI_TARGET_ID *ScsiTargetId;
239 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
240 EFI_SCSI_PASS_THRU_PROTOCOL *ScsiInterface;
241 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtScsiInterface;
242 EFI_SCSI_BUS_PROTOCOL *BusIdentify;
243
244 TargetId = NULL;
245 ScsiTargetId = NULL;
246 ScanOtherPuns = TRUE;
247 FromFirstTarget = FALSE;
248 ExtScsiSupport = FALSE;
249 PassThruStatus = EFI_SUCCESS;
250
251 ScsiTargetId = AllocateZeroPool(sizeof(SCSI_TARGET_ID));
252 if (ScsiTargetId == NULL) {
253 return EFI_OUT_OF_RESOURCES;
254 }
255
256 TargetId = &ScsiTargetId->ScsiId.ExtScsi[0];
257
258 DevicePathStatus = gBS->OpenProtocol (
259 Controller,
260 &gEfiDevicePathProtocolGuid,
261 (VOID **) &ParentDevicePath,
262 This->DriverBindingHandle,
263 Controller,
264 EFI_OPEN_PROTOCOL_BY_DRIVER
265 );
266 if (EFI_ERROR (DevicePathStatus) && (DevicePathStatus != EFI_ALREADY_STARTED)) {
267 return DevicePathStatus;
268 }
269
270 //
271 // To keep backward compatibility, UEFI ExtPassThru Protocol is supported as well as
272 // EFI PassThru Protocol. From priority perspective, ExtPassThru Protocol is firstly
273 // tried to open on host controller handle. If fails, then PassThru Protocol is tried instead.
274 //
275 Status = gBS->OpenProtocol (
276 Controller,
277 &gEfiExtScsiPassThruProtocolGuid,
278 (VOID **) &ExtScsiInterface,
279 This->DriverBindingHandle,
280 Controller,
281 EFI_OPEN_PROTOCOL_BY_DRIVER
282 );
283 //
284 // Fail to open UEFI ExtendPassThru Protocol, then try to open EFI PassThru Protocol instead.
285 //
286 if (EFI_ERROR(Status) && (Status != EFI_ALREADY_STARTED)) {
287 Status = gBS->OpenProtocol (
288 Controller,
289 &gEfiScsiPassThruProtocolGuid,
290 (VOID **) &ScsiInterface,
291 This->DriverBindingHandle,
292 Controller,
293 EFI_OPEN_PROTOCOL_BY_DRIVER
294 );
295 //
296 // Fail to open EFI PassThru Protocol, Close the DevicePathProtocol if it is opened by this time.
297 //
298 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
299 if (!EFI_ERROR(DevicePathStatus)) {
300 gBS->CloseProtocol (
301 Controller,
302 &gEfiDevicePathProtocolGuid,
303 This->DriverBindingHandle,
304 Controller
305 );
306 }
307 return Status;
308 }
309 } else {
310 //
311 // Succeed to open ExtPassThru Protocol, and meanwhile open PassThru Protocol
312 // with BY_DRIVER if it is also present on the handle. The intent is to prevent
313 // another SCSI Bus Driver to work on the same host handle.
314 //
315 ExtScsiSupport = TRUE;
316 PassThruStatus = gBS->OpenProtocol (
317 Controller,
318 &gEfiScsiPassThruProtocolGuid,
319 (VOID **) &ScsiInterface,
320 This->DriverBindingHandle,
321 Controller,
322 EFI_OPEN_PROTOCOL_BY_DRIVER
323 );
324 }
325
326 if (Status != EFI_ALREADY_STARTED) {
327 //
328 // Go through here means either ExtPassThru or PassThru Protocol is successfully opened
329 // on this handle for this time. Then construct Host controller private data.
330 //
331 ScsiBusDev = NULL;
332 ScsiBusDev = AllocateZeroPool(sizeof(SCSI_BUS_DEVICE));
333 if (ScsiBusDev == NULL) {
334 Status = EFI_OUT_OF_RESOURCES;
335 goto ErrorExit;
336 }
337 ScsiBusDev->Signature = SCSI_BUS_DEVICE_SIGNATURE;
338 ScsiBusDev->ExtScsiSupport = ExtScsiSupport;
339 ScsiBusDev->DevicePath = ParentDevicePath;
340 if (ScsiBusDev->ExtScsiSupport) {
341 ScsiBusDev->ExtScsiInterface = ExtScsiInterface;
342 } else {
343 ScsiBusDev->ScsiInterface = ScsiInterface;
344 }
345
346 //
347 // Install EFI_SCSI_BUS_PROTOCOL to the controller handle, So ScsiBusDev could be
348 // retrieved on this controller handle. With ScsiBusDev, we can know which PassThru
349 // Protocol is present on the handle, UEFI ExtPassThru Protocol or EFI PassThru Protocol.
350 //
351 Status = gBS->InstallProtocolInterface (
352 &Controller,
353 &mScsiBusProtocolGuid,
354 EFI_NATIVE_INTERFACE,
355 &ScsiBusDev->BusIdentify
356 );
357 if (EFI_ERROR (Status)) {
358 goto ErrorExit;
359 }
360 } else {
361 //
362 // Go through here means Start() is re-invoked again, nothing special is required to do except
363 // picking up Host controller private information.
364 //
365 Status = gBS->OpenProtocol (
366 Controller,
367 &mScsiBusProtocolGuid,
368 (VOID **) &BusIdentify,
369 This->DriverBindingHandle,
370 Controller,
371 EFI_OPEN_PROTOCOL_GET_PROTOCOL
372 );
373
374 if (EFI_ERROR (Status)) {
375 return Status;
376 }
377 ScsiBusDev = SCSI_BUS_CONTROLLER_DEVICE_FROM_THIS (BusIdentify);
378 }
379
380 if (RemainingDevicePath == NULL) {
381 SetMem (ScsiTargetId, TARGET_MAX_BYTES,0xFF);
382 Lun = 0;
383 FromFirstTarget = TRUE;
384 } else {
385 if (ScsiBusDev->ExtScsiSupport) {
386 ScsiBusDev->ExtScsiInterface->GetTargetLun (ScsiBusDev->ExtScsiInterface, RemainingDevicePath, &TargetId, &Lun);
387 } else {
388 ScsiBusDev->ScsiInterface->GetTargetLun (ScsiBusDev->ScsiInterface, RemainingDevicePath, &ScsiTargetId->ScsiId.Scsi, &Lun);
389 }
390 }
391
392 while(ScanOtherPuns) {
393 if (FromFirstTarget) {
394 //
395 // Remaining Device Path is NULL, scan all the possible Puns in the
396 // SCSI Channel.
397 //
398 if (ScsiBusDev->ExtScsiSupport) {
399 Status = ScsiBusDev->ExtScsiInterface->GetNextTargetLun (ScsiBusDev->ExtScsiInterface, &TargetId, &Lun);
400 } else {
401 Status = ScsiBusDev->ScsiInterface->GetNextDevice (ScsiBusDev->ScsiInterface, &ScsiTargetId->ScsiId.Scsi, &Lun);
402 }
403 if (EFI_ERROR (Status)) {
404 //
405 // no legal Pun and Lun found any more
406 //
407 break;
408 }
409 } else {
410 ScanOtherPuns = FALSE;
411 }
412 //
413 // Avoid creating handle for the host adapter.
414 //
415 if (ScsiBusDev->ExtScsiSupport) {
416 if ((ScsiTargetId->ScsiId.Scsi) == ScsiBusDev->ExtScsiInterface->Mode->AdapterId) {
417 continue;
418 }
419 } else {
420 if ((ScsiTargetId->ScsiId.Scsi) == ScsiBusDev->ScsiInterface->Mode->AdapterId) {
421 continue;
422 }
423 }
424 //
425 // Scan for the scsi device, if it attaches to the scsi bus,
426 // then create handle and install scsi i/o protocol.
427 //
428 Status = ScsiScanCreateDevice (This, Controller, ScsiTargetId, Lun, ScsiBusDev);
429 }
430 FreePool (ScsiTargetId);
431 return EFI_SUCCESS;
432
433 ErrorExit:
434
435 if (ScsiBusDev != NULL) {
436 gBS->FreePool (ScsiBusDev);
437 }
438
439 if (ExtScsiSupport) {
440 gBS->CloseProtocol (
441 Controller,
442 &gEfiExtScsiPassThruProtocolGuid,
443 This->DriverBindingHandle,
444 Controller
445 );
446 if (!EFI_ERROR (PassThruStatus)) {
447 gBS->CloseProtocol (
448 Controller,
449 &gEfiScsiPassThruProtocolGuid,
450 This->DriverBindingHandle,
451 Controller
452 );
453 }
454 } else {
455 gBS->CloseProtocol (
456 Controller,
457 &gEfiScsiPassThruProtocolGuid,
458 This->DriverBindingHandle,
459 Controller
460 );
461 }
462 return Status;
463 }
464
465 /**
466 Stop this driver on ControllerHandle.
467
468 This service is called by the EFI boot service DisconnectController().
469 In order to make drivers as small as possible, there are a few calling
470 restrictions for this service. DisconnectController() must follow these
471 calling restrictions. If any other agent wishes to call Stop() it must also
472 follow these calling restrictions.
473
474 @param This Protocol instance pointer.
475 @param ControllerHandle Handle of device to stop driver on
476 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
477 children is zero stop the entire bus driver.
478 @param ChildHandleBuffer List of Child Handles to Stop.
479
480 @retval EFI_SUCCESS This driver is removed ControllerHandle
481 @retval other This driver was not removed from this device
482
483 **/
484 EFI_STATUS
485 EFIAPI
486 SCSIBusDriverBindingStop (
487 IN EFI_DRIVER_BINDING_PROTOCOL *This,
488 IN EFI_HANDLE Controller,
489 IN UINTN NumberOfChildren,
490 IN EFI_HANDLE *ChildHandleBuffer
491 )
492 {
493 EFI_STATUS Status;
494 BOOLEAN AllChildrenStopped;
495 UINTN Index;
496 EFI_SCSI_IO_PROTOCOL *ScsiIo;
497 SCSI_IO_DEV *ScsiIoDevice;
498 VOID *ScsiPassThru;
499 EFI_SCSI_BUS_PROTOCOL *Scsidentifier;
500 SCSI_BUS_DEVICE *ScsiBusDev;
501
502 if (NumberOfChildren == 0) {
503 //
504 // Get the SCSI_BUS_DEVICE
505 //
506 Status = gBS->OpenProtocol (
507 Controller,
508 &mScsiBusProtocolGuid,
509 (VOID **) &Scsidentifier,
510 This->DriverBindingHandle,
511 Controller,
512 EFI_OPEN_PROTOCOL_GET_PROTOCOL
513 );
514
515 if (EFI_ERROR (Status)) {
516 return EFI_DEVICE_ERROR;
517 }
518
519 ScsiBusDev = SCSI_BUS_CONTROLLER_DEVICE_FROM_THIS (Scsidentifier);
520
521 //
522 // Uninstall SCSI Bus Protocol
523 //
524 gBS->UninstallProtocolInterface (
525 Controller,
526 &mScsiBusProtocolGuid,
527 &ScsiBusDev->BusIdentify
528 );
529
530 //
531 // Close the bus driver
532 //
533 if (ScsiBusDev->ExtScsiSupport) {
534 gBS->CloseProtocol (
535 Controller,
536 &gEfiExtScsiPassThruProtocolGuid,
537 This->DriverBindingHandle,
538 Controller
539 );
540 } else {
541 gBS->CloseProtocol (
542 Controller,
543 &gEfiScsiPassThruProtocolGuid,
544 This->DriverBindingHandle,
545 Controller
546 );
547 }
548
549 gBS->CloseProtocol (
550 Controller,
551 &gEfiDevicePathProtocolGuid,
552 This->DriverBindingHandle,
553 Controller
554 );
555 gBS->FreePool (ScsiBusDev);
556 return EFI_SUCCESS;
557 }
558
559 AllChildrenStopped = TRUE;
560
561 for (Index = 0; Index < NumberOfChildren; Index++) {
562
563 Status = gBS->OpenProtocol (
564 ChildHandleBuffer[Index],
565 &gEfiScsiIoProtocolGuid,
566 (VOID **) &ScsiIo,
567 This->DriverBindingHandle,
568 Controller,
569 EFI_OPEN_PROTOCOL_GET_PROTOCOL
570 );
571 if (EFI_ERROR (Status)) {
572 AllChildrenStopped = FALSE;
573 continue;
574 }
575
576 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (ScsiIo);
577 //
578 // Close the child handle
579 //
580 if (ScsiIoDevice->ExtScsiSupport) {
581 Status = gBS->CloseProtocol (
582 Controller,
583 &gEfiExtScsiPassThruProtocolGuid,
584 This->DriverBindingHandle,
585 ChildHandleBuffer[Index]
586 );
587
588 } else {
589 Status = gBS->CloseProtocol (
590 Controller,
591 &gEfiScsiPassThruProtocolGuid,
592 This->DriverBindingHandle,
593 ChildHandleBuffer[Index]
594 );
595 }
596
597 Status = gBS->UninstallMultipleProtocolInterfaces (
598 ChildHandleBuffer[Index],
599 &gEfiDevicePathProtocolGuid,
600 ScsiIoDevice->DevicePath,
601 &gEfiScsiIoProtocolGuid,
602 &ScsiIoDevice->ScsiIo,
603 NULL
604 );
605 if (EFI_ERROR (Status)) {
606 AllChildrenStopped = FALSE;
607 if (ScsiIoDevice->ExtScsiSupport) {
608 gBS->OpenProtocol (
609 Controller,
610 &gEfiExtScsiPassThruProtocolGuid,
611 &ScsiPassThru,
612 This->DriverBindingHandle,
613 ChildHandleBuffer[Index],
614 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
615 );
616 } else {
617 gBS->OpenProtocol (
618 Controller,
619 &gEfiScsiPassThruProtocolGuid,
620 &ScsiPassThru,
621 This->DriverBindingHandle,
622 ChildHandleBuffer[Index],
623 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
624 );
625 }
626 } else {
627 gBS->FreePool (ScsiIoDevice);
628 }
629 }
630
631 if (!AllChildrenStopped) {
632 return EFI_DEVICE_ERROR;
633 }
634
635 return EFI_SUCCESS;
636 }
637
638
639 /**
640 Retrieves the device type information of the SCSI Controller.
641
642 @param This Protocol instance pointer.
643 @param DeviceType A pointer to the device type information retrieved from
644 the SCSI Controller.
645
646 @retval EFI_SUCCESS Retrieves the device type information successfully.
647 @retval EFI_INVALID_PARAMETER The DeviceType is NULL.
648
649 **/
650 EFI_STATUS
651 EFIAPI
652 ScsiGetDeviceType (
653 IN EFI_SCSI_IO_PROTOCOL *This,
654 OUT UINT8 *DeviceType
655 )
656 {
657 SCSI_IO_DEV *ScsiIoDevice;
658
659 if (DeviceType == NULL) {
660 return EFI_INVALID_PARAMETER;
661 }
662
663 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
664 *DeviceType = ScsiIoDevice->ScsiDeviceType;
665 return EFI_SUCCESS;
666 }
667
668
669 /**
670 Retrieves the device location in the SCSI channel.
671
672 @param This Protocol instance pointer.
673 @param Target A pointer to the Target ID of a SCSI device
674 on the SCSI channel.
675 @param Lun A pointer to the LUN of the SCSI device on
676 the SCSI channel.
677
678 @retval EFI_SUCCESS Retrieves the device location successfully.
679 @retval EFI_INVALID_PARAMETER The Target or Lun is NULL.
680
681 **/
682 EFI_STATUS
683 EFIAPI
684 ScsiGetDeviceLocation (
685 IN EFI_SCSI_IO_PROTOCOL *This,
686 IN OUT UINT8 **Target,
687 OUT UINT64 *Lun
688 )
689 {
690 SCSI_IO_DEV *ScsiIoDevice;
691
692 if (Target == NULL || Lun == NULL) {
693 return EFI_INVALID_PARAMETER;
694 }
695
696 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
697
698 CopyMem (*Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES);
699
700 *Lun = ScsiIoDevice->Lun;
701
702 return EFI_SUCCESS;
703 }
704
705 /**
706 Resets the SCSI Bus that the SCSI Controller is attached to.
707
708 @param This Protocol instance pointer.
709
710 @retval EFI_SUCCESS The SCSI bus is reset successfully.
711 @retval EFI_DEVICE_ERROR Errors encountered when resetting the SCSI bus.
712 @retval EFI_UNSUPPORTED The bus reset operation is not supported by the
713 SCSI Host Controller.
714 @retval EFI_TIMEOUT A timeout occurred while attempting to reset
715 the SCSI bus.
716 **/
717 EFI_STATUS
718 EFIAPI
719 ScsiResetBus (
720 IN EFI_SCSI_IO_PROTOCOL *This
721 )
722 {
723 SCSI_IO_DEV *ScsiIoDevice;
724
725 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
726
727 if (ScsiIoDevice->ExtScsiSupport){
728 return ScsiIoDevice->ExtScsiPassThru->ResetChannel (ScsiIoDevice->ExtScsiPassThru);
729 } else {
730 return ScsiIoDevice->ScsiPassThru->ResetChannel (ScsiIoDevice->ScsiPassThru);
731 }
732 }
733
734
735 /**
736 Resets the SCSI Controller that the device handle specifies.
737
738 @param This Protocol instance pointer.
739
740 @retval EFI_SUCCESS Reset the SCSI controller successfully.
741 @retval EFI_DEVICE_ERROR Errors are encountered when resetting the SCSI Controller.
742 @retval EFI_UNSUPPORTED The SCSI bus does not support a device reset operation.
743 @retval EFI_TIMEOUT A timeout occurred while attempting to reset the
744 SCSI Controller.
745 **/
746 EFI_STATUS
747 EFIAPI
748 ScsiResetDevice (
749 IN EFI_SCSI_IO_PROTOCOL *This
750 )
751 {
752 SCSI_IO_DEV *ScsiIoDevice;
753 UINT8 Target[TARGET_MAX_BYTES];
754
755 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
756 CopyMem (Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES);
757
758
759 if (ScsiIoDevice->ExtScsiSupport) {
760 return ScsiIoDevice->ExtScsiPassThru->ResetTargetLun (
761 ScsiIoDevice->ExtScsiPassThru,
762 Target,
763 ScsiIoDevice->Lun
764 );
765 } else {
766 return ScsiIoDevice->ScsiPassThru->ResetTarget (
767 ScsiIoDevice->ScsiPassThru,
768 ScsiIoDevice->Pun.ScsiId.Scsi,
769 ScsiIoDevice->Lun
770 );
771 }
772 }
773
774
775 /**
776 Sends a SCSI Request Packet to the SCSI Controller for execution.
777
778 @param This Protocol instance pointer.
779 @param CommandPacket The SCSI request packet to send to the SCSI
780 Controller specified by the device handle.
781 @param Event If the SCSI bus where the SCSI device is attached
782 does not support non-blocking I/O, then Event is
783 ignored, and blocking I/O is performed.
784 If Event is NULL, then blocking I/O is performed.
785 If Event is not NULL and non-blocking I/O is
786 supported, then non-blocking I/O is performed,
787 and Event will be signaled when the SCSI Request
788 Packet completes.
789
790 @retval EFI_SUCCESS The SCSI Request Packet was sent by the host
791 successfully, and TransferLength bytes were
792 transferred to/from DataBuffer.See
793 HostAdapterStatus, TargetStatus,
794 SenseDataLength, and SenseData in that order
795 for additional status information.
796 @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was executed,
797 but the entire DataBuffer could not be transferred.
798 The actual number of bytes transferred is returned
799 in TransferLength. See HostAdapterStatus,
800 TargetStatus, SenseDataLength, and SenseData in
801 that order for additional status information.
802 @retval EFI_NOT_READY The SCSI Request Packet could not be sent because
803 there are too many SCSI Command Packets already
804 queued.The caller may retry again later.
805 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send
806 the SCSI Request Packet. See HostAdapterStatus,
807 TargetStatus, SenseDataLength, and SenseData in
808 that order for additional status information.
809 @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid.
810 The SCSI Request Packet was not sent, so no
811 additional status information is available.
812 @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet
813 is not supported by the SCSI initiator(i.e., SCSI
814 Host Controller). The SCSI Request Packet was not
815 sent, so no additional status information is
816 available.
817 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI
818 Request Packet to execute. See HostAdapterStatus,
819 TargetStatus, SenseDataLength, and SenseData in
820 that order for additional status information.
821 **/
822 EFI_STATUS
823 EFIAPI
824 ScsiExecuteSCSICommand (
825 IN EFI_SCSI_IO_PROTOCOL *This,
826 IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet,
827 IN EFI_EVENT Event OPTIONAL
828 )
829 {
830 SCSI_IO_DEV *ScsiIoDevice;
831 EFI_STATUS Status;
832 UINT8 Target[TARGET_MAX_BYTES];
833 EFI_EVENT PacketEvent;
834 EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ExtRequestPacket;
835 SCSI_EVENT_DATA EventData;
836
837 PacketEvent = NULL;
838
839 if (Packet == NULL) {
840 return EFI_INVALID_PARAMETER;
841 }
842
843 ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This);
844 CopyMem (Target,&ScsiIoDevice->Pun, TARGET_MAX_BYTES);
845
846 if (ScsiIoDevice->ExtScsiSupport) {
847 ExtRequestPacket = (EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *) Packet;
848 Status = ScsiIoDevice->ExtScsiPassThru->PassThru (
849 ScsiIoDevice->ExtScsiPassThru,
850 Target,
851 ScsiIoDevice->Lun,
852 ExtRequestPacket,
853 Event
854 );
855 } else {
856
857 Status = gBS->AllocatePool (
858 EfiBootServicesData,
859 sizeof(EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET),
860 (VOID**)&mWorkingBuffer
861 );
862
863 if (EFI_ERROR (Status)) {
864 return EFI_DEVICE_ERROR;
865 }
866
867 //
868 // Convert package into EFI1.0, EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET.
869 //
870 Status = ScsiioToPassThruPacket(Packet, (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)mWorkingBuffer);
871 if (EFI_ERROR(Status)) {
872 FreePool(mWorkingBuffer);
873 return Status;
874 }
875
876 if ((ScsiIoDevice->ScsiPassThru->Mode->Attributes & EFI_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO) && (Event != NULL)) {
877 EventData.Data1 = (VOID*)Packet;
878 EventData.Data2 = Event;
879 //
880 // Create Event
881 //
882 Status = gBS->CreateEvent (
883 EVT_NOTIFY_SIGNAL,
884 TPL_CALLBACK,
885 NotifyFunction,
886 &EventData,
887 &PacketEvent
888 );
889 if (EFI_ERROR(Status)) {
890 FreePool(mWorkingBuffer);
891 return Status;
892 }
893
894 Status = ScsiIoDevice->ScsiPassThru->PassThru (
895 ScsiIoDevice->ScsiPassThru,
896 ScsiIoDevice->Pun.ScsiId.Scsi,
897 ScsiIoDevice->Lun,
898 mWorkingBuffer,
899 PacketEvent
900 );
901
902 if (EFI_ERROR(Status)) {
903 gBS->FreePool(mWorkingBuffer);
904 gBS->CloseEvent(PacketEvent);
905 return Status;
906 }
907
908 } else {
909 //
910 // If there's no event or SCSI Device doesn't support NON-BLOCKING, just convert
911 // EFI1.0 PassThru packet back to UEFI2.0 SCSI IO Packet.
912 //
913 Status = ScsiIoDevice->ScsiPassThru->PassThru (
914 ScsiIoDevice->ScsiPassThru,
915 ScsiIoDevice->Pun.ScsiId.Scsi,
916 ScsiIoDevice->Lun,
917 mWorkingBuffer,
918 Event
919 );
920 if (EFI_ERROR(Status)) {
921 FreePool(mWorkingBuffer);
922 return Status;
923 }
924
925 PassThruToScsiioPacket((EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)mWorkingBuffer,Packet);
926 //
927 // After converting EFI1.0 PassThru Packet back to UEFI2.0 SCSI IO Packet,
928 // free mWorkingBuffer.
929 //
930 FreePool(mWorkingBuffer);
931 }
932 }
933 return Status;
934 }
935
936
937 /**
938 Scan SCSI Bus to discover the device, and attach ScsiIoProtocol to it.
939
940 @param This Protocol instance pointer
941 @param Controller Controller handle
942 @param TargetId Tartget to be scanned
943 @param Lun The Lun of the SCSI device on the SCSI channel.
944 @param ScsiBusDev The pointer of SCSI_BUS_DEVICE
945
946 @retval EFI_SUCCESS Successfully to discover the device and attach
947 ScsiIoProtocol to it.
948 @retval EFI_OUT_OF_RESOURCES Fail to discover the device.
949
950 **/
951 EFI_STATUS
952 EFIAPI
953 ScsiScanCreateDevice (
954 IN EFI_DRIVER_BINDING_PROTOCOL *This,
955 IN EFI_HANDLE Controller,
956 IN SCSI_TARGET_ID *TargetId,
957 IN UINT64 Lun,
958 IN OUT SCSI_BUS_DEVICE *ScsiBusDev
959 )
960 {
961 EFI_STATUS Status;
962 SCSI_IO_DEV *ScsiIoDevice;
963 EFI_DEVICE_PATH_PROTOCOL *ScsiDevicePath;
964
965 ScsiIoDevice = AllocateZeroPool (sizeof (SCSI_IO_DEV));
966 if (ScsiIoDevice == NULL) {
967 return EFI_OUT_OF_RESOURCES;
968 }
969
970 ScsiIoDevice->Signature = SCSI_IO_DEV_SIGNATURE;
971 CopyMem(&ScsiIoDevice->Pun, TargetId, TARGET_MAX_BYTES);
972 ScsiIoDevice->Lun = Lun;
973
974 if (ScsiBusDev->ExtScsiSupport) {
975 ScsiIoDevice->ExtScsiPassThru = ScsiBusDev->ExtScsiInterface;
976 ScsiIoDevice->ExtScsiSupport = TRUE;
977 ScsiIoDevice->ScsiIo.IoAlign = ScsiIoDevice->ExtScsiPassThru->Mode->IoAlign;
978
979 } else {
980 ScsiIoDevice->ScsiPassThru = ScsiBusDev->ScsiInterface;
981 ScsiIoDevice->ExtScsiSupport = FALSE;
982 ScsiIoDevice->ScsiIo.IoAlign = ScsiIoDevice->ScsiPassThru->Mode->IoAlign;
983 }
984
985 ScsiIoDevice->ScsiIo.GetDeviceType = ScsiGetDeviceType;
986 ScsiIoDevice->ScsiIo.GetDeviceLocation = ScsiGetDeviceLocation;
987 ScsiIoDevice->ScsiIo.ResetBus = ScsiResetBus;
988 ScsiIoDevice->ScsiIo.ResetDevice = ScsiResetDevice;
989 ScsiIoDevice->ScsiIo.ExecuteScsiCommand = ScsiExecuteSCSICommand;
990
991
992 if (!DiscoverScsiDevice (ScsiIoDevice)) {
993 FreePool (ScsiIoDevice);
994 return EFI_OUT_OF_RESOURCES;
995 }
996
997 //
998 // Set Device Path
999 //
1000 if (ScsiIoDevice->ExtScsiSupport){
1001 Status = ScsiIoDevice->ExtScsiPassThru->BuildDevicePath (
1002 ScsiIoDevice->ExtScsiPassThru,
1003 &ScsiIoDevice->Pun.ScsiId.ExtScsi[0],
1004 ScsiIoDevice->Lun,
1005 &ScsiDevicePath
1006 );
1007 if (Status == EFI_OUT_OF_RESOURCES) {
1008 FreePool (ScsiIoDevice);
1009 return Status;
1010 }
1011 } else {
1012 Status = ScsiIoDevice->ScsiPassThru->BuildDevicePath (
1013 ScsiIoDevice->ScsiPassThru,
1014 ScsiIoDevice->Pun.ScsiId.Scsi,
1015 ScsiIoDevice->Lun,
1016 &ScsiDevicePath
1017 );
1018 if (Status == EFI_OUT_OF_RESOURCES) {
1019 FreePool (ScsiIoDevice);
1020 return Status;
1021 }
1022 }
1023
1024 ScsiIoDevice->DevicePath = AppendDevicePathNode (
1025 ScsiBusDev->DevicePath,
1026 ScsiDevicePath
1027 );
1028 //
1029 // The memory space for ScsiDevicePath is allocated in
1030 // ScsiPassThru->BuildDevicePath() function; It is no longer used
1031 // after EfiAppendDevicePathNode,so free the memory it occupies.
1032 //
1033 gBS->FreePool (ScsiDevicePath);
1034
1035 if (ScsiIoDevice->DevicePath == NULL) {
1036 gBS->FreePool (ScsiIoDevice);
1037 return EFI_OUT_OF_RESOURCES;
1038 }
1039
1040 Status = gBS->InstallMultipleProtocolInterfaces (
1041 &ScsiIoDevice->Handle,
1042 &gEfiDevicePathProtocolGuid,
1043 ScsiIoDevice->DevicePath,
1044 &gEfiScsiIoProtocolGuid,
1045 &ScsiIoDevice->ScsiIo,
1046 NULL
1047 );
1048 if (EFI_ERROR (Status)) {
1049 gBS->FreePool (ScsiIoDevice);
1050 return EFI_OUT_OF_RESOURCES;
1051 } else {
1052 if (ScsiBusDev->ExtScsiSupport) {
1053 gBS->OpenProtocol (
1054 Controller,
1055 &gEfiExtScsiPassThruProtocolGuid,
1056 (VOID **) &(ScsiBusDev->ExtScsiInterface),
1057 This->DriverBindingHandle,
1058 ScsiIoDevice->Handle,
1059 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1060 );
1061 } else {
1062 gBS->OpenProtocol (
1063 Controller,
1064 &gEfiScsiPassThruProtocolGuid,
1065 (VOID **) &(ScsiBusDev->ScsiInterface),
1066 This->DriverBindingHandle,
1067 ScsiIoDevice->Handle,
1068 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1069 );
1070 }
1071 }
1072 return EFI_SUCCESS;
1073 }
1074
1075
1076 /**
1077 Discovery SCSI Device
1078
1079 @param ScsiIoDevice The pointer of SCSI_IO_DEV
1080
1081 @retval TRUE Find SCSI Device and verify it.
1082 @retval FALSE Unable to find SCSI Device.
1083
1084 **/
1085 BOOLEAN
1086 DiscoverScsiDevice (
1087 IN OUT SCSI_IO_DEV *ScsiIoDevice
1088 )
1089 {
1090 EFI_STATUS Status;
1091 UINT32 InquiryDataLength;
1092 UINT8 SenseDataLength;
1093 UINT8 HostAdapterStatus;
1094 UINT8 TargetStatus;
1095 EFI_SCSI_SENSE_DATA SenseData;
1096 EFI_SCSI_INQUIRY_DATA InquiryData;
1097
1098 HostAdapterStatus = 0;
1099 TargetStatus = 0;
1100 //
1101 // Using Inquiry command to scan for the device
1102 //
1103 InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA);
1104 SenseDataLength = sizeof (EFI_SCSI_SENSE_DATA);
1105
1106 Status = ScsiInquiryCommand (
1107 &ScsiIoDevice->ScsiIo,
1108 EFI_SCSI_STALL_SECONDS (1),
1109 (VOID *) &SenseData,
1110 &SenseDataLength,
1111 &HostAdapterStatus,
1112 &TargetStatus,
1113 (VOID *) &InquiryData,
1114 &InquiryDataLength,
1115 FALSE
1116 );
1117 if (EFI_ERROR (Status)) {
1118 return FALSE;
1119 }
1120 //
1121 // Retrieved inquiry data successfully
1122 //
1123 if ((InquiryData.Peripheral_Qualifier != 0) &&
1124 (InquiryData.Peripheral_Qualifier != 3)) {
1125 return FALSE;
1126 }
1127
1128 if (InquiryData.Peripheral_Qualifier == 3) {
1129 if (InquiryData.Peripheral_Type != 0x1f) {
1130 return FALSE;
1131 }
1132 }
1133
1134 if (0x1e >= InquiryData.Peripheral_Type && InquiryData.Peripheral_Type >= 0xa) {
1135 return FALSE;
1136 }
1137
1138 //
1139 // valid device type and peripheral qualifier combination.
1140 //
1141 ScsiIoDevice->ScsiDeviceType = InquiryData.Peripheral_Type;
1142 ScsiIoDevice->RemovableDevice = InquiryData.RMB;
1143 if (InquiryData.Version == 0) {
1144 ScsiIoDevice->ScsiVersion = 0;
1145 } else {
1146 //
1147 // ANSI-approved version
1148 //
1149 ScsiIoDevice->ScsiVersion = (UINT8) (InquiryData.Version & 0x03);
1150 }
1151
1152 return TRUE;
1153 }
1154
1155
1156 /**
1157 Convert EFI_SCSI_IO_SCSI_REQUEST_PACKET packet to EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet.
1158
1159 @param Packet The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET
1160 @param CommandPacket The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
1161
1162 **/
1163 EFI_STATUS
1164 EFIAPI
1165 ScsiioToPassThruPacket (
1166 IN EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet,
1167 OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *CommandPacket
1168 )
1169 {
1170 //
1171 //EFI 1.10 doesn't support Bi-Direction Command.
1172 //
1173 if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_BIDIRECTIONAL) {
1174 return EFI_UNSUPPORTED;
1175 }
1176
1177 ZeroMem (CommandPacket, sizeof (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET));
1178
1179 CommandPacket->Timeout = Packet->Timeout;
1180 CommandPacket->Cdb = Packet->Cdb;
1181 CommandPacket->CdbLength = Packet->CdbLength;
1182 CommandPacket->DataDirection = Packet->DataDirection;
1183 CommandPacket->HostAdapterStatus = Packet->HostAdapterStatus;
1184 CommandPacket->TargetStatus = Packet->TargetStatus;
1185 CommandPacket->SenseData = Packet->SenseData;
1186 CommandPacket->SenseDataLength = Packet->SenseDataLength;
1187
1188 if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_READ) {
1189 CommandPacket->DataBuffer = Packet->InDataBuffer;
1190 CommandPacket->TransferLength = Packet->InTransferLength;
1191 } else if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_WRITE) {
1192 CommandPacket->DataBuffer = Packet->OutDataBuffer;
1193 CommandPacket->TransferLength = Packet->OutTransferLength;
1194 }
1195 return EFI_SUCCESS;
1196 }
1197
1198
1199 /**
1200 Convert EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET packet to EFI_SCSI_IO_SCSI_REQUEST_PACKET packet.
1201
1202 @param ScsiPacket The pointer of EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
1203 @param Packet The pointer of EFI_SCSI_IO_SCSI_REQUEST_PACKET
1204
1205 **/
1206 EFI_STATUS
1207 EFIAPI
1208 PassThruToScsiioPacket (
1209 IN EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ScsiPacket,
1210 OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet
1211 )
1212 {
1213 Packet->Timeout = ScsiPacket->Timeout;
1214 Packet->Cdb = ScsiPacket->Cdb;
1215 Packet->CdbLength = ScsiPacket->CdbLength;
1216 Packet->DataDirection = ScsiPacket->DataDirection;
1217 Packet->HostAdapterStatus = ScsiPacket->HostAdapterStatus;
1218 Packet->TargetStatus = ScsiPacket->TargetStatus;
1219 Packet->SenseData = ScsiPacket->SenseData;
1220 Packet->SenseDataLength = ScsiPacket->SenseDataLength;
1221
1222 if (ScsiPacket->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_READ) {
1223 Packet->InDataBuffer = ScsiPacket->DataBuffer;
1224 Packet->InTransferLength = ScsiPacket->TransferLength;
1225 } else if (Packet->DataDirection == EFI_SCSI_IO_DATA_DIRECTION_WRITE) {
1226 Packet->OutDataBuffer = ScsiPacket->DataBuffer;
1227 Packet->OutTransferLength = ScsiPacket->TransferLength;
1228 }
1229
1230 return EFI_SUCCESS;
1231 }
1232
1233 /**
1234 Notify Function in which convert EFI1.0 PassThru Packet back to UEF2.0
1235 SCSI IO Packet.
1236
1237 @param Event The instance of EFI_EVENT.
1238 @param Context The parameter passed in.
1239
1240 **/
1241 VOID
1242 EFIAPI
1243 NotifyFunction (
1244 IN EFI_EVENT Event,
1245 IN VOID *Context
1246 )
1247 {
1248 EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet;
1249 EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *ScsiPacket;
1250 EFI_EVENT CallerEvent;
1251 SCSI_EVENT_DATA *PassData;
1252
1253 PassData = (SCSI_EVENT_DATA*)Context;
1254 Packet = (EFI_SCSI_IO_SCSI_REQUEST_PACKET *)PassData->Data1;
1255 ScsiPacket = (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET*)mWorkingBuffer;
1256
1257 //
1258 // Convert EFI1.0 PassThru packet to UEFI2.0 SCSI IO Packet.
1259 //
1260 PassThruToScsiioPacket(ScsiPacket, Packet);
1261
1262 //
1263 // After converting EFI1.0 PassThru Packet back to UEFI2.0 SCSI IO Packet,
1264 // free mWorkingBuffer.
1265 //
1266 gBS->FreePool(mWorkingBuffer);
1267
1268 //
1269 // Signal Event to tell caller to pick up UEFI2.0 SCSI IO Packet.
1270 //
1271 CallerEvent = PassData->Data2;
1272 gBS->CloseEvent(Event);
1273 gBS->SignalEvent(CallerEvent);
1274 }
1275