Fix bugs in PXE driver when using option 43 for boot server list and boot menu prompt.

Signed-off-by: Fu Siyuan <siyuan.fu@intel.com>
Reviewed-by: Ye Ting <ting.ye@intel.com>
Reviewed-by: Ouyang Qian <qian.ouyang@intel.com>

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13676 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
sfu5 2012-08-24 08:25:42 +00:00
parent db999bd39b
commit 9063c328df
5 changed files with 118 additions and 63 deletions

View File

@ -1,7 +1,7 @@
/** @file /** @file
Boot functions implementation for UefiPxeBc Driver. Boot functions implementation for UefiPxeBc Driver.
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR> Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License 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; 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; return EFI_NOT_FOUND;
} }
@ -99,7 +99,7 @@ PxeBcSelectBootPrompt (
VendorOpt = &Cache->Dhcp4.VendorOpt; VendorOpt = &Cache->Dhcp4.VendorOpt;
if (!IS_VALID_BOOT_PROMPT (VendorOpt->BitMap)) { if (!IS_VALID_BOOT_PROMPT (VendorOpt->BitMap)) {
return EFI_SUCCESS; return EFI_TIMEOUT;
} }
Timeout = VendorOpt->MenuPrompt->Timeout; Timeout = VendorOpt->MenuPrompt->Timeout;
@ -110,10 +110,10 @@ PxeBcSelectBootPrompt (
// The valid scope of Timeout refers to PXE2.1 spec. // The valid scope of Timeout refers to PXE2.1 spec.
// //
if (Timeout == 0) { if (Timeout == 0) {
return EFI_SUCCESS; return EFI_TIMEOUT;
} }
if (Timeout == 255) { if (Timeout == 255) {
return EFI_TIMEOUT; return EFI_SUCCESS;
} }
// //
@ -173,6 +173,7 @@ PxeBcSelectBootPrompt (
gST->ConOut->SetCursorPosition (gST->ConOut, SecCol + PromptLen, SecRow); gST->ConOut->SetCursorPosition (gST->ConOut, SecCol + PromptLen, SecRow);
AsciiPrint ("(%d) ", Timeout--); AsciiPrint ("(%d) ", Timeout--);
Status = EFI_TIMEOUT;
while (EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) { while (EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {
if (!EFI_ERROR (gBS->CheckEvent (DescendEvent))) { if (!EFI_ERROR (gBS->CheckEvent (DescendEvent))) {
gST->ConOut->SetCursorPosition (gST->ConOut, SecCol + PromptLen, SecRow); gST->ConOut->SetCursorPosition (gST->ConOut, SecCol + PromptLen, SecRow);
@ -184,6 +185,7 @@ PxeBcSelectBootPrompt (
} }
// //
// Parse the input key by user. // Parse the input key by user.
// If <F8> or <Ctrl> + <M> is pressed, return success to display the boot menu.
// //
if (InputKey.ScanCode == 0) { if (InputKey.ScanCode == 0) {
@ -196,7 +198,7 @@ PxeBcSelectBootPrompt (
case CTRL ('m'): case CTRL ('m'):
case 'm': case 'm':
case 'M': case 'M':
Status = EFI_TIMEOUT; Status = EFI_SUCCESS;
break; break;
default: default:
@ -208,7 +210,7 @@ PxeBcSelectBootPrompt (
switch (InputKey.ScanCode) { switch (InputKey.ScanCode) {
case SCAN_F8: case SCAN_F8:
Status = EFI_TIMEOUT; Status = EFI_SUCCESS;
break; break;
case SCAN_ESC: case SCAN_ESC:
@ -284,10 +286,10 @@ PxeBcSelectBootMenu (
OfferType = Mode->UsingIpv6 ? Cache->Dhcp6.OfferType : Cache->Dhcp4.OfferType; 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 (!Mode->UsingIpv6);
ASSERT (OfferType == PxeOfferTypeProxyPxe10); ASSERT (OfferType == PxeOfferTypeProxyPxe10 || OfferType == PxeOfferTypeDhcpPxe10);
VendorOpt = &Cache->Dhcp4.VendorOpt; VendorOpt = &Cache->Dhcp4.VendorOpt;
if (!IS_VALID_BOOT_MENU (VendorOpt->BitMap)) { if (!IS_VALID_BOOT_MENU (VendorOpt->BitMap)) {
@ -351,7 +353,7 @@ PxeBcSelectBootMenu (
gBS->Stall (10 * TICKS_PER_MS); gBS->Stall (10 * TICKS_PER_MS);
} }
if (InputKey.ScanCode != 0) { if (InputKey.ScanCode == 0) {
switch (InputKey.UnicodeChar) { switch (InputKey.UnicodeChar) {
case CTRL ('c'): case CTRL ('c'):
InputKey.ScanCode = SCAN_ESC; InputKey.ScanCode = SCAN_ESC;
@ -651,7 +653,7 @@ PxeBcDhcp6BootInfo (
@param[in] Private Pointer to PxeBc private data. @param[in] Private Pointer to PxeBc private data.
@param[in] Type The type of bootstrap to perform. @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] BootEntry Pointer to PXEBC_BOOT_SVR_ENTRY.
@param[out] SrvList Pointer to EFI_PXE_BASE_CODE_SRVLIST. @param[out] SrvList Pointer to EFI_PXE_BASE_CODE_SRVLIST.
@ -663,7 +665,7 @@ EFI_STATUS
PxeBcExtractDiscoverInfo ( PxeBcExtractDiscoverInfo (
IN PXEBC_PRIVATE_DATA *Private, IN PXEBC_PRIVATE_DATA *Private,
IN UINT16 Type, 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 PXEBC_BOOT_SVR_ENTRY **BootEntry,
OUT EFI_PXE_BASE_CODE_SRVLIST **SrvList OUT EFI_PXE_BASE_CODE_SRVLIST **SrvList
) )
@ -673,8 +675,11 @@ PxeBcExtractDiscoverInfo (
PXEBC_VENDOR_OPTION *VendorOpt; PXEBC_VENDOR_OPTION *VendorOpt;
PXEBC_BOOT_SVR_ENTRY *Entry; PXEBC_BOOT_SVR_ENTRY *Entry;
BOOLEAN IsFound; BOOLEAN IsFound;
EFI_PXE_BASE_CODE_DISCOVER_INFO *Info;
UINT16 Index;
Mode = Private->PxeBc.Mode; Mode = Private->PxeBc.Mode;
Info = *DiscoverInfo;
if (Mode->UsingIpv6) { if (Mode->UsingIpv6) {
Info->IpCnt = 1; Info->IpCnt = 1;
@ -708,7 +713,7 @@ PxeBcExtractDiscoverInfo (
Info->UseMCast = (BOOLEAN) !IS_DISABLE_MCAST_DISCOVER (VendorOpt->DiscoverCtrl); Info->UseMCast = (BOOLEAN) !IS_DISABLE_MCAST_DISCOVER (VendorOpt->DiscoverCtrl);
Info->UseBCast = (BOOLEAN) !IS_DISABLE_BCAST_DISCOVER (VendorOpt->DiscoverCtrl); Info->UseBCast = (BOOLEAN) !IS_DISABLE_BCAST_DISCOVER (VendorOpt->DiscoverCtrl);
Info->MustUseList = (BOOLEAN) IS_ENABLE_USE_SERVER_LIST (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) { if (Info->UseMCast) {
// //
@ -719,7 +724,7 @@ PxeBcExtractDiscoverInfo (
Info->IpCnt = 0; Info->IpCnt = 0;
if (Info->MustUseList) { if (Info->UseUCast) {
Entry = VendorOpt->BootSvr; Entry = VendorOpt->BootSvr;
while (((UINT8) (Entry - VendorOpt->BootSvr)) < VendorOpt->BootSvrLen) { while (((UINT8) (Entry - VendorOpt->BootSvr)) < VendorOpt->BootSvrLen) {
@ -735,9 +740,24 @@ PxeBcExtractDiscoverInfo (
} }
Info->IpCnt = Entry->IpCnt; 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; *BootEntry = Entry;
*SrvList = Info->SrvList;
} }
return EFI_SUCCESS; return EFI_SUCCESS;
@ -842,12 +862,12 @@ PxeBcDiscoverBootFile (
// //
// Choose by user's input. // Choose by user's input.
// //
Status = PxeBcSelectBootMenu (Private, &Type, TRUE); Status = PxeBcSelectBootMenu (Private, &Type, FALSE);
} else if (Status == EFI_TIMEOUT) { } else if (Status == EFI_TIMEOUT) {
// //
// Choose by default item. // Choose by default item.
// //
Status = PxeBcSelectBootMenu (Private, &Type, FALSE); Status = PxeBcSelectBootMenu (Private, &Type, TRUE);
} }
if (!EFI_ERROR (Status)) { if (!EFI_ERROR (Status)) {
@ -868,6 +888,27 @@ PxeBcDiscoverBootFile (
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
return 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;
}
} }
// //

View File

@ -1,7 +1,7 @@
/** @file /** @file
Boot functions declaration for UefiPxeBc Driver. Boot functions declaration for UefiPxeBc Driver.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR> Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License 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] Private Pointer to PxeBc private data.
@param[in] Type The type of bootstrap to perform. @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] BootEntry Pointer to PXEBC_BOOT_SVR_ENTRY.
@param[out] SrvList Pointer to EFI_PXE_BASE_CODE_SRVLIST. @param[out] SrvList Pointer to EFI_PXE_BASE_CODE_SRVLIST.
@ -41,7 +41,7 @@ EFI_STATUS
PxeBcExtractDiscoverInfo ( PxeBcExtractDiscoverInfo (
IN PXEBC_PRIVATE_DATA *Private, IN PXEBC_PRIVATE_DATA *Private,
IN UINT16 Type, 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 PXEBC_BOOT_SVR_ENTRY **BootEntry,
OUT EFI_PXE_BASE_CODE_SRVLIST **SrvList OUT EFI_PXE_BASE_CODE_SRVLIST **SrvList
); );

View File

@ -1,7 +1,7 @@
/** @file /** @file
Functions implementation related with DHCPv4 for UefiPxeBc Driver. Functions implementation related with DHCPv4 for UefiPxeBc Driver.
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR> Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
@ -1443,7 +1443,7 @@ PxeBcDhcp4Discover (
break; break;
} }
if ((SrvList[SrvIndex].Type == Type) && 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; break;
} }
SrvIndex++; SrvIndex++;
@ -1587,6 +1587,7 @@ PxeBcDhcp4Dora (
AsciiPrint ("\n Station IP address is "); AsciiPrint ("\n Station IP address is ");
PxeBcShowIp4Addr (&Private->StationIp.v4); PxeBcShowIp4Addr (&Private->StationIp.v4);
AsciiPrint ("\n");
ON_EXIT: ON_EXIT:
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {

View File

@ -1,7 +1,7 @@
/** @file /** @file
Functions declaration related with DHCPv4 for UefiPxeBc Driver. Functions declaration related with DHCPv4 for UefiPxeBc Driver.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR> Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License 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_BOOT_MENU) | \
BIT (PXEBC_VENDOR_TAG_MENU_PROMPT)) 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) \ #define IS_VALID_BOOT_PROMPT(x) \
((((x)[0]) & BIT (PXEBC_VENDOR_TAG_MENU_PROMPT)) \ ((((x)[0]) & BIT (PXEBC_VENDOR_TAG_MENU_PROMPT)) \
== 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_MAX_MESG_SIZE *MaxMesgSize;
} PXEBC_DHCP4_OPTION_ENTRY; } PXEBC_DHCP4_OPTION_ENTRY;
#pragma pack(1)
typedef struct { typedef struct {
UINT16 Type; UINT16 Type;
UINT8 IpCnt; UINT8 IpCnt;
@ -272,6 +277,7 @@ typedef struct {
UINT8 Timeout; UINT8 Timeout;
UINT8 Prompt[1]; UINT8 Prompt[1];
} PXEBC_MENU_PROMPT; } PXEBC_MENU_PROMPT;
#pragma pack()
typedef struct { typedef struct {
UINT32 BitMap[8]; UINT32 BitMap[8];

View File

@ -529,6 +529,7 @@ EfiPxeBcDiscover (
UINT16 Index; UINT16 Index;
EFI_STATUS Status; EFI_STATUS Status;
EFI_PXE_BASE_CODE_IP_FILTER IpFilter; EFI_PXE_BASE_CODE_IP_FILTER IpFilter;
EFI_PXE_BASE_CODE_DISCOVER_INFO *NewCreatedInfo;
if (This == NULL) { if (This == NULL) {
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
@ -541,6 +542,7 @@ EfiPxeBcDiscover (
SrvList = NULL; SrvList = NULL;
Status = EFI_DEVICE_ERROR; Status = EFI_DEVICE_ERROR;
Private->Function = EFI_PXE_BASE_CODE_FUNCTION_DISCOVER; Private->Function = EFI_PXE_BASE_CODE_FUNCTION_DISCOVER;
NewCreatedInfo = NULL;
if (!Mode->Started) { if (!Mode->Started) {
return EFI_NOT_STARTED; return EFI_NOT_STARTED;
@ -594,12 +596,12 @@ EfiPxeBcDiscover (
// //
// 2. Extract the discover information from the cached packets if unspecified. // 2. Extract the discover information from the cached packets if unspecified.
// //
Info = &DefaultInfo; NewCreatedInfo = &DefaultInfo;
Status = PxeBcExtractDiscoverInfo (Private, Type, Info, &BootSvrEntry, &SrvList); Status = PxeBcExtractDiscoverInfo (Private, Type, &NewCreatedInfo, &BootSvrEntry, &SrvList);
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
goto ON_EXIT; goto ON_EXIT;
} }
Info = NewCreatedInfo;
} else { } else {
// //
// 3. Take the pass-in information as the discover info, and validate the server list. // 3. Take the pass-in information as the discover info, and validate the server list.
@ -634,7 +636,36 @@ EfiPxeBcDiscover (
Private->IsDoDiscover = TRUE; Private->IsDoDiscover = TRUE;
if (Info->UseUCast) { if (Info->UseMCast) {
//
// Do discover by multicast.
//
Status = PxeBcDiscoverBootServer (
Private,
Type,
Layer,
UseBis,
&Info->ServerMCastIp,
Info->IpCnt,
SrvList
);
} else if (Info->UseBCast) {
//
// Do discover by broadcast, but only valid for IPv4.
//
ASSERT (!Mode->UsingIpv6);
Status = PxeBcDiscoverBootServer (
Private,
Type,
Layer,
UseBis,
NULL,
Info->IpCnt,
SrvList
);
} else if (Info->UseUCast) {
// //
// Do discover by unicast. // Do discover by unicast.
// //
@ -652,39 +683,11 @@ EfiPxeBcDiscover (
Type, Type,
Layer, Layer,
UseBis, UseBis,
&SrvList[Index].IpAddr, &Private->ServerIp,
0, Info->IpCnt,
NULL SrvList
); );
} }
} else if (Info->UseMCast) {
//
// Do discover by multicast.
//
Status = PxeBcDiscoverBootServer (
Private,
Type,
Layer,
UseBis,
&Info->ServerMCastIp,
0,
NULL
);
} else if (Info->UseBCast) {
//
// Do discover by broadcast, but only valid for IPv4.
//
ASSERT (!Mode->UsingIpv6);
Status = PxeBcDiscoverBootServer (
Private,
Type,
Layer,
UseBis,
NULL,
Info->IpCnt,
SrvList
);
} }
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
@ -698,8 +701,8 @@ EfiPxeBcDiscover (
if (!EFI_ERROR (Status)) { if (!EFI_ERROR (Status)) {
CopyMem ( CopyMem (
&Mode->PxeReply.Dhcpv6, &Mode->PxeReply.Dhcpv6,
&Private->PxeReply.Dhcp6.Packet.Offer, &Private->PxeReply.Dhcp6.Packet.Ack.Dhcp6,
Private->PxeReply.Dhcp6.Packet.Offer.Length Private->PxeReply.Dhcp6.Packet.Ack.Length
); );
Mode->PxeReplyReceived = TRUE; Mode->PxeReplyReceived = TRUE;
Mode->PxeDiscoverValid = TRUE; Mode->PxeDiscoverValid = TRUE;
@ -709,8 +712,8 @@ EfiPxeBcDiscover (
if (!EFI_ERROR (Status)) { if (!EFI_ERROR (Status)) {
CopyMem ( CopyMem (
&Mode->PxeReply.Dhcpv4, &Mode->PxeReply.Dhcpv4,
&Private->PxeReply.Dhcp4.Packet.Offer, &Private->PxeReply.Dhcp4.Packet.Ack.Dhcp4,
Private->PxeReply.Dhcp4.Packet.Offer.Length Private->PxeReply.Dhcp4.Packet.Ack.Length
); );
Mode->PxeReplyReceived = TRUE; Mode->PxeReplyReceived = TRUE;
Mode->PxeDiscoverValid = TRUE; Mode->PxeDiscoverValid = TRUE;
@ -720,6 +723,10 @@ EfiPxeBcDiscover (
ON_EXIT: ON_EXIT:
if (NewCreatedInfo != NULL && NewCreatedInfo != &DefaultInfo) {
FreePool (NewCreatedInfo);
}
if (Mode->UsingIpv6) { if (Mode->UsingIpv6) {
Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData); Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData);
} else { } else {