]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.c
Scrubbed part of the code.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Dhcp4Dxe / Dhcp4Impl.c
CommitLineData
772db4bb 1/** @file\r
2\r
7bce0c5a 3Copyright (c) 2006 - 2008, Intel Corporation\r
772db4bb 4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 Dhcp4Impl.c\r
15\r
16Abstract:\r
17\r
18 This file implement the EFI_DHCP4_PROTOCOL interface.\r
19\r
20\r
21**/\r
22\r
23\r
24#include "Dhcp4Impl.h"\r
25\r
f9204641 26/**\r
27 Returns the current operating mode and cached data packet for the EFI DHCPv4 Protocol driver.\r
28 \r
29 The GetModeData() function returns the current operating mode and cached data\r
30 packet for the EFI DHCPv4 Protocol driver.\r
31\r
32 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.\r
33 @param Dhcp4ModeData Pointer to storage for the EFI_DHCP4_MODE_DATA structure.\r
34\r
35 @retval EFI_SUCCESS The mode data was returned.\r
36 @retval EFI_INVALID_PARAMETER This is NULL.\r
37\r
38**/\r
39EFI_STATUS\r
40EFIAPI\r
41EfiDhcp4GetModeData (\r
42 IN EFI_DHCP4_PROTOCOL *This,\r
43 OUT EFI_DHCP4_MODE_DATA *Dhcp4ModeData\r
44 );\r
45\r
46/**\r
47 Initializes, changes, or resets the operational settings for the EFI DHCPv4 Protocol driver.\r
48\r
49 The Configure() function is used to initialize, change, or reset the operational\r
50 settings of the EFI DHCPv4 Protocol driver for the communication device on which\r
51 the EFI DHCPv4 Service Binding Protocol is installed. This function can be\r
52 successfully called only if both of the following are true:\r
53 * This instance of the EFI DHCPv4 Protocol driver is in the Dhcp4Stopped, Dhcp4Init,\r
54 Dhcp4InitReboot, or Dhcp4Bound states.\r
55 * No other EFI DHCPv4 Protocol driver instance that is controlled by this EFI\r
56 DHCPv4 Service Binding Protocol driver instance has configured this EFI DHCPv4\r
57 Protocol driver.\r
58 When this driver is in the Dhcp4Stopped state, it can transfer into one of the\r
59 following two possible initial states:\r
60 * Dhcp4Init\r
61 * Dhcp4InitReboot\r
62 The driver can transfer into these states by calling Configure() with a non-NULL\r
63 Dhcp4CfgData. The driver will transfer into the appropriate state based on the\r
64 supplied client network address in the ClientAddress parameter and DHCP options\r
65 in the OptionList parameter as described in RFC 2131.\r
66 When Configure() is called successfully while Dhcp4CfgData is set to NULL, the\r
67 default configuring data will be reset in the EFI DHCPv4 Protocol driver and\r
68 the state of the EFI DHCPv4 Protocol driver will not be changed. If one instance\r
69 wants to make it possible for another instance to configure the EFI DHCPv4 Protocol\r
70 driver, it must call this function with Dhcp4CfgData set to NULL.\r
71\r
72 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.\r
73 @param Dhcp4CfgData Pointer to the EFI_DHCP4_CONFIG_DATA.\r
74\r
75 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Init or\r
76 Dhcp4InitReboot state, if the original state of this driver\r
77 was Dhcp4Stopped and the value of Dhcp4CfgData was\r
78 not NULL. Otherwise, the state was left unchanged.\r
79 @retval EFI_ACCESS_DENIED This instance of the EFI DHCPv4 Protocol driver was not in the\r
80 Dhcp4Stopped, Dhcp4Init, Dhcp4InitReboot, or Dhcp4Bound state;\r
81 Or onother instance of this EFI DHCPv4 Protocol driver is already\r
82 in a valid configured state.\r
83 @retval EFI_INVALID_PARAMETER Some parameter is NULL.\r
84 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.\r
85 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
86\r
87**/\r
88EFI_STATUS\r
89EFIAPI\r
90EfiDhcp4Configure (\r
91 IN EFI_DHCP4_PROTOCOL *This,\r
92 IN EFI_DHCP4_CONFIG_DATA *Dhcp4CfgData OPTIONAL\r
93 ); \r
94\r
95/**\r
96 Starts the DHCP configuration process.\r
97\r
98 The Start() function starts the DHCP configuration process. This function can\r
99 be called only when the EFI DHCPv4 Protocol driver is in the Dhcp4Init or\r
100 Dhcp4InitReboot state.\r
101 If the DHCP process completes successfully, the state of the EFI DHCPv4 Protocol\r
102 driver will be transferred through Dhcp4Selecting and Dhcp4Requesting to the\r
103 Dhcp4Bound state. The CompletionEvent will then be signaled if it is not NULL.\r
104 If the process aborts, either by the user or by some unexpected network error,\r
105 the state is restored to the Dhcp4Init state. The Start() function can be called\r
106 again to restart the process.\r
107 Refer to RFC 2131 for precise state transitions during this process. At the\r
108 time when each event occurs in this process, the callback function that was set\r
109 by EFI_DHCP4_PROTOCOL.Configure() will be called and the user can take this\r
110 opportunity to control the process.\r
111 \r
112 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.\r
113 @param CompletionEvent If not NULL, indicates the event that will be signaled when the\r
114 EFI DHCPv4 Protocol driver is transferred into the\r
115 Dhcp4Bound state or when the DHCP process is aborted.\r
116 EFI_DHCP4_PROTOCOL.GetModeData() can be called to\r
117 check the completion status. If NULL,\r
118 EFI_DHCP4_PROTOCOL.Start() will wait until the driver\r
119 is transferred into the Dhcp4Bound state or the process fails.\r
120\r
121 @retval EFI_SUCCESS The DHCP configuration process has started, or it has completed\r
122 when CompletionEvent is NULL.\r
123 @retval EFI_NOT_STARTED The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped\r
124 state. EFI_DHCP4_PROTOCOL. Configure() needs to be called.\r
125 @retval EFI_INVALID_PARAMETER This is NULL.\r
126 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.\r
127 @retval EFI_TIMEOUT The DHCP configuration process failed because no response was\r
128 received from the server within the specified timeout value.\r
129 @retval EFI_ABORTED The user aborted the DHCP process.\r
130 @retval EFI_ALREADY_STARTED Some other EFI DHCPv4 Protocol instance already started the\r
131 DHCP process.\r
132 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
133\r
134**/\r
135EFI_STATUS\r
136EFIAPI\r
137EfiDhcp4Start (\r
138 IN EFI_DHCP4_PROTOCOL *This,\r
139 IN EFI_EVENT CompletionEvent OPTIONAL\r
140 );\r
141\r
142/**\r
143 Extends the lease time by sending a request packet.\r
144 \r
145 The RenewRebind() function is used to manually extend the lease time when the\r
146 EFI DHCPv4 Protocol driver is in the Dhcp4Bound state and the lease time has\r
147 not expired yet. This function will send a request packet to the previously\r
148 found server (or to any server when RebindRequest is TRUE) and transfer the\r
149 state into the Dhcp4Renewing state (or Dhcp4Rebinding when RebindingRequest is\r
150 TRUE). When a response is received, the state is returned to Dhcp4Bound.\r
151 If no response is received before the try count is exceeded (the RequestTryCount\r
152 field that is specified in EFI_DHCP4_CONFIG_DATA) but before the lease time that\r
153 was issued by the previous server expires, the driver will return to the Dhcp4Bound\r
154 state and the previous configuration is restored. The outgoing and incoming packets\r
155 can be captured by the EFI_DHCP4_CALLBACK function.\r
156\r
157 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.\r
158 @param RebindRequest If TRUE, this function broadcasts the request packets and enters\r
159 the Dhcp4Rebinding state. Otherwise, it sends a unicast\r
160 request packet and enters the Dhcp4Renewing state.\r
161 @param CompletionEvent If not NULL, this event is signaled when the renew/rebind phase\r
162 completes or some error occurs.\r
163 EFI_DHCP4_PROTOCOL.GetModeData() can be called to\r
164 check the completion status. If NULL,\r
165 EFI_DHCP4_PROTOCOL.RenewRebind() will busy-wait\r
166 until the DHCP process finishes.\r
167\r
168 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the\r
169 Dhcp4Renewing state or is back to the Dhcp4Bound state.\r
170 @retval EFI_NOT_STARTED The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped\r
171 state. EFI_DHCP4_PROTOCOL.Configure() needs to\r
172 be called.\r
173 @retval EFI_INVALID_PARAMETER This is NULL.\r
174 @retval EFI_TIMEOUT There was no response from the server when the try count was\r
175 exceeded.\r
176 @retval EFI_ACCESS_DENIED The driver is not in the Dhcp4Bound state.\r
177 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
178\r
179**/\r
180EFI_STATUS\r
181EFIAPI\r
182EfiDhcp4RenewRebind (\r
183 IN EFI_DHCP4_PROTOCOL *This,\r
184 IN BOOLEAN RebindRequest,\r
185 IN EFI_EVENT CompletionEvent OPTIONAL\r
186 );\r
187\r
188/**\r
189 Releases the current address configuration.\r
190\r
191 The Release() function releases the current configured IP address by doing either\r
192 of the following:\r
193 * Sending a DHCPRELEASE packet when the EFI DHCPv4 Protocol driver is in the\r
194 Dhcp4Bound state\r
195 * Setting the previously assigned IP address that was provided with the\r
196 EFI_DHCP4_PROTOCOL.Configure() function to 0.0.0.0 when the driver is in\r
197 Dhcp4InitReboot state\r
198 After a successful call to this function, the EFI DHCPv4 Protocol driver returns\r
199 to the Dhcp4Init state and any subsequent incoming packets will be discarded silently.\r
200\r
201 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.\r
202\r
203 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Init phase.\r
204 @retval EFI_INVALID_PARAMETER This is NULL.\r
205 @retval EFI_ACCESS_DENIED The EFI DHCPv4 Protocol driver is not Dhcp4InitReboot state.\r
206 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
207\r
208**/\r
209EFI_STATUS\r
210EFIAPI\r
211EfiDhcp4Release (\r
212 IN EFI_DHCP4_PROTOCOL *This\r
213 );\r
214\r
215/**\r
216 Stops the current address configuration.\r
217 \r
218 The Stop() function is used to stop the DHCP configuration process. After this\r
219 function is called successfully, the EFI DHCPv4 Protocol driver is transferred\r
220 into the Dhcp4Stopped state. EFI_DHCP4_PROTOCOL.Configure() needs to be called\r
221 before DHCP configuration process can be started again. This function can be\r
222 called when the EFI DHCPv4 Protocol driver is in any state.\r
223\r
224 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.\r
225\r
226 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Stopped phase.\r
227 @retval EFI_INVALID_PARAMETER This is NULL.\r
228\r
229**/\r
230EFI_STATUS\r
231EFIAPI\r
232EfiDhcp4Stop (\r
233 IN EFI_DHCP4_PROTOCOL *This\r
234 );\r
235\r
236/**\r
237 Builds a DHCP packet, given the options to be appended or deleted or replaced.\r
238\r
239 The Build() function is used to assemble a new packet from the original packet\r
240 by replacing or deleting existing options or appending new options. This function\r
241 does not change any state of the EFI DHCPv4 Protocol driver and can be used at\r
242 any time.\r
243\r
244 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.\r
245 @param SeedPacket Initial packet to be used as a base for building new packet.\r
246 @param DeleteCount Number of opcodes in the DeleteList.\r
247 @param DeleteList List of opcodes to be deleted from the seed packet.\r
248 Ignored if DeleteCount is zero.\r
249 @param AppendCount Number of entries in the OptionList.\r
250 @param AppendList Pointer to a DHCP option list to be appended to SeedPacket.\r
251 If SeedPacket also contains options in this list, they are\r
252 replaced by new options (except pad option). Ignored if\r
253 AppendCount is zero. Type EFI_DHCP4_PACKET_OPTION\r
254 @param NewPacket Pointer to storage for the pointer to the new allocated packet.\r
255 Use the EFI Boot Service FreePool() on the resulting pointer\r
256 when done with the packet.\r
257\r
258 @retval EFI_SUCCESS The new packet was built.\r
259 @retval EFI_OUT_OF_RESOURCES Storage for the new packet could not be allocated.\r
260 @retval EFI_INVALID_PARAMETER Some parameter is NULL.\r
261\r
262**/\r
263EFI_STATUS\r
264EFIAPI\r
265EfiDhcp4Build (\r
266 IN EFI_DHCP4_PROTOCOL *This,\r
267 IN EFI_DHCP4_PACKET *SeedPacket,\r
268 IN UINT32 DeleteCount,\r
269 IN UINT8 *DeleteList OPTIONAL,\r
270 IN UINT32 AppendCount,\r
271 IN EFI_DHCP4_PACKET_OPTION *AppendList[] OPTIONAL,\r
272 OUT EFI_DHCP4_PACKET **NewPacket\r
273 );\r
274 \r
275 /**\r
276 Transmits a DHCP formatted packet and optionally waits for responses.\r
277 \r
278 The TransmitReceive() function is used to transmit a DHCP packet and optionally\r
279 wait for the response from servers. This function does not change the state of\r
280 the EFI DHCPv4 Protocol driver and thus can be used at any time.\r
281\r
282 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.\r
283 @param Token Pointer to the EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN structure.\r
284\r
285 @retval EFI_SUCCESS The packet was successfully queued for transmission.\r
286 @retval EFI_INVALID_PARAMETER Some parameter is NULL.\r
287 @retval EFI_NOT_READY The previous call to this function has not finished yet. Try to call\r
288 this function after collection process completes.\r
289 @retval EFI_NO_MAPPING The default station address is not available yet.\r
290 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.\r
291 @retval Others Some other unexpected error occurred.\r
292\r
293**/\r
294EFI_STATUS\r
295EFIAPI\r
296EfiDhcp4TransmitReceive (\r
297 IN EFI_DHCP4_PROTOCOL *This,\r
298 IN EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token\r
299 );\r
300\r
301/**\r
302 Parses the packed DHCP option data.\r
303 \r
304 The Parse() function is used to retrieve the option list from a DHCP packet.\r
305 If *OptionCount isn’t zero, and there is enough space for all the DHCP options\r
306 in the Packet, each element of PacketOptionList is set to point to somewhere in\r
307 the Packet->Dhcp4.Option where a new DHCP option begins. If RFC3396 is supported,\r
308 the caller should reassemble the parsed DHCP options to get the finial result.\r
309 If *OptionCount is zero or there isn’t enough space for all of them, the number\r
310 of DHCP options in the Packet is returned in OptionCount.\r
311\r
312 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.\r
313 @param Packet Pointer to packet to be parsed.\r
314 @param OptionCount On input, the number of entries in the PacketOptionList.\r
315 On output, the number of entries that were written into the\r
316 PacketOptionList.\r
317 @param PacketOptionList List of packet option entries to be filled in. End option or pad\r
318 options are not included.\r
319\r
320 @retval EFI_SUCCESS The packet was successfully parsed.\r
321 @retval EFI_INVALID_PARAMETER Some parameter is NULL.\r
322 @retval EFI_BUFFER_TOO_SMALL One or more of the following conditions is TRUE:\r
323 1) *OptionCount is smaller than the number of options that\r
324 were found in the Packet.\r
325 2) PacketOptionList is NULL.\r
326\r
327**/\r
328EFI_STATUS\r
329EFIAPI\r
330EfiDhcp4Parse (\r
331 IN EFI_DHCP4_PROTOCOL *This,\r
332 IN EFI_DHCP4_PACKET *Packet,\r
333 IN OUT UINT32 *OptionCount,\r
334 OUT EFI_DHCP4_PACKET_OPTION *PacketOptionList[] OPTIONAL\r
335 );\r
336\r
337EFI_DHCP4_PROTOCOL mDhcp4ProtocolTemplate = {\r
338 EfiDhcp4GetModeData,\r
339 EfiDhcp4Configure,\r
340 EfiDhcp4Start,\r
341 EfiDhcp4RenewRebind,\r
342 EfiDhcp4Release,\r
343 EfiDhcp4Stop,\r
344 EfiDhcp4Build,\r
345 EfiDhcp4TransmitReceive,\r
346 EfiDhcp4Parse\r
347};\r
772db4bb 348\r
349/**\r
f9204641 350 Returns the current operating mode and cached data packet for the EFI DHCPv4 Protocol driver.\r
351 \r
352 The GetModeData() function returns the current operating mode and cached data\r
353 packet for the EFI DHCPv4 Protocol driver.\r
772db4bb 354\r
f9204641 355 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.\r
356 @param Dhcp4ModeData Pointer to storage for the EFI_DHCP4_MODE_DATA structure.\r
772db4bb 357\r
f9204641 358 @retval EFI_SUCCESS The mode data was returned.\r
359 @retval EFI_INVALID_PARAMETER This is NULL.\r
772db4bb 360\r
361**/\r
772db4bb 362EFI_STATUS\r
363EFIAPI\r
364EfiDhcp4GetModeData (\r
365 IN EFI_DHCP4_PROTOCOL *This,\r
366 OUT EFI_DHCP4_MODE_DATA *Dhcp4ModeData\r
367 )\r
368{\r
369 DHCP_PROTOCOL *Instance;\r
370 DHCP_SERVICE *DhcpSb;\r
371 DHCP_PARAMETER *Para;\r
372 EFI_TPL OldTpl;\r
373 IP4_ADDR Ip;\r
374\r
375 //\r
376 // First validate the parameters.\r
377 //\r
378 if ((This == NULL) || (Dhcp4ModeData == NULL)) {\r
379 return EFI_INVALID_PARAMETER;\r
380 }\r
381\r
382 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
982a9eae 383\r
e48e37fc 384 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 385 DhcpSb = Instance->Service;\r
386\r
387 //\r
388 // Caller can use GetModeData to retrieve current DHCP states\r
389 // no matter whether it is the active child or not.\r
390 //\r
f9204641 391 Dhcp4ModeData->State = (EFI_DHCP4_STATE) DhcpSb->DhcpState;\r
687a2e5f 392 CopyMem (&Dhcp4ModeData->ConfigData, &DhcpSb->ActiveConfig, sizeof (Dhcp4ModeData->ConfigData));\r
393 CopyMem (&Dhcp4ModeData->ClientMacAddress, &DhcpSb->Mac, sizeof (Dhcp4ModeData->ClientMacAddress));\r
772db4bb 394\r
395 Ip = HTONL (DhcpSb->ClientAddr);\r
e48e37fc 396 CopyMem (&Dhcp4ModeData->ClientAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
772db4bb 397\r
398 Ip = HTONL (DhcpSb->Netmask);\r
e48e37fc 399 CopyMem (&Dhcp4ModeData->SubnetMask, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
772db4bb 400\r
401 Ip = HTONL (DhcpSb->ServerAddr);\r
e48e37fc 402 CopyMem (&Dhcp4ModeData->ServerAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
772db4bb 403\r
404 Para = DhcpSb->Para;\r
405\r
406 if (Para != NULL) {\r
407 Ip = HTONL (Para->Router);\r
e48e37fc 408 CopyMem (&Dhcp4ModeData->RouterAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
f9204641 409 Dhcp4ModeData->LeaseTime = Para->Lease;\r
772db4bb 410 } else {\r
e48e37fc 411 ZeroMem (&Dhcp4ModeData->RouterAddress, sizeof (EFI_IPv4_ADDRESS));\r
f9204641 412 Dhcp4ModeData->LeaseTime = 0xffffffff;\r
772db4bb 413 }\r
414\r
415 Dhcp4ModeData->ReplyPacket = DhcpSb->Selected;\r
416\r
e48e37fc 417 gBS->RestoreTPL (OldTpl);\r
772db4bb 418 return EFI_SUCCESS;\r
419}\r
420\r
421\r
422/**\r
423 Free the resource related to the configure parameters.\r
424 DHCP driver will make a copy of the user's configure\r
425 such as the time out value.\r
426\r
427 @param Config The DHCP configure data\r
428\r
429 @return None\r
430\r
431**/\r
432VOID\r
433DhcpCleanConfigure (\r
f9204641 434 IN OUT EFI_DHCP4_CONFIG_DATA *Config\r
772db4bb 435 )\r
436{\r
437 UINT32 Index;\r
438\r
439 if (Config->DiscoverTimeout != NULL) {\r
e48e37fc 440 gBS->FreePool (Config->DiscoverTimeout);\r
772db4bb 441 }\r
442\r
443 if (Config->RequestTimeout != NULL) {\r
e48e37fc 444 gBS->FreePool (Config->RequestTimeout);\r
772db4bb 445 }\r
446\r
447 if (Config->OptionList != NULL) {\r
448 for (Index = 0; Index < Config->OptionCount; Index++) {\r
449 if (Config->OptionList[Index] != NULL) {\r
e48e37fc 450 gBS->FreePool (Config->OptionList[Index]);\r
772db4bb 451 }\r
452 }\r
453\r
e48e37fc 454 gBS->FreePool (Config->OptionList);\r
772db4bb 455 }\r
456\r
e48e37fc 457 ZeroMem (Config, sizeof (EFI_DHCP4_CONFIG_DATA));\r
772db4bb 458}\r
459\r
460\r
461/**\r
462 Allocate memory for configure parameter such as timeout value for Dst,\r
463 then copy the configure parameter from Src to Dst.\r
464\r
465 @param Dst The destination DHCP configure data.\r
466 @param Src The source DHCP configure data.\r
467\r
468 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
469 @retval EFI_SUCCESS The configure is copied.\r
470\r
471**/\r
472EFI_STATUS\r
473DhcpCopyConfigure (\r
f9204641 474 OUT EFI_DHCP4_CONFIG_DATA *Dst,\r
475 IN EFI_DHCP4_CONFIG_DATA *Src\r
772db4bb 476 )\r
477{\r
478 EFI_DHCP4_PACKET_OPTION **DstOptions;\r
479 EFI_DHCP4_PACKET_OPTION **SrcOptions;\r
480 INTN Len;\r
481 UINT32 Index;\r
482\r
72030458 483 CopyMem (Dst, Src, sizeof (*Dst));\r
772db4bb 484 Dst->DiscoverTimeout = NULL;\r
485 Dst->RequestTimeout = NULL;\r
486 Dst->OptionList = NULL;\r
487\r
488 //\r
489 // Allocate a memory then copy DiscoverTimeout to it\r
490 //\r
491 if (Src->DiscoverTimeout != NULL) {\r
492 Len = Src->DiscoverTryCount * sizeof (UINT32);\r
e48e37fc 493 Dst->DiscoverTimeout = AllocatePool (Len);\r
772db4bb 494\r
495 if (Dst->DiscoverTimeout == NULL) {\r
496 return EFI_OUT_OF_RESOURCES;\r
497 }\r
498\r
499 for (Index = 0; Index < Src->DiscoverTryCount; Index++) {\r
36ee91ca 500 Dst->DiscoverTimeout[Index] = MAX (Src->DiscoverTimeout[Index], 1);\r
772db4bb 501 }\r
502 }\r
503\r
504 //\r
505 // Allocate a memory then copy RequestTimeout to it\r
506 //\r
507 if (Src->RequestTimeout != NULL) {\r
508 Len = Src->RequestTryCount * sizeof (UINT32);\r
e48e37fc 509 Dst->RequestTimeout = AllocatePool (Len);\r
772db4bb 510\r
511 if (Dst->RequestTimeout == NULL) {\r
512 goto ON_ERROR;\r
513 }\r
514\r
515 for (Index = 0; Index < Src->RequestTryCount; Index++) {\r
36ee91ca 516 Dst->RequestTimeout[Index] = MAX (Src->RequestTimeout[Index], 1);\r
772db4bb 517 }\r
518 }\r
519\r
520 //\r
521 // Allocate an array of dhcp option point, then allocate memory\r
522 // for each option and copy the source option to it\r
523 //\r
524 if (Src->OptionList != NULL) {\r
525 Len = Src->OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *);\r
e48e37fc 526 Dst->OptionList = AllocateZeroPool (Len);\r
772db4bb 527\r
528 if (Dst->OptionList == NULL) {\r
529 goto ON_ERROR;\r
530 }\r
531\r
532 DstOptions = Dst->OptionList;\r
533 SrcOptions = Src->OptionList;\r
534\r
535 for (Index = 0; Index < Src->OptionCount; Index++) {\r
36ee91ca 536 Len = sizeof (EFI_DHCP4_PACKET_OPTION) + MAX (SrcOptions[Index]->Length - 1, 0);\r
772db4bb 537\r
e48e37fc 538 DstOptions[Index] = AllocatePool (Len);\r
772db4bb 539\r
540 if (DstOptions[Index] == NULL) {\r
541 goto ON_ERROR;\r
542 }\r
543\r
e48e37fc 544 CopyMem (DstOptions[Index], SrcOptions[Index], Len);\r
772db4bb 545 }\r
546 }\r
547\r
548 return EFI_SUCCESS;\r
549\r
550ON_ERROR:\r
551 DhcpCleanConfigure (Dst);\r
552 return EFI_OUT_OF_RESOURCES;\r
553}\r
554\r
555\r
556/**\r
557 Give up the control of the DHCP service to let other child\r
558 resume. Don't change the service's DHCP state and the Client\r
559 address and option list configure as required by RFC2131.\r
560\r
561 @param DhcpSb The DHCP service instance.\r
562\r
563 @return None\r
564\r
565**/\r
566VOID\r
567DhcpYieldControl (\r
568 IN DHCP_SERVICE *DhcpSb\r
569 )\r
570{\r
571 EFI_DHCP4_CONFIG_DATA *Config;\r
772db4bb 572\r
772db4bb 573 Config = &DhcpSb->ActiveConfig;\r
574\r
575 DhcpSb->ServiceState = DHCP_UNCONFIGED;\r
576 DhcpSb->ActiveChild = NULL;\r
577\r
578 if (Config->DiscoverTimeout != NULL) {\r
e48e37fc 579 gBS->FreePool (Config->DiscoverTimeout);\r
772db4bb 580\r
581 Config->DiscoverTryCount = 0;\r
582 Config->DiscoverTimeout = NULL;\r
583 }\r
584\r
585 if (Config->RequestTimeout != NULL) {\r
e48e37fc 586 gBS->FreePool (Config->RequestTimeout);\r
772db4bb 587\r
588 Config->RequestTryCount = 0;\r
589 Config->RequestTimeout = NULL;\r
590 }\r
591\r
592 Config->Dhcp4Callback = NULL;\r
593 Config->CallbackContext = NULL;\r
594}\r
595\r
596\r
597/**\r
f9204641 598 Initializes, changes, or resets the operational settings for the EFI DHCPv4 Protocol driver.\r
599\r
600 The Configure() function is used to initialize, change, or reset the operational\r
601 settings of the EFI DHCPv4 Protocol driver for the communication device on which\r
602 the EFI DHCPv4 Service Binding Protocol is installed. This function can be\r
603 successfully called only if both of the following are true:\r
604 * This instance of the EFI DHCPv4 Protocol driver is in the Dhcp4Stopped, Dhcp4Init,\r
605 Dhcp4InitReboot, or Dhcp4Bound states.\r
606 * No other EFI DHCPv4 Protocol driver instance that is controlled by this EFI\r
607 DHCPv4 Service Binding Protocol driver instance has configured this EFI DHCPv4\r
608 Protocol driver.\r
609 When this driver is in the Dhcp4Stopped state, it can transfer into one of the\r
610 following two possible initial states:\r
611 * Dhcp4Init\r
612 * Dhcp4InitReboot\r
613 The driver can transfer into these states by calling Configure() with a non-NULL\r
614 Dhcp4CfgData. The driver will transfer into the appropriate state based on the\r
615 supplied client network address in the ClientAddress parameter and DHCP options\r
616 in the OptionList parameter as described in RFC 2131.\r
617 When Configure() is called successfully while Dhcp4CfgData is set to NULL, the\r
618 default configuring data will be reset in the EFI DHCPv4 Protocol driver and\r
619 the state of the EFI DHCPv4 Protocol driver will not be changed. If one instance\r
620 wants to make it possible for another instance to configure the EFI DHCPv4 Protocol\r
621 driver, it must call this function with Dhcp4CfgData set to NULL.\r
622\r
623 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.\r
624 @param Dhcp4CfgData Pointer to the EFI_DHCP4_CONFIG_DATA.\r
625\r
626 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Init or\r
627 Dhcp4InitReboot state, if the original state of this driver\r
628 was Dhcp4Stopped and the value of Dhcp4CfgData was\r
629 not NULL. Otherwise, the state was left unchanged.\r
630 @retval EFI_ACCESS_DENIED This instance of the EFI DHCPv4 Protocol driver was not in the\r
631 Dhcp4Stopped, Dhcp4Init, Dhcp4InitReboot, or Dhcp4Bound state;\r
632 Or onother instance of this EFI DHCPv4 Protocol driver is already\r
633 in a valid configured state.\r
634 @retval EFI_INVALID_PARAMETER Some parameter is NULL.\r
635 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.\r
636 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
772db4bb 637\r
638**/\r
772db4bb 639EFI_STATUS\r
640EFIAPI\r
641EfiDhcp4Configure (\r
642 IN EFI_DHCP4_PROTOCOL *This,\r
643 IN EFI_DHCP4_CONFIG_DATA *Dhcp4CfgData OPTIONAL\r
644 )\r
645{\r
646 EFI_DHCP4_CONFIG_DATA *Config;\r
647 DHCP_PROTOCOL *Instance;\r
648 DHCP_SERVICE *DhcpSb;\r
649 EFI_STATUS Status;\r
650 EFI_TPL OldTpl;\r
651 UINT32 Index;\r
652 IP4_ADDR Ip;\r
653\r
654 //\r
655 // First validate the parameters\r
656 //\r
657 if (This == NULL) {\r
658 return EFI_INVALID_PARAMETER;\r
659 }\r
660\r
661 if (Dhcp4CfgData != NULL) {\r
662 if (Dhcp4CfgData->DiscoverTryCount && (Dhcp4CfgData->DiscoverTimeout == NULL)) {\r
663 return EFI_INVALID_PARAMETER;\r
664 }\r
665\r
666 if (Dhcp4CfgData->RequestTryCount && (Dhcp4CfgData->RequestTimeout == NULL)) {\r
667 return EFI_INVALID_PARAMETER;\r
668 }\r
669\r
670 if (Dhcp4CfgData->OptionCount && (Dhcp4CfgData->OptionList == NULL)) {\r
671 return EFI_INVALID_PARAMETER;\r
672 }\r
673\r
e48e37fc 674 CopyMem (&Ip, &Dhcp4CfgData->ClientAddress, sizeof (IP4_ADDR));\r
772db4bb 675\r
676 if ((Ip != 0) && !Ip4IsUnicast (NTOHL (Ip), 0)) {\r
677\r
678 return EFI_INVALID_PARAMETER;\r
679 }\r
680 }\r
681\r
682 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
683\r
684 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
685 return EFI_INVALID_PARAMETER;\r
686 }\r
687\r
e48e37fc 688 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 689\r
690 DhcpSb = Instance->Service;\r
691 Config = &DhcpSb->ActiveConfig;\r
692\r
693 Status = EFI_ACCESS_DENIED;\r
694\r
695 if ((DhcpSb->DhcpState != Dhcp4Stopped) &&\r
696 (DhcpSb->DhcpState != Dhcp4Init) &&\r
697 (DhcpSb->DhcpState != Dhcp4InitReboot) &&\r
698 (DhcpSb->DhcpState != Dhcp4Bound)) {\r
699\r
700 goto ON_EXIT;\r
701 }\r
702\r
703 if ((DhcpSb->ActiveChild != NULL) && (DhcpSb->ActiveChild != Instance)) {\r
704 goto ON_EXIT;\r
705 }\r
706\r
707 if (Dhcp4CfgData != NULL) {\r
708 Status = EFI_OUT_OF_RESOURCES;\r
709 DhcpCleanConfigure (Config);\r
710\r
711 if (EFI_ERROR (DhcpCopyConfigure (Config, Dhcp4CfgData))) {\r
712 goto ON_EXIT;\r
713 }\r
714\r
715 DhcpSb->UserOptionLen = 0;\r
716\r
717 for (Index = 0; Index < Dhcp4CfgData->OptionCount; Index++) {\r
718 DhcpSb->UserOptionLen += Dhcp4CfgData->OptionList[Index]->Length + 2;\r
719 }\r
720\r
721 DhcpSb->ActiveChild = Instance;\r
722\r
723 if (DhcpSb->DhcpState == Dhcp4Stopped) {\r
724 DhcpSb->ClientAddr = EFI_NTOHL (Dhcp4CfgData->ClientAddress);\r
725\r
726 if (DhcpSb->ClientAddr != 0) {\r
727 DhcpSb->DhcpState = Dhcp4InitReboot;\r
728 } else {\r
729 DhcpSb->DhcpState = Dhcp4Init;\r
730 }\r
731 }\r
732\r
733 DhcpSb->ServiceState = DHCP_CONFIGED;\r
734 Status = EFI_SUCCESS;\r
735\r
736 } else if (DhcpSb->ActiveChild == Instance) {\r
737 Status = EFI_SUCCESS;\r
738 DhcpYieldControl (DhcpSb);\r
739 }\r
740\r
741ON_EXIT:\r
e48e37fc 742 gBS->RestoreTPL (OldTpl);\r
772db4bb 743 return Status;\r
744}\r
745\r
746\r
747/**\r
f9204641 748 Starts the DHCP configuration process.\r
749\r
750 The Start() function starts the DHCP configuration process. This function can\r
751 be called only when the EFI DHCPv4 Protocol driver is in the Dhcp4Init or\r
752 Dhcp4InitReboot state.\r
753 If the DHCP process completes successfully, the state of the EFI DHCPv4 Protocol\r
754 driver will be transferred through Dhcp4Selecting and Dhcp4Requesting to the\r
755 Dhcp4Bound state. The CompletionEvent will then be signaled if it is not NULL.\r
756 If the process aborts, either by the user or by some unexpected network error,\r
757 the state is restored to the Dhcp4Init state. The Start() function can be called\r
758 again to restart the process.\r
759 Refer to RFC 2131 for precise state transitions during this process. At the\r
760 time when each event occurs in this process, the callback function that was set\r
761 by EFI_DHCP4_PROTOCOL.Configure() will be called and the user can take this\r
762 opportunity to control the process.\r
763 \r
764 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.\r
765 @param CompletionEvent If not NULL, indicates the event that will be signaled when the\r
766 EFI DHCPv4 Protocol driver is transferred into the\r
767 Dhcp4Bound state or when the DHCP process is aborted.\r
768 EFI_DHCP4_PROTOCOL.GetModeData() can be called to\r
769 check the completion status. If NULL,\r
770 EFI_DHCP4_PROTOCOL.Start() will wait until the driver\r
771 is transferred into the Dhcp4Bound state or the process fails.\r
772\r
773 @retval EFI_SUCCESS The DHCP configuration process has started, or it has completed\r
774 when CompletionEvent is NULL.\r
775 @retval EFI_NOT_STARTED The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped\r
776 state. EFI_DHCP4_PROTOCOL. Configure() needs to be called.\r
777 @retval EFI_INVALID_PARAMETER This is NULL.\r
778 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.\r
779 @retval EFI_TIMEOUT The DHCP configuration process failed because no response was\r
780 received from the server within the specified timeout value.\r
781 @retval EFI_ABORTED The user aborted the DHCP process.\r
782 @retval EFI_ALREADY_STARTED Some other EFI DHCPv4 Protocol instance already started the\r
783 DHCP process.\r
784 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
772db4bb 785\r
786**/\r
772db4bb 787EFI_STATUS\r
788EFIAPI\r
789EfiDhcp4Start (\r
790 IN EFI_DHCP4_PROTOCOL *This,\r
791 IN EFI_EVENT CompletionEvent OPTIONAL\r
792 )\r
793{\r
794 DHCP_PROTOCOL *Instance;\r
795 DHCP_SERVICE *DhcpSb;\r
796 EFI_STATUS Status;\r
797 EFI_TPL OldTpl;\r
798\r
799 //\r
800 // First validate the parameters\r
801 //\r
802 if (This == NULL) {\r
803 return EFI_INVALID_PARAMETER;\r
804 }\r
805\r
806 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
807\r
808 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
809 return EFI_INVALID_PARAMETER;\r
810 }\r
811\r
e48e37fc 812 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 813 DhcpSb = Instance->Service;\r
814\r
815 if (DhcpSb->DhcpState == Dhcp4Stopped) {\r
816 Status = EFI_NOT_STARTED;\r
817 goto ON_ERROR;\r
818 }\r
819\r
820 if ((DhcpSb->DhcpState != Dhcp4Init) && (DhcpSb->DhcpState != Dhcp4InitReboot)) {\r
821 Status = EFI_ALREADY_STARTED;\r
822 goto ON_ERROR;\r
823 }\r
824\r
825 DhcpSb->IoStatus = EFI_ALREADY_STARTED;\r
826\r
827 if (EFI_ERROR (Status = DhcpInitRequest (DhcpSb))) {\r
828 goto ON_ERROR;\r
829 }\r
830\r
831 //\r
832 // Start/Restart the receiving.\r
833 //\r
834 Status = UdpIoRecvDatagram (DhcpSb->UdpIo, DhcpInput, DhcpSb, 0);\r
835\r
836 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
837 goto ON_ERROR;\r
838 }\r
839\r
840 Instance->CompletionEvent = CompletionEvent;\r
841\r
842 //\r
e48e37fc 843 // Restore the TPL now, don't call poll function at TPL_CALLBACK.\r
772db4bb 844 //\r
e48e37fc 845 gBS->RestoreTPL (OldTpl);\r
772db4bb 846\r
847 if (CompletionEvent == NULL) {\r
848 while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {\r
849 DhcpSb->UdpIo->Udp->Poll (DhcpSb->UdpIo->Udp);\r
850 }\r
851\r
852 return DhcpSb->IoStatus;\r
853 }\r
854\r
855 return EFI_SUCCESS;\r
856\r
857ON_ERROR:\r
e48e37fc 858 gBS->RestoreTPL (OldTpl);\r
772db4bb 859 return Status;\r
860}\r
861\r
862\r
863/**\r
f9204641 864 Extends the lease time by sending a request packet.\r
865 \r
866 The RenewRebind() function is used to manually extend the lease time when the\r
867 EFI DHCPv4 Protocol driver is in the Dhcp4Bound state and the lease time has\r
868 not expired yet. This function will send a request packet to the previously\r
869 found server (or to any server when RebindRequest is TRUE) and transfer the\r
870 state into the Dhcp4Renewing state (or Dhcp4Rebinding when RebindingRequest is\r
871 TRUE). When a response is received, the state is returned to Dhcp4Bound.\r
872 If no response is received before the try count is exceeded (the RequestTryCount\r
873 field that is specified in EFI_DHCP4_CONFIG_DATA) but before the lease time that\r
874 was issued by the previous server expires, the driver will return to the Dhcp4Bound\r
875 state and the previous configuration is restored. The outgoing and incoming packets\r
876 can be captured by the EFI_DHCP4_CALLBACK function.\r
877\r
878 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.\r
879 @param RebindRequest If TRUE, this function broadcasts the request packets and enters\r
880 the Dhcp4Rebinding state. Otherwise, it sends a unicast\r
881 request packet and enters the Dhcp4Renewing state.\r
882 @param CompletionEvent If not NULL, this event is signaled when the renew/rebind phase\r
883 completes or some error occurs.\r
884 EFI_DHCP4_PROTOCOL.GetModeData() can be called to\r
885 check the completion status. If NULL,\r
886 EFI_DHCP4_PROTOCOL.RenewRebind() will busy-wait\r
887 until the DHCP process finishes.\r
888\r
889 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the\r
890 Dhcp4Renewing state or is back to the Dhcp4Bound state.\r
891 @retval EFI_NOT_STARTED The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped\r
892 state. EFI_DHCP4_PROTOCOL.Configure() needs to\r
893 be called.\r
894 @retval EFI_INVALID_PARAMETER This is NULL.\r
895 @retval EFI_TIMEOUT There was no response from the server when the try count was\r
896 exceeded.\r
897 @retval EFI_ACCESS_DENIED The driver is not in the Dhcp4Bound state.\r
898 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
772db4bb 899\r
900**/\r
772db4bb 901EFI_STATUS\r
902EFIAPI\r
903EfiDhcp4RenewRebind (\r
904 IN EFI_DHCP4_PROTOCOL *This,\r
905 IN BOOLEAN RebindRequest,\r
906 IN EFI_EVENT CompletionEvent OPTIONAL\r
907 )\r
908{\r
909 DHCP_PROTOCOL *Instance;\r
910 DHCP_SERVICE *DhcpSb;\r
911 EFI_STATUS Status;\r
912 EFI_TPL OldTpl;\r
913\r
914 //\r
915 // First validate the parameters\r
916 //\r
917 if (This == NULL) {\r
918 return EFI_INVALID_PARAMETER;\r
919 }\r
920\r
921 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
922\r
923 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
924 return EFI_INVALID_PARAMETER;\r
925 }\r
926\r
e48e37fc 927 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 928 DhcpSb = Instance->Service;\r
929\r
930 if (DhcpSb->DhcpState == Dhcp4Stopped) {\r
931 Status = EFI_NOT_STARTED;\r
932 goto ON_ERROR;\r
933 }\r
934\r
935 if (DhcpSb->DhcpState != Dhcp4Bound) {\r
936 Status = EFI_ACCESS_DENIED;\r
937 goto ON_ERROR;\r
938 }\r
939\r
940 if (DHCP_IS_BOOTP (DhcpSb->Para)) {\r
941 return EFI_SUCCESS;\r
942 }\r
943\r
944 //\r
945 // Transit the states then send a extra DHCP request\r
946 //\r
947 if (!RebindRequest) {\r
948 DhcpSetState (DhcpSb, Dhcp4Renewing, FALSE);\r
949 } else {\r
950 DhcpSetState (DhcpSb, Dhcp4Rebinding, FALSE);\r
951 }\r
952\r
953 Status = DhcpSendMessage (\r
954 DhcpSb,\r
955 DhcpSb->Selected,\r
956 DhcpSb->Para,\r
957 DHCP_MSG_REQUEST,\r
67a58d0f 958 (UINT8 *) "Extra renew/rebind by the application"\r
772db4bb 959 );\r
960\r
961 if (EFI_ERROR (Status)) {\r
962 DhcpSetState (DhcpSb, Dhcp4Bound, FALSE);\r
963 goto ON_ERROR;\r
964 }\r
965\r
966 DhcpSb->ExtraRefresh = TRUE;\r
967 DhcpSb->IoStatus = EFI_ALREADY_STARTED;\r
968 Instance->RenewRebindEvent = CompletionEvent;\r
969\r
e48e37fc 970 gBS->RestoreTPL (OldTpl);\r
772db4bb 971\r
972 if (CompletionEvent == NULL) {\r
973 while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {\r
974 DhcpSb->UdpIo->Udp->Poll (DhcpSb->UdpIo->Udp);\r
975 }\r
976\r
977 return DhcpSb->IoStatus;\r
978 }\r
979\r
980 return EFI_SUCCESS;\r
981\r
982ON_ERROR:\r
e48e37fc 983 gBS->RestoreTPL (OldTpl);\r
772db4bb 984 return Status;\r
985}\r
986\r
987\r
988/**\r
f9204641 989 Releases the current address configuration.\r
990\r
991 The Release() function releases the current configured IP address by doing either\r
992 of the following:\r
993 * Sending a DHCPRELEASE packet when the EFI DHCPv4 Protocol driver is in the\r
994 Dhcp4Bound state\r
995 * Setting the previously assigned IP address that was provided with the\r
996 EFI_DHCP4_PROTOCOL.Configure() function to 0.0.0.0 when the driver is in\r
997 Dhcp4InitReboot state\r
998 After a successful call to this function, the EFI DHCPv4 Protocol driver returns\r
999 to the Dhcp4Init state and any subsequent incoming packets will be discarded silently.\r
772db4bb 1000\r
f9204641 1001 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.\r
772db4bb 1002\r
f9204641 1003 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Init phase.\r
1004 @retval EFI_INVALID_PARAMETER This is NULL.\r
1005 @retval EFI_ACCESS_DENIED The EFI DHCPv4 Protocol driver is not Dhcp4InitReboot state.\r
1006 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
772db4bb 1007\r
1008**/\r
772db4bb 1009EFI_STATUS\r
1010EFIAPI\r
1011EfiDhcp4Release (\r
1012 IN EFI_DHCP4_PROTOCOL *This\r
1013 )\r
1014{\r
1015 DHCP_PROTOCOL *Instance;\r
1016 DHCP_SERVICE *DhcpSb;\r
1017 EFI_STATUS Status;\r
1018 EFI_TPL OldTpl;\r
1019\r
1020 //\r
1021 // First validate the parameters\r
1022 //\r
1023 if (This == NULL) {\r
1024 return EFI_INVALID_PARAMETER;\r
1025 }\r
1026\r
1027 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
1028\r
1029 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
1030 return EFI_INVALID_PARAMETER;\r
1031 }\r
1032\r
1033 Status = EFI_SUCCESS;\r
e48e37fc 1034 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 1035 DhcpSb = Instance->Service;\r
1036\r
1037 if ((DhcpSb->DhcpState != Dhcp4InitReboot) && (DhcpSb->DhcpState != Dhcp4Bound)) {\r
1038 Status = EFI_ACCESS_DENIED;\r
1039 goto ON_EXIT;\r
1040 }\r
1041\r
1042 if (!DHCP_IS_BOOTP (DhcpSb->Para) && (DhcpSb->DhcpState == Dhcp4Bound)) {\r
1043 Status = DhcpSendMessage (\r
1044 DhcpSb,\r
1045 DhcpSb->Selected,\r
1046 DhcpSb->Para,\r
1047 DHCP_MSG_RELEASE,\r
1048 NULL\r
1049 );\r
1050\r
1051 if (EFI_ERROR (Status)) {\r
1052 Status = EFI_DEVICE_ERROR;\r
1053 goto ON_EXIT;\r
1054 }\r
1055 }\r
1056\r
1057 DhcpCleanLease (DhcpSb);\r
1058\r
1059ON_EXIT:\r
e48e37fc 1060 gBS->RestoreTPL (OldTpl);\r
772db4bb 1061 return Status;\r
1062}\r
1063\r
1064\r
1065/**\r
f9204641 1066 Stops the current address configuration.\r
1067 \r
1068 The Stop() function is used to stop the DHCP configuration process. After this\r
1069 function is called successfully, the EFI DHCPv4 Protocol driver is transferred\r
1070 into the Dhcp4Stopped state. EFI_DHCP4_PROTOCOL.Configure() needs to be called\r
1071 before DHCP configuration process can be started again. This function can be\r
1072 called when the EFI DHCPv4 Protocol driver is in any state.\r
772db4bb 1073\r
f9204641 1074 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.\r
772db4bb 1075\r
f9204641 1076 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Stopped phase.\r
1077 @retval EFI_INVALID_PARAMETER This is NULL.\r
772db4bb 1078\r
1079**/\r
772db4bb 1080EFI_STATUS\r
1081EFIAPI\r
1082EfiDhcp4Stop (\r
1083 IN EFI_DHCP4_PROTOCOL *This\r
1084 )\r
1085{\r
1086 DHCP_PROTOCOL *Instance;\r
1087 DHCP_SERVICE *DhcpSb;\r
1088 EFI_TPL OldTpl;\r
1089\r
1090 //\r
1091 // First validate the parameters\r
1092 //\r
1093 if (This == NULL) {\r
1094 return EFI_INVALID_PARAMETER;\r
1095 }\r
1096\r
1097 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
1098\r
1099 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
1100 return EFI_INVALID_PARAMETER;\r
1101 }\r
1102\r
e48e37fc 1103 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 1104 DhcpSb = Instance->Service;\r
1105\r
1106 DhcpCleanLease (DhcpSb);\r
1107\r
1108 DhcpSb->DhcpState = Dhcp4Stopped;\r
1109 DhcpSb->ServiceState = DHCP_UNCONFIGED;\r
1110\r
e48e37fc 1111 gBS->RestoreTPL (OldTpl);\r
772db4bb 1112 return EFI_SUCCESS;\r
1113}\r
1114\r
1115\r
1116/**\r
f9204641 1117 Builds a DHCP packet, given the options to be appended or deleted or replaced.\r
1118\r
1119 The Build() function is used to assemble a new packet from the original packet\r
1120 by replacing or deleting existing options or appending new options. This function\r
1121 does not change any state of the EFI DHCPv4 Protocol driver and can be used at\r
1122 any time.\r
1123\r
1124 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.\r
1125 @param SeedPacket Initial packet to be used as a base for building new packet.\r
1126 @param DeleteCount Number of opcodes in the DeleteList.\r
1127 @param DeleteList List of opcodes to be deleted from the seed packet.\r
1128 Ignored if DeleteCount is zero.\r
1129 @param AppendCount Number of entries in the OptionList.\r
1130 @param AppendList Pointer to a DHCP option list to be appended to SeedPacket.\r
1131 If SeedPacket also contains options in this list, they are\r
1132 replaced by new options (except pad option). Ignored if\r
1133 AppendCount is zero. Type EFI_DHCP4_PACKET_OPTION\r
1134 @param NewPacket Pointer to storage for the pointer to the new allocated packet.\r
1135 Use the EFI Boot Service FreePool() on the resulting pointer\r
1136 when done with the packet.\r
1137\r
1138 @retval EFI_SUCCESS The new packet was built.\r
1139 @retval EFI_OUT_OF_RESOURCES Storage for the new packet could not be allocated.\r
1140 @retval EFI_INVALID_PARAMETER Some parameter is NULL.\r
772db4bb 1141\r
1142**/\r
772db4bb 1143EFI_STATUS\r
1144EFIAPI\r
1145EfiDhcp4Build (\r
1146 IN EFI_DHCP4_PROTOCOL *This,\r
1147 IN EFI_DHCP4_PACKET *SeedPacket,\r
1148 IN UINT32 DeleteCount,\r
1149 IN UINT8 *DeleteList OPTIONAL,\r
1150 IN UINT32 AppendCount,\r
1151 IN EFI_DHCP4_PACKET_OPTION *AppendList[] OPTIONAL,\r
1152 OUT EFI_DHCP4_PACKET **NewPacket\r
1153 )\r
1154{\r
1155 //\r
1156 // First validate the parameters\r
1157 //\r
1158 if ((This == NULL) || (NewPacket == NULL)) {\r
1159 return EFI_INVALID_PARAMETER;\r
1160 }\r
1161\r
1162 if ((SeedPacket == NULL) || (SeedPacket->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||\r
1163 EFI_ERROR (DhcpValidateOptions (SeedPacket, NULL))) {\r
1164\r
1165 return EFI_INVALID_PARAMETER;\r
1166 }\r
1167\r
1168 if (((DeleteCount == 0) && (AppendCount == 0)) ||\r
1169 ((DeleteCount != 0) && (DeleteList == NULL)) ||\r
1170 ((AppendCount != 0) && (AppendList == NULL))) {\r
1171\r
1172 return EFI_INVALID_PARAMETER;\r
1173 }\r
1174\r
1175 return DhcpBuild (\r
1176 SeedPacket,\r
1177 DeleteCount,\r
1178 DeleteList,\r
1179 AppendCount,\r
1180 AppendList,\r
1181 NewPacket\r
1182 );\r
1183}\r
1184\r
f9204641 1185/**\r
1186 Callback by UdpIoCreatePort() when creating UdpIo for this Dhcp4 instance.\r
1187 \r
1188 @param UdpIo The UdpIo being created.\r
1189 @param Context Dhcp4 instance.\r
1190 \r
1191 @retval EFI_SUCCESS UdpIo is configured successfully.\r
1192 @retval other Other error occurs.\r
1193**/\r
c4a62a12 1194EFI_STATUS\r
1195Dhcp4InstanceConfigUdpIo (\r
1196 IN UDP_IO_PORT *UdpIo,\r
1197 IN VOID *Context\r
1198 )\r
1199{\r
1200 DHCP_PROTOCOL *Instance;\r
1201 DHCP_SERVICE *DhcpSb;\r
1202 EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token;\r
1203 EFI_UDP4_CONFIG_DATA UdpConfigData;\r
1204 IP4_ADDR Ip;\r
1205\r
1206 Instance = (DHCP_PROTOCOL *) Context;\r
1207 DhcpSb = Instance->Service;\r
1208 Token = Instance->Token;\r
1209\r
e48e37fc 1210 ZeroMem (&UdpConfigData, sizeof (EFI_UDP4_CONFIG_DATA));\r
c4a62a12 1211\r
1212 UdpConfigData.AcceptBroadcast = TRUE;\r
1213 UdpConfigData.AllowDuplicatePort = TRUE;\r
1214 UdpConfigData.TimeToLive = 64;\r
1215 UdpConfigData.DoNotFragment = TRUE;\r
1216\r
1217 Ip = HTONL (DhcpSb->ClientAddr);\r
e48e37fc 1218 CopyMem (&UdpConfigData.StationAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
c4a62a12 1219\r
1220 Ip = HTONL (DhcpSb->Netmask);\r
e48e37fc 1221 CopyMem (&UdpConfigData.SubnetMask, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
c4a62a12 1222\r
1223 if ((Token->ListenPointCount == 0) || (Token->ListenPoints[0].ListenPort == 0)) {\r
1224 UdpConfigData.StationPort = DHCP_CLIENT_PORT;\r
1225 } else {\r
1226 UdpConfigData.StationPort = Token->ListenPoints[0].ListenPort;\r
1227 }\r
1228\r
1229 return UdpIo->Udp->Configure (UdpIo->Udp, &UdpConfigData);\r
1230}\r
1231\r
f9204641 1232/**\r
1233 Create UdpIo for this Dhcp4 instance.\r
1234 \r
1235 @param Instance The Dhcp4 instance.\r
1236 \r
1237 @retval EFI_SUCCESS UdpIo is created successfully.\r
1238 @retval EFI_OUT_OF_RESOURCES Fails to create UdpIo because of limited\r
1239 resources or configuration failure.\r
1240**/\r
c4a62a12 1241EFI_STATUS\r
1242Dhcp4InstanceCreateUdpIo (\r
f9204641 1243 IN OUT DHCP_PROTOCOL *Instance\r
c4a62a12 1244 )\r
1245{\r
1246 DHCP_SERVICE *DhcpSb;\r
1247\r
1248 ASSERT (Instance->Token != NULL);\r
1249\r
1250 DhcpSb = Instance->Service;\r
1251 Instance->UdpIo = UdpIoCreatePort (DhcpSb->Controller, DhcpSb->Image, Dhcp4InstanceConfigUdpIo, Instance);\r
1252 if (Instance->UdpIo == NULL) {\r
1253 return EFI_OUT_OF_RESOURCES;\r
1254 } else {\r
1255 return EFI_SUCCESS;\r
1256 }\r
1257}\r
1258\r
f9204641 1259/**\r
1260 Callback of Dhcp packet. Does nothing.\r
1261 \r
1262 @param Arg The context.\r
1263 \r
1264 @return None.\r
1265**/\r
c4a62a12 1266VOID\r
1267DhcpDummyExtFree (\r
1268 IN VOID *Arg\r
1269 )\r
982a9eae 1270{\r
c4a62a12 1271}\r
1272\r
f9204641 1273/**\r
1274 Callback of UdpIoRecvDatagram() that handles a Dhcp4 packet.\r
1275 \r
1276 Only BOOTP responses will be handled that correspond to the Xid of the request\r
1277 sent out. The packet will be queued to the response queue.\r
1278 \r
1279 @param UdpPacket The Dhcp4 packet.\r
1280 @param Points Udp4 address pair.\r
1281 @param IoStatus Status of the input.\r
1282 @param Context Extra info for the input.\r
1283 \r
1284 @return None.\r
1285 \r
1286**/\r
c4a62a12 1287VOID\r
1288PxeDhcpInput (\r
1289 NET_BUF *UdpPacket,\r
1290 UDP_POINTS *Points,\r
1291 EFI_STATUS IoStatus,\r
1292 VOID *Context\r
1293 )\r
1294{\r
1295 DHCP_PROTOCOL *Instance;\r
1296 DHCP_SERVICE *DhcpSb;\r
1297 EFI_DHCP4_HEADER *Head;\r
1298 NET_BUF *Wrap;\r
1299 EFI_DHCP4_PACKET *Packet;\r
1300 EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token;\r
1301 UINT32 Len;\r
1302 EFI_STATUS Status;\r
1303\r
1304 Wrap = NULL;\r
1305 Instance = (DHCP_PROTOCOL *) Context;\r
1306 Token = Instance->Token;\r
1307 DhcpSb = Instance->Service;\r
1308\r
1309 //\r
f9204641 1310 // Don't restart receive if error occurs or DHCP is destroyed.\r
c4a62a12 1311 //\r
1312 if (EFI_ERROR (IoStatus)) {\r
1313 return ;\r
1314 }\r
1315\r
1316 ASSERT (UdpPacket != NULL);\r
982a9eae 1317\r
c4a62a12 1318 //\r
1319 // Validate the packet received\r
1320 //\r
1321 if (UdpPacket->TotalSize < sizeof (EFI_DHCP4_HEADER)) {\r
1322 goto RESTART;\r
1323 }\r
982a9eae 1324\r
c4a62a12 1325 //\r
1326 // Copy the DHCP message to a continuous memory block, make the buffer size\r
1327 // of the EFI_DHCP4_PACKET a multiple of 4-byte.\r
1328 //\r
1329 Len = NET_ROUNDUP (sizeof (EFI_DHCP4_PACKET) + UdpPacket->TotalSize - sizeof (EFI_DHCP4_HEADER), 4);\r
1330 Wrap = NetbufAlloc (Len);\r
1331\r
1332 if (Wrap == NULL) {\r
1333 goto RESTART;\r
1334 }\r
1335\r
1336 Packet = (EFI_DHCP4_PACKET *) NetbufAllocSpace (Wrap, Len, NET_BUF_TAIL);\r
1337 Packet->Size = Len;\r
1338 Head = &Packet->Dhcp4.Header;\r
1339 Packet->Length = NetbufCopy (UdpPacket, 0, UdpPacket->TotalSize, (UINT8 *) Head);\r
1340\r
1341 if (Packet->Length != UdpPacket->TotalSize) {\r
1342 goto RESTART;\r
1343 }\r
982a9eae 1344\r
c4a62a12 1345 //\r
1346 // Is this packet the answer to our packet?\r
1347 //\r
1348 if ((Head->OpCode != BOOTP_REPLY) ||\r
1349 (Head->Xid != Token->Packet->Dhcp4.Header.Xid) ||\r
982a9eae 1350 (CompareMem (DhcpSb->ClientAddressSendOut, Head->ClientHwAddr, Head->HwAddrLen) != 0)) {\r
c4a62a12 1351 goto RESTART;\r
1352 }\r
982a9eae 1353\r
c4a62a12 1354 //\r
1355 // Validate the options and retrieve the interested options\r
1356 //\r
1357 if ((Packet->Length > sizeof (EFI_DHCP4_HEADER) + sizeof (UINT32)) &&\r
1358 (Packet->Dhcp4.Magik == DHCP_OPTION_MAGIC) &&\r
1359 EFI_ERROR (DhcpValidateOptions (Packet, NULL))) {\r
1360\r
1361 goto RESTART;\r
1362 }\r
1363\r
1364 //\r
1365 // Keep this packet in the ResponseQueue.\r
1366 //\r
1367 NET_GET_REF (Wrap);\r
1368 NetbufQueAppend (&Instance->ResponseQueue, Wrap);\r
1369\r
1370RESTART:\r
1371\r
1372 NetbufFree (UdpPacket);\r
1373\r
1374 if (Wrap != NULL) {\r
1375 NetbufFree (Wrap);\r
1376 }\r
1377\r
1378 Status = UdpIoRecvDatagram (Instance->UdpIo, PxeDhcpInput, Instance, 0);\r
1379 if (EFI_ERROR (Status)) {\r
1380 PxeDhcpDone (Instance);\r
1381 }\r
1382}\r
1383\r
f9204641 1384/**\r
1385 Complete a Dhcp4 transaction and signal the upper layer.\r
1386 \r
1387 @param Instance Dhcp4 instance.\r
1388 \r
1389 @return None.\r
1390\r
1391**/\r
c4a62a12 1392VOID\r
1393PxeDhcpDone (\r
1394 IN DHCP_PROTOCOL *Instance\r
1395 )\r
1396{\r
1397 EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token;\r
1398\r
1399 Token = Instance->Token;\r
1400\r
1401 Token->ResponseCount = Instance->ResponseQueue.BufNum;\r
1402 if (Token->ResponseCount != 0) {\r
e48e37fc 1403 Token->ResponseList = (EFI_DHCP4_PACKET *) AllocatePool (Instance->ResponseQueue.BufSize);\r
c4a62a12 1404 if (Token->ResponseList == NULL) {\r
1405 Token->Status = EFI_OUT_OF_RESOURCES;\r
1406 goto SIGNAL_USER;\r
1407 }\r
1408\r
1409 //\r
f9204641 1410 // Copy the received DHCP responses.\r
c4a62a12 1411 //\r
1412 NetbufQueCopy (&Instance->ResponseQueue, 0, Instance->ResponseQueue.BufSize, (UINT8 *) Token->ResponseList);\r
1413 Token->Status = EFI_SUCCESS;\r
1414 } else {\r
1415 Token->ResponseList = NULL;\r
1416 Token->Status = EFI_TIMEOUT;\r
1417 }\r
1418\r
1419SIGNAL_USER:\r
1420 //\r
f9204641 1421 // Clean up the resources dedicated for this transmit receive transaction.\r
c4a62a12 1422 //\r
1423 NetbufQueFlush (&Instance->ResponseQueue);\r
1424 UdpIoCleanPort (Instance->UdpIo);\r
1425 UdpIoFreePort (Instance->UdpIo);\r
1426 Instance->UdpIo = NULL;\r
1427 Instance->Token = NULL;\r
1428\r
1429 if (Token->CompletionEvent != NULL) {\r
1430 gBS->SignalEvent (Token->CompletionEvent);\r
982a9eae 1431 }\r
c4a62a12 1432}\r
1433\r
772db4bb 1434\r
1435/**\r
ba39e316 1436 Transmits a DHCP formatted packet and optionally waits for responses.\r
f9204641 1437 \r
1438 The TransmitReceive() function is used to transmit a DHCP packet and optionally\r
1439 wait for the response from servers. This function does not change the state of\r
1440 the EFI DHCPv4 Protocol driver and thus can be used at any time.\r
ba39e316 1441\r
1442 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.\r
1443 @param Token Pointer to the EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN structure.\r
1444\r
1445 @retval EFI_SUCCESS The packet was successfully queued for transmission.\r
1446 @retval EFI_INVALID_PARAMETER Some parameter is NULL.\r
1447 @retval EFI_NOT_READY The previous call to this function has not finished yet. Try to call\r
1448 this function after collection process completes.\r
1449 @retval EFI_NO_MAPPING The default station address is not available yet.\r
1450 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.\r
1451 @retval Others Some other unexpected error occurred.\r
772db4bb 1452\r
1453**/\r
772db4bb 1454EFI_STATUS\r
1455EFIAPI\r
1456EfiDhcp4TransmitReceive (\r
1457 IN EFI_DHCP4_PROTOCOL *This,\r
1458 IN EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token\r
1459 )\r
1460{\r
c4a62a12 1461 DHCP_PROTOCOL *Instance;\r
1462 EFI_TPL OldTpl;\r
1463 EFI_STATUS Status;\r
1464 NET_FRAGMENT Frag;\r
1465 NET_BUF *Wrap;\r
1466 UDP_POINTS EndPoint;\r
1467 IP4_ADDR Ip;\r
1468 DHCP_SERVICE *DhcpSb;\r
1469 IP4_ADDR Gateway;\r
1470 IP4_ADDR SubnetMask;\r
1471\r
1472 if ((This == NULL) || (Token == NULL) || (Token->Packet == NULL)) {\r
1473 return EFI_INVALID_PARAMETER;\r
1474 }\r
1475\r
1476 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
1477 DhcpSb = Instance->Service;\r
1478\r
1479 if (Instance->Token != NULL) {\r
1480 //\r
1481 // The previous call to TransmitReceive is not finished.\r
1482 //\r
1483 return EFI_NOT_READY;\r
1484 }\r
1485\r
f9204641 1486 if ((Token->Packet->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||\r
1487 (NTOHL (Token->Packet->Dhcp4.Header.Xid) == Instance->Service->Xid) ||\r
1488 (Token->TimeoutValue == 0) ||\r
1489 ((Token->ListenPointCount != 0) && (Token->ListenPoints == NULL)) ||\r
1490 EFI_ERROR (DhcpValidateOptions (Token->Packet, NULL)) ||\r
1491 EFI_IP4_EQUAL (&Token->RemoteAddress, &mZeroIp4Addr)\r
1492 ) {\r
c4a62a12 1493 //\r
f9204641 1494 // The DHCP packet isn't well-formed, the Transaction ID is already used,\r
1495 // the timeout value is zero, the ListenPoint is invalid, or the\r
1496 // RemoteAddress is zero.\r
c4a62a12 1497 //\r
1498 return EFI_INVALID_PARAMETER;\r
1499 }\r
1500\r
1501 if (DhcpSb->ClientAddr == 0) {\r
1502\r
1503 return EFI_NO_MAPPING;\r
1504 }\r
1505\r
e48e37fc 1506 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
c4a62a12 1507\r
1508 //\r
1509 // Save the token and the timeout value.\r
1510 //\r
1511 Instance->Token = Token;\r
1512 Instance->Timeout = Token->TimeoutValue;\r
1513\r
1514 //\r
1515 // Create a UDP IO for this transmit receive transaction.\r
1516 //\r
1517 Status = Dhcp4InstanceCreateUdpIo (Instance);\r
1518 if (EFI_ERROR (Status)) {\r
1519 goto ON_ERROR;\r
1520 }\r
1521\r
982a9eae 1522 //\r
1523 // Save the Client Address is sent out\r
1524 //\r
f9204641 1525 CopyMem (\r
1526 &DhcpSb->ClientAddressSendOut[0],\r
1527 &Token->Packet->Dhcp4.Header.ClientHwAddr[0],\r
1528 Token->Packet->Dhcp4.Header.HwAddrLen\r
1529 );\r
982a9eae 1530\r
772db4bb 1531 //\r
c4a62a12 1532 // Wrap the DHCP packet into a net buffer.\r
772db4bb 1533 //\r
c4a62a12 1534 Frag.Bulk = (UINT8 *) &Token->Packet->Dhcp4;\r
1535 Frag.Len = Token->Packet->Length;\r
1536 Wrap = NetbufFromExt (&Frag, 1, 0, 0, DhcpDummyExtFree, NULL);\r
1537 if (Wrap == NULL) {\r
1538 Status = EFI_OUT_OF_RESOURCES;\r
1539 goto ON_ERROR;\r
1540 }\r
1541\r
1542 //\r
1543 // Set the local address and local port.\r
1544 //\r
1545 EndPoint.LocalAddr = 0;\r
1546 EndPoint.LocalPort = 0;\r
1547\r
1548 //\r
1549 // Set the destination address and destination port.\r
1550 //\r
e48e37fc 1551 CopyMem (&Ip, &Token->RemoteAddress, sizeof (EFI_IPv4_ADDRESS));\r
c4a62a12 1552 EndPoint.RemoteAddr = NTOHL (Ip);\r
1553\r
1554 if (Token->RemotePort == 0) {\r
1555 EndPoint.RemotePort = DHCP_SERVER_PORT;\r
1556 } else {\r
1557 EndPoint.RemotePort = Token->RemotePort;\r
1558 }\r
1559\r
1560 //\r
1561 // Get the gateway.\r
1562 //\r
1563 SubnetMask = DhcpSb->Netmask;\r
1564 Gateway = 0;\r
1565 if (!IP4_NET_EQUAL (DhcpSb->ClientAddr, EndPoint.RemoteAddr, SubnetMask)) {\r
e48e37fc 1566 CopyMem (&Gateway, &Token->GatewayAddress, sizeof (EFI_IPv4_ADDRESS));\r
c4a62a12 1567 Gateway = NTOHL (Gateway);\r
1568 }\r
1569\r
1570 //\r
1571 // Transmit the DHCP packet.\r
1572 //\r
1573 Status = UdpIoSendDatagram (Instance->UdpIo, Wrap, &EndPoint, Gateway, DhcpOnPacketSent, NULL);\r
1574 if (EFI_ERROR (Status)) {\r
1575 NetbufFree (Wrap);\r
1576 goto ON_ERROR;\r
1577 }\r
1578\r
1579 //\r
1580 // Start to receive the DHCP response.\r
1581 //\r
1582 Status = UdpIoRecvDatagram (Instance->UdpIo, PxeDhcpInput, Instance, 0);\r
1583 if (EFI_ERROR (Status)) {\r
1584 goto ON_ERROR;\r
1585 }\r
1586\r
1587ON_ERROR:\r
1588\r
1589 if (EFI_ERROR (Status) && (Instance->UdpIo != NULL)) {\r
1590 UdpIoCleanPort (Instance->UdpIo);\r
1591 UdpIoFreePort (Instance->UdpIo);\r
1592 Instance->UdpIo = NULL;\r
1593 Instance->Token = NULL;\r
1594 }\r
1595\r
e48e37fc 1596 gBS->RestoreTPL (OldTpl);\r
c4a62a12 1597\r
1598 if (!EFI_ERROR (Status) && (Token->CompletionEvent == NULL)) {\r
1599 //\r
1600 // Keep polling until timeout if no error happens and the CompletionEvent\r
1601 // is NULL.\r
1602 //\r
1603 while (Instance->Timeout != 0) {\r
1604 Instance->UdpIo->Udp->Poll (Instance->UdpIo->Udp);\r
1605 }\r
1606 }\r
1607\r
1608 return Status;\r
772db4bb 1609}\r
1610\r
1611\r
1612/**\r
1613 Callback function for DhcpIterateOptions. This callback sets the\r
1614 EFI_DHCP4_PACKET_OPTION array in the DHCP_PARSE_CONTEXT to point\r
1615 the individual DHCP option in the packet.\r
1616\r
1617 @param Tag The DHCP option type\r
f9204641 1618 @param Len Length of the DHCP option data\r
772db4bb 1619 @param Data The DHCP option data\r
1620 @param Context The context, to pass several parameters in.\r
1621\r
1622 @retval EFI_SUCCESS It always returns EFI_SUCCESS\r
1623\r
1624**/\r
772db4bb 1625EFI_STATUS\r
1626Dhcp4ParseCheckOption (\r
1627 IN UINT8 Tag,\r
1628 IN UINT8 Len,\r
1629 IN UINT8 *Data,\r
1630 IN VOID *Context\r
1631 )\r
1632{\r
1633 DHCP_PARSE_CONTEXT *Parse;\r
1634\r
1635 Parse = (DHCP_PARSE_CONTEXT *) Context;\r
1636 Parse->Index++;\r
1637\r
36ee91ca 1638 if (Parse->Index <= Parse->OptionCount) {\r
772db4bb 1639 //\r
1640 // Use _CR to get the memory position of EFI_DHCP4_PACKET_OPTION for\r
1641 // the EFI_DHCP4_PACKET_OPTION->Data because DhcpIterateOptions only\r
1642 // pass in the point to option data.\r
1643 //\r
1644 Parse->Option[Parse->Index - 1] = _CR (Data, EFI_DHCP4_PACKET_OPTION, Data);\r
1645 }\r
1646\r
1647 return EFI_SUCCESS;\r
1648}\r
1649\r
1650\r
1651/**\r
f9204641 1652 Parses the packed DHCP option data.\r
1653 \r
1654 The Parse() function is used to retrieve the option list from a DHCP packet.\r
1655 If *OptionCount isn’t zero, and there is enough space for all the DHCP options\r
1656 in the Packet, each element of PacketOptionList is set to point to somewhere in\r
1657 the Packet->Dhcp4.Option where a new DHCP option begins. If RFC3396 is supported,\r
1658 the caller should reassemble the parsed DHCP options to get the finial result.\r
1659 If *OptionCount is zero or there isn’t enough space for all of them, the number\r
1660 of DHCP options in the Packet is returned in OptionCount.\r
1661\r
1662 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.\r
1663 @param Packet Pointer to packet to be parsed.\r
1664 @param OptionCount On input, the number of entries in the PacketOptionList.\r
1665 On output, the number of entries that were written into the\r
1666 PacketOptionList.\r
1667 @param PacketOptionList List of packet option entries to be filled in. End option or pad\r
1668 options are not included.\r
1669\r
1670 @retval EFI_SUCCESS The packet was successfully parsed.\r
1671 @retval EFI_INVALID_PARAMETER Some parameter is NULL.\r
1672 @retval EFI_BUFFER_TOO_SMALL One or more of the following conditions is TRUE:\r
1673 1) *OptionCount is smaller than the number of options that\r
1674 were found in the Packet.\r
1675 2) PacketOptionList is NULL.\r
772db4bb 1676\r
1677**/\r
772db4bb 1678EFI_STATUS\r
1679EFIAPI\r
1680EfiDhcp4Parse (\r
1681 IN EFI_DHCP4_PROTOCOL *This,\r
1682 IN EFI_DHCP4_PACKET *Packet,\r
1683 IN OUT UINT32 *OptionCount,\r
1684 OUT EFI_DHCP4_PACKET_OPTION *PacketOptionList[] OPTIONAL\r
1685 )\r
1686{\r
1687 DHCP_PARSE_CONTEXT Context;\r
1688 EFI_STATUS Status;\r
1689\r
1690 //\r
1691 // First validate the parameters\r
1692 //\r
1693 if ((This == NULL) || (Packet == NULL) || (OptionCount == NULL)) {\r
1694 return EFI_INVALID_PARAMETER;\r
1695 }\r
1696\r
1697 if ((Packet->Size < Packet->Length + 2 * sizeof (UINT32)) ||\r
1698 (Packet->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||\r
1699 EFI_ERROR (DhcpValidateOptions (Packet, NULL))) {\r
1700\r
1701 return EFI_INVALID_PARAMETER;\r
1702 }\r
1703\r
1704 if ((*OptionCount != 0) && (PacketOptionList == NULL)) {\r
1705 return EFI_BUFFER_TOO_SMALL;\r
1706 }\r
1707\r
e48e37fc 1708 ZeroMem (PacketOptionList, *OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));\r
772db4bb 1709\r
1710 Context.Option = PacketOptionList;\r
1711 Context.OptionCount = *OptionCount;\r
1712 Context.Index = 0;\r
1713\r
1714 Status = DhcpIterateOptions (Packet, Dhcp4ParseCheckOption, &Context);\r
1715\r
1716 if (EFI_ERROR (Status)) {\r
1717 return Status;\r
1718 }\r
1719\r
1720 *OptionCount = Context.Index;\r
1721\r
1722 if (Context.Index > Context.OptionCount) {\r
1723 return EFI_BUFFER_TOO_SMALL;\r
1724 }\r
1725\r
1726 return EFI_SUCCESS;\r
1727}\r