2 Functions implementation related with DHCPv4 for HTTP boot driver.
4 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available under
6 the terms and conditions of the BSD License that accompanies this distribution.
7 The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "HttpBootDxe.h"
18 // This is a map from the interested DHCP4 option tags' index to the tag value.
20 UINT8 mInterestedDhcp4Tags
[HTTP_BOOT_DHCP4_TAG_INDEX_MAX
] = {
21 HTTP_BOOT_DHCP4_TAG_BOOTFILE_LEN
,
22 HTTP_BOOT_DHCP4_TAG_OVERLOAD
,
23 HTTP_BOOT_DHCP4_TAG_MSG_TYPE
,
24 HTTP_BOOT_DHCP4_TAG_SERVER_ID
,
25 HTTP_BOOT_DHCP4_TAG_CLASS_ID
,
26 HTTP_BOOT_DHCP4_TAG_BOOTFILE
,
27 HTTP_BOOT_DHCP4_TAG_DNS_SERVER
31 // There are 4 times retries with the value of 4, 8, 16 and 32, refers to UEFI 2.5 spec.
33 UINT32 mHttpDhcpTimeout
[4] = {4, 8, 16, 32};
36 Build the options buffer for the DHCPv4 request packet.
38 @param[in] Private Pointer to HTTP boot driver private data.
39 @param[out] OptList Pointer to the option pointer array.
40 @param[in] Buffer Pointer to the buffer to contain the option list.
42 @return Index The count of the built-in options.
46 HttpBootBuildDhcp4Options (
47 IN HTTP_BOOT_PRIVATE_DATA
*Private
,
48 OUT EFI_DHCP4_PACKET_OPTION
**OptList
,
52 HTTP_BOOT_DHCP4_OPTION_ENTRY OptEnt
;
57 OptList
[0] = (EFI_DHCP4_PACKET_OPTION
*) Buffer
;
60 // Append parameter request list option.
62 OptList
[Index
]->OpCode
= HTTP_BOOT_DHCP4_TAG_PARA_LIST
;
63 OptList
[Index
]->Length
= 27;
64 OptEnt
.Para
= (HTTP_BOOT_DHCP4_OPTION_PARA
*) OptList
[Index
]->Data
;
65 OptEnt
.Para
->ParaList
[0] = HTTP_BOOT_DHCP4_TAG_NETMASK
;
66 OptEnt
.Para
->ParaList
[1] = HTTP_BOOT_DHCP4_TAG_TIME_OFFSET
;
67 OptEnt
.Para
->ParaList
[2] = HTTP_BOOT_DHCP4_TAG_ROUTER
;
68 OptEnt
.Para
->ParaList
[3] = HTTP_BOOT_DHCP4_TAG_TIME_SERVER
;
69 OptEnt
.Para
->ParaList
[4] = HTTP_BOOT_DHCP4_TAG_NAME_SERVER
;
70 OptEnt
.Para
->ParaList
[5] = HTTP_BOOT_DHCP4_TAG_DNS_SERVER
;
71 OptEnt
.Para
->ParaList
[6] = HTTP_BOOT_DHCP4_TAG_HOSTNAME
;
72 OptEnt
.Para
->ParaList
[7] = HTTP_BOOT_DHCP4_TAG_BOOTFILE_LEN
;
73 OptEnt
.Para
->ParaList
[8] = HTTP_BOOT_DHCP4_TAG_DOMAINNAME
;
74 OptEnt
.Para
->ParaList
[9] = HTTP_BOOT_DHCP4_TAG_ROOTPATH
;
75 OptEnt
.Para
->ParaList
[10] = HTTP_BOOT_DHCP4_TAG_EXTEND_PATH
;
76 OptEnt
.Para
->ParaList
[11] = HTTP_BOOT_DHCP4_TAG_EMTU
;
77 OptEnt
.Para
->ParaList
[12] = HTTP_BOOT_DHCP4_TAG_TTL
;
78 OptEnt
.Para
->ParaList
[13] = HTTP_BOOT_DHCP4_TAG_BROADCAST
;
79 OptEnt
.Para
->ParaList
[14] = HTTP_BOOT_DHCP4_TAG_NIS_DOMAIN
;
80 OptEnt
.Para
->ParaList
[15] = HTTP_BOOT_DHCP4_TAG_NIS_SERVER
;
81 OptEnt
.Para
->ParaList
[16] = HTTP_BOOT_DHCP4_TAG_NTP_SERVER
;
82 OptEnt
.Para
->ParaList
[17] = HTTP_BOOT_DHCP4_TAG_VENDOR
;
83 OptEnt
.Para
->ParaList
[18] = HTTP_BOOT_DHCP4_TAG_REQUEST_IP
;
84 OptEnt
.Para
->ParaList
[19] = HTTP_BOOT_DHCP4_TAG_LEASE
;
85 OptEnt
.Para
->ParaList
[20] = HTTP_BOOT_DHCP4_TAG_SERVER_ID
;
86 OptEnt
.Para
->ParaList
[21] = HTTP_BOOT_DHCP4_TAG_T1
;
87 OptEnt
.Para
->ParaList
[22] = HTTP_BOOT_DHCP4_TAG_T2
;
88 OptEnt
.Para
->ParaList
[23] = HTTP_BOOT_DHCP4_TAG_CLASS_ID
;
89 OptEnt
.Para
->ParaList
[25] = HTTP_BOOT_DHCP4_TAG_BOOTFILE
;
90 OptEnt
.Para
->ParaList
[26] = HTTP_BOOT_DHCP4_TAG_UUID
;
92 OptList
[Index
] = GET_NEXT_DHCP_OPTION (OptList
[Index
- 1]);
95 // Append UUID/Guid-based client identifier option
97 OptList
[Index
]->OpCode
= HTTP_BOOT_DHCP4_TAG_UUID
;
98 OptList
[Index
]->Length
= (UINT8
) sizeof (HTTP_BOOT_DHCP4_OPTION_UUID
);
99 OptEnt
.Uuid
= (HTTP_BOOT_DHCP4_OPTION_UUID
*) OptList
[Index
]->Data
;
100 OptEnt
.Uuid
->Type
= 0;
101 if (EFI_ERROR (NetLibGetSystemGuid ((EFI_GUID
*) OptEnt
.Uuid
->Guid
))) {
103 // Zero the Guid to indicate NOT programable if failed to get system Guid.
105 ZeroMem (OptEnt
.Uuid
->Guid
, sizeof (EFI_GUID
));
108 OptList
[Index
] = GET_NEXT_DHCP_OPTION (OptList
[Index
- 1]);
111 // Append client network device interface option
113 OptList
[Index
]->OpCode
= HTTP_BOOT_DHCP4_TAG_UNDI
;
114 OptList
[Index
]->Length
= (UINT8
) sizeof (HTTP_BOOT_DHCP4_OPTION_UNDI
);
115 OptEnt
.Undi
= (HTTP_BOOT_DHCP4_OPTION_UNDI
*) OptList
[Index
]->Data
;
117 if (Private
->Nii
!= NULL
) {
118 OptEnt
.Undi
->Type
= Private
->Nii
->Type
;
119 OptEnt
.Undi
->MajorVer
= Private
->Nii
->MajorVer
;
120 OptEnt
.Undi
->MinorVer
= Private
->Nii
->MinorVer
;
122 OptEnt
.Undi
->Type
= DEFAULT_UNDI_TYPE
;
123 OptEnt
.Undi
->MajorVer
= DEFAULT_UNDI_MAJOR
;
124 OptEnt
.Undi
->MinorVer
= DEFAULT_UNDI_MINOR
;
128 OptList
[Index
] = GET_NEXT_DHCP_OPTION (OptList
[Index
- 1]);
131 // Append client system architecture option
133 OptList
[Index
]->OpCode
= HTTP_BOOT_DHCP4_TAG_ARCH
;
134 OptList
[Index
]->Length
= (UINT8
) sizeof (HTTP_BOOT_DHCP4_OPTION_ARCH
);
135 OptEnt
.Arch
= (HTTP_BOOT_DHCP4_OPTION_ARCH
*) OptList
[Index
]->Data
;
136 Value
= HTONS (EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE
);
137 CopyMem (&OptEnt
.Arch
->Type
, &Value
, sizeof (UINT16
));
139 OptList
[Index
] = GET_NEXT_DHCP_OPTION (OptList
[Index
- 1]);
142 // Append vendor class identify option
144 OptList
[Index
]->OpCode
= HTTP_BOOT_DHCP4_TAG_CLASS_ID
;
145 OptList
[Index
]->Length
= (UINT8
) sizeof (HTTP_BOOT_DHCP4_OPTION_CLID
);
146 OptEnt
.Clid
= (HTTP_BOOT_DHCP4_OPTION_CLID
*) OptList
[Index
]->Data
;
149 DEFAULT_CLASS_ID_DATA
,
150 sizeof (HTTP_BOOT_DHCP4_OPTION_CLID
)
152 HttpBootUintnToAscDecWithFormat (
153 EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE
,
154 OptEnt
.Clid
->ArchitectureType
,
155 sizeof (OptEnt
.Clid
->ArchitectureType
)
158 if (Private
->Nii
!= NULL
) {
159 CopyMem (OptEnt
.Clid
->InterfaceName
, Private
->Nii
->StringId
, sizeof (OptEnt
.Clid
->InterfaceName
));
160 HttpBootUintnToAscDecWithFormat (Private
->Nii
->MajorVer
, OptEnt
.Clid
->UndiMajor
, sizeof (OptEnt
.Clid
->UndiMajor
));
161 HttpBootUintnToAscDecWithFormat (Private
->Nii
->MinorVer
, OptEnt
.Clid
->UndiMinor
, sizeof (OptEnt
.Clid
->UndiMinor
));
170 Parse a certain dhcp4 option by OptTag in Buffer, and return with start pointer.
172 @param[in] Buffer Pointer to the option buffer.
173 @param[in] Length Length of the option buffer.
174 @param[in] OptTag Tag of the required option.
176 @retval NULL Failed to find the required option.
177 @retval Others The position of the required option.
180 EFI_DHCP4_PACKET_OPTION
*
181 HttpBootParseDhcp4Options (
187 EFI_DHCP4_PACKET_OPTION
*Option
;
190 Option
= (EFI_DHCP4_PACKET_OPTION
*) Buffer
;
193 while (Offset
< Length
&& Option
->OpCode
!= HTTP_BOOT_DHCP4_TAG_EOP
) {
195 if (Option
->OpCode
== OptTag
) {
197 // Found the required option.
203 // Skip the current option to the next.
205 if (Option
->OpCode
== HTTP_BOOT_DHCP4_TAG_PAD
) {
208 Offset
+= Option
->Length
+ 2;
211 Option
= (EFI_DHCP4_PACKET_OPTION
*) (Buffer
+ Offset
);
218 Cache the DHCPv4 packet.
220 @param[in] Dst Pointer to the cache buffer for DHCPv4 packet.
221 @param[in] Src Pointer to the DHCPv4 packet to be cached.
225 HttpBootCacheDhcp4Packet (
226 IN EFI_DHCP4_PACKET
*Dst
,
227 IN EFI_DHCP4_PACKET
*Src
230 ASSERT (Dst
->Size
>= Src
->Length
);
232 CopyMem (&Dst
->Dhcp4
, &Src
->Dhcp4
, Src
->Length
);
233 Dst
->Length
= Src
->Length
;
237 Parse the cached DHCPv4 packet, including all the options.
239 @param[in] Cache4 Pointer to cached DHCPv4 packet.
241 @retval EFI_SUCCESS Parsed the DHCPv4 packet successfully.
242 @retval EFI_DEVICE_ERROR Failed to parse an invalid packet.
246 HttpBootParseDhcp4Packet (
247 IN HTTP_BOOT_DHCP4_PACKET_CACHE
*Cache4
250 EFI_DHCP4_PACKET
*Offer
;
251 EFI_DHCP4_PACKET_OPTION
**Options
;
253 EFI_DHCP4_PACKET_OPTION
*Option
;
254 BOOLEAN IsProxyOffer
;
257 BOOLEAN IpExpressedUri
;
260 HTTP_BOOT_OFFER_TYPE OfferType
;
261 EFI_IPv4_ADDRESS IpAddr
;
264 IpExpressedUri
= FALSE
;
265 IsProxyOffer
= FALSE
;
268 ZeroMem (Cache4
->OptList
, sizeof (Cache4
->OptList
));
270 Offer
= &Cache4
->Packet
.Offer
;
271 Options
= Cache4
->OptList
;
274 // Parse DHCPv4 options in this offer, and store the pointers.
275 // First, try to parse DHCPv4 options from the DHCP optional parameters field.
277 for (Index
= 0; Index
< HTTP_BOOT_DHCP4_TAG_INDEX_MAX
; Index
++) {
278 Options
[Index
] = HttpBootParseDhcp4Options (
280 GET_OPTION_BUFFER_LEN (Offer
),
281 mInterestedDhcp4Tags
[Index
]
285 // Second, Check if bootfilename and serverhostname is overloaded to carry DHCP options refers to rfc-2132.
286 // If yes, try to parse options from the BootFileName field, then ServerName field.
288 Option
= Options
[HTTP_BOOT_DHCP4_TAG_INDEX_OVERLOAD
];
289 if (Option
!= NULL
) {
290 if ((Option
->Data
[0] & HTTP_BOOT_DHCP4_OVERLOAD_FILE
) != 0) {
291 for (Index
= 0; Index
< HTTP_BOOT_DHCP4_TAG_INDEX_MAX
; Index
++) {
292 if (Options
[Index
] == NULL
) {
293 Options
[Index
] = HttpBootParseDhcp4Options (
294 (UINT8
*) Offer
->Dhcp4
.Header
.BootFileName
,
295 sizeof (Offer
->Dhcp4
.Header
.BootFileName
),
296 mInterestedDhcp4Tags
[Index
]
301 if ((Option
->Data
[0] & HTTP_BOOT_DHCP4_OVERLOAD_SERVER_NAME
) != 0) {
302 for (Index
= 0; Index
< HTTP_BOOT_DHCP4_TAG_INDEX_MAX
; Index
++) {
303 if (Options
[Index
] == NULL
) {
304 Options
[Index
] = HttpBootParseDhcp4Options (
305 (UINT8
*) Offer
->Dhcp4
.Header
.ServerName
,
306 sizeof (Offer
->Dhcp4
.Header
.ServerName
),
307 mInterestedDhcp4Tags
[Index
]
315 // The offer with "yiaddr" is a proxy offer.
317 if (Offer
->Dhcp4
.Header
.YourAddr
.Addr
[0] == 0) {
322 // The offer with "HTTPClient" is a Http offer.
324 Option
= Options
[HTTP_BOOT_DHCP4_TAG_INDEX_CLASS_ID
];
325 if ((Option
!= NULL
) && (Option
->Length
>= 9) &&
326 (CompareMem (Option
->Data
, DEFAULT_CLASS_ID_DATA
, 9) == 0)) {
331 // The offer with Domain Server is a DNS offer.
333 Option
= Options
[HTTP_BOOT_DHCP4_TAG_INDEX_DNS_SERVER
];
334 if (Option
!= NULL
) {
339 // Parse boot file name:
340 // Boot URI information is provided thru 'file' field in DHCP Header or option 67.
341 // According to RFC 2132, boot file name should be read from DHCP option 67 (bootfile name) if present.
342 // Otherwise, read from boot file field in DHCP header.
344 if (Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
] != NULL
) {
346 // RFC 2132, Section 9.5 does not strictly state Bootfile name (option 67) is null
347 // terminated string. So force to append null terminated character at the end of string.
349 Ptr8
= (UINT8
*)&Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
]->Data
[0];
350 Ptr8
+= Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
]->Length
;
351 if (*(Ptr8
- 1) != '\0') {
354 } else if (Offer
->Dhcp4
.Header
.BootFileName
[0] != 0) {
356 // If the bootfile is not present and bootfilename is present in DHCPv4 packet, just parse it.
357 // Do not count dhcp option header here, or else will destroy the serverhostname.
359 Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
] = (EFI_DHCP4_PACKET_OPTION
*)
360 (&Offer
->Dhcp4
.Header
.BootFileName
[0] -
361 OFFSET_OF (EFI_DHCP4_PACKET_OPTION
, Data
[0]));
365 // Http offer must have a boot URI.
367 if (IsHttpOffer
&& Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
] == NULL
) {
368 return EFI_DEVICE_ERROR
;
372 // Try to retrieve the IP of HTTP server from URI.
375 Status
= HttpParseUrl (
376 (CHAR8
*) Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
]->Data
,
377 (UINT32
) AsciiStrLen ((CHAR8
*) Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
]->Data
),
381 if (EFI_ERROR (Status
)) {
382 return EFI_DEVICE_ERROR
;
385 Status
= HttpUrlGetIp4 (
386 (CHAR8
*) Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
]->Data
,
390 IpExpressedUri
= !EFI_ERROR (Status
);
394 // Determine offer type of the DHCPv4 packet.
397 if (IpExpressedUri
) {
398 OfferType
= IsProxyOffer
? HttpOfferTypeProxyIpUri
: HttpOfferTypeDhcpIpUri
;
401 OfferType
= IsDnsOffer
? HttpOfferTypeDhcpNameUriDns
: HttpOfferTypeDhcpNameUri
;
403 OfferType
= HttpOfferTypeProxyNameUri
;
409 OfferType
= IsDnsOffer
? HttpOfferTypeDhcpDns
: HttpOfferTypeDhcpOnly
;
411 return EFI_DEVICE_ERROR
;
415 Cache4
->OfferType
= OfferType
;
420 Cache all the received DHCPv4 offers, and set OfferIndex and OfferCount.
422 @param[in] Private Pointer to HTTP boot driver private data.
423 @param[in] RcvdOffer Pointer to the received offer packet.
427 HttpBootCacheDhcp4Offer (
428 IN HTTP_BOOT_PRIVATE_DATA
*Private
,
429 IN EFI_DHCP4_PACKET
*RcvdOffer
432 HTTP_BOOT_DHCP4_PACKET_CACHE
*Cache4
;
433 EFI_DHCP4_PACKET
*Offer
;
434 HTTP_BOOT_OFFER_TYPE OfferType
;
436 ASSERT (Private
->OfferNum
< HTTP_BOOT_OFFER_MAX_NUM
);
437 Cache4
= &Private
->OfferBuffer
[Private
->OfferNum
].Dhcp4
;
438 Offer
= &Cache4
->Packet
.Offer
;
441 // Cache the content of DHCPv4 packet firstly.
443 HttpBootCacheDhcp4Packet (Offer
, RcvdOffer
);
446 // Validate the DHCPv4 packet, and parse the options and offer type.
448 if (EFI_ERROR (HttpBootParseDhcp4Packet (Cache4
))) {
453 // Determine whether cache the current offer by type, and record OfferIndex and OfferCount.
455 OfferType
= Cache4
->OfferType
;
456 ASSERT (OfferType
< HttpOfferTypeMax
);
457 ASSERT (Private
->OfferCount
[OfferType
] < HTTP_BOOT_OFFER_MAX_NUM
);
458 Private
->OfferIndex
[OfferType
][Private
->OfferCount
[OfferType
]] = Private
->OfferNum
;
459 Private
->OfferCount
[OfferType
]++;
464 Select an DHCPv4 or DHCP6 offer, and record SelectIndex and SelectProxyType.
466 @param[in] Private Pointer to HTTP boot driver private data.
470 HttpBootSelectDhcpOffer (
471 IN HTTP_BOOT_PRIVATE_DATA
*Private
474 Private
->SelectIndex
= 0;
475 Private
->SelectProxyType
= HttpOfferTypeMax
;
478 // Priority1: HttpOfferTypeDhcpIpUri
479 // Priority2: HttpOfferTypeDhcpNameUriDns
480 // Priority3: HttpOfferTypeDhcpOnly + HttpOfferTypeProxyIpUri
481 // Priority4: HttpOfferTypeDhcpDns + HttpOfferTypeProxyIpUri
482 // Priority5: HttpOfferTypeDhcpDns + HttpOfferTypeProxyNameUri
483 // Priority6: HttpOfferTypeDhcpDns + HttpOfferTypeDhcpNameUri
485 if (Private
->OfferCount
[HttpOfferTypeDhcpIpUri
] > 0) {
487 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpIpUri
][0] + 1;
489 } else if (Private
->OfferCount
[HttpOfferTypeDhcpNameUriDns
] > 0) {
491 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpNameUriDns
][0] + 1;
493 } else if (Private
->OfferCount
[HttpOfferTypeDhcpOnly
] > 0 &&
494 Private
->OfferCount
[HttpOfferTypeProxyIpUri
] > 0) {
496 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpOnly
][0] + 1;
497 Private
->SelectProxyType
= HttpOfferTypeProxyIpUri
;
499 } else if (Private
->OfferCount
[HttpOfferTypeDhcpDns
] > 0 &&
500 Private
->OfferCount
[HttpOfferTypeProxyIpUri
] > 0) {
502 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpDns
][0] + 1;
503 Private
->SelectProxyType
= HttpOfferTypeProxyIpUri
;
505 } else if (Private
->OfferCount
[HttpOfferTypeDhcpDns
] > 0 &&
506 Private
->OfferCount
[HttpOfferTypeProxyNameUri
] > 0) {
508 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpDns
][0] + 1;
509 Private
->SelectProxyType
= HttpOfferTypeProxyNameUri
;
511 } else if (Private
->OfferCount
[HttpOfferTypeDhcpDns
] > 0 &&
512 Private
->OfferCount
[HttpOfferTypeDhcpNameUri
] > 0) {
514 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpDns
][0] + 1;
515 Private
->SelectProxyType
= HttpOfferTypeDhcpNameUri
;
521 EFI_DHCP4_CALLBACK is provided by the consumer of the EFI DHCPv4 Protocol driver
522 to intercept events that occurred in the configuration process.
524 @param[in] This Pointer to the EFI DHCPv4 Protocol.
525 @param[in] Context Pointer to the context set by EFI_DHCP4_PROTOCOL.Configure().
526 @param[in] CurrentState The current operational state of the EFI DHCPv4 Protocol driver.
527 @param[in] Dhcp4Event The event that occurs in the current state, which usually means a
529 @param[in] Packet The DHCPv4 packet that is going to be sent or already received.
530 @param[out] NewPacket The packet that is used to replace the above Packet.
532 @retval EFI_SUCCESS Tells the EFI DHCPv4 Protocol driver to continue the DHCP process.
533 @retval EFI_NOT_READY Only used in the Dhcp4Selecting state. The EFI DHCPv4 Protocol
534 driver will continue to wait for more DHCPOFFER packets until the
535 retry timeout expires.
536 @retval EFI_ABORTED Tells the EFI DHCPv4 Protocol driver to abort the current process
537 and return to the Dhcp4Init or Dhcp4InitReboot state.
542 HttpBootDhcp4CallBack (
543 IN EFI_DHCP4_PROTOCOL
*This
,
545 IN EFI_DHCP4_STATE CurrentState
,
546 IN EFI_DHCP4_EVENT Dhcp4Event
,
547 IN EFI_DHCP4_PACKET
*Packet OPTIONAL
,
548 OUT EFI_DHCP4_PACKET
**NewPacket OPTIONAL
551 HTTP_BOOT_PRIVATE_DATA
*Private
;
552 EFI_DHCP4_PACKET_OPTION
*MaxMsgSize
;
556 if ((Dhcp4Event
!= Dhcp4RcvdOffer
) && (Dhcp4Event
!= Dhcp4SelectOffer
)) {
560 Private
= (HTTP_BOOT_PRIVATE_DATA
*) Context
;
563 // Override the Maximum DHCP Message Size.
565 MaxMsgSize
= HttpBootParseDhcp4Options (
566 Packet
->Dhcp4
.Option
,
567 GET_OPTION_BUFFER_LEN (Packet
),
568 HTTP_BOOT_DHCP4_TAG_MAXMSG
570 if (MaxMsgSize
!= NULL
) {
571 Value
= HTONS (HTTP_BOOT_DHCP4_PACKET_MAX_SIZE
);
572 CopyMem (MaxMsgSize
->Data
, &Value
, sizeof (Value
));
575 Status
= EFI_SUCCESS
;
576 switch (Dhcp4Event
) {
578 Status
= EFI_NOT_READY
;
579 if (Private
->OfferNum
< HTTP_BOOT_OFFER_MAX_NUM
) {
581 // Cache the DHCPv4 offers to OfferBuffer[] for select later, and record
582 // the OfferIndex and OfferCount.
584 HttpBootCacheDhcp4Offer (Private
, Packet
);
588 case Dhcp4SelectOffer
:
590 // Select offer according to the priority in UEFI spec, and record the SelectIndex
591 // and SelectProxyType.
593 HttpBootSelectDhcpOffer (Private
);
595 if (Private
->SelectIndex
== 0) {
596 Status
= EFI_ABORTED
;
598 *NewPacket
= &Private
->OfferBuffer
[Private
->SelectIndex
- 1].Dhcp4
.Packet
.Offer
;
610 This function will register the IPv4 gateway address to the network device.
612 @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.
614 @retval EFI_SUCCESS The new IP configuration has been configured successfully.
615 @retval Others Failed to configure the address.
619 HttpBootRegisterIp4Gateway (
620 IN HTTP_BOOT_PRIVATE_DATA
*Private
624 EFI_IP4_CONFIG2_PROTOCOL
*Ip4Config2
;
626 ASSERT (!Private
->UsingIpv6
);
628 Ip4Config2
= Private
->Ip4Config2
;
631 // Configure the gateway if valid.
633 if (!EFI_IP4_EQUAL (&Private
->GatewayIp
, &mZeroIp4Addr
)) {
634 Status
= Ip4Config2
->SetData (
636 Ip4Config2DataTypeGateway
,
637 sizeof (EFI_IPv4_ADDRESS
),
640 if (EFI_ERROR (Status
)) {
649 This function will register the default DNS addresses to the network device.
651 @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.
652 @param[in] DataLength Size of the buffer pointed to by DnsServerData in bytes.
653 @param[in] DnsServerData Point a list of DNS server address in an array
654 of EFI_IPv4_ADDRESS instances.
656 @retval EFI_SUCCESS The DNS configuration has been configured successfully.
657 @retval Others Failed to configure the address.
661 HttpBootRegisterIp4Dns (
662 IN HTTP_BOOT_PRIVATE_DATA
*Private
,
664 IN VOID
*DnsServerData
667 EFI_IP4_CONFIG2_PROTOCOL
*Ip4Config2
;
669 ASSERT (!Private
->UsingIpv6
);
671 Ip4Config2
= Private
->Ip4Config2
;
673 return Ip4Config2
->SetData (
675 Ip4Config2DataTypeDnsServer
,
683 This function will switch the IP4 configuration policy to Static.
685 @param[in] Private Pointer to HTTP boot driver private data.
687 @retval EFI_SUCCESS The policy is already configured to static.
688 @retval Others Other error as indicated..
692 HttpBootSetIp4Policy (
693 IN HTTP_BOOT_PRIVATE_DATA
*Private
696 EFI_IP4_CONFIG2_POLICY Policy
;
698 EFI_IP4_CONFIG2_PROTOCOL
*Ip4Config2
;
701 Ip4Config2
= Private
->Ip4Config2
;
703 DataSize
= sizeof (EFI_IP4_CONFIG2_POLICY
);
704 Status
= Ip4Config2
->GetData (
706 Ip4Config2DataTypePolicy
,
710 if (EFI_ERROR (Status
)) {
714 if (Policy
!= Ip4Config2PolicyStatic
) {
715 Policy
= Ip4Config2PolicyStatic
;
716 Status
= Ip4Config2
->SetData (
718 Ip4Config2DataTypePolicy
,
719 sizeof (EFI_IP4_CONFIG2_POLICY
),
722 if (EFI_ERROR (Status
)) {
731 Start the D.O.R.A DHCPv4 process to acquire the IPv4 address and other Http boot information.
733 @param[in] Private Pointer to HTTP boot driver private data.
735 @retval EFI_SUCCESS The D.O.R.A process successfully finished.
736 @retval Others Failed to finish the D.O.R.A process.
741 IN HTTP_BOOT_PRIVATE_DATA
*Private
744 EFI_DHCP4_PROTOCOL
*Dhcp4
;
746 EFI_DHCP4_PACKET_OPTION
*OptList
[HTTP_BOOT_DHCP4_OPTION_MAX_NUM
];
747 UINT8 Buffer
[HTTP_BOOT_DHCP4_OPTION_MAX_SIZE
];
748 EFI_DHCP4_CONFIG_DATA Config
;
750 EFI_DHCP4_MODE_DATA Mode
;
752 Dhcp4
= Private
->Dhcp4
;
753 ASSERT (Dhcp4
!= NULL
);
755 Status
= HttpBootSetIp4Policy (Private
);
756 if (EFI_ERROR (Status
)) {
761 // Build option list for the request packet.
763 OptCount
= HttpBootBuildDhcp4Options (Private
, OptList
, Buffer
);
764 ASSERT (OptCount
> 0);
766 ZeroMem (&Config
, sizeof(Config
));
767 Config
.OptionCount
= OptCount
;
768 Config
.OptionList
= OptList
;
769 Config
.Dhcp4Callback
= HttpBootDhcp4CallBack
;
770 Config
.CallbackContext
= Private
;
771 Config
.DiscoverTryCount
= HTTP_BOOT_DHCP_RETRIES
;
772 Config
.DiscoverTimeout
= mHttpDhcpTimeout
;
775 // Configure the DHCPv4 instance for HTTP boot.
777 Status
= Dhcp4
->Configure (Dhcp4
, &Config
);
778 if (EFI_ERROR (Status
)) {
783 // Initialize the record fields for DHCPv4 offer in private data.
785 Private
->OfferNum
= 0;
786 ZeroMem (Private
->OfferCount
, sizeof (Private
->OfferCount
));
787 ZeroMem (Private
->OfferIndex
, sizeof (Private
->OfferIndex
));
790 // Start DHCPv4 D.O.R.A. process to acquire IPv4 address.
792 Status
= Dhcp4
->Start (Dhcp4
, NULL
);
793 if (EFI_ERROR (Status
)) {
798 // Get the acquired IPv4 address and store them.
800 Status
= Dhcp4
->GetModeData (Dhcp4
, &Mode
);
801 if (EFI_ERROR (Status
)) {
805 ASSERT (Mode
.State
== Dhcp4Bound
);
806 CopyMem (&Private
->StationIp
, &Mode
.ClientAddress
, sizeof (EFI_IPv4_ADDRESS
));
807 CopyMem (&Private
->SubnetMask
, &Mode
.SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
808 CopyMem (&Private
->GatewayIp
, &Mode
.RouterAddress
, sizeof (EFI_IPv4_ADDRESS
));
810 Status
= HttpBootRegisterIp4Gateway (Private
);
811 if (EFI_ERROR (Status
)) {
815 AsciiPrint ("\n Station IP address is ");
816 HttpBootShowIp4Addr (&Private
->StationIp
.v4
);
820 if (EFI_ERROR (Status
)) {
822 Dhcp4
->Configure (Dhcp4
, NULL
);
824 ZeroMem (&Config
, sizeof (EFI_DHCP4_CONFIG_DATA
));
825 Dhcp4
->Configure (Dhcp4
, &Config
);