2 Functions implementation related with DHCPv4 for HTTP boot driver.
4 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "HttpBootDxe.h"
12 // This is a map from the interested DHCP4 option tags' index to the tag value.
14 UINT8 mInterestedDhcp4Tags
[HTTP_BOOT_DHCP4_TAG_INDEX_MAX
] = {
15 DHCP4_TAG_BOOTFILE_LEN
,
19 DHCP4_TAG_VENDOR_CLASS_ID
,
25 // There are 4 times retries with the value of 4, 8, 16 and 32, refers to UEFI 2.5 spec.
27 UINT32 mHttpDhcpTimeout
[4] = {4, 8, 16, 32};
30 Build the options buffer for the DHCPv4 request packet.
32 @param[in] Private Pointer to HTTP boot driver private data.
33 @param[out] OptList Pointer to the option pointer array.
34 @param[in] Buffer Pointer to the buffer to contain the option list.
36 @return Index The count of the built-in options.
40 HttpBootBuildDhcp4Options (
41 IN HTTP_BOOT_PRIVATE_DATA
*Private
,
42 OUT EFI_DHCP4_PACKET_OPTION
**OptList
,
46 HTTP_BOOT_DHCP4_OPTION_ENTRY OptEnt
;
51 OptList
[0] = (EFI_DHCP4_PACKET_OPTION
*) Buffer
;
54 // Append parameter request list option.
56 OptList
[Index
]->OpCode
= DHCP4_TAG_PARA_LIST
;
57 OptList
[Index
]->Length
= 27;
58 OptEnt
.Para
= (HTTP_BOOT_DHCP4_OPTION_PARA
*) OptList
[Index
]->Data
;
59 OptEnt
.Para
->ParaList
[0] = DHCP4_TAG_NETMASK
;
60 OptEnt
.Para
->ParaList
[1] = DHCP4_TAG_TIME_OFFSET
;
61 OptEnt
.Para
->ParaList
[2] = DHCP4_TAG_ROUTER
;
62 OptEnt
.Para
->ParaList
[3] = DHCP4_TAG_TIME_SERVER
;
63 OptEnt
.Para
->ParaList
[4] = DHCP4_TAG_NAME_SERVER
;
64 OptEnt
.Para
->ParaList
[5] = DHCP4_TAG_DNS_SERVER
;
65 OptEnt
.Para
->ParaList
[6] = DHCP4_TAG_HOSTNAME
;
66 OptEnt
.Para
->ParaList
[7] = DHCP4_TAG_BOOTFILE_LEN
;
67 OptEnt
.Para
->ParaList
[8] = DHCP4_TAG_DOMAINNAME
;
68 OptEnt
.Para
->ParaList
[9] = DHCP4_TAG_ROOTPATH
;
69 OptEnt
.Para
->ParaList
[10] = DHCP4_TAG_EXTEND_PATH
;
70 OptEnt
.Para
->ParaList
[11] = DHCP4_TAG_EMTU
;
71 OptEnt
.Para
->ParaList
[12] = DHCP4_TAG_TTL
;
72 OptEnt
.Para
->ParaList
[13] = DHCP4_TAG_BROADCAST
;
73 OptEnt
.Para
->ParaList
[14] = DHCP4_TAG_NIS_DOMAIN
;
74 OptEnt
.Para
->ParaList
[15] = DHCP4_TAG_NIS_SERVER
;
75 OptEnt
.Para
->ParaList
[16] = DHCP4_TAG_NTP_SERVER
;
76 OptEnt
.Para
->ParaList
[17] = DHCP4_TAG_VENDOR
;
77 OptEnt
.Para
->ParaList
[18] = DHCP4_TAG_REQUEST_IP
;
78 OptEnt
.Para
->ParaList
[19] = DHCP4_TAG_LEASE
;
79 OptEnt
.Para
->ParaList
[20] = DHCP4_TAG_SERVER_ID
;
80 OptEnt
.Para
->ParaList
[21] = DHCP4_TAG_T1
;
81 OptEnt
.Para
->ParaList
[22] = DHCP4_TAG_T2
;
82 OptEnt
.Para
->ParaList
[23] = DHCP4_TAG_VENDOR_CLASS_ID
;
83 OptEnt
.Para
->ParaList
[25] = DHCP4_TAG_BOOTFILE
;
84 OptEnt
.Para
->ParaList
[26] = DHCP4_TAG_UUID
;
86 OptList
[Index
] = GET_NEXT_DHCP_OPTION (OptList
[Index
- 1]);
89 // Append UUID/Guid-based client identifier option
91 OptList
[Index
]->OpCode
= DHCP4_TAG_UUID
;
92 OptList
[Index
]->Length
= (UINT8
) sizeof (HTTP_BOOT_DHCP4_OPTION_UUID
);
93 OptEnt
.Uuid
= (HTTP_BOOT_DHCP4_OPTION_UUID
*) OptList
[Index
]->Data
;
94 OptEnt
.Uuid
->Type
= 0;
95 if (EFI_ERROR (NetLibGetSystemGuid ((EFI_GUID
*) OptEnt
.Uuid
->Guid
))) {
97 // Zero the Guid to indicate NOT programable if failed to get system Guid.
99 ZeroMem (OptEnt
.Uuid
->Guid
, sizeof (EFI_GUID
));
102 OptList
[Index
] = GET_NEXT_DHCP_OPTION (OptList
[Index
- 1]);
105 // Append client network device interface option
107 OptList
[Index
]->OpCode
= DHCP4_TAG_UNDI
;
108 OptList
[Index
]->Length
= (UINT8
) sizeof (HTTP_BOOT_DHCP4_OPTION_UNDI
);
109 OptEnt
.Undi
= (HTTP_BOOT_DHCP4_OPTION_UNDI
*) OptList
[Index
]->Data
;
111 if (Private
->Nii
!= NULL
) {
112 OptEnt
.Undi
->Type
= Private
->Nii
->Type
;
113 OptEnt
.Undi
->MajorVer
= Private
->Nii
->MajorVer
;
114 OptEnt
.Undi
->MinorVer
= Private
->Nii
->MinorVer
;
116 OptEnt
.Undi
->Type
= DEFAULT_UNDI_TYPE
;
117 OptEnt
.Undi
->MajorVer
= DEFAULT_UNDI_MAJOR
;
118 OptEnt
.Undi
->MinorVer
= DEFAULT_UNDI_MINOR
;
122 OptList
[Index
] = GET_NEXT_DHCP_OPTION (OptList
[Index
- 1]);
125 // Append client system architecture option
127 OptList
[Index
]->OpCode
= DHCP4_TAG_ARCH
;
128 OptList
[Index
]->Length
= (UINT8
) sizeof (HTTP_BOOT_DHCP4_OPTION_ARCH
);
129 OptEnt
.Arch
= (HTTP_BOOT_DHCP4_OPTION_ARCH
*) OptList
[Index
]->Data
;
130 Value
= HTONS (EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE
);
131 CopyMem (&OptEnt
.Arch
->Type
, &Value
, sizeof (UINT16
));
133 OptList
[Index
] = GET_NEXT_DHCP_OPTION (OptList
[Index
- 1]);
136 // Append vendor class identify option
138 OptList
[Index
]->OpCode
= DHCP4_TAG_VENDOR_CLASS_ID
;
139 OptList
[Index
]->Length
= (UINT8
) sizeof (HTTP_BOOT_DHCP4_OPTION_CLID
);
140 OptEnt
.Clid
= (HTTP_BOOT_DHCP4_OPTION_CLID
*) OptList
[Index
]->Data
;
143 DEFAULT_CLASS_ID_DATA
,
144 sizeof (HTTP_BOOT_DHCP4_OPTION_CLID
)
146 HttpBootUintnToAscDecWithFormat (
147 EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE
,
148 OptEnt
.Clid
->ArchitectureType
,
149 sizeof (OptEnt
.Clid
->ArchitectureType
)
152 if (Private
->Nii
!= NULL
) {
153 CopyMem (OptEnt
.Clid
->InterfaceName
, Private
->Nii
->StringId
, sizeof (OptEnt
.Clid
->InterfaceName
));
154 HttpBootUintnToAscDecWithFormat (Private
->Nii
->MajorVer
, OptEnt
.Clid
->UndiMajor
, sizeof (OptEnt
.Clid
->UndiMajor
));
155 HttpBootUintnToAscDecWithFormat (Private
->Nii
->MinorVer
, OptEnt
.Clid
->UndiMinor
, sizeof (OptEnt
.Clid
->UndiMinor
));
164 Parse a certain dhcp4 option by OptTag in Buffer, and return with start pointer.
166 @param[in] Buffer Pointer to the option buffer.
167 @param[in] Length Length of the option buffer.
168 @param[in] OptTag Tag of the required option.
170 @retval NULL Failed to find the required option.
171 @retval Others The position of the required option.
174 EFI_DHCP4_PACKET_OPTION
*
175 HttpBootParseDhcp4Options (
181 EFI_DHCP4_PACKET_OPTION
*Option
;
184 Option
= (EFI_DHCP4_PACKET_OPTION
*) Buffer
;
187 while (Offset
< Length
&& Option
->OpCode
!= DHCP4_TAG_EOP
) {
189 if (Option
->OpCode
== OptTag
) {
191 // Found the required option.
197 // Skip the current option to the next.
199 if (Option
->OpCode
== DHCP4_TAG_PAD
) {
202 Offset
+= Option
->Length
+ 2;
205 Option
= (EFI_DHCP4_PACKET_OPTION
*) (Buffer
+ Offset
);
212 Cache the DHCPv4 packet.
214 @param[in] Dst Pointer to the cache buffer for DHCPv4 packet.
215 @param[in] Src Pointer to the DHCPv4 packet to be cached.
217 @retval EFI_SUCCESS Packet is copied.
218 @retval EFI_BUFFER_TOO_SMALL Cache buffer is not big enough to hold the packet.
222 HttpBootCacheDhcp4Packet (
223 IN EFI_DHCP4_PACKET
*Dst
,
224 IN EFI_DHCP4_PACKET
*Src
227 if (Dst
->Size
< Src
->Length
) {
228 return EFI_BUFFER_TOO_SMALL
;
231 CopyMem (&Dst
->Dhcp4
, &Src
->Dhcp4
, Src
->Length
);
232 Dst
->Length
= Src
->Length
;
238 Parse the cached DHCPv4 packet, including all the options.
240 @param[in] Cache4 Pointer to cached DHCPv4 packet.
242 @retval EFI_SUCCESS Parsed the DHCPv4 packet successfully.
243 @retval EFI_DEVICE_ERROR Failed to parse an invalid packet.
247 HttpBootParseDhcp4Packet (
248 IN HTTP_BOOT_DHCP4_PACKET_CACHE
*Cache4
251 EFI_DHCP4_PACKET
*Offer
;
252 EFI_DHCP4_PACKET_OPTION
**Options
;
254 EFI_DHCP4_PACKET_OPTION
*Option
;
255 BOOLEAN IsProxyOffer
;
258 BOOLEAN IpExpressedUri
;
261 HTTP_BOOT_OFFER_TYPE OfferType
;
262 EFI_IPv4_ADDRESS IpAddr
;
263 BOOLEAN FileFieldOverloaded
;
266 IpExpressedUri
= FALSE
;
267 IsProxyOffer
= FALSE
;
269 FileFieldOverloaded
= FALSE
;
271 ZeroMem (Cache4
->OptList
, sizeof (Cache4
->OptList
));
273 Offer
= &Cache4
->Packet
.Offer
;
274 Options
= Cache4
->OptList
;
277 // Parse DHCPv4 options in this offer, and store the pointers.
278 // First, try to parse DHCPv4 options from the DHCP optional parameters field.
280 for (Index
= 0; Index
< HTTP_BOOT_DHCP4_TAG_INDEX_MAX
; Index
++) {
281 Options
[Index
] = HttpBootParseDhcp4Options (
283 GET_OPTION_BUFFER_LEN (Offer
),
284 mInterestedDhcp4Tags
[Index
]
288 // Second, Check if bootfilename and serverhostname is overloaded to carry DHCP options refers to rfc-2132.
289 // If yes, try to parse options from the BootFileName field, then ServerName field.
291 Option
= Options
[HTTP_BOOT_DHCP4_TAG_INDEX_OVERLOAD
];
292 if (Option
!= NULL
) {
293 if ((Option
->Data
[0] & HTTP_BOOT_DHCP4_OVERLOAD_FILE
) != 0) {
294 FileFieldOverloaded
= TRUE
;
295 for (Index
= 0; Index
< HTTP_BOOT_DHCP4_TAG_INDEX_MAX
; Index
++) {
296 if (Options
[Index
] == NULL
) {
297 Options
[Index
] = HttpBootParseDhcp4Options (
298 (UINT8
*) Offer
->Dhcp4
.Header
.BootFileName
,
299 sizeof (Offer
->Dhcp4
.Header
.BootFileName
),
300 mInterestedDhcp4Tags
[Index
]
305 if ((Option
->Data
[0] & HTTP_BOOT_DHCP4_OVERLOAD_SERVER_NAME
) != 0) {
306 for (Index
= 0; Index
< HTTP_BOOT_DHCP4_TAG_INDEX_MAX
; Index
++) {
307 if (Options
[Index
] == NULL
) {
308 Options
[Index
] = HttpBootParseDhcp4Options (
309 (UINT8
*) Offer
->Dhcp4
.Header
.ServerName
,
310 sizeof (Offer
->Dhcp4
.Header
.ServerName
),
311 mInterestedDhcp4Tags
[Index
]
319 // The offer with "yiaddr" is a proxy offer.
321 if (Offer
->Dhcp4
.Header
.YourAddr
.Addr
[0] == 0) {
326 // The offer with "HTTPClient" is a Http offer.
328 Option
= Options
[HTTP_BOOT_DHCP4_TAG_INDEX_CLASS_ID
];
329 if ((Option
!= NULL
) && (Option
->Length
>= 10) &&
330 (CompareMem (Option
->Data
, DEFAULT_CLASS_ID_DATA
, 10) == 0)) {
335 // The offer with Domain Server is a DNS offer.
337 Option
= Options
[HTTP_BOOT_DHCP4_TAG_INDEX_DNS_SERVER
];
338 if (Option
!= NULL
) {
343 // Parse boot file name:
344 // Boot URI information is provided thru 'file' field in DHCP Header or option 67.
345 // According to RFC 2132, boot file name should be read from DHCP option 67 (bootfile name) if present.
346 // Otherwise, read from boot file field in DHCP header.
348 if (Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
] != NULL
) {
350 // RFC 2132, Section 9.5 does not strictly state Bootfile name (option 67) is null
351 // terminated string. So force to append null terminated character at the end of string.
353 Ptr8
= (UINT8
*)&Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
]->Data
[0];
354 Ptr8
+= Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
]->Length
;
355 if (*(Ptr8
- 1) != '\0') {
358 } else if (!FileFieldOverloaded
&& Offer
->Dhcp4
.Header
.BootFileName
[0] != 0) {
360 // If the bootfile is not present and bootfilename is present in DHCPv4 packet, just parse it.
361 // Do not count dhcp option header here, or else will destroy the serverhostname.
363 Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
] = (EFI_DHCP4_PACKET_OPTION
*)
364 (&Offer
->Dhcp4
.Header
.BootFileName
[0] -
365 OFFSET_OF (EFI_DHCP4_PACKET_OPTION
, Data
[0]));
369 // Http offer must have a boot URI.
371 if (IsHttpOffer
&& Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
] == NULL
) {
372 return EFI_DEVICE_ERROR
;
376 // Try to retrieve the IP of HTTP server from URI.
379 Status
= HttpParseUrl (
380 (CHAR8
*) Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
]->Data
,
381 (UINT32
) AsciiStrLen ((CHAR8
*) Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
]->Data
),
385 if (EFI_ERROR (Status
)) {
386 return EFI_DEVICE_ERROR
;
389 Status
= HttpUrlGetIp4 (
390 (CHAR8
*) Options
[HTTP_BOOT_DHCP4_TAG_INDEX_BOOTFILE
]->Data
,
394 IpExpressedUri
= !EFI_ERROR (Status
);
398 // Determine offer type of the DHCPv4 packet.
401 if (IpExpressedUri
) {
403 OfferType
= HttpOfferTypeProxyIpUri
;
405 OfferType
= IsDnsOffer
? HttpOfferTypeDhcpIpUriDns
: HttpOfferTypeDhcpIpUri
;
409 OfferType
= IsDnsOffer
? HttpOfferTypeDhcpNameUriDns
: HttpOfferTypeDhcpNameUri
;
411 OfferType
= HttpOfferTypeProxyNameUri
;
417 OfferType
= IsDnsOffer
? HttpOfferTypeDhcpDns
: HttpOfferTypeDhcpOnly
;
419 if (Cache4
->UriParser
!= NULL
) {
420 FreePool (Cache4
->UriParser
);
422 return EFI_DEVICE_ERROR
;
426 Cache4
->OfferType
= OfferType
;
431 Cache all the received DHCPv4 offers, and set OfferIndex and OfferCount.
433 @param[in] Private Pointer to HTTP boot driver private data.
434 @param[in] RcvdOffer Pointer to the received offer packet.
436 @retval EFI_SUCCESS Cache and parse the packet successfully.
437 @retval Others Operation failed.
440 HttpBootCacheDhcp4Offer (
441 IN HTTP_BOOT_PRIVATE_DATA
*Private
,
442 IN EFI_DHCP4_PACKET
*RcvdOffer
445 HTTP_BOOT_DHCP4_PACKET_CACHE
*Cache4
;
446 EFI_DHCP4_PACKET
*Offer
;
447 HTTP_BOOT_OFFER_TYPE OfferType
;
450 ASSERT (Private
->OfferNum
< HTTP_BOOT_OFFER_MAX_NUM
);
451 Cache4
= &Private
->OfferBuffer
[Private
->OfferNum
].Dhcp4
;
452 Offer
= &Cache4
->Packet
.Offer
;
455 // Cache the content of DHCPv4 packet firstly.
457 Status
= HttpBootCacheDhcp4Packet (Offer
, RcvdOffer
);
458 if (EFI_ERROR (Status
)) {
463 // Validate the DHCPv4 packet, and parse the options and offer type.
465 if (EFI_ERROR (HttpBootParseDhcp4Packet (Cache4
))) {
470 // Determine whether cache the current offer by type, and record OfferIndex and OfferCount.
472 OfferType
= Cache4
->OfferType
;
473 ASSERT (OfferType
< HttpOfferTypeMax
);
474 ASSERT (Private
->OfferCount
[OfferType
] < HTTP_BOOT_OFFER_MAX_NUM
);
475 Private
->OfferIndex
[OfferType
][Private
->OfferCount
[OfferType
]] = Private
->OfferNum
;
476 Private
->OfferCount
[OfferType
]++;
483 Select an DHCPv4 or DHCP6 offer, and record SelectIndex and SelectProxyType.
485 @param[in] Private Pointer to HTTP boot driver private data.
489 HttpBootSelectDhcpOffer (
490 IN HTTP_BOOT_PRIVATE_DATA
*Private
493 Private
->SelectIndex
= 0;
494 Private
->SelectProxyType
= HttpOfferTypeMax
;
496 if (Private
->FilePathUri
!= NULL
) {
498 // We are in home environment, the URI is already specified.
499 // Just need to choose a DHCP offer.
500 // The offer with DNS server address takes priority here.
502 if (Private
->OfferCount
[HttpOfferTypeDhcpDns
] > 0) {
504 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpDns
][0] + 1;
506 } else if (Private
->OfferCount
[HttpOfferTypeDhcpIpUriDns
] > 0) {
508 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpIpUriDns
][0] + 1;
510 } else if (Private
->OfferCount
[HttpOfferTypeDhcpNameUriDns
] > 0) {
512 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpNameUriDns
][0] + 1;
514 } else if (Private
->OfferCount
[HttpOfferTypeDhcpOnly
] > 0) {
516 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpOnly
][0] + 1;
518 } else if (Private
->OfferCount
[HttpOfferTypeDhcpIpUri
] > 0) {
520 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpIpUri
][0] + 1;
525 // We are in corporate environment.
527 // Priority1: HttpOfferTypeDhcpIpUri or HttpOfferTypeDhcpIpUriDns
528 // Priority2: HttpOfferTypeDhcpNameUriDns
529 // Priority3: HttpOfferTypeDhcpOnly + HttpOfferTypeProxyIpUri
530 // Priority4: HttpOfferTypeDhcpDns + HttpOfferTypeProxyIpUri
531 // Priority5: HttpOfferTypeDhcpDns + HttpOfferTypeProxyNameUri
532 // Priority6: HttpOfferTypeDhcpDns + HttpOfferTypeDhcpNameUri
534 if (Private
->OfferCount
[HttpOfferTypeDhcpIpUri
] > 0) {
536 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpIpUri
][0] + 1;
538 } else if (Private
->OfferCount
[HttpOfferTypeDhcpIpUriDns
] > 0) {
540 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpIpUriDns
][0] + 1;
542 }else if (Private
->OfferCount
[HttpOfferTypeDhcpNameUriDns
] > 0) {
544 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpNameUriDns
][0] + 1;
546 } else if (Private
->OfferCount
[HttpOfferTypeDhcpOnly
] > 0 &&
547 Private
->OfferCount
[HttpOfferTypeProxyIpUri
] > 0) {
549 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpOnly
][0] + 1;
550 Private
->SelectProxyType
= HttpOfferTypeProxyIpUri
;
552 } else if (Private
->OfferCount
[HttpOfferTypeDhcpDns
] > 0 &&
553 Private
->OfferCount
[HttpOfferTypeProxyIpUri
] > 0) {
555 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpDns
][0] + 1;
556 Private
->SelectProxyType
= HttpOfferTypeProxyIpUri
;
558 } else if (Private
->OfferCount
[HttpOfferTypeDhcpDns
] > 0 &&
559 Private
->OfferCount
[HttpOfferTypeProxyNameUri
] > 0) {
561 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpDns
][0] + 1;
562 Private
->SelectProxyType
= HttpOfferTypeProxyNameUri
;
564 } else if (Private
->OfferCount
[HttpOfferTypeDhcpDns
] > 0 &&
565 Private
->OfferCount
[HttpOfferTypeDhcpNameUri
] > 0) {
567 Private
->SelectIndex
= Private
->OfferIndex
[HttpOfferTypeDhcpDns
][0] + 1;
568 Private
->SelectProxyType
= HttpOfferTypeDhcpNameUri
;
575 EFI_DHCP4_CALLBACK is provided by the consumer of the EFI DHCPv4 Protocol driver
576 to intercept events that occurred in the configuration process.
578 @param[in] This Pointer to the EFI DHCPv4 Protocol.
579 @param[in] Context Pointer to the context set by EFI_DHCP4_PROTOCOL.Configure().
580 @param[in] CurrentState The current operational state of the EFI DHCPv4 Protocol driver.
581 @param[in] Dhcp4Event The event that occurs in the current state, which usually means a
583 @param[in] Packet The DHCPv4 packet that is going to be sent or already received.
584 @param[out] NewPacket The packet that is used to replace the above Packet.
586 @retval EFI_SUCCESS Tells the EFI DHCPv4 Protocol driver to continue the DHCP process.
587 @retval EFI_NOT_READY Only used in the Dhcp4Selecting state. The EFI DHCPv4 Protocol
588 driver will continue to wait for more DHCPOFFER packets until the
589 retry timeout expires.
590 @retval EFI_ABORTED Tells the EFI DHCPv4 Protocol driver to abort the current process
591 and return to the Dhcp4Init or Dhcp4InitReboot state.
596 HttpBootDhcp4CallBack (
597 IN EFI_DHCP4_PROTOCOL
*This
,
599 IN EFI_DHCP4_STATE CurrentState
,
600 IN EFI_DHCP4_EVENT Dhcp4Event
,
601 IN EFI_DHCP4_PACKET
*Packet OPTIONAL
,
602 OUT EFI_DHCP4_PACKET
**NewPacket OPTIONAL
605 HTTP_BOOT_PRIVATE_DATA
*Private
;
606 EFI_DHCP4_PACKET_OPTION
*MaxMsgSize
;
611 if ((Dhcp4Event
!= Dhcp4SendDiscover
) &&
612 (Dhcp4Event
!= Dhcp4RcvdOffer
) &&
613 (Dhcp4Event
!= Dhcp4SendRequest
) &&
614 (Dhcp4Event
!= Dhcp4RcvdAck
) &&
615 (Dhcp4Event
!= Dhcp4SelectOffer
)) {
619 Private
= (HTTP_BOOT_PRIVATE_DATA
*) Context
;
622 // Override the Maximum DHCP Message Size.
624 MaxMsgSize
= HttpBootParseDhcp4Options (
625 Packet
->Dhcp4
.Option
,
626 GET_OPTION_BUFFER_LEN (Packet
),
629 if (MaxMsgSize
!= NULL
) {
630 Value
= HTONS (HTTP_BOOT_DHCP4_PACKET_MAX_SIZE
);
631 CopyMem (MaxMsgSize
->Data
, &Value
, sizeof (Value
));
635 // Callback to user if any packets sent or received.
637 if (Private
->HttpBootCallback
!= NULL
&& Dhcp4Event
!= Dhcp4SelectOffer
) {
638 Received
= (BOOLEAN
) (Dhcp4Event
== Dhcp4RcvdOffer
|| Dhcp4Event
== Dhcp4RcvdAck
);
639 Status
= Private
->HttpBootCallback
->Callback (
640 Private
->HttpBootCallback
,
646 if (EFI_ERROR (Status
)) {
651 Status
= EFI_SUCCESS
;
652 switch (Dhcp4Event
) {
654 Status
= EFI_NOT_READY
;
655 if (Packet
->Length
> HTTP_BOOT_DHCP4_PACKET_MAX_SIZE
) {
657 // Ignore the incoming packets which exceed the maximum length.
661 if (Private
->OfferNum
< HTTP_BOOT_OFFER_MAX_NUM
) {
663 // Cache the DHCPv4 offers to OfferBuffer[] for select later, and record
664 // the OfferIndex and OfferCount.
665 // If error happens, just ignore this packet and continue to wait more offer.
667 HttpBootCacheDhcp4Offer (Private
, Packet
);
671 case Dhcp4SelectOffer
:
673 // Select offer according to the priority in UEFI spec, and record the SelectIndex
674 // and SelectProxyType.
676 HttpBootSelectDhcpOffer (Private
);
678 if (Private
->SelectIndex
== 0) {
679 Status
= EFI_ABORTED
;
681 *NewPacket
= &Private
->OfferBuffer
[Private
->SelectIndex
- 1].Dhcp4
.Packet
.Offer
;
693 This function will register the IPv4 gateway address to the network device.
695 @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.
697 @retval EFI_SUCCESS The new IP configuration has been configured successfully.
698 @retval Others Failed to configure the address.
702 HttpBootRegisterIp4Gateway (
703 IN HTTP_BOOT_PRIVATE_DATA
*Private
707 EFI_IP4_CONFIG2_PROTOCOL
*Ip4Config2
;
709 ASSERT (!Private
->UsingIpv6
);
711 Ip4Config2
= Private
->Ip4Config2
;
714 // Configure the gateway if valid.
716 if (!EFI_IP4_EQUAL (&Private
->GatewayIp
, &mZeroIp4Addr
)) {
717 Status
= Ip4Config2
->SetData (
719 Ip4Config2DataTypeGateway
,
720 sizeof (EFI_IPv4_ADDRESS
),
723 if (EFI_ERROR (Status
)) {
732 This function will register the default DNS addresses to the network device.
734 @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.
735 @param[in] DataLength Size of the buffer pointed to by DnsServerData in bytes.
736 @param[in] DnsServerData Point a list of DNS server address in an array
737 of EFI_IPv4_ADDRESS instances.
739 @retval EFI_SUCCESS The DNS configuration has been configured successfully.
740 @retval Others Failed to configure the address.
744 HttpBootRegisterIp4Dns (
745 IN HTTP_BOOT_PRIVATE_DATA
*Private
,
747 IN VOID
*DnsServerData
750 EFI_IP4_CONFIG2_PROTOCOL
*Ip4Config2
;
752 ASSERT (!Private
->UsingIpv6
);
754 Ip4Config2
= Private
->Ip4Config2
;
756 return Ip4Config2
->SetData (
758 Ip4Config2DataTypeDnsServer
,
766 This function will switch the IP4 configuration policy to Static.
768 @param[in] Private Pointer to HTTP boot driver private data.
770 @retval EFI_SUCCESS The policy is already configured to static.
771 @retval Others Other error as indicated..
775 HttpBootSetIp4Policy (
776 IN HTTP_BOOT_PRIVATE_DATA
*Private
779 EFI_IP4_CONFIG2_POLICY Policy
;
781 EFI_IP4_CONFIG2_PROTOCOL
*Ip4Config2
;
784 Ip4Config2
= Private
->Ip4Config2
;
786 DataSize
= sizeof (EFI_IP4_CONFIG2_POLICY
);
787 Status
= Ip4Config2
->GetData (
789 Ip4Config2DataTypePolicy
,
793 if (EFI_ERROR (Status
)) {
797 if (Policy
!= Ip4Config2PolicyStatic
) {
798 Policy
= Ip4Config2PolicyStatic
;
799 Status
= Ip4Config2
->SetData (
801 Ip4Config2DataTypePolicy
,
802 sizeof (EFI_IP4_CONFIG2_POLICY
),
805 if (EFI_ERROR (Status
)) {
814 Start the D.O.R.A DHCPv4 process to acquire the IPv4 address and other Http boot information.
816 @param[in] Private Pointer to HTTP boot driver private data.
818 @retval EFI_SUCCESS The D.O.R.A process successfully finished.
819 @retval Others Failed to finish the D.O.R.A process.
824 IN HTTP_BOOT_PRIVATE_DATA
*Private
827 EFI_DHCP4_PROTOCOL
*Dhcp4
;
829 EFI_DHCP4_PACKET_OPTION
*OptList
[HTTP_BOOT_DHCP4_OPTION_MAX_NUM
];
830 UINT8 Buffer
[HTTP_BOOT_DHCP4_OPTION_MAX_SIZE
];
831 EFI_DHCP4_CONFIG_DATA Config
;
833 EFI_DHCP4_MODE_DATA Mode
;
835 Dhcp4
= Private
->Dhcp4
;
836 ASSERT (Dhcp4
!= NULL
);
838 Status
= HttpBootSetIp4Policy (Private
);
839 if (EFI_ERROR (Status
)) {
844 // Build option list for the request packet.
846 OptCount
= HttpBootBuildDhcp4Options (Private
, OptList
, Buffer
);
847 ASSERT (OptCount
> 0);
849 ZeroMem (&Config
, sizeof(Config
));
850 Config
.OptionCount
= OptCount
;
851 Config
.OptionList
= OptList
;
852 Config
.Dhcp4Callback
= HttpBootDhcp4CallBack
;
853 Config
.CallbackContext
= Private
;
854 Config
.DiscoverTryCount
= HTTP_BOOT_DHCP_RETRIES
;
855 Config
.DiscoverTimeout
= mHttpDhcpTimeout
;
858 // Configure the DHCPv4 instance for HTTP boot.
860 Status
= Dhcp4
->Configure (Dhcp4
, &Config
);
861 if (EFI_ERROR (Status
)) {
866 // Initialize the record fields for DHCPv4 offer in private data.
868 Private
->OfferNum
= 0;
869 ZeroMem (Private
->OfferCount
, sizeof (Private
->OfferCount
));
870 ZeroMem (Private
->OfferIndex
, sizeof (Private
->OfferIndex
));
873 // Start DHCPv4 D.O.R.A. process to acquire IPv4 address.
875 Status
= Dhcp4
->Start (Dhcp4
, NULL
);
876 if (EFI_ERROR (Status
)) {
881 // Get the acquired IPv4 address and store them.
883 Status
= Dhcp4
->GetModeData (Dhcp4
, &Mode
);
884 if (EFI_ERROR (Status
)) {
888 ASSERT (Mode
.State
== Dhcp4Bound
);
889 CopyMem (&Private
->StationIp
, &Mode
.ClientAddress
, sizeof (EFI_IPv4_ADDRESS
));
890 CopyMem (&Private
->SubnetMask
, &Mode
.SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
891 CopyMem (&Private
->GatewayIp
, &Mode
.RouterAddress
, sizeof (EFI_IPv4_ADDRESS
));
893 Status
= HttpBootRegisterIp4Gateway (Private
);
894 if (EFI_ERROR (Status
)) {
898 AsciiPrint ("\n Station IP address is ");
899 HttpBootShowIp4Addr (&Private
->StationIp
.v4
);
903 if (EFI_ERROR (Status
)) {
905 Dhcp4
->Configure (Dhcp4
, NULL
);
907 ZeroMem (&Config
, sizeof (EFI_DHCP4_CONFIG_DATA
));
908 Dhcp4
->Configure (Dhcp4
, &Config
);