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