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