]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/IScsiDxe/IScsiMisc.c
1) Add BufToHexString, HexStringToBuf and IsHexDigit to BaseLib.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / IScsiDxe / IScsiMisc.c
1 /** @file
2 Miscellaneous routines for IScsi driver.
3
4 Copyright (c) 2004 - 2008, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 Module Name:
14
15 IScsiMisc.c
16
17 Abstract:
18
19 Miscellaneous routines for IScsi driver.
20
21 **/
22
23 #include "IScsiImpl.h"
24
25 STATIC CONST CHAR8 IScsiHexString[] = "0123456789ABCDEFabcdef";
26
27 /**
28 Removes (trims) specified leading and trailing characters from a string.
29
30 @param str[in][out] Pointer to the null-terminated string to be trimmed. On return,
31 str will hold the trimmed string.
32
33 @param CharC[in] Character will be trimmed from str.
34
35 @retval NONE.
36
37 **/
38 static
39 VOID
40 StrTrim (
41 IN OUT CHAR16 *str,
42 IN CHAR16 CharC
43 )
44 {
45 CHAR16 *p1;
46 CHAR16 *p2;
47
48 if (*str == 0) {
49 return;
50 }
51
52 //
53 // Trim off the leading and trailing characters c
54 //
55 for (p1 = str; *p1 && *p1 == CharC; p1++) {
56 ;
57 }
58
59 p2 = str;
60 if (p2 == p1) {
61 while (*p1) {
62 p2++;
63 p1++;
64 }
65 } else {
66 while (*p1) {
67 *p2 = *p1;
68 p1++;
69 p2++;
70 }
71 *p2 = 0;
72 }
73
74
75 for (p1 = str + StrLen(str) - 1; p1 >= str && *p1 == CharC; p1--) {
76 ;
77 }
78 if (p1 != str + StrLen(str) - 1) {
79 *(p1 + 1) = 0;
80 }
81 }
82
83 /**
84 Calculate the prefix length of the IPv4 subnet mask.
85
86 @param SubnetMask[in] The IPv4 subnet mask.
87
88 @retval The prefix length of the subnet mask.
89
90 **/
91 UINT8
92 IScsiGetSubnetMaskPrefixLength (
93 IN EFI_IPv4_ADDRESS *SubnetMask
94 )
95 {
96 UINT8 Len;
97 UINT32 ReverseMask;
98
99 //
100 // The SubnetMask is in network byte order.
101 //
102 ReverseMask = (SubnetMask->Addr[0] << 24) | (SubnetMask->Addr[1] << 16) | (SubnetMask->Addr[2] << 8) | (SubnetMask->Addr[3]);
103
104 //
105 // Reverse it.
106 //
107 ReverseMask = ~ReverseMask;
108
109 if (ReverseMask & (ReverseMask + 1)) {
110 return 0;
111 }
112
113 Len = 0;
114
115 while (ReverseMask != 0) {
116 ReverseMask = ReverseMask >> 1;
117 Len++;
118 }
119
120 return (UINT8) (32 - Len);
121 }
122
123 /**
124 Convert the hexadecimal encoded LUN string into the 64-bit LUN.
125
126 @param Str[in] The hexadecimal encoded LUN string.
127
128 @param Lun[out] Storage to return the 64-bit LUN.
129
130 @retval EFI_SUCCESS The 64-bit LUN is stored in Lun.
131
132 @retval EFI_INVALID_PARAMETER The string is malformatted.
133
134 **/
135 EFI_STATUS
136 IScsiAsciiStrToLun (
137 IN CHAR8 *Str,
138 OUT UINT8 *Lun
139 )
140 {
141 UINT32 Index;
142 CHAR8 *LunUnitStr[4];
143 CHAR8 Digit;
144 UINTN Temp;
145
146 ZeroMem (Lun, 8);
147 ZeroMem (LunUnitStr, sizeof (LunUnitStr));
148
149 Index = 0;
150 LunUnitStr[0] = Str;
151
152 if (!IsHexDigit ((UINT8 *) &Digit, *Str)) {
153 return EFI_INVALID_PARAMETER;
154 }
155
156 while (*Str != '\0') {
157 //
158 // Legal representations of LUN:
159 // 4752-3A4F-6b7e-2F99,
160 // 6734-9-156f-127,
161 // 4186-9
162 //
163 if (*Str == '-') {
164 *Str = '\0';
165 Index++;
166
167 if (*(Str + 1) != '\0') {
168 if (!IsHexDigit ((UINT8 *) &Digit, *(Str + 1))) {
169 return EFI_INVALID_PARAMETER;
170 }
171
172 LunUnitStr[Index] = Str + 1;
173 }
174 } else if (!IsHexDigit ((UINT8 *) &Digit, *Str)) {
175 return EFI_INVALID_PARAMETER;
176 }
177
178 Str++;
179 }
180
181 for (Index = 0; (Index < 4) && (LunUnitStr[Index] != NULL); Index++) {
182 if (AsciiStrLen (LunUnitStr[Index]) > 4) {
183 return EFI_INVALID_PARAMETER;
184 }
185
186 Temp = AsciiStrHexToUintn (LunUnitStr[Index]);
187 *((UINT16 *) &Lun[Index * 2]) = HTONS (Temp);
188 }
189
190 return EFI_SUCCESS;
191 }
192
193 /**
194 Convert the 64-bit LUN into the hexadecimal encoded LUN string.
195
196 @param Lun[in] The 64-bit LUN.
197
198 @param Str[out] The storage to return the hexadecimal encoded LUN string.
199
200 @retval None.
201
202 **/
203 VOID
204 IScsiLunToUnicodeStr (
205 IN UINT8 *Lun,
206 OUT CHAR16 *Str
207 )
208 {
209 UINTN Index;
210 CHAR16 *TempStr;
211
212 TempStr = Str;
213
214 for (Index = 0; Index < 4; Index++) {
215
216 if ((Lun[2 * Index] | Lun[2 * Index + 1]) == 0) {
217 StrCpy (TempStr, L"0-");
218 } else {
219 TempStr[0] = (CHAR16) IScsiHexString[Lun[2 * Index] >> 4];
220 TempStr[1] = (CHAR16) IScsiHexString[Lun[2 * Index] & 0xf];
221 TempStr[2] = (CHAR16) IScsiHexString[Lun[2 * Index + 1] >> 4];
222 TempStr[3] = (CHAR16) IScsiHexString[Lun[2 * Index + 1] & 0xf];
223 TempStr[4] = L'-';
224 TempStr[5] = 0;
225
226 StrTrim (TempStr, L'0');
227 }
228
229 TempStr += StrLen (TempStr);
230 }
231
232 Str[StrLen (Str) - 1] = 0;
233
234 for (Index = StrLen (Str) - 1; Index > 1; Index = Index - 2) {
235 if ((Str[Index] == L'0') && (Str[Index - 1] == L'-')) {
236 Str[Index - 1] = 0;
237 } else {
238 break;
239 }
240 }
241 }
242
243 /**
244 Convert the ASCII string into a UNICODE string.
245
246 @param Source[out] The ASCII string.
247
248 @param Destination[out] The storage to return the UNICODE string.
249
250 @retval CHAR16 * Pointer to the UNICODE string.
251
252 **/
253 CHAR16 *
254 IScsiAsciiStrToUnicodeStr (
255 IN CHAR8 *Source,
256 OUT CHAR16 *Destination
257 )
258 {
259 ASSERT (Destination != NULL);
260 ASSERT (Source != NULL);
261
262 while (*Source != '\0') {
263 *(Destination++) = (CHAR16) *(Source++);
264 }
265
266 *Destination = '\0';
267
268 return Destination;
269 }
270
271 /**
272 Convert the UNICODE string into an ASCII string.
273
274 @param Source[in] The UNICODE string.
275
276 @param Destination[out] The storage to return the ASCII string.
277
278 @retval CHAR8 * Pointer to the ASCII string.
279
280 **/
281 CHAR8 *
282 IScsiUnicodeStrToAsciiStr (
283 IN CHAR16 *Source,
284 OUT CHAR8 *Destination
285 )
286 {
287 ASSERT (Destination != NULL);
288 ASSERT (Source != NULL);
289
290 while (*Source != '\0') {
291 //
292 // If any Unicode characters in Source contain
293 // non-zero value in the upper 8 bits, then ASSERT().
294 //
295 ASSERT (*Source < 0x100);
296 *(Destination++) = (CHAR8) *(Source++);
297 }
298
299 *Destination = '\0';
300
301 return Destination;
302 }
303
304 /**
305 Convert the decimal dotted IPv4 address into the binary IPv4 address.
306
307 @param Str[in] The UNICODE string.
308
309 @param Ip[out] The storage to return the ASCII string.
310
311 @retval EFI_SUCCESS The binary IP address is returned in Ip.
312
313 @retval EFI_INVALID_PARAMETER The IP string is malformatted.
314
315 **/
316 EFI_STATUS
317 IScsiAsciiStrToIp (
318 IN CHAR8 *Str,
319 OUT EFI_IPv4_ADDRESS *Ip
320 )
321 {
322 UINTN Index;
323 UINTN Number;
324
325 Index = 0;
326
327 while (*Str) {
328
329 if (Index > 3) {
330 return EFI_INVALID_PARAMETER;
331 }
332
333 Number = 0;
334 while (NET_IS_DIGIT (*Str)) {
335 Number = Number * 10 + (*Str - '0');
336 Str++;
337 }
338
339 if (Number > 0xFF) {
340 return EFI_INVALID_PARAMETER;
341 }
342
343 Ip->Addr[Index] = (UINT8) Number;
344
345 if ((*Str != '\0') && (*Str != '.')) {
346 //
347 // The current character should be either the NULL terminator or
348 // the dot delimiter.
349 //
350 return EFI_INVALID_PARAMETER;
351 }
352
353 if (*Str == '.') {
354 //
355 // Skip the delimiter.
356 //
357 Str++;
358 }
359
360 Index++;
361 }
362
363 if (Index != 4) {
364 return EFI_INVALID_PARAMETER;
365 }
366
367 return EFI_SUCCESS;
368 }
369
370 /**
371 Convert the mac address into a hexadecimal encoded "-" seperated string.
372
373 @param Mac[in] The mac address.
374
375 @param Len[in] Length in bytes of the mac address.
376
377 @param Str[out] The storage to return the mac string.
378
379 @retval None.
380
381 **/
382 VOID
383 IScsiMacAddrToStr (
384 IN EFI_MAC_ADDRESS *Mac,
385 IN UINT32 Len,
386 OUT CHAR16 *Str
387 )
388 {
389 UINT32 Index;
390
391 for (Index = 0; Index < Len; Index++) {
392 Str[3 * Index] = NibbleToHexChar ((UINT8) (Mac->Addr[Index] >> 4));
393 Str[3 * Index + 1] = NibbleToHexChar (Mac->Addr[Index]);
394 Str[3 * Index + 2] = L'-';
395 }
396
397 Str[3 * Index - 1] = L'\0';
398 }
399
400 /**
401 Convert the binary encoded buffer into a hexadecimal encoded string.
402
403 @param BinBuffer[in] The buffer containing the binary data.
404
405 @param BinLength[in] Length of the binary buffer.
406
407 @param HexStr[in][out] Pointer to the string.
408
409 @param HexLength[in][out] The length of the string.
410
411 @retval EFI_SUCCESS The binary data is converted to the hexadecimal string
412 and the length of the string is updated.
413
414 @retval EFI_BUFFER_TOO_SMALL The string is too small.
415
416 **/
417 EFI_STATUS
418 IScsiBinToHex (
419 IN UINT8 *BinBuffer,
420 IN UINT32 BinLength,
421 IN OUT CHAR8 *HexStr,
422 IN OUT UINT32 *HexLength
423 )
424 {
425 UINTN Index;
426
427 if ((HexStr == NULL) || (BinBuffer == NULL) || (BinLength == 0)) {
428 return EFI_INVALID_PARAMETER;
429 }
430
431 if (((*HexLength) - 3) < BinLength * 2) {
432 *HexLength = BinLength * 2 + 3;
433 return EFI_BUFFER_TOO_SMALL;
434 }
435
436 *HexLength = BinLength * 2 + 3;
437 //
438 // Prefix for Hex String
439 //
440 HexStr[0] = '0';
441 HexStr[1] = 'x';
442
443 for (Index = 0; Index < BinLength; Index++) {
444 HexStr[Index * 2 + 2] = IScsiHexString[BinBuffer[Index] >> 4];
445 HexStr[Index * 2 + 3] = IScsiHexString[BinBuffer[Index] & 0xf];
446 }
447
448 HexStr[Index * 2 + 2] = '\0';
449
450 return EFI_SUCCESS;
451 }
452
453 /**
454 Convert the hexadecimal string into a binary encoded buffer.
455
456 @param BinBuffer[in][out] The binary buffer.
457
458 @param BinLength[in][out] Length of the binary buffer.
459
460 @param HexStr[in] The hexadecimal string.
461
462 @retval EFI_SUCCESS The hexadecimal string is converted into a binary
463 encoded buffer.
464
465 @retval EFI_BUFFER_TOO_SMALL The binary buffer is too small to hold the converted data.s
466
467 **/
468 EFI_STATUS
469 IScsiHexToBin (
470 IN OUT UINT8 *BinBuffer,
471 IN OUT UINT32 *BinLength,
472 IN CHAR8 *HexStr
473 )
474 {
475 UINTN Index;
476 UINT32 HexCount;
477 CHAR8 *HexBuf;
478 UINT8 Digit;
479 UINT8 Byte;
480
481 Digit = 0;
482
483 //
484 // Find out how many hex characters the string has.
485 //
486 HexBuf = HexStr;
487 if ((HexBuf[0] == '0') && ((HexBuf[1] == 'x') || (HexBuf[1] == 'X'))) {
488 HexBuf += 2;
489 }
490
491 for (Index = 0, HexCount = 0; IsHexDigit (&Digit, HexBuf[Index]); Index++, HexCount++)
492 ;
493
494 if (HexCount == 0) {
495 *BinLength = 0;
496 return EFI_SUCCESS;
497 }
498 //
499 // Test if buffer is passed enough.
500 //
501 if (((HexCount + 1) / 2) > *BinLength) {
502 *BinLength = (HexCount + 1) / 2;
503 return EFI_BUFFER_TOO_SMALL;
504 }
505
506 *BinLength = (HexCount + 1) / 2;
507
508 for (Index = 0; Index < HexCount; Index++) {
509
510 IsHexDigit (&Digit, HexBuf[HexCount - 1 - Index]);
511
512 if ((Index & 1) == 0) {
513 Byte = Digit;
514 } else {
515 Byte = BinBuffer[*BinLength - 1 - Index / 2];
516 Byte &= 0x0F;
517 Byte = (UINT8) (Byte | (Digit << 4));
518 }
519
520 BinBuffer[*BinLength - 1 - Index / 2] = Byte;
521 }
522
523 return EFI_SUCCESS;
524 }
525
526 /**
527 Generate random numbers.
528
529 @param Rand[in][out] The buffer to contain random numbers.
530
531 @param RandLength[in] The length of the Rand buffer.
532
533 @retval None.
534
535 **/
536 VOID
537 IScsiGenRandom (
538 IN OUT UINT8 *Rand,
539 IN UINTN RandLength
540 )
541 {
542 UINT32 Random;
543
544 while (RandLength > 0) {
545 Random = NET_RANDOM (NetRandomInitSeed ());
546 *Rand++ = (UINT8) (Random);
547 RandLength--;
548 }
549 }
550
551 /**
552 Create the iSCSI driver data..
553
554 @param Image[in] The handle of the driver image.
555
556 @param Controller[in] The handle of the controller.
557
558 @retval The iSCSI driver data created.
559
560 **/
561 ISCSI_DRIVER_DATA *
562 IScsiCreateDriverData (
563 IN EFI_HANDLE Image,
564 IN EFI_HANDLE Controller
565 )
566 {
567 ISCSI_DRIVER_DATA *Private;
568 EFI_STATUS Status;
569
570 Private = AllocateZeroPool (sizeof (ISCSI_DRIVER_DATA));
571 if (Private == NULL) {
572 return NULL;
573 }
574
575 Private->Signature = ISCSI_DRIVER_DATA_SIGNATURE;
576 Private->Image = Image;
577 Private->Controller = Controller;
578
579 //
580 // Create an event to be signal when the BS to RT transition is triggerd so
581 // as to abort the iSCSI session.
582 //
583 Status = gBS->CreateEvent (
584 EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,
585 TPL_CALLBACK,
586 IScsiOnExitBootService,
587 Private,
588 &Private->ExitBootServiceEvent
589 );
590 if (EFI_ERROR (Status)) {
591 gBS->FreePool (Private);
592 return NULL;
593 }
594
595 CopyMem(&Private->IScsiExtScsiPassThru, &gIScsiExtScsiPassThruProtocolTemplate, sizeof(EFI_EXT_SCSI_PASS_THRU_PROTOCOL));
596
597 //
598 // 0 is designated to the TargetId, so use another value for the AdapterId.
599 //
600 Private->ExtScsiPassThruMode.AdapterId = 2;
601 Private->ExtScsiPassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
602 Private->ExtScsiPassThruMode.IoAlign = 4;
603 Private->IScsiExtScsiPassThru.Mode = &Private->ExtScsiPassThruMode;
604
605 //
606 // Install the Ext SCSI PASS THRU protocol.
607 //
608 Status = gBS->InstallProtocolInterface (
609 &Private->ExtScsiPassThruHandle,
610 &gEfiExtScsiPassThruProtocolGuid,
611 EFI_NATIVE_INTERFACE,
612 &Private->IScsiExtScsiPassThru
613 );
614 if (EFI_ERROR (Status)) {
615 gBS->CloseEvent (Private->ExitBootServiceEvent);
616 gBS->FreePool (Private);
617
618 return NULL;
619 }
620
621 IScsiSessionInit (&Private->Session, FALSE);
622
623 return Private;
624 }
625
626 /**
627 Clean the iSCSI driver data.
628
629 @param Private[in] The iSCSI driver data.
630
631 @retval None.
632
633 **/
634 VOID
635 IScsiCleanDriverData (
636 IN ISCSI_DRIVER_DATA *Private
637 )
638 {
639 if (Private->DevicePath != NULL) {
640 gBS->UninstallProtocolInterface (
641 Private->ExtScsiPassThruHandle,
642 &gEfiDevicePathProtocolGuid,
643 Private->DevicePath
644 );
645
646 gBS->FreePool (Private->DevicePath);
647 }
648
649 if (Private->ExtScsiPassThruHandle != NULL) {
650 gBS->UninstallProtocolInterface (
651 Private->ExtScsiPassThruHandle,
652 &gEfiExtScsiPassThruProtocolGuid,
653 &Private->IScsiExtScsiPassThru
654 );
655 }
656
657 gBS->CloseEvent (Private->ExitBootServiceEvent);
658
659 gBS->FreePool (Private);
660 }
661
662 /**
663
664 Get the various configuration data of this iSCSI instance.
665
666 @param Private[in] The iSCSI driver data.
667
668 @retval EFI_SUCCESS The configuration of this instance is got.
669
670 @retval EFI_NOT_FOUND This iSCSI instance is not configured yet.
671
672 **/
673 EFI_STATUS
674 IScsiGetConfigData (
675 IN ISCSI_DRIVER_DATA *Private
676 )
677 {
678 EFI_STATUS Status;
679 ISCSI_SESSION *Session;
680 UINTN BufferSize;
681 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
682 EFI_SIMPLE_NETWORK_MODE *Mode;
683 CHAR16 MacString[65];
684
685 //
686 // get the iSCSI Initiator Name
687 //
688 Session = &Private->Session;
689 Session->InitiatorNameLength = ISCSI_NAME_MAX_SIZE;
690 Status = gIScsiInitiatorName.Get (
691 &gIScsiInitiatorName,
692 &Session->InitiatorNameLength,
693 Session->InitiatorName
694 );
695 if (EFI_ERROR (Status)) {
696 return Status;
697 }
698
699 Status = gBS->HandleProtocol (
700 Private->Controller,
701 &gEfiSimpleNetworkProtocolGuid,
702 (VOID **)&Snp
703 );
704 if (EFI_ERROR (Status)) {
705 return Status;
706 }
707
708 Mode = Snp->Mode;
709
710 //
711 // Get the mac string, it's the name of various variable
712 //
713 IScsiMacAddrToStr (&Mode->PermanentAddress, Mode->HwAddressSize, MacString);
714
715 //
716 // Get the normal configuration.
717 //
718 BufferSize = sizeof (Session->ConfigData.NvData);
719 Status = gRT->GetVariable (
720 MacString,
721 &gEfiIScsiInitiatorNameProtocolGuid,
722 NULL,
723 &BufferSize,
724 &Session->ConfigData.NvData
725 );
726 if (EFI_ERROR (Status)) {
727 return Status;
728 }
729
730 if (!Session->ConfigData.NvData.Enabled) {
731 return EFI_ABORTED;
732 }
733 //
734 // Get the CHAP Auth information.
735 //
736 BufferSize = sizeof (Session->AuthData.AuthConfig);
737 Status = gRT->GetVariable (
738 MacString,
739 &mIScsiCHAPAuthInfoGuid,
740 NULL,
741 &BufferSize,
742 &Session->AuthData.AuthConfig
743 );
744
745 if (!EFI_ERROR (Status) && Session->ConfigData.NvData.InitiatorInfoFromDhcp) {
746 //
747 // Start dhcp.
748 //
749 Status = IScsiDoDhcp (Private->Image, Private->Controller, &Session->ConfigData);
750 }
751
752 return Status;
753 }
754
755 /**
756 Get the device path of the iSCSI tcp connection and update it.
757
758 @param Private[in] The iSCSI driver data.
759
760 @retval The updated device path.
761
762 **/
763 EFI_DEVICE_PATH_PROTOCOL *
764 IScsiGetTcpConnDevicePath (
765 IN ISCSI_DRIVER_DATA *Private
766 )
767 {
768 ISCSI_SESSION *Session;
769 ISCSI_CONNECTION *Conn;
770 TCP4_IO *Tcp4Io;
771 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
772 EFI_STATUS Status;
773 EFI_DEV_PATH *DPathNode;
774
775 Session = &Private->Session;
776 if (Session->State != SESSION_STATE_LOGGED_IN) {
777 return NULL;
778 }
779
780 Conn = NET_LIST_USER_STRUCT_S (
781 Session->Conns.ForwardLink,
782 ISCSI_CONNECTION,
783 Link,
784 ISCSI_CONNECTION_SIGNATURE
785 );
786 Tcp4Io = &Conn->Tcp4Io;
787
788 Status = gBS->HandleProtocol (
789 Tcp4Io->Handle,
790 &gEfiDevicePathProtocolGuid,
791 (VOID **)&DevicePath
792 );
793 if (EFI_ERROR (Status)) {
794 return NULL;
795 }
796 //
797 // Duplicate it.
798 //
799 DevicePath = DuplicateDevicePath (DevicePath);
800
801 DPathNode = (EFI_DEV_PATH *) DevicePath;
802
803 while (!IsDevicePathEnd (&DPathNode->DevPath)) {
804 if ((DevicePathType (&DPathNode->DevPath) == MESSAGING_DEVICE_PATH) &&
805 (DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP)
806 ) {
807
808 DPathNode->Ipv4.LocalPort = 0;
809 DPathNode->Ipv4.StaticIpAddress = (BOOLEAN) (!Session->ConfigData.NvData.InitiatorInfoFromDhcp);
810 break;
811 }
812
813 DPathNode = (EFI_DEV_PATH *) NextDevicePathNode (&DPathNode->DevPath);
814 }
815
816 return DevicePath;
817 }
818
819 /**
820 Abort the session when the transition from BS to RT is initiated.
821
822 @param Event[in] The event signaled.
823
824 @param Context[in] The iSCSI driver data.
825
826 @retval None.
827
828 **/
829 VOID
830 EFIAPI
831 IScsiOnExitBootService (
832 IN EFI_EVENT Event,
833 IN VOID *Context
834 )
835 {
836 ISCSI_DRIVER_DATA *Private;
837
838 Private = (ISCSI_DRIVER_DATA *) Context;
839 gBS->CloseEvent (Private->ExitBootServiceEvent);
840
841 IScsiSessionAbort (&Private->Session);
842 }