2 Functions implementation related with DHCPv4 for HTTP boot driver.
4 Copyright (c) 2015 - 2016, 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 DHCP4_TAG_BOOTFILE_LEN
,
25 DHCP4_TAG_VENDOR_CLASS_ID
,
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
= 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] = DHCP4_TAG_NETMASK
;
66 OptEnt
.Para
->ParaList
[1] = DHCP4_TAG_TIME_OFFSET
;
67 OptEnt
.Para
->ParaList
[2] = DHCP4_TAG_ROUTER
;
68 OptEnt
.Para
->ParaList
[3] = DHCP4_TAG_TIME_SERVER
;
69 OptEnt
.Para
->ParaList
[4] = DHCP4_TAG_NAME_SERVER
;
70 OptEnt
.Para
->ParaList
[5] = DHCP4_TAG_DNS_SERVER
;
71 OptEnt
.Para
->ParaList
[6] = DHCP4_TAG_HOSTNAME
;
72 OptEnt
.Para
->ParaList
[7] = DHCP4_TAG_BOOTFILE_LEN
;
73 OptEnt
.Para
->ParaList
[8] = DHCP4_TAG_DOMAINNAME
;
74 OptEnt
.Para
->ParaList
[9] = DHCP4_TAG_ROOTPATH
;
75 OptEnt
.Para
->ParaList
[10] = DHCP4_TAG_EXTEND_PATH
;
76 OptEnt
.Para
->ParaList
[11] = DHCP4_TAG_EMTU
;
77 OptEnt
.Para
->ParaList
[12] = DHCP4_TAG_TTL
;
78 OptEnt
.Para
->ParaList
[13] = DHCP4_TAG_BROADCAST
;
79 OptEnt
.Para
->ParaList
[14] = DHCP4_TAG_NIS_DOMAIN
;
80 OptEnt
.Para
->ParaList
[15] = DHCP4_TAG_NIS_SERVER
;
81 OptEnt
.Para
->ParaList
[16] = DHCP4_TAG_NTP_SERVER
;
82 OptEnt
.Para
->ParaList
[17] = DHCP4_TAG_VENDOR
;
83 OptEnt
.Para
->ParaList
[18] = DHCP4_TAG_REQUEST_IP
;
84 OptEnt
.Para
->ParaList
[19] = DHCP4_TAG_LEASE
;
85 OptEnt
.Para
->ParaList
[20] = DHCP4_TAG_SERVER_ID
;
86 OptEnt
.Para
->ParaList
[21] = DHCP4_TAG_T1
;
87 OptEnt
.Para
->ParaList
[22] = DHCP4_TAG_T2
;
88 OptEnt
.Para
->ParaList
[23] = DHCP4_TAG_VENDOR_CLASS_ID
;
89 OptEnt
.Para
->ParaList
[25] = DHCP4_TAG_BOOTFILE
;
90 OptEnt
.Para
->ParaList
[26] = 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
= 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
= 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
= 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
= DHCP4_TAG_VENDOR_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
!= 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
== 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
;
262 BOOLEAN FileFieldOverloaded
;
265 IpExpressedUri
= FALSE
;
266 IsProxyOffer
= FALSE
;
268 FileFieldOverloaded
= FALSE
;
270 ZeroMem (Cache4
->OptList
, sizeof (Cache4
->OptList
));
272 Offer
= &Cache4
->Packet
.Offer
;
273 Options
= Cache4
->OptList
;
276 // Parse DHCPv4 options in this offer, and store the pointers.
277 // First, try to parse DHCPv4 options from the DHCP optional parameters field.
279 for (Index
= 0; Index
< HTTP_BOOT_DHCP4_TAG_INDEX_MAX
; Index
++) {
280 Options
[Index
] = HttpBootParseDhcp4Options (
282 GET_OPTION_BUFFER_LEN (Offer
),
283 mInterestedDhcp4Tags
[Index
]
287 // Second, Check if bootfilename and serverhostname is overloaded to carry DHCP options refers to rfc-2132.
288 // If yes, try to parse options from the BootFileName field, then ServerName field.
290 Option
= Options
[HTTP_BOOT_DHCP4_TAG_INDEX_OVERLOAD
];
291 if (Option
!= NULL
) {
292 if ((Option
->Data
[0] & HTTP_BOOT_DHCP4_OVERLOAD_FILE
) != 0) {
293 FileFieldOverloaded
= TRUE
;
294 for (Index
= 0; Index
< HTTP_BOOT_DHCP4_TAG_INDEX_MAX
; Index
++) {
295 if (Options
[Index
] == NULL
) {
296 Options
[Index
] = HttpBootParseDhcp4Options (
297 (UINT8
*) Offer
->Dhcp4
.Header
.BootFileName
,
298 sizeof (Offer
->Dhcp4
.Header
.BootFileName
),
299 mInterestedDhcp4Tags
[Index
]
304 if ((Option
->Data
[0] & HTTP_BOOT_DHCP4_OVERLOAD_SERVER_NAME
) != 0) {
305 for (Index
= 0; Index
< HTTP_BOOT_DHCP4_TAG_INDEX_MAX
; Index
++) {
306 if (Options
[Index
] == NULL
) {
307 Options
[Index
] = HttpBootParseDhcp4Options (
308 (UINT8
*) Offer
->Dhcp4
.Header
.ServerName
,
309 sizeof (Offer
->Dhcp4
.Header
.ServerName
),
310 mInterestedDhcp4Tags
[Index
]
318 // The offer with "yiaddr" is a proxy offer.
320 if (Offer
->Dhcp4
.Header
.YourAddr
.Addr
[0] == 0) {
325 // The offer with "HTTPClient" is a Http offer.
327 Option
= Options
[HTTP_BOOT_DHCP4_TAG_INDEX_CLASS_ID
];
328 if ((Option
!= NULL
) && (Option
->Length
>= 9) &&
329 (CompareMem (Option
->Data
, DEFAULT_CLASS_ID_DATA
, 9) == 0)) {
334 // The offer with Domain Server is a DNS offer.
336 Option
= Options
[HTTP_BOOT_DHCP4_TAG_INDEX_DNS_SERVER
];
337 if (Option
!= NULL
) {
342 // Parse boot file name:
343 // Boot URI information is provided thru 'file' field in DHCP Header or option 67.
344 // According to RFC 2132, boot file name should be read from DHCP option 67 (bootfile name) if present.
345 // Otherwise, read from boot file field in DHCP header.
347 if (Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
] != NULL
) {
349 // RFC 2132, Section 9.5 does not strictly state Bootfile name (option 67) is null
350 // terminated string. So force to append null terminated character at the end of string.
352 Ptr8
= (UINT8
*)&Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
]->Data
[0];
353 Ptr8
+= Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
]->Length
;
354 if (*(Ptr8
- 1) != '\0') {
357 } else if (!FileFieldOverloaded
&& Offer
->Dhcp4
.Header
.BootFileName
[0] != 0) {
359 // If the bootfile is not present and bootfilename is present in DHCPv4 packet, just parse it.
360 // Do not count dhcp option header here, or else will destroy the serverhostname.
362 Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
] = (EFI_DHCP4_PACKET_OPTION
*)
363 (&Offer
->Dhcp4
.Header
.BootFileName
[0] -
364 OFFSET_OF (EFI_DHCP4_PACKET_OPTION
, Data
[0]));
368 // Http offer must have a boot URI.
370 if (IsHttpOffer
&& Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
] == NULL
) {
371 return EFI_DEVICE_ERROR
;
375 // Try to retrieve the IP of HTTP server from URI.
378 Status
= HttpParseUrl (
379 (CHAR8
*) Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
]->Data
,
380 (UINT32
) AsciiStrLen ((CHAR8
*) Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
]->Data
),
384 if (EFI_ERROR (Status
)) {
385 return EFI_DEVICE_ERROR
;
388 Status
= HttpUrlGetIp4 (
389 (CHAR8
*) Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
]->Data
,
393 IpExpressedUri
= !EFI_ERROR (Status
);
397 // Determine offer type of the DHCPv4 packet.
400 if (IpExpressedUri
) {
402 OfferType
= HttpOfferTypeProxyIpUri
;
404 OfferType
= IsDnsOffer
? HttpOfferTypeDhcpIpUriDns
: HttpOfferTypeDhcpIpUri
;
408 OfferType
= IsDnsOffer
? HttpOfferTypeDhcpNameUriDns
: HttpOfferTypeDhcpNameUri
;
410 OfferType
= HttpOfferTypeProxyNameUri
;
416 OfferType
= IsDnsOffer
? HttpOfferTypeDhcpDns
: HttpOfferTypeDhcpOnly
;
418 return EFI_DEVICE_ERROR
;
422 Cache4
->OfferType
= OfferType
;
427 Cache all the received DHCPv4 offers, and set OfferIndex and OfferCount.
429 @param[in] Private Pointer to HTTP boot driver private data.
430 @param[in] RcvdOffer Pointer to the received offer packet.
434 HttpBootCacheDhcp4Offer (
435 IN HTTP_BOOT_PRIVATE_DATA
*Private
,
436 IN EFI_DHCP4_PACKET
*RcvdOffer
439 HTTP_BOOT_DHCP4_PACKET_CACHE
*Cache4
;
440 EFI_DHCP4_PACKET
*Offer
;
441 HTTP_BOOT_OFFER_TYPE OfferType
;
443 ASSERT (Private
->OfferNum
< HTTP_BOOT_OFFER_MAX_NUM
);
444 Cache4
= &Private
->OfferBuffer
[Private
->OfferNum
].Dhcp4
;
445 Offer
= &Cache4
->Packet
.Offer
;
448 // Cache the content of DHCPv4 packet firstly.
450 HttpBootCacheDhcp4Packet (Offer
, RcvdOffer
);
453 // Validate the DHCPv4 packet, and parse the options and offer type.
455 if (EFI_ERROR (HttpBootParseDhcp4Packet (Cache4
))) {
460 // Determine whether cache the current offer by type, and record OfferIndex and OfferCount.
462 OfferType
= Cache4
->OfferType
;
463 ASSERT (OfferType
< HttpOfferTypeMax
);
464 ASSERT (Private
->OfferCount
[OfferType
] < HTTP_BOOT_OFFER_MAX_NUM
);
465 Private
->OfferIndex
[OfferType
][Private
->OfferCount
[OfferType
]] = Private
->OfferNum
;
466 Private
->OfferCount
[OfferType
]++;
471 Select an DHCPv4 or DHCP6 offer, and record SelectIndex and SelectProxyType.
473 @param[in] Private Pointer to HTTP boot driver private data.
477 HttpBootSelectDhcpOffer (
478 IN HTTP_BOOT_PRIVATE_DATA
*Private
481 Private
->SelectIndex
= 0;
482 Private
->SelectProxyType
= HttpOfferTypeMax
;
484 if (Private
->FilePathUri
!= NULL
) {
486 // We are in home environment, the URI is already specified.
487 // Just need to choose a DHCP offer.
488 // The offer with DNS server address takes priority here.
490 if (Private
->OfferCount
[HttpOfferTypeDhcpDns
] > 0) {
492 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpDns
][0] + 1;
494 } else if (Private
->OfferCount
[HttpOfferTypeDhcpIpUriDns
] > 0) {
496 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpIpUriDns
][0] + 1;
498 } else if (Private
->OfferCount
[HttpOfferTypeDhcpNameUriDns
] > 0) {
500 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpNameUriDns
][0] + 1;
502 } else if (Private
->OfferCount
[HttpOfferTypeDhcpOnly
] > 0) {
504 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpOnly
][0] + 1;
506 } else if (Private
->OfferCount
[HttpOfferTypeDhcpIpUri
] > 0) {
508 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpIpUri
][0] + 1;
513 // We are in corporate environment.
515 // Priority1: HttpOfferTypeDhcpIpUri or HttpOfferTypeDhcpIpUriDns
516 // Priority2: HttpOfferTypeDhcpNameUriDns
517 // Priority3: HttpOfferTypeDhcpOnly + HttpOfferTypeProxyIpUri
518 // Priority4: HttpOfferTypeDhcpDns + HttpOfferTypeProxyIpUri
519 // Priority5: HttpOfferTypeDhcpDns + HttpOfferTypeProxyNameUri
520 // Priority6: HttpOfferTypeDhcpDns + HttpOfferTypeDhcpNameUri
522 if (Private
->OfferCount
[HttpOfferTypeDhcpIpUri
] > 0) {
524 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpIpUri
][0] + 1;
526 } else if (Private
->OfferCount
[HttpOfferTypeDhcpIpUriDns
] > 0) {
528 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpIpUriDns
][0] + 1;
530 }else if (Private
->OfferCount
[HttpOfferTypeDhcpNameUriDns
] > 0) {
532 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpNameUriDns
][0] + 1;
534 } else if (Private
->OfferCount
[HttpOfferTypeDhcpOnly
] > 0 &&
535 Private
->OfferCount
[HttpOfferTypeProxyIpUri
] > 0) {
537 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpOnly
][0] + 1;
538 Private
->SelectProxyType
= HttpOfferTypeProxyIpUri
;
540 } else if (Private
->OfferCount
[HttpOfferTypeDhcpDns
] > 0 &&
541 Private
->OfferCount
[HttpOfferTypeProxyIpUri
] > 0) {
543 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpDns
][0] + 1;
544 Private
->SelectProxyType
= HttpOfferTypeProxyIpUri
;
546 } else if (Private
->OfferCount
[HttpOfferTypeDhcpDns
] > 0 &&
547 Private
->OfferCount
[HttpOfferTypeProxyNameUri
] > 0) {
549 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpDns
][0] + 1;
550 Private
->SelectProxyType
= HttpOfferTypeProxyNameUri
;
552 } else if (Private
->OfferCount
[HttpOfferTypeDhcpDns
] > 0 &&
553 Private
->OfferCount
[HttpOfferTypeDhcpNameUri
] > 0) {
555 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpDns
][0] + 1;
556 Private
->SelectProxyType
= HttpOfferTypeDhcpNameUri
;
563 EFI_DHCP4_CALLBACK is provided by the consumer of the EFI DHCPv4 Protocol driver
564 to intercept events that occurred in the configuration process.
566 @param[in] This Pointer to the EFI DHCPv4 Protocol.
567 @param[in] Context Pointer to the context set by EFI_DHCP4_PROTOCOL.Configure().
568 @param[in] CurrentState The current operational state of the EFI DHCPv4 Protocol driver.
569 @param[in] Dhcp4Event The event that occurs in the current state, which usually means a
571 @param[in] Packet The DHCPv4 packet that is going to be sent or already received.
572 @param[out] NewPacket The packet that is used to replace the above Packet.
574 @retval EFI_SUCCESS Tells the EFI DHCPv4 Protocol driver to continue the DHCP process.
575 @retval EFI_NOT_READY Only used in the Dhcp4Selecting state. The EFI DHCPv4 Protocol
576 driver will continue to wait for more DHCPOFFER packets until the
577 retry timeout expires.
578 @retval EFI_ABORTED Tells the EFI DHCPv4 Protocol driver to abort the current process
579 and return to the Dhcp4Init or Dhcp4InitReboot state.
584 HttpBootDhcp4CallBack (
585 IN EFI_DHCP4_PROTOCOL
*This
,
587 IN EFI_DHCP4_STATE CurrentState
,
588 IN EFI_DHCP4_EVENT Dhcp4Event
,
589 IN EFI_DHCP4_PACKET
*Packet OPTIONAL
,
590 OUT EFI_DHCP4_PACKET
**NewPacket OPTIONAL
593 HTTP_BOOT_PRIVATE_DATA
*Private
;
594 EFI_DHCP4_PACKET_OPTION
*MaxMsgSize
;
598 if ((Dhcp4Event
!= Dhcp4RcvdOffer
) && (Dhcp4Event
!= Dhcp4SelectOffer
)) {
602 Private
= (HTTP_BOOT_PRIVATE_DATA
*) Context
;
605 // Override the Maximum DHCP Message Size.
607 MaxMsgSize
= HttpBootParseDhcp4Options (
608 Packet
->Dhcp4
.Option
,
609 GET_OPTION_BUFFER_LEN (Packet
),
612 if (MaxMsgSize
!= NULL
) {
613 Value
= HTONS (HTTP_BOOT_DHCP4_PACKET_MAX_SIZE
);
614 CopyMem (MaxMsgSize
->Data
, &Value
, sizeof (Value
));
617 Status
= EFI_SUCCESS
;
618 switch (Dhcp4Event
) {
620 Status
= EFI_NOT_READY
;
621 if (Private
->OfferNum
< HTTP_BOOT_OFFER_MAX_NUM
) {
623 // Cache the DHCPv4 offers to OfferBuffer[] for select later, and record
624 // the OfferIndex and OfferCount.
626 HttpBootCacheDhcp4Offer (Private
, Packet
);
630 case Dhcp4SelectOffer
:
632 // Select offer according to the priority in UEFI spec, and record the SelectIndex
633 // and SelectProxyType.
635 HttpBootSelectDhcpOffer (Private
);
637 if (Private
->SelectIndex
== 0) {
638 Status
= EFI_ABORTED
;
640 *NewPacket
= &Private
->OfferBuffer
[Private
->SelectIndex
- 1].Dhcp4
.Packet
.Offer
;
652 This function will register the IPv4 gateway address to the network device.
654 @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.
656 @retval EFI_SUCCESS The new IP configuration has been configured successfully.
657 @retval Others Failed to configure the address.
661 HttpBootRegisterIp4Gateway (
662 IN HTTP_BOOT_PRIVATE_DATA
*Private
666 EFI_IP4_CONFIG2_PROTOCOL
*Ip4Config2
;
668 ASSERT (!Private
->UsingIpv6
);
670 Ip4Config2
= Private
->Ip4Config2
;
673 // Configure the gateway if valid.
675 if (!EFI_IP4_EQUAL (&Private
->GatewayIp
, &mZeroIp4Addr
)) {
676 Status
= Ip4Config2
->SetData (
678 Ip4Config2DataTypeGateway
,
679 sizeof (EFI_IPv4_ADDRESS
),
682 if (EFI_ERROR (Status
)) {
691 This function will register the default DNS addresses to the network device.
693 @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.
694 @param[in] DataLength Size of the buffer pointed to by DnsServerData in bytes.
695 @param[in] DnsServerData Point a list of DNS server address in an array
696 of EFI_IPv4_ADDRESS instances.
698 @retval EFI_SUCCESS The DNS configuration has been configured successfully.
699 @retval Others Failed to configure the address.
703 HttpBootRegisterIp4Dns (
704 IN HTTP_BOOT_PRIVATE_DATA
*Private
,
706 IN VOID
*DnsServerData
709 EFI_IP4_CONFIG2_PROTOCOL
*Ip4Config2
;
711 ASSERT (!Private
->UsingIpv6
);
713 Ip4Config2
= Private
->Ip4Config2
;
715 return Ip4Config2
->SetData (
717 Ip4Config2DataTypeDnsServer
,
725 This function will switch the IP4 configuration policy to Static.
727 @param[in] Private Pointer to HTTP boot driver private data.
729 @retval EFI_SUCCESS The policy is already configured to static.
730 @retval Others Other error as indicated..
734 HttpBootSetIp4Policy (
735 IN HTTP_BOOT_PRIVATE_DATA
*Private
738 EFI_IP4_CONFIG2_POLICY Policy
;
740 EFI_IP4_CONFIG2_PROTOCOL
*Ip4Config2
;
743 Ip4Config2
= Private
->Ip4Config2
;
745 DataSize
= sizeof (EFI_IP4_CONFIG2_POLICY
);
746 Status
= Ip4Config2
->GetData (
748 Ip4Config2DataTypePolicy
,
752 if (EFI_ERROR (Status
)) {
756 if (Policy
!= Ip4Config2PolicyStatic
) {
757 Policy
= Ip4Config2PolicyStatic
;
758 Status
= Ip4Config2
->SetData (
760 Ip4Config2DataTypePolicy
,
761 sizeof (EFI_IP4_CONFIG2_POLICY
),
764 if (EFI_ERROR (Status
)) {
773 Start the D.O.R.A DHCPv4 process to acquire the IPv4 address and other Http boot information.
775 @param[in] Private Pointer to HTTP boot driver private data.
777 @retval EFI_SUCCESS The D.O.R.A process successfully finished.
778 @retval Others Failed to finish the D.O.R.A process.
783 IN HTTP_BOOT_PRIVATE_DATA
*Private
786 EFI_DHCP4_PROTOCOL
*Dhcp4
;
788 EFI_DHCP4_PACKET_OPTION
*OptList
[HTTP_BOOT_DHCP4_OPTION_MAX_NUM
];
789 UINT8 Buffer
[HTTP_BOOT_DHCP4_OPTION_MAX_SIZE
];
790 EFI_DHCP4_CONFIG_DATA Config
;
792 EFI_DHCP4_MODE_DATA Mode
;
794 Dhcp4
= Private
->Dhcp4
;
795 ASSERT (Dhcp4
!= NULL
);
797 Status
= HttpBootSetIp4Policy (Private
);
798 if (EFI_ERROR (Status
)) {
803 // Build option list for the request packet.
805 OptCount
= HttpBootBuildDhcp4Options (Private
, OptList
, Buffer
);
806 ASSERT (OptCount
> 0);
808 ZeroMem (&Config
, sizeof(Config
));
809 Config
.OptionCount
= OptCount
;
810 Config
.OptionList
= OptList
;
811 Config
.Dhcp4Callback
= HttpBootDhcp4CallBack
;
812 Config
.CallbackContext
= Private
;
813 Config
.DiscoverTryCount
= HTTP_BOOT_DHCP_RETRIES
;
814 Config
.DiscoverTimeout
= mHttpDhcpTimeout
;
817 // Configure the DHCPv4 instance for HTTP boot.
819 Status
= Dhcp4
->Configure (Dhcp4
, &Config
);
820 if (EFI_ERROR (Status
)) {
825 // Initialize the record fields for DHCPv4 offer in private data.
827 Private
->OfferNum
= 0;
828 ZeroMem (Private
->OfferCount
, sizeof (Private
->OfferCount
));
829 ZeroMem (Private
->OfferIndex
, sizeof (Private
->OfferIndex
));
832 // Start DHCPv4 D.O.R.A. process to acquire IPv4 address.
834 Status
= Dhcp4
->Start (Dhcp4
, NULL
);
835 if (EFI_ERROR (Status
)) {
840 // Get the acquired IPv4 address and store them.
842 Status
= Dhcp4
->GetModeData (Dhcp4
, &Mode
);
843 if (EFI_ERROR (Status
)) {
847 ASSERT (Mode
.State
== Dhcp4Bound
);
848 CopyMem (&Private
->StationIp
, &Mode
.ClientAddress
, sizeof (EFI_IPv4_ADDRESS
));
849 CopyMem (&Private
->SubnetMask
, &Mode
.SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
850 CopyMem (&Private
->GatewayIp
, &Mode
.RouterAddress
, sizeof (EFI_IPv4_ADDRESS
));
852 Status
= HttpBootRegisterIp4Gateway (Private
);
853 if (EFI_ERROR (Status
)) {
857 AsciiPrint ("\n Station IP address is ");
858 HttpBootShowIp4Addr (&Private
->StationIp
.v4
);
862 if (EFI_ERROR (Status
)) {
864 Dhcp4
->Configure (Dhcp4
, NULL
);
866 ZeroMem (&Config
, sizeof (EFI_DHCP4_CONFIG_DATA
));
867 Dhcp4
->Configure (Dhcp4
, &Config
);