X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=NetworkPkg%2FUefiPxeBcDxe%2FPxeBcDhcp4.c;h=91146b78cb1e4931b137b8d060ac5f6f043512cb;hb=d1050b9dff1cace252aff86630bfdb59dff5f507;hp=6566afd6af2dbe42a70a28ebeb69e2171485c8d1;hpb=142c00c3d659a6d5d66416385b4c93fd9a9f10e6;p=mirror_edk2.git diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c index 6566afd6af..91146b78cb 100644 --- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c +++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c @@ -1,15 +1,9 @@ /** @file Functions implementation related with DHCPv4 for UefiPxeBc Driver. - Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
- This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php. - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -18,7 +12,7 @@ // // This is a map from the interested DHCP4 option tags' index to the tag value. // -UINT8 mInterestedDhcp4Tags[PXEBC_DHCP4_TAG_INDEX_MAX] = { +UINT8 mInterestedDhcp4Tags[PXEBC_DHCP4_TAG_INDEX_MAX] = { DHCP4_TAG_BOOTFILE_LEN, DHCP4_TAG_VENDOR, DHCP4_TAG_OVERLOAD, @@ -31,8 +25,7 @@ UINT8 mInterestedDhcp4Tags[PXEBC_DHCP4_TAG_INDEX_MAX] = { // // There are 4 times retries with the value of 4, 8, 16 and 32, refers to PXE2.1 spec. // -UINT32 mPxeDhcpTimeout[4] = {4, 8, 16, 32}; - +UINT32 mPxeDhcpTimeout[4] = { 4, 8, 16, 32 }; /** Parse a certain dhcp4 option by OptTag in Buffer, and return with start pointer. @@ -47,19 +40,18 @@ UINT32 mPxeDhcpTimeout[4] = {4, 8, 16, 32}; **/ EFI_DHCP4_PACKET_OPTION * PxeBcParseDhcp4Options ( - IN UINT8 *Buffer, - IN UINT32 Length, - IN UINT8 OptTag + IN UINT8 *Buffer, + IN UINT32 Length, + IN UINT8 OptTag ) { - EFI_DHCP4_PACKET_OPTION *Option; - UINT32 Offset; + EFI_DHCP4_PACKET_OPTION *Option; + UINT32 Offset; - Option = (EFI_DHCP4_PACKET_OPTION *) Buffer; - Offset = 0; + Option = (EFI_DHCP4_PACKET_OPTION *)Buffer; + Offset = 0; while (Offset < Length && Option->OpCode != DHCP4_TAG_EOP) { - if (Option->OpCode == OptTag) { // // Found the required option. @@ -76,15 +68,14 @@ PxeBcParseDhcp4Options ( Offset += Option->Length + 2; } - Option = (EFI_DHCP4_PACKET_OPTION *) (Buffer + Offset); + Option = (EFI_DHCP4_PACKET_OPTION *)(Buffer + Offset); } return NULL; } - /** - Parse the PXE vender options and extract the information from them. + Parse the PXE vendor options and extract the information from them. @param[in] Dhcp4Option Pointer to vendor options in buffer. @param[in] VendorOption Pointer to structure to store information in vendor options. @@ -92,18 +83,18 @@ PxeBcParseDhcp4Options ( **/ VOID PxeBcParseVendorOptions ( - IN EFI_DHCP4_PACKET_OPTION *Dhcp4Option, - IN PXEBC_VENDOR_OPTION *VendorOption + IN EFI_DHCP4_PACKET_OPTION *Dhcp4Option, + IN PXEBC_VENDOR_OPTION *VendorOption ) { - UINT32 *BitMap; - UINT8 VendorOptionLen; - EFI_DHCP4_PACKET_OPTION *PxeOption; - UINT8 Offset; + UINT32 *BitMap; + UINT8 VendorOptionLen; + EFI_DHCP4_PACKET_OPTION *PxeOption; + UINT8 Offset; BitMap = VendorOption->BitMap; VendorOptionLen = Dhcp4Option->Length; - PxeOption = (EFI_DHCP4_PACKET_OPTION *) &Dhcp4Option->Data[0]; + PxeOption = (EFI_DHCP4_PACKET_OPTION *)&Dhcp4Option->Data[0]; Offset = 0; ASSERT (PxeOption != NULL); @@ -113,84 +104,83 @@ PxeBcParseVendorOptions ( // Parse all the interesting PXE vendor options one by one. // switch (PxeOption->OpCode) { + case PXEBC_VENDOR_TAG_MTFTP_IP: - case PXEBC_VENDOR_TAG_MTFTP_IP: - - CopyMem (&VendorOption->MtftpIp, PxeOption->Data, sizeof (EFI_IPv4_ADDRESS)); - break; + CopyMem (&VendorOption->MtftpIp, PxeOption->Data, sizeof (EFI_IPv4_ADDRESS)); + break; - case PXEBC_VENDOR_TAG_MTFTP_CPORT: + case PXEBC_VENDOR_TAG_MTFTP_CPORT: - CopyMem (&VendorOption->MtftpCPort, PxeOption->Data, sizeof (VendorOption->MtftpCPort)); - break; + CopyMem (&VendorOption->MtftpCPort, PxeOption->Data, sizeof (VendorOption->MtftpCPort)); + break; - case PXEBC_VENDOR_TAG_MTFTP_SPORT: + case PXEBC_VENDOR_TAG_MTFTP_SPORT: - CopyMem (&VendorOption->MtftpSPort, PxeOption->Data, sizeof (VendorOption->MtftpSPort)); - break; + CopyMem (&VendorOption->MtftpSPort, PxeOption->Data, sizeof (VendorOption->MtftpSPort)); + break; - case PXEBC_VENDOR_TAG_MTFTP_TIMEOUT: + case PXEBC_VENDOR_TAG_MTFTP_TIMEOUT: - VendorOption->MtftpTimeout = *PxeOption->Data; - break; + VendorOption->MtftpTimeout = *PxeOption->Data; + break; - case PXEBC_VENDOR_TAG_MTFTP_DELAY: + case PXEBC_VENDOR_TAG_MTFTP_DELAY: - VendorOption->MtftpDelay = *PxeOption->Data; - break; + VendorOption->MtftpDelay = *PxeOption->Data; + break; - case PXEBC_VENDOR_TAG_DISCOVER_CTRL: + case PXEBC_VENDOR_TAG_DISCOVER_CTRL: - VendorOption->DiscoverCtrl = *PxeOption->Data; - break; + VendorOption->DiscoverCtrl = *PxeOption->Data; + break; - case PXEBC_VENDOR_TAG_DISCOVER_MCAST: + case PXEBC_VENDOR_TAG_DISCOVER_MCAST: - CopyMem (&VendorOption->DiscoverMcastIp, PxeOption->Data, sizeof (EFI_IPv4_ADDRESS)); - break; + CopyMem (&VendorOption->DiscoverMcastIp, PxeOption->Data, sizeof (EFI_IPv4_ADDRESS)); + break; - case PXEBC_VENDOR_TAG_BOOT_SERVERS: + case PXEBC_VENDOR_TAG_BOOT_SERVERS: - VendorOption->BootSvrLen = PxeOption->Length; - VendorOption->BootSvr = (PXEBC_BOOT_SVR_ENTRY *) PxeOption->Data; - break; + VendorOption->BootSvrLen = PxeOption->Length; + VendorOption->BootSvr = (PXEBC_BOOT_SVR_ENTRY *)PxeOption->Data; + break; - case PXEBC_VENDOR_TAG_BOOT_MENU: + case PXEBC_VENDOR_TAG_BOOT_MENU: - VendorOption->BootMenuLen = PxeOption->Length; - VendorOption->BootMenu = (PXEBC_BOOT_MENU_ENTRY *) PxeOption->Data; - break; + VendorOption->BootMenuLen = PxeOption->Length; + VendorOption->BootMenu = (PXEBC_BOOT_MENU_ENTRY *)PxeOption->Data; + break; - case PXEBC_VENDOR_TAG_MENU_PROMPT: + case PXEBC_VENDOR_TAG_MENU_PROMPT: - VendorOption->MenuPromptLen = PxeOption->Length; - VendorOption->MenuPrompt = (PXEBC_MENU_PROMPT *) PxeOption->Data; - break; + VendorOption->MenuPromptLen = PxeOption->Length; + VendorOption->MenuPrompt = (PXEBC_MENU_PROMPT *)PxeOption->Data; + break; - case PXEBC_VENDOR_TAG_MCAST_ALLOC: + case PXEBC_VENDOR_TAG_MCAST_ALLOC: - CopyMem (&VendorOption->McastIpBase, PxeOption->Data, sizeof (EFI_IPv4_ADDRESS)); - CopyMem (&VendorOption->McastIpBlock, PxeOption->Data + 4, sizeof (VendorOption->McastIpBlock)); - CopyMem (&VendorOption->McastIpRange, PxeOption->Data + 6, sizeof (VendorOption->McastIpRange)); - break; + CopyMem (&VendorOption->McastIpBase, PxeOption->Data, sizeof (EFI_IPv4_ADDRESS)); + CopyMem (&VendorOption->McastIpBlock, PxeOption->Data + 4, sizeof (VendorOption->McastIpBlock)); + CopyMem (&VendorOption->McastIpRange, PxeOption->Data + 6, sizeof (VendorOption->McastIpRange)); + break; - case PXEBC_VENDOR_TAG_CREDENTIAL_TYPES: + case PXEBC_VENDOR_TAG_CREDENTIAL_TYPES: - VendorOption->CredTypeLen = PxeOption->Length; - VendorOption->CredType = (UINT32 *) PxeOption->Data; - break; + VendorOption->CredTypeLen = PxeOption->Length; + VendorOption->CredType = (UINT32 *)PxeOption->Data; + break; - case PXEBC_VENDOR_TAG_BOOT_ITEM: + case PXEBC_VENDOR_TAG_BOOT_ITEM: - CopyMem (&VendorOption->BootSrvType, PxeOption->Data, sizeof (VendorOption->BootSrvType)); - CopyMem (&VendorOption->BootSrvLayer, PxeOption->Data + 2, sizeof (VendorOption->BootSrvLayer)); - break; + CopyMem (&VendorOption->BootSrvType, PxeOption->Data, sizeof (VendorOption->BootSrvType)); + CopyMem (&VendorOption->BootSrvLayer, PxeOption->Data + 2, sizeof (VendorOption->BootSrvLayer)); + break; - default: - // - // Not interesting PXE vendor options. - // - break; + default: + // + // Not interesting PXE vendor options. + // + break; } // @@ -204,14 +194,13 @@ PxeBcParseVendorOptions ( if (PxeOption->OpCode == DHCP4_TAG_PAD) { Offset++; } else { - Offset = (UINT8) (Offset + PxeOption->Length + 2); + Offset = (UINT8)(Offset + PxeOption->Length + 2); } - PxeOption = (EFI_DHCP4_PACKET_OPTION *) (Dhcp4Option->Data + Offset); + PxeOption = (EFI_DHCP4_PACKET_OPTION *)(Dhcp4Option->Data + Offset); } } - /** Build the options buffer for the DHCPv4 request packet. @@ -232,34 +221,34 @@ PxeBcBuildDhcp4Options ( IN BOOLEAN NeedMsgType ) { - UINT32 Index; - PXEBC_DHCP4_OPTION_ENTRY OptEnt; - UINT16 Value; + UINT32 Index; + PXEBC_DHCP4_OPTION_ENTRY OptEnt; + UINT16 Value; Index = 0; - OptList[0] = (EFI_DHCP4_PACKET_OPTION *) Buffer; + OptList[0] = (EFI_DHCP4_PACKET_OPTION *)Buffer; if (NeedMsgType) { // // Append message type. // - OptList[Index]->OpCode = DHCP4_TAG_MSG_TYPE; - OptList[Index]->Length = 1; - OptEnt.Mesg = (PXEBC_DHCP4_OPTION_MESG *) OptList[Index]->Data; - OptEnt.Mesg->Type = PXEBC_DHCP4_MSG_TYPE_REQUEST; + OptList[Index]->OpCode = DHCP4_TAG_MSG_TYPE; + OptList[Index]->Length = 1; + OptEnt.Mesg = (PXEBC_DHCP4_OPTION_MESG *)OptList[Index]->Data; + OptEnt.Mesg->Type = PXEBC_DHCP4_MSG_TYPE_REQUEST; Index++; - OptList[Index] = GET_NEXT_DHCP_OPTION (OptList[Index - 1]); + OptList[Index] = GET_NEXT_DHCP_OPTION (OptList[Index - 1]); // // Append max message size. // - OptList[Index]->OpCode = DHCP4_TAG_MAXMSG; - OptList[Index]->Length = (UINT8) sizeof (PXEBC_DHCP4_OPTION_MAX_MESG_SIZE); - OptEnt.MaxMesgSize = (PXEBC_DHCP4_OPTION_MAX_MESG_SIZE *) OptList[Index]->Data; - Value = NTOHS (PXEBC_DHCP4_PACKET_MAX_SIZE - 8); + OptList[Index]->OpCode = DHCP4_TAG_MAXMSG; + OptList[Index]->Length = (UINT8)sizeof (PXEBC_DHCP4_OPTION_MAX_MESG_SIZE); + OptEnt.MaxMesgSize = (PXEBC_DHCP4_OPTION_MAX_MESG_SIZE *)OptList[Index]->Data; + Value = NTOHS (PXEBC_DHCP4_PACKET_MAX_SIZE); CopyMem (&OptEnt.MaxMesgSize->Size, &Value, sizeof (UINT16)); Index++; - OptList[Index] = GET_NEXT_DHCP_OPTION (OptList[Index - 1]); + OptList[Index] = GET_NEXT_DHCP_OPTION (OptList[Index - 1]); } // @@ -267,7 +256,7 @@ PxeBcBuildDhcp4Options ( // OptList[Index]->OpCode = DHCP4_TAG_PARA_LIST; OptList[Index]->Length = 35; - OptEnt.Para = (PXEBC_DHCP4_OPTION_PARA *) OptList[Index]->Data; + OptEnt.Para = (PXEBC_DHCP4_OPTION_PARA *)OptList[Index]->Data; OptEnt.Para->ParaList[0] = DHCP4_TAG_NETMASK; OptEnt.Para->ParaList[1] = DHCP4_TAG_TIME_OFFSET; OptEnt.Para->ParaList[2] = DHCP4_TAG_ROUTER; @@ -304,31 +293,32 @@ PxeBcBuildDhcp4Options ( OptEnt.Para->ParaList[33] = 0x86; OptEnt.Para->ParaList[34] = 0x87; Index++; - OptList[Index] = GET_NEXT_DHCP_OPTION (OptList[Index - 1]); + OptList[Index] = GET_NEXT_DHCP_OPTION (OptList[Index - 1]); // // Append UUID/Guid-based client identifier option // - OptList[Index]->OpCode = DHCP4_TAG_UUID; - OptList[Index]->Length = (UINT8) sizeof (PXEBC_DHCP4_OPTION_UUID); - OptEnt.Uuid = (PXEBC_DHCP4_OPTION_UUID *) OptList[Index]->Data; - OptEnt.Uuid->Type = 0; + OptList[Index]->OpCode = DHCP4_TAG_UUID; + OptList[Index]->Length = (UINT8)sizeof (PXEBC_DHCP4_OPTION_UUID); + OptEnt.Uuid = (PXEBC_DHCP4_OPTION_UUID *)OptList[Index]->Data; + OptEnt.Uuid->Type = 0; Index++; - OptList[Index] = GET_NEXT_DHCP_OPTION (OptList[Index - 1]); + OptList[Index] = GET_NEXT_DHCP_OPTION (OptList[Index - 1]); - if (EFI_ERROR (NetLibGetSystemGuid ((EFI_GUID *) OptEnt.Uuid->Guid))) { + if (EFI_ERROR (NetLibGetSystemGuid ((EFI_GUID *)OptEnt.Uuid->Guid))) { // - // Zero the Guid to indicate NOT programable if failed to get system Guid. + // Zero the Guid to indicate NOT programmable if failed to get system Guid. // + DEBUG ((DEBUG_WARN, "PXE: Failed to read system GUID from the smbios table!\n")); ZeroMem (OptEnt.Uuid->Guid, sizeof (EFI_GUID)); } // // Append client network device interface option // - OptList[Index]->OpCode = DHCP4_TAG_UNDI; - OptList[Index]->Length = (UINT8) sizeof (PXEBC_DHCP4_OPTION_UNDI); - OptEnt.Undi = (PXEBC_DHCP4_OPTION_UNDI *) OptList[Index]->Data; + OptList[Index]->OpCode = DHCP4_TAG_UNDI; + OptList[Index]->Length = (UINT8)sizeof (PXEBC_DHCP4_OPTION_UNDI); + OptEnt.Undi = (PXEBC_DHCP4_OPTION_UNDI *)OptList[Index]->Data; if (Private->Nii != NULL) { OptEnt.Undi->Type = Private->Nii->Type; @@ -346,20 +336,20 @@ PxeBcBuildDhcp4Options ( // // Append client system architecture option // - OptList[Index]->OpCode = DHCP4_TAG_ARCH; - OptList[Index]->Length = (UINT8) sizeof (PXEBC_DHCP4_OPTION_ARCH); - OptEnt.Arch = (PXEBC_DHCP4_OPTION_ARCH *) OptList[Index]->Data; - Value = HTONS (EFI_PXE_CLIENT_SYSTEM_ARCHITECTURE); + OptList[Index]->OpCode = DHCP4_TAG_ARCH; + OptList[Index]->Length = (UINT8)sizeof (PXEBC_DHCP4_OPTION_ARCH); + OptEnt.Arch = (PXEBC_DHCP4_OPTION_ARCH *)OptList[Index]->Data; + Value = HTONS (EFI_PXE_CLIENT_SYSTEM_ARCHITECTURE); CopyMem (&OptEnt.Arch->Type, &Value, sizeof (UINT16)); Index++; - OptList[Index] = GET_NEXT_DHCP_OPTION (OptList[Index - 1]); + OptList[Index] = GET_NEXT_DHCP_OPTION (OptList[Index - 1]); // // Append vendor class identify option // - OptList[Index]->OpCode = DHCP4_TAG_VENDOR_CLASS_ID; - OptList[Index]->Length = (UINT8) sizeof (PXEBC_DHCP4_OPTION_CLID); - OptEnt.Clid = (PXEBC_DHCP4_OPTION_CLID *) OptList[Index]->Data; + OptList[Index]->OpCode = DHCP4_TAG_VENDOR_CLASS_ID; + OptList[Index]->Length = (UINT8)sizeof (PXEBC_DHCP4_OPTION_CLID); + OptEnt.Clid = (PXEBC_DHCP4_OPTION_CLID *)OptList[Index]->Data; CopyMem ( OptEnt.Clid, DEFAULT_CLASS_ID_DATA, @@ -382,7 +372,6 @@ PxeBcBuildDhcp4Options ( return Index; } - /** Create a template DHCPv4 packet as a seed. @@ -392,51 +381,56 @@ PxeBcBuildDhcp4Options ( **/ VOID PxeBcSeedDhcp4Packet ( - OUT EFI_DHCP4_PACKET *Seed, - IN EFI_UDP4_PROTOCOL *Udp4 + OUT EFI_DHCP4_PACKET *Seed, + IN EFI_UDP4_PROTOCOL *Udp4 ) { - EFI_SIMPLE_NETWORK_MODE Mode; - EFI_DHCP4_HEADER *Header; + EFI_SIMPLE_NETWORK_MODE Mode; + EFI_DHCP4_HEADER *Header; // // Get IfType and HwAddressSize from SNP mode data. // Udp4->GetModeData (Udp4, NULL, NULL, NULL, &Mode); - Seed->Size = sizeof (EFI_DHCP4_PACKET); - Seed->Length = sizeof (Seed->Dhcp4); - Header = &Seed->Dhcp4.Header; + Seed->Size = sizeof (EFI_DHCP4_PACKET); + Seed->Length = sizeof (Seed->Dhcp4); + Header = &Seed->Dhcp4.Header; ZeroMem (Header, sizeof (EFI_DHCP4_HEADER)); - Header->OpCode = PXEBC_DHCP4_OPCODE_REQUEST; - Header->HwType = Mode.IfType; - Header->HwAddrLen = (UINT8) Mode.HwAddressSize; + Header->OpCode = PXEBC_DHCP4_OPCODE_REQUEST; + Header->HwType = Mode.IfType; + Header->HwAddrLen = (UINT8)Mode.HwAddressSize; CopyMem (Header->ClientHwAddr, &Mode.CurrentAddress, Header->HwAddrLen); Seed->Dhcp4.Magik = PXEBC_DHCP4_MAGIC; Seed->Dhcp4.Option[0] = DHCP4_TAG_EOP; } - /** Cache the DHCPv4 packet. @param[in] Dst Pointer to the cache buffer for DHCPv4 packet. @param[in] Src Pointer to the DHCPv4 packet to be cached. + @retval EFI_SUCCESS Packet is copied. + @retval EFI_BUFFER_TOO_SMALL Cache buffer is not big enough to hold the packet. + **/ -VOID +EFI_STATUS PxeBcCacheDhcp4Packet ( - IN EFI_DHCP4_PACKET *Dst, - IN EFI_DHCP4_PACKET *Src + IN EFI_DHCP4_PACKET *Dst, + IN EFI_DHCP4_PACKET *Src ) { - ASSERT (Dst->Size >= Src->Length); + if (Dst->Size < Src->Length) { + return EFI_BUFFER_TOO_SMALL; + } CopyMem (&Dst->Dhcp4, &Src->Dhcp4, Src->Length); Dst->Length = Src->Length; -} + return EFI_SUCCESS; +} /** Parse the cached DHCPv4 packet, including all the options. @@ -449,21 +443,21 @@ PxeBcCacheDhcp4Packet ( **/ EFI_STATUS PxeBcParseDhcp4Packet ( - IN PXEBC_DHCP4_PACKET_CACHE *Cache4 + IN PXEBC_DHCP4_PACKET_CACHE *Cache4 ) { - EFI_DHCP4_PACKET *Offer; - EFI_DHCP4_PACKET_OPTION **Options; - EFI_DHCP4_PACKET_OPTION *Option; - PXEBC_OFFER_TYPE OfferType; - UINTN Index; - BOOLEAN IsProxyOffer; - BOOLEAN IsPxeOffer; - UINT8 *Ptr8; - BOOLEAN FileFieldOverloaded; - - IsProxyOffer = FALSE; - IsPxeOffer = FALSE; + EFI_DHCP4_PACKET *Offer; + EFI_DHCP4_PACKET_OPTION **Options; + EFI_DHCP4_PACKET_OPTION *Option; + PXEBC_OFFER_TYPE OfferType; + UINTN Index; + BOOLEAN IsProxyOffer; + BOOLEAN IsPxeOffer; + UINT8 *Ptr8; + BOOLEAN FileFieldOverloaded; + + IsProxyOffer = FALSE; + IsPxeOffer = FALSE; FileFieldOverloaded = FALSE; ZeroMem (Cache4->OptList, sizeof (Cache4->OptList)); @@ -483,8 +477,9 @@ PxeBcParseDhcp4Packet ( mInterestedDhcp4Tags[Index] ); } + // - // Second, Check if bootfilename and serverhostname is overloaded to carry DHCP options refers to rfc-2132. + // Second, Check if bootfilename and serverhostname is overloaded to carry DHCP options refers to rfc-2132. // If yes, try to parse options from the BootFileName field, then ServerName field. // Option = Options[PXEBC_DHCP4_TAG_INDEX_OVERLOAD]; @@ -494,18 +489,19 @@ PxeBcParseDhcp4Packet ( for (Index = 0; Index < PXEBC_DHCP4_TAG_INDEX_MAX; Index++) { if (Options[Index] == NULL) { Options[Index] = PxeBcParseDhcp4Options ( - (UINT8 *) Offer->Dhcp4.Header.BootFileName, + (UINT8 *)Offer->Dhcp4.Header.BootFileName, sizeof (Offer->Dhcp4.Header.BootFileName), mInterestedDhcp4Tags[Index] ); } } } + if ((Option->Data[0] & PXEBC_DHCP4_OVERLOAD_SERVER_NAME) != 0) { for (Index = 0; Index < PXEBC_DHCP4_TAG_INDEX_MAX; Index++) { if (Options[Index] == NULL) { Options[Index] = PxeBcParseDhcp4Options ( - (UINT8 *) Offer->Dhcp4.Header.ServerName, + (UINT8 *)Offer->Dhcp4.Header.ServerName, sizeof (Offer->Dhcp4.Header.ServerName), mInterestedDhcp4Tags[Index] ); @@ -526,7 +522,8 @@ PxeBcParseDhcp4Packet ( // Option = Options[PXEBC_DHCP4_TAG_INDEX_CLASS_ID]; if ((Option != NULL) && (Option->Length >= 9) && - (CompareMem (Option->Data, DEFAULT_CLASS_ID_DATA, 9) == 0)) { + (CompareMem (Option->Data, DEFAULT_CLASS_ID_DATA, 9) == 0)) + { IsPxeOffer = TRUE; } @@ -534,7 +531,7 @@ PxeBcParseDhcp4Packet ( // Parse PXE vendor options in this offer, and store the contents/pointers. // Option = Options[PXEBC_DHCP4_TAG_INDEX_VENDOR]; - if (IsPxeOffer && Option != NULL) { + if (IsPxeOffer && (Option != NULL)) { PxeBcParseVendorOptions (Option, &Cache4->VendorOpt); } @@ -548,33 +545,32 @@ PxeBcParseDhcp4Packet ( // RFC 2132, Section 9.5 does not strictly state Bootfile name (option 67) is null // terminated string. So force to append null terminated character at the end of string. // - Ptr8 = (UINT8*)&Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Data[0]; + Ptr8 = (UINT8 *)&Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Data[0]; Ptr8 += Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]->Length; if (*(Ptr8 - 1) != '\0') { *Ptr8 = '\0'; } - } else if (!FileFieldOverloaded && Offer->Dhcp4.Header.BootFileName[0] != 0) { + } else if (!FileFieldOverloaded && (Offer->Dhcp4.Header.BootFileName[0] != 0)) { // // If the bootfile is not present and bootfilename is present in DHCPv4 packet, just parse it. // Do not count dhcp option header here, or else will destroy the serverhostname. // Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] = (EFI_DHCP4_PACKET_OPTION *) - (&Offer->Dhcp4.Header.BootFileName[0] - - OFFSET_OF (EFI_DHCP4_PACKET_OPTION, Data[0])); - + (&Offer->Dhcp4.Header.BootFileName[0] - + OFFSET_OF (EFI_DHCP4_PACKET_OPTION, Data[0])); } // // Determine offer type of the DHCPv4 packet. // Option = Options[PXEBC_DHCP4_TAG_INDEX_MSG_TYPE]; - if (Option == NULL || Option->Data[0] == 0) { + if ((Option == NULL) || (Option->Data[0] == 0)) { // // It's a Bootp offer. // OfferType = PxeOfferTypeBootp; - Option = Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]; + Option = Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE]; if (Option == NULL) { // // If the Bootp offer without bootfilename, discard it. @@ -582,7 +578,6 @@ PxeBcParseDhcp4Packet ( return EFI_DEVICE_ERROR; } } else { - if (IS_VALID_DISCOVER_VENDOR_OPTION (Cache4->VendorOpt.BitMap)) { // // It's a PXE10 offer with PXEClient and discover vendor option. @@ -612,7 +607,6 @@ PxeBcParseDhcp4Packet ( return EFI_SUCCESS; } - /** Cache the DHCPv4 ack packet, and parse it on demand. @@ -620,19 +614,26 @@ PxeBcParseDhcp4Packet ( @param[in] Ack Pointer to the DHCPv4 ack packet. @param[in] Verified If TRUE, parse the ACK packet and store info into mode data. + @retval EFI_SUCCESS Cache and parse the packet successfully. + @retval EFI_BUFFER_TOO_SMALL Cache buffer is not big enough to hold the packet. + **/ -VOID +EFI_STATUS PxeBcCopyDhcp4Ack ( - IN PXEBC_PRIVATE_DATA *Private, - IN EFI_DHCP4_PACKET *Ack, - IN BOOLEAN Verified + IN PXEBC_PRIVATE_DATA *Private, + IN EFI_DHCP4_PACKET *Ack, + IN BOOLEAN Verified ) { EFI_PXE_BASE_CODE_MODE *Mode; + EFI_STATUS Status; Mode = Private->PxeBc.Mode; - PxeBcCacheDhcp4Packet (&Private->DhcpAck.Dhcp4.Packet.Ack, Ack); + Status = PxeBcCacheDhcp4Packet (&Private->DhcpAck.Dhcp4.Packet.Ack, Ack); + if (EFI_ERROR (Status)) { + return Status; + } if (Verified) { // @@ -642,8 +643,9 @@ PxeBcCopyDhcp4Ack ( CopyMem (&Mode->DhcpAck.Dhcpv4, &Ack->Dhcp4, Ack->Length); Mode->DhcpAckReceived = TRUE; } -} + return EFI_SUCCESS; +} /** Cache the DHCPv4 proxy offer packet according to the received order. @@ -651,15 +653,19 @@ PxeBcCopyDhcp4Ack ( @param[in] Private Pointer to PxeBc private data. @param[in] OfferIndex The received order of offer packets. + @retval EFI_SUCCESS Cache and parse the packet successfully. + @retval EFI_BUFFER_TOO_SMALL Cache buffer is not big enough to hold the packet. + **/ -VOID +EFI_STATUS PxeBcCopyProxyOffer ( - IN PXEBC_PRIVATE_DATA *Private, - IN UINT32 OfferIndex + IN PXEBC_PRIVATE_DATA *Private, + IN UINT32 OfferIndex ) { EFI_PXE_BASE_CODE_MODE *Mode; EFI_DHCP4_PACKET *Offer; + EFI_STATUS Status; ASSERT (OfferIndex < Private->OfferNum); ASSERT (OfferIndex < PXEBC_OFFER_MAX_NUM); @@ -670,7 +676,11 @@ PxeBcCopyProxyOffer ( // // Cache the proxy offer packet and parse it. // - PxeBcCacheDhcp4Packet (&Private->ProxyOffer.Dhcp4.Packet.Offer, Offer); + Status = PxeBcCacheDhcp4Packet (&Private->ProxyOffer.Dhcp4.Packet.Offer, Offer); + if (EFI_ERROR (Status)) { + return Status; + } + PxeBcParseDhcp4Packet (&Private->ProxyOffer.Dhcp4); // @@ -678,8 +688,9 @@ PxeBcCopyProxyOffer ( // CopyMem (&Mode->ProxyOffer.Dhcpv4, &Offer->Dhcp4, Offer->Length); Mode->ProxyOfferReceived = TRUE; -} + return EFI_SUCCESS; +} /** Retry to request bootfile name by the BINL offer. @@ -693,8 +704,8 @@ PxeBcCopyProxyOffer ( **/ EFI_STATUS PxeBcRetryBinlOffer ( - IN PXEBC_PRIVATE_DATA *Private, - IN UINT32 Index + IN PXEBC_PRIVATE_DATA *Private, + IN UINT32 Index ) { EFI_DHCP4_PACKET *Offer; @@ -704,8 +715,10 @@ PxeBcRetryBinlOffer ( EFI_DHCP4_PACKET *Reply; ASSERT (Index < PXEBC_OFFER_MAX_NUM); - ASSERT (Private->OfferBuffer[Index].Dhcp4.OfferType == PxeOfferTypeDhcpBinl || - Private->OfferBuffer[Index].Dhcp4.OfferType == PxeOfferTypeProxyBinl); + ASSERT ( + Private->OfferBuffer[Index].Dhcp4.OfferType == PxeOfferTypeDhcpBinl || + Private->OfferBuffer[Index].Dhcp4.OfferType == PxeOfferTypeProxyBinl + ); Offer = &Private->OfferBuffer[Index].Dhcp4.Packet.Offer; @@ -754,9 +767,10 @@ PxeBcRetryBinlOffer ( return Status; } - if (Cache4->OfferType != PxeOfferTypeProxyPxe10 && - Cache4->OfferType != PxeOfferTypeProxyWfm11a && - Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] == NULL) { + if ((Cache4->OfferType != PxeOfferTypeProxyPxe10) && + (Cache4->OfferType != PxeOfferTypeProxyWfm11a) && + (Cache4->OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] == NULL)) + { // // This BINL ack doesn't have discovery option set or multicast option set // or bootfile name specified. @@ -773,23 +787,26 @@ PxeBcRetryBinlOffer ( return EFI_SUCCESS; } - /** Cache all the received DHCPv4 offers, and set OfferIndex and OfferCount. @param[in] Private Pointer to PxeBc private data. @param[in] RcvdOffer Pointer to the received offer packet. + @retval EFI_SUCCESS Cache and parse the packet successfully. + @retval Others Operation failed. + **/ -VOID +EFI_STATUS PxeBcCacheDhcp4Offer ( - IN PXEBC_PRIVATE_DATA *Private, - IN EFI_DHCP4_PACKET *RcvdOffer + IN PXEBC_PRIVATE_DATA *Private, + IN EFI_DHCP4_PACKET *RcvdOffer ) { PXEBC_DHCP4_PACKET_CACHE *Cache4; EFI_DHCP4_PACKET *Offer; PXEBC_OFFER_TYPE OfferType; + EFI_STATUS Status; ASSERT (Private->OfferNum < PXEBC_OFFER_MAX_NUM); Cache4 = &Private->OfferBuffer[Private->OfferNum].Dhcp4; @@ -798,13 +815,16 @@ PxeBcCacheDhcp4Offer ( // // Cache the content of DHCPv4 packet firstly. // - PxeBcCacheDhcp4Packet (Offer, RcvdOffer); + Status = PxeBcCacheDhcp4Packet (Offer, RcvdOffer); + if (EFI_ERROR (Status)) { + return Status; + } // // Validate the DHCPv4 packet, and parse the options and offer type. // if (EFI_ERROR (PxeBcParseDhcp4Packet (Cache4))) { - return; + return EFI_ABORTED; } // @@ -821,7 +841,7 @@ PxeBcCacheDhcp4Offer ( Private->OfferIndex[OfferType][0] = Private->OfferNum; Private->OfferCount[OfferType] = 1; } else { - return; + return EFI_ABORTED; } } else { ASSERT (Private->OfferCount[OfferType] < PXEBC_OFFER_MAX_NUM); @@ -837,14 +857,16 @@ PxeBcCacheDhcp4Offer ( // Private->OfferIndex[OfferType][Private->OfferCount[OfferType]] = Private->OfferNum; Private->OfferCount[OfferType]++; - } else if (Private->OfferCount[OfferType] > 0) { + } else if (((OfferType == PxeOfferTypeProxyPxe10) || (OfferType == PxeOfferTypeProxyWfm11a)) && + (Private->OfferCount[OfferType] < 1)) + { // // Only cache the first PXE10/WFM11a offer, and discard the others. // Private->OfferIndex[OfferType][0] = Private->OfferNum; Private->OfferCount[OfferType] = 1; } else { - return ; + return EFI_ABORTED; } } else { // @@ -856,8 +878,9 @@ PxeBcCacheDhcp4Offer ( } Private->OfferNum++; -} + return EFI_SUCCESS; +} /** Select an DHCPv4 offer, and record SelectIndex and SelectProxyType. @@ -867,12 +890,12 @@ PxeBcCacheDhcp4Offer ( **/ VOID PxeBcSelectDhcp4Offer ( - IN PXEBC_PRIVATE_DATA *Private + IN PXEBC_PRIVATE_DATA *Private ) { - UINT32 Index; - UINT32 OfferIndex; - EFI_DHCP4_PACKET *Offer; + UINT32 Index; + UINT32 OfferIndex; + EFI_DHCP4_PACKET *Offer; Private->SelectIndex = 0; @@ -885,43 +908,40 @@ PxeBcSelectDhcp4Offer ( // 1. DhcpPxe10 offer // Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpPxe10][0] + 1; - } else if (Private->OfferCount[PxeOfferTypeDhcpWfm11a] > 0) { // // 2. DhcpWfm11a offer // Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpWfm11a][0] + 1; - - } else if (Private->OfferCount[PxeOfferTypeDhcpOnly] > 0 && - Private->OfferCount[PxeOfferTypeProxyPxe10] > 0) { + } else if ((Private->OfferCount[PxeOfferTypeDhcpOnly] > 0) && + (Private->OfferCount[PxeOfferTypeProxyPxe10] > 0)) + { // // 3. DhcpOnly offer and ProxyPxe10 offer. // Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpOnly][0] + 1; Private->SelectProxyType = PxeOfferTypeProxyPxe10; - - } else if (Private->OfferCount[PxeOfferTypeDhcpOnly] > 0 && - Private->OfferCount[PxeOfferTypeProxyWfm11a] > 0) { + } else if ((Private->OfferCount[PxeOfferTypeDhcpOnly] > 0) && + (Private->OfferCount[PxeOfferTypeProxyWfm11a] > 0)) + { // // 4. DhcpOnly offer and ProxyWfm11a offer. // Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpOnly][0] + 1; Private->SelectProxyType = PxeOfferTypeProxyWfm11a; - } else if (Private->OfferCount[PxeOfferTypeDhcpBinl] > 0) { // // 5. DhcpBinl offer. // Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpBinl][0] + 1; - - } else if (Private->OfferCount[PxeOfferTypeDhcpOnly] > 0 && - Private->OfferCount[PxeOfferTypeProxyBinl] > 0) { + } else if ((Private->OfferCount[PxeOfferTypeDhcpOnly] > 0) && + (Private->OfferCount[PxeOfferTypeProxyBinl] > 0)) + { // // 6. DhcpOnly offer and ProxyBinl offer. // Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpOnly][0] + 1; Private->SelectProxyType = PxeOfferTypeProxyBinl; - } else { // // 7. DhcpOnly offer with bootfilename. @@ -933,13 +953,15 @@ PxeBcSelectDhcp4Offer ( break; } } + // // 8. Bootp offer with bootfilename. // OfferIndex = Private->OfferIndex[PxeOfferTypeBootp][0]; - if (Private->SelectIndex == 0 && - Private->OfferCount[PxeOfferTypeBootp] > 0 && - Private->OfferBuffer[OfferIndex].Dhcp4.OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] != NULL) { + if ((Private->SelectIndex == 0) && + (Private->OfferCount[PxeOfferTypeBootp] > 0) && + (Private->OfferBuffer[OfferIndex].Dhcp4.OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] != NULL)) + { Private->SelectIndex = OfferIndex + 1; } } @@ -948,7 +970,6 @@ PxeBcSelectDhcp4Offer ( // Select offer by received order. // for (Index = 0; Index < Private->OfferNum; Index++) { - Offer = &Private->OfferBuffer[Index].Dhcp4.Packet.Offer; if (IS_PROXY_DHCP_OFFER (Offer)) { @@ -959,8 +980,9 @@ PxeBcSelectDhcp4Offer ( } if (!Private->IsProxyRecved && - Private->OfferBuffer[Index].Dhcp4.OfferType == PxeOfferTypeDhcpOnly && - Private->OfferBuffer[Index].Dhcp4.OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] == NULL) { + (Private->OfferBuffer[Index].Dhcp4.OfferType == PxeOfferTypeDhcpOnly) && + (Private->OfferBuffer[Index].Dhcp4.OptList[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] == NULL)) + { // // Skip if DhcpOnly offer without any other proxy offers or bootfilename. // @@ -976,20 +998,20 @@ PxeBcSelectDhcp4Offer ( } } - /** Handle the DHCPv4 offer packet. - @param[in] Private Pointer to PxeBc private data. + @param[in] Private Pointer to PxeBc private data. - @retval EFI_SUCCESS Handled the DHCPv4 offer packet successfully. - @retval EFI_NO_RESPONSE No response to the following request packet. - @retval EFI_NOT_FOUND No boot filename received. + @retval EFI_SUCCESS Handled the DHCPv4 offer packet successfully. + @retval EFI_NO_RESPONSE No response to the following request packet. + @retval EFI_NOT_FOUND No boot filename received. + @retval EFI_BUFFER_TOO_SMALL Can't cache the offer pacet. **/ EFI_STATUS PxeBcHandleDhcp4Offer ( - IN PXEBC_PRIVATE_DATA *Private + IN PXEBC_PRIVATE_DATA *Private ) { PXEBC_DHCP4_PACKET_CACHE *Cache4; @@ -1004,11 +1026,11 @@ PxeBcHandleDhcp4Offer ( EFI_DHCP4_PACKET *Ack; ASSERT (Private->SelectIndex > 0); - SelectIndex = (UINT32) (Private->SelectIndex - 1); + SelectIndex = (UINT32)(Private->SelectIndex - 1); ASSERT (SelectIndex < PXEBC_OFFER_MAX_NUM); - Cache4 = &Private->OfferBuffer[SelectIndex].Dhcp4; - Options = Cache4->OptList; - Status = EFI_SUCCESS; + Cache4 = &Private->OfferBuffer[SelectIndex].Dhcp4; + Options = Cache4->OptList; + Status = EFI_SUCCESS; if (Cache4->OfferType == PxeOfferTypeDhcpBinl) { // @@ -1018,7 +1040,6 @@ PxeBcHandleDhcp4Offer ( Status = EFI_NO_RESPONSE; } } else if (Cache4->OfferType == PxeOfferTypeDhcpOnly) { - if (Private->IsProxyRecved) { // // DhcpOnly offer is selected, so need try to request bootfile name. @@ -1043,6 +1064,7 @@ PxeBcHandleDhcp4Offer ( break; } } + if (Index == Private->OfferCount[Private->SelectProxyType]) { Status = EFI_NO_RESPONSE; } @@ -1085,15 +1107,15 @@ PxeBcHandleDhcp4Offer ( } } - if (!EFI_ERROR (Status) && Private->SelectProxyType != PxeOfferTypeProxyBinl) { + if (!EFI_ERROR (Status) && (Private->SelectProxyType != PxeOfferTypeProxyBinl)) { // // Success to try to request by a ProxyPxe10 or ProxyWfm11a offer, copy and parse it. // - PxeBcCopyProxyOffer (Private, ProxyIndex); + Status = PxeBcCopyProxyOffer (Private, ProxyIndex); } } else { // - // Othewise, the bootfile name must be included in DhcpOnly offer. + // Otherwise, the bootfile name must be included in DhcpOnly offer. // if (Options[PXEBC_DHCP4_TAG_INDEX_BOOTFILE] == NULL) { Status = EFI_NOT_FOUND; @@ -1116,14 +1138,17 @@ PxeBcHandleDhcp4Offer ( Ack = Offer; } - PxeBcCopyDhcp4Ack (Private, Ack, TRUE); + Status = PxeBcCopyDhcp4Ack (Private, Ack, TRUE); + if (EFI_ERROR (Status)) { + return Status; + } + Mode->DhcpDiscoverValid = TRUE; } return Status; } - /** EFI_DHCP4_CALLBACK is provided by the consumer of the EFI DHCPv4 Protocol driver to intercept events that occurred in the configuration process. @@ -1147,12 +1172,12 @@ PxeBcHandleDhcp4Offer ( EFI_STATUS EFIAPI PxeBcDhcp4CallBack ( - IN EFI_DHCP4_PROTOCOL *This, - IN VOID *Context, - IN EFI_DHCP4_STATE CurrentState, - IN EFI_DHCP4_EVENT Dhcp4Event, - IN EFI_DHCP4_PACKET *Packet OPTIONAL, - OUT EFI_DHCP4_PACKET **NewPacket OPTIONAL + IN EFI_DHCP4_PROTOCOL *This, + IN VOID *Context, + IN EFI_DHCP4_STATE CurrentState, + IN EFI_DHCP4_EVENT Dhcp4Event, + IN EFI_DHCP4_PACKET *Packet OPTIONAL, + OUT EFI_DHCP4_PACKET **NewPacket OPTIONAL ) { PXEBC_PRIVATE_DATA *Private; @@ -1166,13 +1191,16 @@ PxeBcDhcp4CallBack ( if ((Dhcp4Event != Dhcp4RcvdOffer) && (Dhcp4Event != Dhcp4SelectOffer) && (Dhcp4Event != Dhcp4SendDiscover) && - (Dhcp4Event != Dhcp4RcvdAck)) { + (Dhcp4Event != Dhcp4RcvdAck)) + { return EFI_SUCCESS; } - Private = (PXEBC_PRIVATE_DATA *) Context; - Mode = Private->PxeBc.Mode; - Callback = Private->PxeBcCallback; + ASSERT (Packet != NULL); + + Private = (PXEBC_PRIVATE_DATA *)Context; + Mode = Private->PxeBc.Mode; + Callback = Private->PxeBcCallback; // // Override the Maximum DHCP Message Size. @@ -1183,22 +1211,22 @@ PxeBcDhcp4CallBack ( DHCP4_TAG_MAXMSG ); if (MaxMsgSize != NULL) { - Value = HTONS (PXEBC_DHCP4_PACKET_MAX_SIZE - 8); + Value = HTONS (PXEBC_DHCP4_PACKET_MAX_SIZE); CopyMem (MaxMsgSize->Data, &Value, sizeof (Value)); } // // Callback to user if any packets sent or received. // - if (Dhcp4Event != Dhcp4SelectOffer && Callback != NULL) { - Received = (BOOLEAN) (Dhcp4Event == Dhcp4RcvdOffer || Dhcp4Event == Dhcp4RcvdAck); - Status = Callback->Callback ( - Callback, - Private->Function, - Received, - Packet->Length, - (EFI_PXE_BASE_CODE_PACKET *) &Packet->Dhcp4 - ); + if ((Dhcp4Event != Dhcp4SelectOffer) && (Callback != NULL)) { + Received = (BOOLEAN)(Dhcp4Event == Dhcp4RcvdOffer || Dhcp4Event == Dhcp4RcvdAck); + Status = Callback->Callback ( + Callback, + Private->Function, + Received, + Packet->Length, + (EFI_PXE_BASE_CODE_PACKET *)&Packet->Dhcp4 + ); if (Status != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) { return EFI_ABORTED; } @@ -1207,72 +1235,105 @@ PxeBcDhcp4CallBack ( Status = EFI_SUCCESS; switch (Dhcp4Event) { + case Dhcp4SendDiscover: + if (Packet->Length > PXEBC_DHCP4_PACKET_MAX_SIZE) { + // + // If the to be sent packet exceeds the maximum length, abort the DHCP process. + // + Status = EFI_ABORTED; + break; + } - case Dhcp4SendDiscover: - // - // Cache the DHCPv4 discover packet to mode data directly. - // It need to check SendGuid as well as Dhcp4SendRequest. - // - CopyMem (&Mode->DhcpDiscover.Dhcpv4, &Packet->Dhcp4, Packet->Length); - - case Dhcp4SendRequest: - if (Mode->SendGUID) { // - // Send the system Guid instead of the MAC address as the hardware address if required. + // Cache the DHCPv4 discover packet to mode data directly. + // It need to check SendGuid as well as Dhcp4SendRequest. // - if (EFI_ERROR (NetLibGetSystemGuid ((EFI_GUID *) Packet->Dhcp4.Header.ClientHwAddr))) { + CopyMem (&Mode->DhcpDiscover.Dhcpv4, &Packet->Dhcp4, Packet->Length); + + case Dhcp4SendRequest: + if (Packet->Length > PXEBC_DHCP4_PACKET_MAX_SIZE) { // - // Zero the Guid to indicate NOT programable if failed to get system Guid. + // If the to be sent packet exceeds the maximum length, abort the DHCP process. // - ZeroMem (Packet->Dhcp4.Header.ClientHwAddr, sizeof (EFI_GUID)); + Status = EFI_ABORTED; + break; + } + + if (Mode->SendGUID) { + // + // Send the system Guid instead of the MAC address as the hardware address if required. + // + if (EFI_ERROR (NetLibGetSystemGuid ((EFI_GUID *)Packet->Dhcp4.Header.ClientHwAddr))) { + // + // Zero the Guid to indicate NOT programmable if failed to get system Guid. + // + DEBUG ((DEBUG_WARN, "PXE: Failed to read system GUID from the smbios table!\n")); + ZeroMem (Packet->Dhcp4.Header.ClientHwAddr, sizeof (EFI_GUID)); + } + + Packet->Dhcp4.Header.HwAddrLen = (UINT8)sizeof (EFI_GUID); + } + + break; + + case Dhcp4RcvdOffer: + Status = EFI_NOT_READY; + if (Packet->Length > PXEBC_DHCP4_PACKET_MAX_SIZE) { + // + // Ignore the incoming packets which exceed the maximum length. + // + break; + } + + if (Private->OfferNum < PXEBC_OFFER_MAX_NUM) { + // + // Cache the DHCPv4 offers to OfferBuffer[] for select later, and record + // the OfferIndex and OfferCount. + // If error happens, just ignore this packet and continue to wait more offer. + // + PxeBcCacheDhcp4Offer (Private, Packet); } - Packet->Dhcp4.Header.HwAddrLen = (UINT8) sizeof (EFI_GUID); - } - break; - case Dhcp4RcvdOffer: - Status = EFI_NOT_READY; - if (Private->OfferNum < PXEBC_OFFER_MAX_NUM) { + break; + + case Dhcp4SelectOffer: + ASSERT (NewPacket != NULL); + // - // Cache the DHCPv4 offers to OfferBuffer[] for select later, and record - // the OfferIndex and OfferCount. + // Select offer by the default policy or by order, and record the SelectIndex + // and SelectProxyType. // - PxeBcCacheDhcp4Offer (Private, Packet); - } - break; + PxeBcSelectDhcp4Offer (Private); - case Dhcp4SelectOffer: - // - // Select offer by the default policy or by order, and record the SelectIndex - // and SelectProxyType. - // - PxeBcSelectDhcp4Offer (Private); + if (Private->SelectIndex == 0) { + Status = EFI_ABORTED; + } else { + *NewPacket = &Private->OfferBuffer[Private->SelectIndex - 1].Dhcp4.Packet.Offer; + } - if (Private->SelectIndex == 0) { - Status = EFI_ABORTED; - } else { - *NewPacket = &Private->OfferBuffer[Private->SelectIndex - 1].Dhcp4.Packet.Offer; - } - break; + break; - case Dhcp4RcvdAck: - // - // Cache the DHCPv4 ack to Private->Dhcp4Ack, but it's not the final ack in mode data - // without verification. - // - ASSERT (Private->SelectIndex != 0); + case Dhcp4RcvdAck: + // + // Cache the DHCPv4 ack to Private->Dhcp4Ack, but it's not the final ack in mode data + // without verification. + // + ASSERT (Private->SelectIndex != 0); - PxeBcCopyDhcp4Ack (Private, Packet, FALSE); - break; + Status = PxeBcCopyDhcp4Ack (Private, Packet, FALSE); + if (EFI_ERROR (Status)) { + Status = EFI_ABORTED; + } + + break; - default: - break; + default: + break; } return Status; } - /** Build and send out the request packet for the bootfile, and parse the reply. @@ -1292,37 +1353,37 @@ PxeBcDhcp4CallBack ( **/ EFI_STATUS PxeBcDhcp4Discover ( - IN PXEBC_PRIVATE_DATA *Private, - IN UINT16 Type, - IN UINT16 *Layer, - IN BOOLEAN UseBis, - IN EFI_IP_ADDRESS *DestIp, - IN UINT16 IpCount, - IN EFI_PXE_BASE_CODE_SRVLIST *SrvList + IN PXEBC_PRIVATE_DATA *Private, + IN UINT16 Type, + IN UINT16 *Layer, + IN BOOLEAN UseBis, + IN EFI_IP_ADDRESS *DestIp, + IN UINT16 IpCount, + IN EFI_PXE_BASE_CODE_SRVLIST *SrvList ) { - EFI_PXE_BASE_CODE_UDP_PORT Sport; - EFI_PXE_BASE_CODE_MODE *Mode; - EFI_DHCP4_PROTOCOL *Dhcp4; - EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN Token; - BOOLEAN IsBCast; - EFI_STATUS Status; - UINT16 RepIndex; - UINT16 SrvIndex; - UINT16 TryIndex; - EFI_DHCP4_LISTEN_POINT ListenPoint; - EFI_DHCP4_PACKET *Response; - UINT8 Buffer[PXEBC_DHCP4_OPTION_MAX_SIZE]; - EFI_DHCP4_PACKET_OPTION *OptList[PXEBC_DHCP4_OPTION_MAX_NUM]; - UINT32 OptCount; - EFI_DHCP4_PACKET_OPTION *PxeOpt; - PXEBC_OPTION_BOOT_ITEM *PxeBootItem; - UINT8 VendorOptLen; - UINT32 Xid; - - Mode = Private->PxeBc.Mode; - Dhcp4 = Private->Dhcp4; - Status = EFI_SUCCESS; + EFI_PXE_BASE_CODE_UDP_PORT Sport; + EFI_PXE_BASE_CODE_MODE *Mode; + EFI_DHCP4_PROTOCOL *Dhcp4; + EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN Token; + BOOLEAN IsBCast; + EFI_STATUS Status; + UINT16 RepIndex; + UINT16 SrvIndex; + UINT16 TryIndex; + EFI_DHCP4_LISTEN_POINT ListenPoint; + EFI_DHCP4_PACKET *Response; + UINT8 Buffer[PXEBC_DHCP4_OPTION_MAX_SIZE]; + EFI_DHCP4_PACKET_OPTION *OptList[PXEBC_DHCP4_OPTION_MAX_NUM]; + UINT32 OptCount; + EFI_DHCP4_PACKET_OPTION *PxeOpt; + PXEBC_OPTION_BOOT_ITEM *PxeBootItem; + UINT8 VendorOptLen; + UINT32 Xid; + + Mode = Private->PxeBc.Mode; + Dhcp4 = Private->Dhcp4; + Status = EFI_SUCCESS; ZeroMem (&Token, sizeof (EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN)); @@ -1337,7 +1398,7 @@ PxeBcDhcp4Discover ( IsBCast = FALSE; } - if (!UseBis && Layer != NULL) { + if (!UseBis && (Layer != NULL)) { *Layer &= EFI_PXE_BASE_CODE_BOOT_LAYER_MASK; } @@ -1350,23 +1411,23 @@ PxeBcDhcp4Discover ( // // Add vendor option of PXE_BOOT_ITEM // - VendorOptLen = (UINT8) ((sizeof (EFI_DHCP4_PACKET_OPTION) - 1) * 2 + sizeof (PXEBC_OPTION_BOOT_ITEM) + 1); + VendorOptLen = (UINT8)((sizeof (EFI_DHCP4_PACKET_OPTION) - 1) * 2 + sizeof (PXEBC_OPTION_BOOT_ITEM) + 1); OptList[OptCount] = AllocateZeroPool (VendorOptLen); if (OptList[OptCount] == NULL) { return EFI_OUT_OF_RESOURCES; } - OptList[OptCount]->OpCode = DHCP4_TAG_VENDOR; - OptList[OptCount]->Length = (UINT8) (VendorOptLen - 2); - PxeOpt = (EFI_DHCP4_PACKET_OPTION *) OptList[OptCount]->Data; - PxeOpt->OpCode = PXEBC_VENDOR_TAG_BOOT_ITEM; - PxeOpt->Length = (UINT8) sizeof (PXEBC_OPTION_BOOT_ITEM); - PxeBootItem = (PXEBC_OPTION_BOOT_ITEM *) PxeOpt->Data; - PxeBootItem->Type = HTONS (Type); - PxeOpt->Data[PxeOpt->Length] = DHCP4_TAG_EOP; + OptList[OptCount]->OpCode = DHCP4_TAG_VENDOR; + OptList[OptCount]->Length = (UINT8)(VendorOptLen - 2); + PxeOpt = (EFI_DHCP4_PACKET_OPTION *)OptList[OptCount]->Data; + PxeOpt->OpCode = PXEBC_VENDOR_TAG_BOOT_ITEM; + PxeOpt->Length = (UINT8)sizeof (PXEBC_OPTION_BOOT_ITEM); + PxeBootItem = (PXEBC_OPTION_BOOT_ITEM *)PxeOpt->Data; + PxeBootItem->Type = HTONS (Type); + PxeOpt->Data[PxeOpt->Length] = DHCP4_TAG_EOP; if (Layer != NULL) { - PxeBootItem->Layer = HTONS (*Layer); + PxeBootItem->Layer = HTONS (*Layer); } OptCount++; @@ -1396,13 +1457,15 @@ PxeBcDhcp4Discover ( } if (Mode->SendGUID) { - if (EFI_ERROR (NetLibGetSystemGuid ((EFI_GUID *) Token.Packet->Dhcp4.Header.ClientHwAddr))) { + if (EFI_ERROR (NetLibGetSystemGuid ((EFI_GUID *)Token.Packet->Dhcp4.Header.ClientHwAddr))) { // - // Zero the Guid to indicate NOT programable if failed to get system Guid. + // Zero the Guid to indicate NOT programmable if failed to get system Guid. // + DEBUG ((DEBUG_WARN, "PXE: Failed to read system GUID from the smbios table!\n")); ZeroMem (Token.Packet->Dhcp4.Header.ClientHwAddr, sizeof (EFI_GUID)); } - Token.Packet->Dhcp4.Header.HwAddrLen = (UINT8) sizeof (EFI_GUID); + + Token.Packet->Dhcp4.Header.HwAddrLen = (UINT8)sizeof (EFI_GUID); } // @@ -1410,7 +1473,7 @@ PxeBcDhcp4Discover ( // Xid = NET_RANDOM (NetRandomInitSeed ()); Token.Packet->Dhcp4.Header.Xid = HTONL (Xid); - Token.Packet->Dhcp4.Header.Reserved = HTONS ((UINT16) ((IsBCast) ? 0x8000 : 0x0)); + Token.Packet->Dhcp4.Header.Reserved = HTONS ((UINT16)((IsBCast) ? 0x8000 : 0x0)); CopyMem (&Token.Packet->Dhcp4.Header.ClientAddr, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS)); Token.RemotePort = Sport; @@ -1424,20 +1487,19 @@ PxeBcDhcp4Discover ( CopyMem (&Token.GatewayAddress, &Private->GatewayIp, sizeof (EFI_IPv4_ADDRESS)); if (!IsBCast) { - Token.ListenPointCount = 1; - Token.ListenPoints = &ListenPoint; - Token.ListenPoints[0].ListenPort = PXEBC_BS_DISCOVER_PORT; - CopyMem (&Token.ListenPoints[0].ListenAddress, &Private->StationIp, sizeof(EFI_IPv4_ADDRESS)); - CopyMem (&Token.ListenPoints[0].SubnetMask, &Private->SubnetMask, sizeof(EFI_IPv4_ADDRESS)); + Token.ListenPointCount = 1; + Token.ListenPoints = &ListenPoint; + Token.ListenPoints[0].ListenPort = PXEBC_BS_DISCOVER_PORT; + CopyMem (&Token.ListenPoints[0].ListenAddress, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS)); + CopyMem (&Token.ListenPoints[0].SubnetMask, &Private->SubnetMask, sizeof (EFI_IPv4_ADDRESS)); } // // Send out the request packet to discover the bootfile. // for (TryIndex = 1; TryIndex <= PXEBC_BOOT_REQUEST_RETRIES; TryIndex++) { - - Token.TimeoutValue = (UINT16) (PXEBC_BOOT_REQUEST_TIMEOUT * TryIndex); - Token.Packet->Dhcp4.Header.Seconds = (UINT16) (PXEBC_BOOT_REQUEST_TIMEOUT * (TryIndex - 1)); + Token.TimeoutValue = (UINT16)(PXEBC_BOOT_REQUEST_TIMEOUT * TryIndex); + Token.Packet->Dhcp4.Header.Seconds = (UINT16)(PXEBC_BOOT_REQUEST_TIMEOUT * (TryIndex - 1)); Status = Dhcp4->TransmitReceive (Dhcp4, &Token); if (Token.Status != EFI_TIMEOUT) { @@ -1453,23 +1515,31 @@ PxeBcDhcp4Discover ( } if (!EFI_ERROR (Status)) { - - RepIndex = 0; - SrvIndex = 0; - Response = Token.ResponseList; + RepIndex = 0; + SrvIndex = 0; + Response = Token.ResponseList; // // Find the right PXE Reply according to server address. // while (RepIndex < Token.ResponseCount) { + if (Response->Length > PXEBC_DHCP4_PACKET_MAX_SIZE) { + SrvIndex = 0; + RepIndex++; + Response = (EFI_DHCP4_PACKET *)((UINT8 *)Response + Response->Size); + continue; + } while (SrvIndex < IpCount) { if (SrvList[SrvIndex].AcceptAnyResponse) { break; } + if ((SrvList[SrvIndex].Type == Type) && - EFI_IP4_EQUAL (&Response->Dhcp4.Header.ServerAddr, &SrvList[SrvIndex].IpAddr)) { + EFI_IP4_EQUAL (&Response->Dhcp4.Header.ServerAddr, &SrvList[SrvIndex].IpAddr)) + { break; } + SrvIndex++; } @@ -1479,8 +1549,7 @@ PxeBcDhcp4Discover ( SrvIndex = 0; RepIndex++; - - Response = (EFI_DHCP4_PACKET *) ((UINT8 *) Response + Response->Size); + Response = (EFI_DHCP4_PACKET *)((UINT8 *)Response + Response->Size); } if (RepIndex < Token.ResponseCount) { @@ -1489,10 +1558,17 @@ PxeBcDhcp4Discover ( // Especially for PXE discover packet, store it into mode data here. // if (Private->IsDoDiscover) { - PxeBcCacheDhcp4Packet (&Private->PxeReply.Dhcp4.Packet.Ack, Response); + Status = PxeBcCacheDhcp4Packet (&Private->PxeReply.Dhcp4.Packet.Ack, Response); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + CopyMem (&Mode->PxeDiscover, &Token.Packet->Dhcp4, Token.Packet->Length); } else { - PxeBcCacheDhcp4Packet (&Private->ProxyOffer.Dhcp4.Packet.Offer, Response); + Status = PxeBcCacheDhcp4Packet (&Private->ProxyOffer.Dhcp4.Packet.Offer, Response); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } } } else { // @@ -1500,12 +1576,18 @@ PxeBcDhcp4Discover ( // Status = EFI_NOT_FOUND; } - if (Token.ResponseList != NULL) { - FreePool (Token.ResponseList); - } } - FreePool (Token.Packet); +ON_EXIT: + + if (Token.ResponseList != NULL) { + FreePool (Token.ResponseList); + } + + if (Token.Packet != NULL) { + FreePool (Token.Packet); + } + return Status; } @@ -1519,41 +1601,41 @@ PxeBcDhcp4Discover ( **/ EFI_STATUS -PxeBcSetIp4Policy ( - IN PXEBC_PRIVATE_DATA *Private +PxeBcSetIp4Policy ( + IN PXEBC_PRIVATE_DATA *Private ) { - EFI_STATUS Status; - EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2; - EFI_IP4_CONFIG2_POLICY Policy; - UINTN DataSize; + EFI_STATUS Status; + EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2; + EFI_IP4_CONFIG2_POLICY Policy; + UINTN DataSize; Ip4Config2 = Private->Ip4Config2; - DataSize = sizeof (EFI_IP4_CONFIG2_POLICY); - Status = Ip4Config2->GetData ( - Ip4Config2, - Ip4Config2DataTypePolicy, - &DataSize, - &Policy - ); + DataSize = sizeof (EFI_IP4_CONFIG2_POLICY); + Status = Ip4Config2->GetData ( + Ip4Config2, + Ip4Config2DataTypePolicy, + &DataSize, + &Policy + ); if (EFI_ERROR (Status)) { return Status; } - + if (Policy != Ip4Config2PolicyStatic) { Policy = Ip4Config2PolicyStatic; - Status= Ip4Config2->SetData ( - Ip4Config2, - Ip4Config2DataTypePolicy, - sizeof (EFI_IP4_CONFIG2_POLICY), - &Policy - ); + Status = Ip4Config2->SetData ( + Ip4Config2, + Ip4Config2DataTypePolicy, + sizeof (EFI_IP4_CONFIG2_POLICY), + &Policy + ); if (EFI_ERROR (Status)) { return Status; - } + } } - return EFI_SUCCESS; + return EFI_SUCCESS; } /** @@ -1568,28 +1650,28 @@ PxeBcSetIp4Policy ( **/ EFI_STATUS PxeBcDhcp4Dora ( - IN PXEBC_PRIVATE_DATA *Private, - IN EFI_DHCP4_PROTOCOL *Dhcp4 + IN PXEBC_PRIVATE_DATA *Private, + IN EFI_DHCP4_PROTOCOL *Dhcp4 ) { - EFI_PXE_BASE_CODE_MODE *PxeMode; - EFI_DHCP4_CONFIG_DATA Config; - EFI_DHCP4_MODE_DATA Mode; - EFI_DHCP4_PACKET_OPTION *OptList[PXEBC_DHCP4_OPTION_MAX_NUM]; - UINT8 Buffer[PXEBC_DHCP4_OPTION_MAX_SIZE]; - UINT32 OptCount; - EFI_STATUS Status; + EFI_PXE_BASE_CODE_MODE *PxeMode; + EFI_DHCP4_CONFIG_DATA Config; + EFI_DHCP4_MODE_DATA Mode; + EFI_DHCP4_PACKET_OPTION *OptList[PXEBC_DHCP4_OPTION_MAX_NUM]; + UINT8 Buffer[PXEBC_DHCP4_OPTION_MAX_SIZE]; + UINT32 OptCount; + EFI_STATUS Status; ASSERT (Dhcp4 != NULL); - Status = EFI_SUCCESS; - PxeMode = Private->PxeBc.Mode; + Status = EFI_SUCCESS; + PxeMode = Private->PxeBc.Mode; // // Build option list for the request packet. // OptCount = PxeBcBuildDhcp4Options (Private, OptList, Buffer, FALSE); - ASSERT (OptCount> 0); + ASSERT (OptCount > 0); ZeroMem (&Mode, sizeof (EFI_DHCP4_MODE_DATA)); ZeroMem (&Config, sizeof (EFI_DHCP4_CONFIG_DATA)); @@ -1617,16 +1699,16 @@ PxeBcDhcp4Dora ( ZeroMem (Private->OfferCount, sizeof (Private->OfferCount)); ZeroMem (Private->OfferIndex, sizeof (Private->OfferIndex)); - // - // Start DHCPv4 D.O.R.A. process to acquire IPv4 address. This may - // have already been done, thus do not leave in error if the return - // code is EFI_ALREADY_STARTED. - // Status = Dhcp4->Start (Dhcp4, NULL); - if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + if (EFI_ERROR (Status)) { if (Status == EFI_ICMP_ERROR) { PxeMode->IcmpErrorReceived = TRUE; } + + if ((Status == EFI_TIMEOUT) && (Private->OfferNum > 0)) { + Status = EFI_NO_RESPONSE; + } + goto ON_EXIT; }