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