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