From: sfu5 Date: Fri, 24 Aug 2012 08:25:42 +0000 (+0000) Subject: Fix bugs in PXE driver when using option 43 for boot server list and boot menu prompt. X-Git-Tag: edk2-stable201903~13104 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=9063c328dff827ef9deb1ce0dde75112c496e072 Fix bugs in PXE driver when using option 43 for boot server list and boot menu prompt. Signed-off-by: Fu Siyuan Reviewed-by: Ye Ting Reviewed-by: Ouyang Qian git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13676 6f19259b-4bc3-4df7-8a09-765794883524 --- diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcBoot.c b/NetworkPkg/UefiPxeBcDxe/PxeBcBoot.c index e26b412781..e814d5a84c 100644 --- a/NetworkPkg/UefiPxeBcDxe/PxeBcBoot.c +++ b/NetworkPkg/UefiPxeBcDxe/PxeBcBoot.c @@ -1,7 +1,7 @@ /** @file Boot functions implementation for UefiPxeBc Driver. - Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2012, 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 @@ -86,9 +86,9 @@ PxeBcSelectBootPrompt ( OfferType = Mode->UsingIpv6 ? Cache->Dhcp6.OfferType : Cache->Dhcp4.OfferType; // - // Only ProxyPxe10 offer needs boot prompt. + // Only DhcpPxe10 and ProxyPxe10 offer needs boot prompt. // - if (OfferType != PxeOfferTypeProxyPxe10) { + if (OfferType != PxeOfferTypeProxyPxe10 && OfferType != PxeOfferTypeDhcpPxe10) { return EFI_NOT_FOUND; } @@ -99,7 +99,7 @@ PxeBcSelectBootPrompt ( VendorOpt = &Cache->Dhcp4.VendorOpt; if (!IS_VALID_BOOT_PROMPT (VendorOpt->BitMap)) { - return EFI_SUCCESS; + return EFI_TIMEOUT; } Timeout = VendorOpt->MenuPrompt->Timeout; @@ -110,10 +110,10 @@ PxeBcSelectBootPrompt ( // The valid scope of Timeout refers to PXE2.1 spec. // if (Timeout == 0) { - return EFI_SUCCESS; + return EFI_TIMEOUT; } if (Timeout == 255) { - return EFI_TIMEOUT; + return EFI_SUCCESS; } // @@ -173,6 +173,7 @@ PxeBcSelectBootPrompt ( gST->ConOut->SetCursorPosition (gST->ConOut, SecCol + PromptLen, SecRow); AsciiPrint ("(%d) ", Timeout--); + Status = EFI_TIMEOUT; while (EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) { if (!EFI_ERROR (gBS->CheckEvent (DescendEvent))) { gST->ConOut->SetCursorPosition (gST->ConOut, SecCol + PromptLen, SecRow); @@ -184,6 +185,7 @@ PxeBcSelectBootPrompt ( } // // Parse the input key by user. + // If or + is pressed, return success to display the boot menu. // if (InputKey.ScanCode == 0) { @@ -196,7 +198,7 @@ PxeBcSelectBootPrompt ( case CTRL ('m'): case 'm': case 'M': - Status = EFI_TIMEOUT; + Status = EFI_SUCCESS; break; default: @@ -208,7 +210,7 @@ PxeBcSelectBootPrompt ( switch (InputKey.ScanCode) { case SCAN_F8: - Status = EFI_TIMEOUT; + Status = EFI_SUCCESS; break; case SCAN_ESC: @@ -284,10 +286,10 @@ PxeBcSelectBootMenu ( OfferType = Mode->UsingIpv6 ? Cache->Dhcp6.OfferType : Cache->Dhcp4.OfferType; // - // There is no specified ProxyPxe10 for IPv6 in PXE and UEFI spec. + // There is no specified DhcpPxe10/ProxyPxe10 for IPv6 in PXE and UEFI spec. // ASSERT (!Mode->UsingIpv6); - ASSERT (OfferType == PxeOfferTypeProxyPxe10); + ASSERT (OfferType == PxeOfferTypeProxyPxe10 || OfferType == PxeOfferTypeDhcpPxe10); VendorOpt = &Cache->Dhcp4.VendorOpt; if (!IS_VALID_BOOT_MENU (VendorOpt->BitMap)) { @@ -351,7 +353,7 @@ PxeBcSelectBootMenu ( gBS->Stall (10 * TICKS_PER_MS); } - if (InputKey.ScanCode != 0) { + if (InputKey.ScanCode == 0) { switch (InputKey.UnicodeChar) { case CTRL ('c'): InputKey.ScanCode = SCAN_ESC; @@ -651,7 +653,7 @@ PxeBcDhcp6BootInfo ( @param[in] Private Pointer to PxeBc private data. @param[in] Type The type of bootstrap to perform. - @param[in, out] Info Pointer to EFI_PXE_BASE_CODE_DISCOVER_INFO. + @param[in, out] DiscoverInfo Pointer to EFI_PXE_BASE_CODE_DISCOVER_INFO. @param[out] BootEntry Pointer to PXEBC_BOOT_SVR_ENTRY. @param[out] SrvList Pointer to EFI_PXE_BASE_CODE_SRVLIST. @@ -663,7 +665,7 @@ EFI_STATUS PxeBcExtractDiscoverInfo ( IN PXEBC_PRIVATE_DATA *Private, IN UINT16 Type, - IN OUT EFI_PXE_BASE_CODE_DISCOVER_INFO *Info, + IN OUT EFI_PXE_BASE_CODE_DISCOVER_INFO **DiscoverInfo, OUT PXEBC_BOOT_SVR_ENTRY **BootEntry, OUT EFI_PXE_BASE_CODE_SRVLIST **SrvList ) @@ -673,8 +675,11 @@ PxeBcExtractDiscoverInfo ( PXEBC_VENDOR_OPTION *VendorOpt; PXEBC_BOOT_SVR_ENTRY *Entry; BOOLEAN IsFound; + EFI_PXE_BASE_CODE_DISCOVER_INFO *Info; + UINT16 Index; Mode = Private->PxeBc.Mode; + Info = *DiscoverInfo; if (Mode->UsingIpv6) { Info->IpCnt = 1; @@ -708,7 +713,7 @@ PxeBcExtractDiscoverInfo ( Info->UseMCast = (BOOLEAN) !IS_DISABLE_MCAST_DISCOVER (VendorOpt->DiscoverCtrl); Info->UseBCast = (BOOLEAN) !IS_DISABLE_BCAST_DISCOVER (VendorOpt->DiscoverCtrl); Info->MustUseList = (BOOLEAN) IS_ENABLE_USE_SERVER_LIST (VendorOpt->DiscoverCtrl); - Info->UseUCast = Info->MustUseList; + Info->UseUCast = (BOOLEAN) IS_VALID_BOOT_SERVERS (VendorOpt->BitMap); if (Info->UseMCast) { // @@ -719,7 +724,7 @@ PxeBcExtractDiscoverInfo ( Info->IpCnt = 0; - if (Info->MustUseList) { + if (Info->UseUCast) { Entry = VendorOpt->BootSvr; while (((UINT8) (Entry - VendorOpt->BootSvr)) < VendorOpt->BootSvrLen) { @@ -735,9 +740,24 @@ PxeBcExtractDiscoverInfo ( } Info->IpCnt = Entry->IpCnt; + if (Info->IpCnt >= 1) { + *DiscoverInfo = AllocatePool (sizeof (*Info) + (Info->IpCnt - 1) * sizeof (**SrvList)); + if (*DiscoverInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem (*DiscoverInfo, Info, sizeof (*Info)); + Info = *DiscoverInfo; + } + + for (Index = 0; Index < Info->IpCnt; Index++) { + CopyMem (&Info->SrvList[Index].IpAddr, &Entry->IpAddr[Index], sizeof (EFI_IPv4_ADDRESS)); + Info->SrvList[Index].AcceptAnyResponse = !Info->MustUseList; + Info->SrvList[Index].Type = NTOHS (Entry->Type); + } } *BootEntry = Entry; + *SrvList = Info->SrvList; } return EFI_SUCCESS; @@ -842,12 +862,12 @@ PxeBcDiscoverBootFile ( // // Choose by user's input. // - Status = PxeBcSelectBootMenu (Private, &Type, TRUE); + Status = PxeBcSelectBootMenu (Private, &Type, FALSE); } else if (Status == EFI_TIMEOUT) { // // Choose by default item. // - Status = PxeBcSelectBootMenu (Private, &Type, FALSE); + Status = PxeBcSelectBootMenu (Private, &Type, TRUE); } if (!EFI_ERROR (Status)) { @@ -868,6 +888,27 @@ PxeBcDiscoverBootFile ( if (EFI_ERROR (Status)) { return Status; } + + if (Mode->PxeReplyReceived && !Mode->ProxyOfferReceived) { + // + // Some network boot loader only search the packet in Mode.ProxyOffer to get its server + // IP address, so we need to store a copy of Mode.PxeReply packet into Mode.ProxyOffer. + // + if (Mode->UsingIpv6) { + CopyMem ( + &Mode->ProxyOffer.Dhcpv6, + &Mode->PxeReply.Dhcpv6, + Private->PxeReply.Dhcp6.Packet.Ack.Length + ); + } else { + CopyMem ( + &Mode->ProxyOffer.Dhcpv4, + &Mode->PxeReply.Dhcpv4, + Private->PxeReply.Dhcp4.Packet.Ack.Length + ); + } + Mode->ProxyOfferReceived = TRUE; + } } // diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcBoot.h b/NetworkPkg/UefiPxeBcDxe/PxeBcBoot.h index ef18907aa6..d998200ce0 100644 --- a/NetworkPkg/UefiPxeBcDxe/PxeBcBoot.h +++ b/NetworkPkg/UefiPxeBcDxe/PxeBcBoot.h @@ -1,7 +1,7 @@ /** @file Boot functions declaration for UefiPxeBc Driver. - Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2012, 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 @@ -29,7 +29,7 @@ @param[in] Private Pointer to PxeBc private data. @param[in] Type The type of bootstrap to perform. - @param[in, out] Info Pointer to EFI_PXE_BASE_CODE_DISCOVER_INFO. + @param[in, out] DiscoverInfo Pointer to EFI_PXE_BASE_CODE_DISCOVER_INFO. @param[out] BootEntry Pointer to PXEBC_BOOT_SVR_ENTRY. @param[out] SrvList Pointer to EFI_PXE_BASE_CODE_SRVLIST. @@ -41,7 +41,7 @@ EFI_STATUS PxeBcExtractDiscoverInfo ( IN PXEBC_PRIVATE_DATA *Private, IN UINT16 Type, - IN OUT EFI_PXE_BASE_CODE_DISCOVER_INFO *Info, + IN OUT EFI_PXE_BASE_CODE_DISCOVER_INFO **DiscoverInfo, OUT PXEBC_BOOT_SVR_ENTRY **BootEntry, OUT EFI_PXE_BASE_CODE_SRVLIST **SrvList ); diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c index 60942fb908..ecafc86a03 100644 --- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c +++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c @@ -1,7 +1,7 @@ /** @file Functions implementation related with DHCPv4 for UefiPxeBc Driver. - Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2012, 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 @@ -1443,7 +1443,7 @@ PxeBcDhcp4Discover ( break; } if ((SrvList[SrvIndex].Type == Type) && - EFI_IP4_EQUAL (&Response->Dhcp4.Header.ServerAddr, &Private->ServerIp)) { + EFI_IP4_EQUAL (&Response->Dhcp4.Header.ServerAddr, &SrvList[SrvIndex].IpAddr)) { break; } SrvIndex++; @@ -1587,6 +1587,7 @@ PxeBcDhcp4Dora ( AsciiPrint ("\n Station IP address is "); PxeBcShowIp4Addr (&Private->StationIp.v4); + AsciiPrint ("\n"); ON_EXIT: if (EFI_ERROR (Status)) { diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.h b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.h index bc21b212a2..37747ac74f 100644 --- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.h +++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.h @@ -1,7 +1,7 @@ /** @file Functions declaration related with DHCPv4 for UefiPxeBc Driver. - Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2012, 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 @@ -146,6 +146,10 @@ typedef enum { BIT (PXEBC_VENDOR_TAG_BOOT_MENU) | \ BIT (PXEBC_VENDOR_TAG_MENU_PROMPT)) +#define IS_VALID_BOOT_SERVERS(x) \ + ((((x)[0]) & BIT (PXEBC_VENDOR_TAG_BOOT_SERVERS)) \ + == BIT (PXEBC_VENDOR_TAG_BOOT_SERVERS)) + #define IS_VALID_BOOT_PROMPT(x) \ ((((x)[0]) & BIT (PXEBC_VENDOR_TAG_MENU_PROMPT)) \ == BIT (PXEBC_VENDOR_TAG_MENU_PROMPT)) @@ -256,6 +260,7 @@ typedef union { PXEBC_DHCP4_OPTION_MAX_MESG_SIZE *MaxMesgSize; } PXEBC_DHCP4_OPTION_ENTRY; +#pragma pack(1) typedef struct { UINT16 Type; UINT8 IpCnt; @@ -272,6 +277,7 @@ typedef struct { UINT8 Timeout; UINT8 Prompt[1]; } PXEBC_MENU_PROMPT; +#pragma pack() typedef struct { UINT32 BitMap[8]; diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcImpl.c b/NetworkPkg/UefiPxeBcDxe/PxeBcImpl.c index ba7f948594..5f693729d6 100644 --- a/NetworkPkg/UefiPxeBcDxe/PxeBcImpl.c +++ b/NetworkPkg/UefiPxeBcDxe/PxeBcImpl.c @@ -529,6 +529,7 @@ EfiPxeBcDiscover ( UINT16 Index; EFI_STATUS Status; EFI_PXE_BASE_CODE_IP_FILTER IpFilter; + EFI_PXE_BASE_CODE_DISCOVER_INFO *NewCreatedInfo; if (This == NULL) { return EFI_INVALID_PARAMETER; @@ -541,6 +542,7 @@ EfiPxeBcDiscover ( SrvList = NULL; Status = EFI_DEVICE_ERROR; Private->Function = EFI_PXE_BASE_CODE_FUNCTION_DISCOVER; + NewCreatedInfo = NULL; if (!Mode->Started) { return EFI_NOT_STARTED; @@ -594,12 +596,12 @@ EfiPxeBcDiscover ( // // 2. Extract the discover information from the cached packets if unspecified. // - Info = &DefaultInfo; - Status = PxeBcExtractDiscoverInfo (Private, Type, Info, &BootSvrEntry, &SrvList); + NewCreatedInfo = &DefaultInfo; + Status = PxeBcExtractDiscoverInfo (Private, Type, &NewCreatedInfo, &BootSvrEntry, &SrvList); if (EFI_ERROR (Status)) { goto ON_EXIT; } - + Info = NewCreatedInfo; } else { // // 3. Take the pass-in information as the discover info, and validate the server list. @@ -634,30 +636,7 @@ EfiPxeBcDiscover ( Private->IsDoDiscover = TRUE; - if (Info->UseUCast) { - // - // Do discover by unicast. - // - for (Index = 0; Index < Info->IpCnt; Index++) { - if (BootSvrEntry == NULL) { - CopyMem (&Private->ServerIp, &SrvList[Index].IpAddr, sizeof (EFI_IP_ADDRESS)); - } else { - ASSERT (!Mode->UsingIpv6); - ZeroMem (&Private->ServerIp, sizeof (EFI_IP_ADDRESS)); - CopyMem (&Private->ServerIp, &BootSvrEntry->IpAddr[Index], sizeof (EFI_IPv4_ADDRESS)); - } - - Status = PxeBcDiscoverBootServer ( - Private, - Type, - Layer, - UseBis, - &SrvList[Index].IpAddr, - 0, - NULL - ); - } - } else if (Info->UseMCast) { + if (Info->UseMCast) { // // Do discover by multicast. // @@ -667,8 +646,8 @@ EfiPxeBcDiscover ( Layer, UseBis, &Info->ServerMCastIp, - 0, - NULL + Info->IpCnt, + SrvList ); } else if (Info->UseBCast) { @@ -685,6 +664,30 @@ EfiPxeBcDiscover ( Info->IpCnt, SrvList ); + + } else if (Info->UseUCast) { + // + // Do discover by unicast. + // + for (Index = 0; Index < Info->IpCnt; Index++) { + if (BootSvrEntry == NULL) { + CopyMem (&Private->ServerIp, &SrvList[Index].IpAddr, sizeof (EFI_IP_ADDRESS)); + } else { + ASSERT (!Mode->UsingIpv6); + ZeroMem (&Private->ServerIp, sizeof (EFI_IP_ADDRESS)); + CopyMem (&Private->ServerIp, &BootSvrEntry->IpAddr[Index], sizeof (EFI_IPv4_ADDRESS)); + } + + Status = PxeBcDiscoverBootServer ( + Private, + Type, + Layer, + UseBis, + &Private->ServerIp, + Info->IpCnt, + SrvList + ); + } } if (EFI_ERROR (Status)) { @@ -698,8 +701,8 @@ EfiPxeBcDiscover ( if (!EFI_ERROR (Status)) { CopyMem ( &Mode->PxeReply.Dhcpv6, - &Private->PxeReply.Dhcp6.Packet.Offer, - Private->PxeReply.Dhcp6.Packet.Offer.Length + &Private->PxeReply.Dhcp6.Packet.Ack.Dhcp6, + Private->PxeReply.Dhcp6.Packet.Ack.Length ); Mode->PxeReplyReceived = TRUE; Mode->PxeDiscoverValid = TRUE; @@ -709,8 +712,8 @@ EfiPxeBcDiscover ( if (!EFI_ERROR (Status)) { CopyMem ( &Mode->PxeReply.Dhcpv4, - &Private->PxeReply.Dhcp4.Packet.Offer, - Private->PxeReply.Dhcp4.Packet.Offer.Length + &Private->PxeReply.Dhcp4.Packet.Ack.Dhcp4, + Private->PxeReply.Dhcp4.Packet.Ack.Length ); Mode->PxeReplyReceived = TRUE; Mode->PxeDiscoverValid = TRUE; @@ -720,6 +723,10 @@ EfiPxeBcDiscover ( ON_EXIT: + if (NewCreatedInfo != NULL && NewCreatedInfo != &DefaultInfo) { + FreePool (NewCreatedInfo); + } + if (Mode->UsingIpv6) { Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData); } else {