]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/IScsiDxe/IScsiDhcp.c
NetworkPkg: Clean up source files
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiDhcp.c
CommitLineData
4c5a5e0c 1/** @file\r
2 iSCSI DHCP4 related configuration routines.\r
3\r
f75a7f56 4Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
4c5a5e0c 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
17\r
18/**\r
19 Extract the Root Path option and get the required target information.\r
20\r
21 @param[in] RootPath The RootPath.\r
22 @param[in] Length Length of the RootPath option payload.\r
23 @param[in, out] ConfigData The iSCSI attempt configuration data read\r
24 from a nonvolatile device.\r
25\r
26 @retval EFI_SUCCESS All required information is extracted from the RootPath option.\r
27 @retval EFI_NOT_FOUND The RootPath is not an iSCSI RootPath.\r
28 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
29 @retval EFI_INVALID_PARAMETER The RootPath is malformatted.\r
30\r
31**/\r
32EFI_STATUS\r
33IScsiDhcpExtractRootPath (\r
34 IN CHAR8 *RootPath,\r
35 IN UINT8 Length,\r
36 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA *ConfigData\r
37 )\r
38{\r
39 EFI_STATUS Status;\r
40 UINT8 IScsiRootPathIdLen;\r
41 CHAR8 *TmpStr;\r
42 ISCSI_ROOT_PATH_FIELD Fields[RP_FIELD_IDX_MAX];\r
43 ISCSI_ROOT_PATH_FIELD *Field;\r
44 UINT32 FieldIndex;\r
45 UINT8 Index;\r
46 ISCSI_SESSION_CONFIG_NVDATA *ConfigNvData;\r
47 EFI_IP_ADDRESS Ip;\r
48 UINT8 IpMode;\r
49\r
50 ConfigNvData = &ConfigData->SessionConfigData;\r
51\r
52 //\r
53 // "iscsi:"<servername>":"<protocol>":"<port>":"<LUN>":"<targetname>\r
54 //\r
55 IScsiRootPathIdLen = (UINT8) AsciiStrLen (ISCSI_ROOT_PATH_ID);\r
56\r
57 if ((Length <= IScsiRootPathIdLen) || (CompareMem (RootPath, ISCSI_ROOT_PATH_ID, IScsiRootPathIdLen) != 0)) {\r
58 return EFI_NOT_FOUND;\r
59 }\r
60 //\r
61 // Skip the iSCSI RootPath ID "iscsi:".\r
62 //\r
63 RootPath += IScsiRootPathIdLen;\r
64 Length = (UINT8) (Length - IScsiRootPathIdLen);\r
65\r
66 TmpStr = (CHAR8 *) AllocatePool (Length + 1);\r
67 if (TmpStr == NULL) {\r
68 return EFI_OUT_OF_RESOURCES;\r
69 }\r
70\r
71 CopyMem (TmpStr, RootPath, Length);\r
72 TmpStr[Length] = '\0';\r
73\r
74 Index = 0;\r
75 FieldIndex = RP_FIELD_IDX_SERVERNAME;\r
76 ZeroMem (&Fields[0], sizeof (Fields));\r
77\r
78 //\r
79 // Extract the fields in the Root Path option string.\r
80 //\r
81 for (FieldIndex = RP_FIELD_IDX_SERVERNAME; (FieldIndex < RP_FIELD_IDX_MAX) && (Index < Length); FieldIndex++) {\r
82 if (TmpStr[Index] != ISCSI_ROOT_PATH_FIELD_DELIMITER) {\r
83 Fields[FieldIndex].Str = &TmpStr[Index];\r
84 }\r
85\r
86 while ((TmpStr[Index] != ISCSI_ROOT_PATH_FIELD_DELIMITER) && (Index < Length)) {\r
87 Index++;\r
88 }\r
89\r
90 if (TmpStr[Index] == ISCSI_ROOT_PATH_FIELD_DELIMITER) {\r
91 if (FieldIndex != RP_FIELD_IDX_TARGETNAME) {\r
92 TmpStr[Index] = '\0';\r
93 Index++;\r
94 }\r
95\r
96 if (Fields[FieldIndex].Str != NULL) {\r
97 Fields[FieldIndex].Len = (UINT8) AsciiStrLen (Fields[FieldIndex].Str);\r
98 }\r
99 }\r
100 }\r
101\r
102 if (FieldIndex != RP_FIELD_IDX_MAX) {\r
103 Status = EFI_INVALID_PARAMETER;\r
104 goto ON_EXIT;\r
105 }\r
106\r
107 if ((Fields[RP_FIELD_IDX_SERVERNAME].Str == NULL) ||\r
108 (Fields[RP_FIELD_IDX_TARGETNAME].Str == NULL) ||\r
109 (Fields[RP_FIELD_IDX_PROTOCOL].Len > 1)\r
110 ) {\r
111\r
112 Status = EFI_INVALID_PARAMETER;\r
113 goto ON_EXIT;\r
114 }\r
115 //\r
116 // Get the IP address of the target.\r
117 //\r
118 Field = &Fields[RP_FIELD_IDX_SERVERNAME];\r
119\r
120 if (ConfigNvData->IpMode < IP_MODE_AUTOCONFIG) {\r
121 IpMode = ConfigNvData->IpMode;\r
122 } else {\r
123 IpMode = ConfigData->AutoConfigureMode;\r
124 }\r
125\r
eabc6e59
ZL
126 //\r
127 // Server name is expressed as domain name, just save it.\r
128 //\r
129 if ((!NET_IS_DIGIT (*(Field->Str))) && (*(Field->Str) != '[')) {\r
130 ConfigNvData->DnsMode = TRUE;\r
131 if (Field->Len > sizeof (ConfigNvData->TargetUrl)) {\r
132 return EFI_INVALID_PARAMETER;\r
133 }\r
134 CopyMem (&ConfigNvData->TargetUrl, Field->Str, Field->Len);\r
135 ConfigNvData->TargetUrl[Field->Len + 1] = '\0';\r
136 } else {\r
db0cd7ec 137 ConfigNvData->DnsMode = FALSE;\r
eabc6e59
ZL
138 ZeroMem(ConfigNvData->TargetUrl, sizeof (ConfigNvData->TargetUrl));\r
139 Status = IScsiAsciiStrToIp (Field->Str, IpMode, &Ip);\r
140 CopyMem (&ConfigNvData->TargetIp, &Ip, sizeof (EFI_IP_ADDRESS));\r
4c5a5e0c 141\r
eabc6e59
ZL
142 if (EFI_ERROR (Status)) {\r
143 goto ON_EXIT;\r
144 }\r
4c5a5e0c 145 }\r
146 //\r
147 // Check the protocol type.\r
148 //\r
149 Field = &Fields[RP_FIELD_IDX_PROTOCOL];\r
150 if ((Field->Str != NULL) && ((*(Field->Str) - '0') != EFI_IP_PROTO_TCP)) {\r
151 Status = EFI_INVALID_PARAMETER;\r
152 goto ON_EXIT;\r
153 }\r
154 //\r
155 // Get the port of the iSCSI target.\r
156 //\r
157 Field = &Fields[RP_FIELD_IDX_PORT];\r
158 if (Field->Str != NULL) {\r
159 ConfigNvData->TargetPort = (UINT16) AsciiStrDecimalToUintn (Field->Str);\r
160 } else {\r
161 ConfigNvData->TargetPort = ISCSI_WELL_KNOWN_PORT;\r
162 }\r
163 //\r
164 // Get the LUN.\r
165 //\r
166 Field = &Fields[RP_FIELD_IDX_LUN];\r
167 if (Field->Str != NULL) {\r
168 Status = IScsiAsciiStrToLun (Field->Str, ConfigNvData->BootLun);\r
169 if (EFI_ERROR (Status)) {\r
170 goto ON_EXIT;\r
171 }\r
172 } else {\r
173 ZeroMem (ConfigNvData->BootLun, sizeof (ConfigNvData->BootLun));\r
174 }\r
175 //\r
176 // Get the target iSCSI Name.\r
177 //\r
178 Field = &Fields[RP_FIELD_IDX_TARGETNAME];\r
179\r
180 if (AsciiStrLen (Field->Str) > ISCSI_NAME_MAX_SIZE - 1) {\r
181 Status = EFI_INVALID_PARAMETER;\r
182 goto ON_EXIT;\r
183 }\r
184 //\r
185 // Validate the iSCSI name.\r
186 //\r
187 Status = IScsiNormalizeName (Field->Str, AsciiStrLen (Field->Str));\r
188 if (EFI_ERROR (Status)) {\r
189 goto ON_EXIT;\r
190 }\r
191\r
c960bdc2 192 AsciiStrCpyS (ConfigNvData->TargetName, ISCSI_NAME_MAX_SIZE, Field->Str);\r
4c5a5e0c 193\r
194ON_EXIT:\r
195\r
196 FreePool (TmpStr);\r
197\r
198 return Status;\r
199}\r
200\r
201/**\r
202 The callback function registerd to the DHCP4 instance that is used to select\r
203 the qualified DHCP OFFER.\r
f75a7f56 204\r
4c5a5e0c 205 @param[in] This The DHCP4 protocol.\r
206 @param[in] Context The context set when configuring the DHCP4 protocol.\r
207 @param[in] CurrentState The current state of the DHCP4 protocol.\r
208 @param[in] Dhcp4Event The event occurs in the current state.\r
f75a7f56 209 @param[in] Packet The DHCP packet that is to be sent or was already received.\r
4c5a5e0c 210 @param[out] NewPacket The packet used to replace the above Packet.\r
f75a7f56 211\r
4c5a5e0c 212 @retval EFI_SUCCESS Either the DHCP OFFER is qualified or we're not intereseted\r
213 in the Dhcp4Event.\r
214 @retval EFI_NOT_READY The DHCP OFFER packet doesn't match our requirements.\r
215 @retval Others Other errors as indicated.\r
216\r
217**/\r
218EFI_STATUS\r
219EFIAPI\r
220IScsiDhcpSelectOffer (\r
221 IN EFI_DHCP4_PROTOCOL *This,\r
222 IN VOID *Context,\r
223 IN EFI_DHCP4_STATE CurrentState,\r
224 IN EFI_DHCP4_EVENT Dhcp4Event,\r
225 IN EFI_DHCP4_PACKET *Packet, OPTIONAL\r
226 OUT EFI_DHCP4_PACKET **NewPacket OPTIONAL\r
227 )\r
228{\r
229 EFI_STATUS Status;\r
230 UINT32 OptionCount;\r
231 EFI_DHCP4_PACKET_OPTION **OptionList;\r
232 UINT32 Index;\r
233\r
234 if ((Dhcp4Event != Dhcp4RcvdOffer) && (Dhcp4Event != Dhcp4SelectOffer)) {\r
235 return EFI_SUCCESS;\r
236 }\r
237\r
238 OptionCount = 0;\r
239\r
240 Status = This->Parse (This, Packet, &OptionCount, NULL);\r
241 if (Status != EFI_BUFFER_TOO_SMALL) {\r
242 return EFI_NOT_READY;\r
243 }\r
244\r
245 OptionList = AllocatePool (OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));\r
246 if (OptionList == NULL) {\r
247 return EFI_NOT_READY;\r
248 }\r
249\r
250 Status = This->Parse (This, Packet, &OptionCount, OptionList);\r
251 if (EFI_ERROR (Status)) {\r
252 FreePool (OptionList);\r
253 return EFI_NOT_READY;\r
254 }\r
255\r
256 for (Index = 0; Index < OptionCount; Index++) {\r
142c00c3 257 if (OptionList[Index]->OpCode != DHCP4_TAG_ROOTPATH) {\r
4c5a5e0c 258 continue;\r
259 }\r
260\r
261 Status = IScsiDhcpExtractRootPath (\r
262 (CHAR8 *) &OptionList[Index]->Data[0],\r
263 OptionList[Index]->Length,\r
264 (ISCSI_ATTEMPT_CONFIG_NVDATA *) Context\r
265 );\r
266\r
267 break;\r
268 }\r
269\r
cf260a47 270 if (Index == OptionCount) {\r
4c5a5e0c 271 Status = EFI_NOT_READY;\r
272 }\r
273\r
274 FreePool (OptionList);\r
275\r
276 return Status;\r
277}\r
278\r
279/**\r
280 Parse the DHCP ACK to get the address configuration and DNS information.\r
281\r
282 @param[in] Dhcp4 The DHCP4 protocol.\r
283 @param[in, out] ConfigData The session configuration data.\r
284\r
285 @retval EFI_SUCCESS The DNS information is got from the DHCP ACK.\r
286 @retval EFI_NO_MAPPING DHCP failed to acquire address and other information.\r
287 @retval EFI_INVALID_PARAMETER The DHCP ACK's DNS option is malformatted.\r
288 @retval EFI_DEVICE_ERROR Other errors as indicated.\r
289 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
290\r
291**/\r
292EFI_STATUS\r
293IScsiParseDhcpAck (\r
294 IN EFI_DHCP4_PROTOCOL *Dhcp4,\r
295 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA *ConfigData\r
296 )\r
297{\r
298 EFI_STATUS Status;\r
299 EFI_DHCP4_MODE_DATA Dhcp4ModeData;\r
300 UINT32 OptionCount;\r
301 EFI_DHCP4_PACKET_OPTION **OptionList;\r
302 UINT32 Index;\r
303 ISCSI_SESSION_CONFIG_NVDATA *NvData;\r
304\r
305 Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4ModeData);\r
306 if (EFI_ERROR (Status)) {\r
307 return Status;\r
308 }\r
309\r
310 if (Dhcp4ModeData.State != Dhcp4Bound) {\r
311 return EFI_NO_MAPPING;\r
312 }\r
313\r
314 NvData = &ConfigData->SessionConfigData;\r
315\r
316 CopyMem (&NvData->LocalIp, &Dhcp4ModeData.ClientAddress, sizeof (EFI_IPv4_ADDRESS));\r
317 CopyMem (&NvData->SubnetMask, &Dhcp4ModeData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
318 CopyMem (&NvData->Gateway, &Dhcp4ModeData.RouterAddress, sizeof (EFI_IPv4_ADDRESS));\r
319\r
320 OptionCount = 0;\r
321 OptionList = NULL;\r
322\r
323 Status = Dhcp4->Parse (Dhcp4, Dhcp4ModeData.ReplyPacket, &OptionCount, OptionList);\r
324 if (Status != EFI_BUFFER_TOO_SMALL) {\r
325 return EFI_DEVICE_ERROR;\r
326 }\r
327\r
328 OptionList = AllocatePool (OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));\r
329 if (OptionList == NULL) {\r
330 return EFI_OUT_OF_RESOURCES;\r
331 }\r
332\r
333 Status = Dhcp4->Parse (Dhcp4, Dhcp4ModeData.ReplyPacket, &OptionCount, OptionList);\r
334 if (EFI_ERROR (Status)) {\r
335 FreePool (OptionList);\r
336 return EFI_DEVICE_ERROR;\r
337 }\r
338\r
339 for (Index = 0; Index < OptionCount; Index++) {\r
340 //\r
341 // Get DNS server addresses and DHCP server address from this offer.\r
342 //\r
142c00c3 343 if (OptionList[Index]->OpCode == DHCP4_TAG_DNS_SERVER) {\r
4c5a5e0c 344\r
345 if (((OptionList[Index]->Length & 0x3) != 0) || (OptionList[Index]->Length == 0)) {\r
346 Status = EFI_INVALID_PARAMETER;\r
347 break;\r
348 }\r
349 //\r
350 // Primary DNS server address.\r
351 //\r
352 CopyMem (&ConfigData->PrimaryDns, &OptionList[Index]->Data[0], sizeof (EFI_IPv4_ADDRESS));\r
353\r
354 if (OptionList[Index]->Length > 4) {\r
355 //\r
356 // Secondary DNS server address.\r
357 //\r
358 CopyMem (&ConfigData->SecondaryDns, &OptionList[Index]->Data[4], sizeof (EFI_IPv4_ADDRESS));\r
359 }\r
360 } else if (OptionList[Index]->OpCode == DHCP4_TAG_SERVER_ID) {\r
361 if (OptionList[Index]->Length != 4) {\r
362 Status = EFI_INVALID_PARAMETER;\r
363 break;\r
364 }\r
365\r
366 CopyMem (&ConfigData->DhcpServer, &OptionList[Index]->Data[0], sizeof (EFI_IPv4_ADDRESS));\r
367 }\r
368 }\r
369\r
370 FreePool (OptionList);\r
371\r
372 return Status;\r
373}\r
374\r
ef810bc8
JW
375/**\r
376 This function will switch the IP4 configuration policy to Static.\r
377\r
378 @param[in] Ip4Config2 Pointer to the IP4 configuration protocol.\r
379\r
380 @retval EFI_SUCCESS The policy is already configured to static.\r
381 @retval Others Other error as indicated.\r
382\r
383**/\r
384EFI_STATUS\r
385IScsiSetIp4Policy (\r
386 IN EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2\r
387 )\r
388{\r
389 EFI_IP4_CONFIG2_POLICY Policy;\r
390 EFI_STATUS Status;\r
391 UINTN DataSize;\r
392\r
393 DataSize = sizeof (EFI_IP4_CONFIG2_POLICY);\r
394 Status = Ip4Config2->GetData (\r
395 Ip4Config2,\r
396 Ip4Config2DataTypePolicy,\r
397 &DataSize,\r
398 &Policy\r
399 );\r
400 if (EFI_ERROR (Status)) {\r
401 return Status;\r
402 }\r
403\r
404 if (Policy != Ip4Config2PolicyStatic) {\r
405 Policy = Ip4Config2PolicyStatic;\r
406 Status= Ip4Config2->SetData (\r
407 Ip4Config2,\r
408 Ip4Config2DataTypePolicy,\r
409 sizeof (EFI_IP4_CONFIG2_POLICY),\r
410 &Policy\r
411 );\r
412 if (EFI_ERROR (Status)) {\r
413 return Status;\r
f75a7f56 414 }\r
ef810bc8
JW
415 }\r
416\r
417 return EFI_SUCCESS;\r
418}\r
4c5a5e0c 419\r
420/**\r
421 Parse the DHCP ACK to get the address configuration and DNS information.\r
422\r
423 @param[in] Image The handle of the driver image.\r
424 @param[in] Controller The handle of the controller.\r
425 @param[in, out] ConfigData The attempt configuration data.\r
426\r
427 @retval EFI_SUCCESS The DNS information is got from the DHCP ACK.\r
428 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
429 @retval EFI_NO_MEDIA There was a media error.\r
430 @retval Others Other errors as indicated.\r
431\r
432**/\r
433EFI_STATUS\r
434IScsiDoDhcp (\r
435 IN EFI_HANDLE Image,\r
436 IN EFI_HANDLE Controller,\r
437 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA *ConfigData\r
438 )\r
439{\r
440 EFI_HANDLE Dhcp4Handle;\r
ef810bc8 441 EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2;\r
4c5a5e0c 442 EFI_DHCP4_PROTOCOL *Dhcp4;\r
443 EFI_STATUS Status;\r
444 EFI_DHCP4_PACKET_OPTION *ParaList;\r
445 EFI_DHCP4_CONFIG_DATA Dhcp4ConfigData;\r
446 ISCSI_SESSION_CONFIG_NVDATA *NvData;\r
152f2d5e 447 EFI_STATUS MediaStatus;\r
4c5a5e0c 448\r
449 Dhcp4Handle = NULL;\r
ef810bc8 450 Ip4Config2 = NULL;\r
4c5a5e0c 451 Dhcp4 = NULL;\r
452 ParaList = NULL;\r
453\r
454 //\r
455 // Check media status before doing DHCP.\r
456 //\r
152f2d5e 457 MediaStatus = EFI_SUCCESS;\r
458 NetLibDetectMediaWaitTimeout (Controller, ISCSI_CHECK_MEDIA_GET_DHCP_WAITING_TIME, &MediaStatus);\r
459 if (MediaStatus!= EFI_SUCCESS) {\r
460 AsciiPrint ("\n Error: Could not detect network connection.\n");\r
4c5a5e0c 461 return EFI_NO_MEDIA;\r
462 }\r
463\r
ef810bc8 464 //\r
f75a7f56
LG
465 // DHCP4 service allows only one of its children to be configured in\r
466 // the active state, If the DHCP4 D.O.R.A started by IP4 auto\r
467 // configuration and has not been completed, the Dhcp4 state machine\r
468 // will not be in the right state for the iSCSI to start a new round D.O.R.A.\r
ef810bc8
JW
469 // So, we need to switch it's policy to static.\r
470 //\r
471 Status = gBS->HandleProtocol (Controller, &gEfiIp4Config2ProtocolGuid, (VOID **) &Ip4Config2);\r
472 if (!EFI_ERROR (Status)) {\r
473 Status = IScsiSetIp4Policy (Ip4Config2);\r
474 if (EFI_ERROR (Status)) {\r
475 return Status;\r
476 }\r
477 }\r
478\r
4c5a5e0c 479 //\r
480 // Create a DHCP4 child instance and get the protocol.\r
481 //\r
482 Status = NetLibCreateServiceChild (\r
483 Controller,\r
484 Image,\r
485 &gEfiDhcp4ServiceBindingProtocolGuid,\r
486 &Dhcp4Handle\r
487 );\r
488 if (EFI_ERROR (Status)) {\r
489 return Status;\r
490 }\r
491\r
492 Status = gBS->OpenProtocol (\r
493 Dhcp4Handle,\r
494 &gEfiDhcp4ProtocolGuid,\r
495 (VOID **) &Dhcp4,\r
496 Image,\r
497 Controller,\r
498 EFI_OPEN_PROTOCOL_BY_DRIVER\r
499 );\r
500 if (EFI_ERROR (Status)) {\r
501 goto ON_EXIT;\r
502 }\r
503\r
504 NvData = &ConfigData->SessionConfigData;\r
505\r
506 ParaList = AllocatePool (sizeof (EFI_DHCP4_PACKET_OPTION) + 3);\r
507 if (ParaList == NULL) {\r
508 Status = EFI_OUT_OF_RESOURCES;\r
509 goto ON_EXIT;\r
510 }\r
511\r
512 //\r
513 // Ask the server to reply with Netmask, Router, DNS, and RootPath options.\r
514 //\r
515 ParaList->OpCode = DHCP4_TAG_PARA_LIST;\r
516 ParaList->Length = (UINT8) (NvData->TargetInfoFromDhcp ? 4 : 3);\r
517 ParaList->Data[0] = DHCP4_TAG_NETMASK;\r
518 ParaList->Data[1] = DHCP4_TAG_ROUTER;\r
142c00c3
ZL
519 ParaList->Data[2] = DHCP4_TAG_DNS_SERVER;\r
520 ParaList->Data[3] = DHCP4_TAG_ROOTPATH;\r
4c5a5e0c 521\r
522 ZeroMem (&Dhcp4ConfigData, sizeof (EFI_DHCP4_CONFIG_DATA));\r
523 Dhcp4ConfigData.OptionCount = 1;\r
524 Dhcp4ConfigData.OptionList = &ParaList;\r
525\r
526 if (NvData->TargetInfoFromDhcp) {\r
527 //\r
528 // Use callback to select an offer that contains target information.\r
529 //\r
530 Dhcp4ConfigData.Dhcp4Callback = IScsiDhcpSelectOffer;\r
531 Dhcp4ConfigData.CallbackContext = ConfigData;\r
532 }\r
533\r
534 Status = Dhcp4->Configure (Dhcp4, &Dhcp4ConfigData);\r
535 if (EFI_ERROR (Status)) {\r
536 goto ON_EXIT;\r
537 }\r
538\r
539 Status = Dhcp4->Start (Dhcp4, NULL);\r
540 if (EFI_ERROR (Status)) {\r
541 goto ON_EXIT;\r
542 }\r
543 //\r
544 // Parse the ACK to get required information.\r
545 //\r
546 Status = IScsiParseDhcpAck (Dhcp4, ConfigData);\r
547\r
548ON_EXIT:\r
549\r
550 if (ParaList != NULL) {\r
551 FreePool (ParaList);\r
552 }\r
553\r
554 if (Dhcp4 != NULL) {\r
555 Dhcp4->Stop (Dhcp4);\r
556 Dhcp4->Configure (Dhcp4, NULL);\r
557\r
558 gBS->CloseProtocol (\r
559 Dhcp4Handle,\r
560 &gEfiDhcp4ProtocolGuid,\r
561 Image,\r
562 Controller\r
563 );\r
564 }\r
565\r
566 NetLibDestroyServiceChild (\r
567 Controller,\r
568 Image,\r
569 &gEfiDhcp4ServiceBindingProtocolGuid,\r
570 Dhcp4Handle\r
571 );\r
572\r
573 return Status;\r
574}\r