]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/IScsiDxe/IScsiMisc.c
add security check.
[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[out] Str The storage to return the mac string.
359 **/
360 VOID
361 IScsiMacAddrToStr (
362 IN EFI_MAC_ADDRESS *Mac,
363 IN UINT32 Len,
364 OUT CHAR16 *Str
365 )
366 {
367 UINT32 Index;
368
369 for (Index = 0; Index < Len; Index++) {
370 Str[3 * Index] = (CHAR16) IScsiHexString[(Mac->Addr[Index] >> 4) & 0x0F];
371 Str[3 * Index + 1] = (CHAR16) IScsiHexString[Mac->Addr[Index] & 0x0F];
372 Str[3 * Index + 2] = L'-';
373 }
374
375 Str[3 * Index - 1] = L'\0';
376 }
377
378 /**
379 Convert the binary encoded buffer into a hexadecimal encoded string.
380
381 @param[in] BinBuffer The buffer containing the binary data.
382 @param[in] BinLength Length of the binary buffer.
383 @param[in, out] HexStr Pointer to the string.
384 @param[in, out] HexLength The length of the string.
385
386 @retval EFI_SUCCESS The binary data is converted to the hexadecimal string
387 and the length of the string is updated.
388 @retval EFI_BUFFER_TOO_SMALL The string is too small.
389 @retval EFI_INVALID_PARAMETER The IP string is malformatted.
390 **/
391 EFI_STATUS
392 IScsiBinToHex (
393 IN UINT8 *BinBuffer,
394 IN UINT32 BinLength,
395 IN OUT CHAR8 *HexStr,
396 IN OUT UINT32 *HexLength
397 )
398 {
399 UINTN Index;
400
401 if ((HexStr == NULL) || (BinBuffer == NULL) || (BinLength == 0)) {
402 return EFI_INVALID_PARAMETER;
403 }
404
405 if (((*HexLength) - 3) < BinLength * 2) {
406 *HexLength = BinLength * 2 + 3;
407 return EFI_BUFFER_TOO_SMALL;
408 }
409
410 *HexLength = BinLength * 2 + 3;
411 //
412 // Prefix for Hex String
413 //
414 HexStr[0] = '0';
415 HexStr[1] = 'x';
416
417 for (Index = 0; Index < BinLength; Index++) {
418 HexStr[Index * 2 + 2] = IScsiHexString[BinBuffer[Index] >> 4];
419 HexStr[Index * 2 + 3] = IScsiHexString[BinBuffer[Index] & 0x0F];
420 }
421
422 HexStr[Index * 2 + 2] = '\0';
423
424 return EFI_SUCCESS;
425 }
426
427 /**
428 Convert the hexadecimal string into a binary encoded buffer.
429
430 @param[in, out] BinBuffer The binary buffer.
431 @param[in, out] BinLength Length of the binary buffer.
432 @param[in] HexStr The hexadecimal string.
433
434 @retval EFI_SUCCESS The hexadecimal string is converted into a binary
435 encoded buffer.
436 @retval EFI_BUFFER_TOO_SMALL The binary buffer is too small to hold the converted data.
437 **/
438 EFI_STATUS
439 IScsiHexToBin (
440 IN OUT UINT8 *BinBuffer,
441 IN OUT UINT32 *BinLength,
442 IN CHAR8 *HexStr
443 )
444 {
445 UINTN Index;
446 UINTN Length;
447 UINT8 Digit;
448 CHAR8 TemStr[2];
449
450 ZeroMem (TemStr, sizeof (TemStr));
451
452 //
453 // Find out how many hex characters the string has.
454 //
455 if ((HexStr[0] == '0') && ((HexStr[1] == 'x') || (HexStr[1] == 'X'))) {
456 HexStr += 2;
457 }
458
459 Length = AsciiStrLen (HexStr);
460
461 for (Index = 0; Index < Length; Index ++) {
462 TemStr[0] = HexStr[Index];
463 Digit = (UINT8) AsciiStrHexToUint64 (TemStr);
464 if (Digit == 0 && TemStr[0] != '0') {
465 //
466 // Invalid Lun Char
467 //
468 break;
469 }
470 if ((Index & 1) == 0) {
471 BinBuffer [Index/2] = Digit;
472 } else {
473 BinBuffer [Index/2] = (UINT8) ((BinBuffer [Index/2] << 4) + Digit);
474 }
475 }
476
477 *BinLength = (UINT32) ((Index + 1)/2);
478
479 return EFI_SUCCESS;
480 }
481
482 /**
483 Generate random numbers.
484
485 @param[in, out] Rand The buffer to contain random numbers.
486 @param[in] RandLength The length of the Rand buffer.
487 **/
488 VOID
489 IScsiGenRandom (
490 IN OUT UINT8 *Rand,
491 IN UINTN RandLength
492 )
493 {
494 UINT32 Random;
495
496 while (RandLength > 0) {
497 Random = NET_RANDOM (NetRandomInitSeed ());
498 *Rand++ = (UINT8) (Random);
499 RandLength--;
500 }
501 }
502
503 /**
504 Create the iSCSI driver data..
505
506 @param[in] Image The handle of the driver image.
507 @param[in] Controller The handle of the controller.
508
509 @return The iSCSI driver data created.
510 @retval NULL Other errors as indicated.
511 **/
512 ISCSI_DRIVER_DATA *
513 IScsiCreateDriverData (
514 IN EFI_HANDLE Image,
515 IN EFI_HANDLE Controller
516 )
517 {
518 ISCSI_DRIVER_DATA *Private;
519 EFI_STATUS Status;
520
521 Private = AllocateZeroPool (sizeof (ISCSI_DRIVER_DATA));
522 if (Private == NULL) {
523 return NULL;
524 }
525
526 Private->Signature = ISCSI_DRIVER_DATA_SIGNATURE;
527 Private->Image = Image;
528 Private->Controller = Controller;
529
530 //
531 // Create an event to be signal when the BS to RT transition is triggerd so
532 // as to abort the iSCSI session.
533 //
534 Status = gBS->CreateEventEx (
535 EVT_NOTIFY_SIGNAL,
536 TPL_CALLBACK,
537 IScsiOnExitBootService,
538 Private,
539 &gEfiEventExitBootServicesGuid,
540 &Private->ExitBootServiceEvent
541 );
542 if (EFI_ERROR (Status)) {
543 gBS->FreePool (Private);
544 return NULL;
545 }
546
547 CopyMem(&Private->IScsiExtScsiPassThru, &gIScsiExtScsiPassThruProtocolTemplate, sizeof(EFI_EXT_SCSI_PASS_THRU_PROTOCOL));
548
549 //
550 // 0 is designated to the TargetId, so use another value for the AdapterId.
551 //
552 Private->ExtScsiPassThruMode.AdapterId = 2;
553 Private->ExtScsiPassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
554 Private->ExtScsiPassThruMode.IoAlign = 4;
555 Private->IScsiExtScsiPassThru.Mode = &Private->ExtScsiPassThruMode;
556
557 //
558 // Install the Ext SCSI PASS THRU protocol.
559 //
560 Status = gBS->InstallProtocolInterface (
561 &Private->ExtScsiPassThruHandle,
562 &gEfiExtScsiPassThruProtocolGuid,
563 EFI_NATIVE_INTERFACE,
564 &Private->IScsiExtScsiPassThru
565 );
566 if (EFI_ERROR (Status)) {
567 gBS->CloseEvent (Private->ExitBootServiceEvent);
568 gBS->FreePool (Private);
569
570 return NULL;
571 }
572
573 IScsiSessionInit (&Private->Session, FALSE);
574
575 return Private;
576 }
577
578 /**
579 Clean the iSCSI driver data.
580
581 @param[in] Private The iSCSI driver data.
582 **/
583 VOID
584 IScsiCleanDriverData (
585 IN ISCSI_DRIVER_DATA *Private
586 )
587 {
588 if (Private->DevicePath != NULL) {
589 gBS->UninstallProtocolInterface (
590 Private->ExtScsiPassThruHandle,
591 &gEfiDevicePathProtocolGuid,
592 Private->DevicePath
593 );
594
595 gBS->FreePool (Private->DevicePath);
596 }
597
598 if (Private->ExtScsiPassThruHandle != NULL) {
599 gBS->UninstallProtocolInterface (
600 Private->ExtScsiPassThruHandle,
601 &gEfiExtScsiPassThruProtocolGuid,
602 &Private->IScsiExtScsiPassThru
603 );
604 }
605
606 gBS->CloseEvent (Private->ExitBootServiceEvent);
607
608 gBS->FreePool (Private);
609 }
610
611 /**
612 Get the various configuration data of this iSCSI instance.
613
614 @param[in] Private The iSCSI driver data.
615
616 @retval EFI_SUCCESS The configuration of this instance is got.
617 @retval EFI_ABORTED The operation was aborted.
618 @retval Others Other errors as indicated.
619 **/
620 EFI_STATUS
621 IScsiGetConfigData (
622 IN ISCSI_DRIVER_DATA *Private
623 )
624 {
625 EFI_STATUS Status;
626 ISCSI_SESSION *Session;
627 UINTN BufferSize;
628 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
629 EFI_SIMPLE_NETWORK_MODE *Mode;
630 CHAR16 MacString[65];
631
632 //
633 // get the iSCSI Initiator Name
634 //
635 Session = &Private->Session;
636 Session->InitiatorNameLength = ISCSI_NAME_MAX_SIZE;
637 Status = gIScsiInitiatorName.Get (
638 &gIScsiInitiatorName,
639 &Session->InitiatorNameLength,
640 Session->InitiatorName
641 );
642 if (EFI_ERROR (Status)) {
643 return Status;
644 }
645
646 Status = gBS->HandleProtocol (
647 Private->Controller,
648 &gEfiSimpleNetworkProtocolGuid,
649 (VOID **)&Snp
650 );
651 if (EFI_ERROR (Status)) {
652 return Status;
653 }
654
655 Mode = Snp->Mode;
656
657 //
658 // Get the mac string, it's the name of various variable
659 //
660 IScsiMacAddrToStr (&Mode->PermanentAddress, Mode->HwAddressSize, MacString);
661
662 //
663 // Get the normal configuration.
664 //
665 BufferSize = sizeof (Session->ConfigData.NvData);
666 Status = gRT->GetVariable (
667 MacString,
668 &gEfiIScsiInitiatorNameProtocolGuid,
669 NULL,
670 &BufferSize,
671 &Session->ConfigData.NvData
672 );
673 if (EFI_ERROR (Status)) {
674 return Status;
675 }
676
677 if (!Session->ConfigData.NvData.Enabled) {
678 return EFI_ABORTED;
679 }
680 //
681 // Get the CHAP Auth information.
682 //
683 BufferSize = sizeof (Session->AuthData.AuthConfig);
684 Status = gRT->GetVariable (
685 MacString,
686 &mIScsiCHAPAuthInfoGuid,
687 NULL,
688 &BufferSize,
689 &Session->AuthData.AuthConfig
690 );
691
692 if (!EFI_ERROR (Status) && Session->ConfigData.NvData.InitiatorInfoFromDhcp) {
693 //
694 // Start dhcp.
695 //
696 Status = IScsiDoDhcp (Private->Image, Private->Controller, &Session->ConfigData);
697 }
698
699 return Status;
700 }
701
702 /**
703 Get the device path of the iSCSI tcp connection and update it.
704
705 @param[in] Private The iSCSI driver data.
706
707 @return The updated device path.
708 @retval NULL Other errors as indicated.
709 **/
710 EFI_DEVICE_PATH_PROTOCOL *
711 IScsiGetTcpConnDevicePath (
712 IN ISCSI_DRIVER_DATA *Private
713 )
714 {
715 ISCSI_SESSION *Session;
716 ISCSI_CONNECTION *Conn;
717 TCP4_IO *Tcp4Io;
718 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
719 EFI_STATUS Status;
720 EFI_DEV_PATH *DPathNode;
721
722 Session = &Private->Session;
723 if (Session->State != SESSION_STATE_LOGGED_IN) {
724 return NULL;
725 }
726
727 Conn = NET_LIST_USER_STRUCT_S (
728 Session->Conns.ForwardLink,
729 ISCSI_CONNECTION,
730 Link,
731 ISCSI_CONNECTION_SIGNATURE
732 );
733 Tcp4Io = &Conn->Tcp4Io;
734
735 Status = gBS->HandleProtocol (
736 Tcp4Io->Handle,
737 &gEfiDevicePathProtocolGuid,
738 (VOID **)&DevicePath
739 );
740 if (EFI_ERROR (Status)) {
741 return NULL;
742 }
743 //
744 // Duplicate it.
745 //
746 DevicePath = DuplicateDevicePath (DevicePath);
747 if (DevicePath == NULL) {
748 return NULL;
749 }
750
751 DPathNode = (EFI_DEV_PATH *) DevicePath;
752
753 while (!IsDevicePathEnd (&DPathNode->DevPath)) {
754 if ((DevicePathType (&DPathNode->DevPath) == MESSAGING_DEVICE_PATH) &&
755 (DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP)
756 ) {
757
758 DPathNode->Ipv4.LocalPort = 0;
759 DPathNode->Ipv4.StaticIpAddress = (BOOLEAN) (!Session->ConfigData.NvData.InitiatorInfoFromDhcp);
760 break;
761 }
762
763 DPathNode = (EFI_DEV_PATH *) NextDevicePathNode (&DPathNode->DevPath);
764 }
765
766 return DevicePath;
767 }
768
769 /**
770 Abort the session when the transition from BS to RT is initiated.
771
772 @param[in] Event The event signaled.
773 @param[in] Context The iSCSI driver data.
774 **/
775 VOID
776 EFIAPI
777 IScsiOnExitBootService (
778 IN EFI_EVENT Event,
779 IN VOID *Context
780 )
781 {
782 ISCSI_DRIVER_DATA *Private;
783
784 Private = (ISCSI_DRIVER_DATA *) Context;
785 gBS->CloseEvent (Private->ExitBootServiceEvent);
786
787 IScsiSessionAbort (&Private->Session);
788 }