/** @file\r
Functions implementation related with DHCPv4 for UefiPxeBc Driver.\r
\r
- Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
BOOLEAN IsProxyOffer;\r
BOOLEAN IsPxeOffer;\r
UINT8 *Ptr8;\r
+ BOOLEAN FileFieldOverloaded;\r
\r
IsProxyOffer = FALSE;\r
IsPxeOffer = FALSE;\r
+ FileFieldOverloaded = FALSE;\r
\r
ZeroMem (Cache4->OptList, sizeof (Cache4->OptList));\r
ZeroMem (&Cache4->VendorOpt, sizeof (Cache4->VendorOpt));\r
\r
//\r
// Parse DHCPv4 options in this offer, and store the pointers.\r
+ // First, try to parse DHCPv4 options from the DHCP optional parameters field.\r
//\r
for (Index = 0; Index < PXEBC_DHCP4_TAG_INDEX_MAX; Index++) {\r
Options[Index] = PxeBcParseDhcp4Options (\r
mInterestedDhcp4Tags[Index]\r
);\r
}\r
+ //\r
+ // Second, Check if bootfilename and serverhostname is overloaded to carry DHCP options refers to rfc-2132. \r
+ // If yes, try to parse options from the BootFileName field, then ServerName field.\r
+ //\r
+ Option = Options[PXEBC_DHCP4_TAG_INDEX_OVERLOAD];\r
+ if (Option != NULL) {\r
+ if ((Option->Data[0] & PXEBC_DHCP4_OVERLOAD_FILE) != 0) {\r
+ FileFieldOverloaded = TRUE;\r
+ for (Index = 0; Index < PXEBC_DHCP4_TAG_INDEX_MAX; Index++) {\r
+ if (Options[Index] == NULL) {\r
+ Options[Index] = PxeBcParseDhcp4Options (\r
+ (UINT8 *) Offer->Dhcp4.Header.BootFileName,\r
+ sizeof (Offer->Dhcp4.Header.BootFileName),\r
+ mInterestedDhcp4Tags[Index]\r
+ );\r
+ }\r
+ }\r
+ }\r
+ if ((Option->Data[0] & PXEBC_DHCP4_OVERLOAD_SERVER_NAME) != 0) {\r
+ for (Index = 0; Index < PXEBC_DHCP4_TAG_INDEX_MAX; Index++) {\r
+ if (Options[Index] == NULL) {\r
+ Options[Index] = PxeBcParseDhcp4Options (\r
+ (UINT8 *) Offer->Dhcp4.Header.ServerName,\r
+ sizeof (Offer->Dhcp4.Header.ServerName),\r
+ mInterestedDhcp4Tags[Index]\r
+ );\r
+ }\r
+ }\r
+ }\r
+ }\r
\r
//\r
- // The offer with "yiaddr" is a proxy offer.\r
+ // The offer with zero "yiaddr" is a proxy offer.\r
//\r
if (Offer->Dhcp4.Header.YourAddr.Addr[0] == 0) {\r
IsProxyOffer = TRUE;\r
}\r
\r
//\r
- // Check whether bootfilename and serverhostname overloaded, refers to rfc-2132 in details.\r
- // If overloaded, parse the buffer as nested DHCPv4 options, or else just parse as bootfilename\r
- // and serverhostname option.\r
+ // Parse PXE boot file name:\r
+ // According to PXE spec, boot file name should be read from DHCP option 67 (bootfile name) if present.\r
+ // Otherwise, read from boot file field in DHCP header.\r
//\r
- Option = Options[PXEBC_DHCP4_TAG_INDEX_OVERLOAD];\r
- if (Option != NULL && (Option->Data[0] & PXEBC_DHCP4_OVERLOAD_FILE) != 0) {\r
-\r
- Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] = PxeBcParseDhcp4Options (\r
- (UINT8 *) Offer->Dhcp4.Header.BootFileName,\r
- sizeof (Offer->Dhcp4.Header.BootFileName),\r
- PXEBC_DHCP4_TAG_BOOTFILE\r
- );\r
+ if (Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] != NULL) {\r
//\r
// RFC 2132, Section 9.5 does not strictly state Bootfile name (option 67) is null\r
// terminated string. So force to append null terminated character at the end of string.\r
//\r
- if (Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] != NULL) {\r
- Ptr8 = (UINT8*)&Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Data[0];\r
- Ptr8 += Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Length;\r
- *Ptr8 = '\0';\r
+ Ptr8 = (UINT8*)&Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Data[0];\r
+ Ptr8 += Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Length;\r
+ if (*(Ptr8 - 1) != '\0') {\r
+ *Ptr8 = '\0';\r
}\r
-\r
- } else if ((Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] == NULL) &&\r
- (Offer->Dhcp4.Header.BootFileName[0] != 0)) {\r
+ } else if (!FileFieldOverloaded && Offer->Dhcp4.Header.BootFileName[0] != 0) {\r
//\r
// If the bootfile is not present and bootfilename is present in DHCPv4 packet, just parse it.\r
- // Do not count dhcp option header here, or else will destory the serverhostname.\r
+ // Do not count dhcp option header here, or else will destroy the serverhostname.\r
//\r
Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] = (EFI_DHCP4_PACKET_OPTION *)\r
(&Offer->Dhcp4.Header.BootFileName[0] -\r
break;\r
}\r
if ((SrvList[SrvIndex].Type == Type) &&\r
- EFI_IP4_EQUAL (&Response->Dhcp4.Header.ServerAddr, &Private->ServerIp)) {\r
+ EFI_IP4_EQUAL (&Response->Dhcp4.Header.ServerAddr, &SrvList[SrvIndex].IpAddr)) {\r
break;\r
}\r
SrvIndex++;\r
return Status;\r
}\r
\r
+/**\r
+ Switch the Ip4 policy to static.\r
+\r
+ @param[in] Private The pointer to PXEBC_PRIVATE_DATA.\r
+\r
+ @retval EFI_SUCCESS The policy is already configured to static.\r
+ @retval Others Other error as indicated..\r
+\r
+**/\r
+EFI_STATUS\r
+PxeBcSetIp4Policy ( \r
+ IN PXEBC_PRIVATE_DATA *Private\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2;\r
+ EFI_IP4_CONFIG2_POLICY Policy;\r
+ UINTN DataSize;\r
+\r
+ Ip4Config2 = Private->Ip4Config2;\r
+ DataSize = sizeof (EFI_IP4_CONFIG2_POLICY);\r
+ Status = Ip4Config2->GetData (\r
+ Ip4Config2,\r
+ Ip4Config2DataTypePolicy,\r
+ &DataSize,\r
+ &Policy\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ if (Policy != Ip4Config2PolicyStatic) {\r
+ Policy = Ip4Config2PolicyStatic;\r
+ Status= Ip4Config2->SetData (\r
+ Ip4Config2,\r
+ Ip4Config2DataTypePolicy,\r
+ sizeof (EFI_IP4_CONFIG2_POLICY),\r
+ &Policy\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ } \r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
\r
/**\r
Start the D.O.R.A DHCPv4 process to acquire the IPv4 address and other PXE boot information.\r
ZeroMem (Private->OfferIndex, sizeof (Private->OfferIndex));\r
\r
//\r
- // Start DHCPv4 D.O.R.A. process to acquire IPv4 address.\r
+ // Start DHCPv4 D.O.R.A. process to acquire IPv4 address. This may \r
+ // have already been done, thus do not leave in error if the return\r
+ // code is EFI_ALREADY_STARTED.\r
//\r
Status = Dhcp4->Start (Dhcp4, NULL);\r
- if (EFI_ERROR (Status)) {\r
+ if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
if (Status == EFI_ICMP_ERROR) {\r
PxeMode->IcmpErrorReceived = TRUE;\r
}\r
CopyMem (&PxeMode->StationIp, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS));\r
CopyMem (&PxeMode->SubnetMask, &Private->SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
\r
- Status = PxeBcFlushStaionIp (Private, &Private->StationIp, &Private->SubnetMask);\r
+ Status = PxeBcFlushStationIp (Private, &Private->StationIp, &Private->SubnetMask);\r
if (EFI_ERROR (Status)) {\r
goto ON_EXIT;\r
}\r
AsciiPrint ("\n Station IP address is ");\r
\r
PxeBcShowIp4Addr (&Private->StationIp.v4);\r
+ AsciiPrint ("\n");\r
\r
ON_EXIT:\r
if (EFI_ERROR (Status)) {\r