+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2006 - 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-Module Name:\r
- bc.c\r
-\r
-Abstract:\r
-\r
---*/\r
-\r
-#include "Bc.h"\r
-\r
-//\r
-// helper routines\r
-//\r
-VOID\r
-CvtNum (\r
- IN UINTN Number,\r
- IN UINT8 *Buffer,\r
- IN INTN Length\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Convert number to ASCII value\r
-\r
- Arguments:\r
- Number - Numeric value to convert to decimal ASCII value.\r
- Buffer - Buffer to place ASCII version of the Number\r
- Length - Length of Buffer.\r
-\r
- Returns:\r
- none - none\r
-\r
---*/\r
-{\r
- UINTN Remainder;\r
-\r
- while (Length--) {\r
- Remainder = Number % 10;\r
- Number /= 10;\r
- Buffer[Length] = (UINT8) ('0' + Remainder);\r
- }\r
-}\r
-\r
-VOID\r
-UtoA10 (\r
- IN UINTN Number,\r
- IN UINT8 *Buffer\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Convert number to decimal ASCII value at Buffer location\r
-\r
- Arguments:\r
- Number - Numeric value to convert to decimal ASCII value.\r
- Buffer - Buffer to place ASCII version of the Number\r
-\r
- Returns:\r
- none - none\r
-\r
---*/\r
-{\r
- INTN Index;\r
- UINT8 BuffArray[31];\r
-\r
- BuffArray[30] = 0;\r
- CvtNum (Number, BuffArray, 30);\r
-\r
- for (Index = 0; Index < 30; ++Index) {\r
- if (BuffArray[Index] != '0') {\r
- break;\r
- }\r
- }\r
-\r
- CopyMem (Buffer, BuffArray + Index, 31 - Index);\r
-}\r
-\r
-UINTN\r
-AtoU (\r
- IN UINT8 *Buffer\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Convert ASCII numeric string to a UINTN value\r
-\r
- Arguments:\r
- Number - Numeric value to convert to decimal ASCII value.\r
- Buffer - Buffer to place ASCII version of the Number\r
-\r
- Returns:\r
- Value - UINTN value of the ASCII string.\r
-\r
---*/\r
-{\r
- UINTN Value;\r
- INT8 Character;\r
-\r
- Value = 0;\r
- Character = *Buffer++;\r
- do {\r
- Value = Value * 10 + Character - '0';\r
- Character = *Buffer++;\r
- } while (Character);\r
-\r
- return Value;\r
-}\r
-\r
-UINT64\r
-AtoU64 (\r
- IN UINT8 *Buffer\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Convert ASCII numeric string to a UINTN value\r
-\r
- Arguments:\r
- Number - Numeric value to convert to decimal ASCII value.\r
- Buffer - Buffer to place ASCII version of the Number\r
-\r
- Returns:\r
- Value - UINTN value of the ASCII string.\r
-\r
---*/\r
-{\r
- UINT64 Value;\r
- UINT8 Character;\r
-\r
- Value = 0;\r
- while ((Character = *Buffer++) != '\0') {\r
- Value = MultU64x32 (Value, 10) + (Character - '0');\r
- }\r
-\r
- return Value;\r
-}\r
-//\r
-// random number generator\r
-//\r
-#define RANDOM_MULTIPLIER 2053\r
-#define RANDOM_ADD_IN_VALUE 19\r
-\r
-VOID\r
-SeedRandom (\r
- IN PXE_BASECODE_DEVICE *Private,\r
- IN UINT16 InitialSeed\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Initialize the Seed for the random number generator\r
-\r
- Arguments:\r
-\r
- Returns:\r
- none -\r
-\r
---*/\r
-{\r
- if (Private != NULL) {\r
- Private->RandomSeed = InitialSeed;\r
- }\r
-}\r
-\r
-UINT16\r
-Random (\r
- IN PXE_BASECODE_DEVICE *Private\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Generate and return a pseudo-random number\r
-\r
- Arguments:\r
-\r
- Returns:\r
- Number - UINT16 random number\r
-\r
---*/\r
-{\r
- UINTN Number;\r
-\r
- if (Private != NULL) {\r
- Number = -(INTN) Private->RandomSeed * RANDOM_MULTIPLIER + RANDOM_ADD_IN_VALUE;\r
-\r
- return Private->RandomSeed = (UINT16) Number;\r
- } else {\r
- return 0;\r
- }\r
-}\r
-//\r
-// calculate the internet checksum (RFC 1071)\r
-// return 16 bit ones complement of ones complement sum of 16 bit words\r
-//\r
-UINT16\r
-IpChecksum (\r
- IN UINT16 *Packet,\r
- IN UINTN Length\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Calculate the internet checksum (see RFC 1071)\r
-\r
- Arguments:\r
- Packet - Buffer which contains the data to be checksummed\r
- Length - Length to be checksummed\r
-\r
- Returns:\r
- Checksum - Returns the 16 bit ones complement of\r
- ones complement sum of 16 bit words\r
-\r
---*/\r
-{\r
- UINT32 Sum;\r
- UINT8 Odd;\r
-\r
- Sum = 0;\r
- Odd = (UINT8) (Length & 1);\r
- Length >>= 1;\r
- while (Length--) {\r
- Sum += *Packet++;\r
- }\r
-\r
- if (Odd) {\r
- Sum += *(UINT8 *) Packet;\r
- }\r
-\r
- Sum = (Sum & 0xffff) + (Sum >> 16);\r
- //\r
- // in case above carried\r
- //\r
- Sum += Sum >> 16;\r
-\r
- return (UINT16) (~ (UINT16) Sum);\r
-}\r
-\r
-UINT16\r
-IpChecksum2 (\r
- IN UINT16 *Header,\r
- IN UINTN HeaderLen,\r
- IN UINT16 *Message,\r
- IN UINTN MessageLen\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Calculate the internet checksum (see RFC 1071)\r
- on a non contiguous header and data\r
-\r
- Arguments:\r
- Header - Buffer which contains the data to be checksummed\r
- HeaderLen - Length to be checksummed\r
- Message - Buffer which contains the data to be checksummed\r
- MessageLen - Length to be checksummed\r
-\r
- Returns:\r
- Checksum - Returns the 16 bit ones complement of\r
- ones complement sum of 16 bit words\r
-\r
---*/\r
-{\r
- UINT32 Sum;\r
-\r
- Sum = (UINT16)~IpChecksum (Header, HeaderLen);\r
- Sum = Sum + (UINT16)~IpChecksum (Message, MessageLen);\r
- //\r
- // in case above carried\r
- //\r
- Sum += Sum >> 16;\r
-\r
- return (UINT16) (~ (UINT16) Sum);\r
-}\r
-\r
-UINT16\r
-UpdateChecksum (\r
- IN UINT16 OldChksum,\r
- IN UINT16 OldWord,\r
- IN UINT16 NewWord\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Adjust the internet checksum (see RFC 1071) on a single word update.\r
-\r
- Arguments:\r
- OldChkSum - Checksum previously calculated\r
- OldWord - Value\r
- NewWord - New Value\r
-\r
- Returns:\r
- Checksum - Returns the 16 bit ones complement of\r
- ones complement sum of 16 bit words\r
-\r
---*/\r
-{\r
- UINT32 sum;\r
-\r
- sum = ~OldChksum + NewWord - OldWord;\r
- //\r
- // in case above carried\r
- //\r
- sum += sum >> 16;\r
- return (UINT16) (~ (UINT16) sum);\r
-}\r
-\r
-STATIC\r
-BOOLEAN\r
-SetMakeCallback (\r
- IN PXE_BASECODE_DEVICE *Private\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- See if a callback is in play\r
-\r
- Arguments:\r
- Private - Pointer to Pxe BaseCode Protocol\r
-\r
- Returns:\r
- 0 - Callbacks are active on the handle\r
- 1 - Callbacks are not active on the handle\r
-\r
---*/\r
-{\r
- Private->EfiBc.Mode->MakeCallbacks = (BOOLEAN) (gBS->HandleProtocol (\r
- Private->Handle,\r
- &gEfiPxeBaseCodeCallbackProtocolGuid,\r
- (VOID *) &Private->CallbackProtocolPtr\r
- ) == EFI_SUCCESS);\r
-\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nMode->MakeCallbacks == %d ",\r
- Private->EfiBc.Mode->MakeCallbacks)\r
- );\r
-\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nPrivate->CallbackProtocolPtr == %xh ",\r
- Private->CallbackProtocolPtr)\r
- );\r
-\r
- if (Private->CallbackProtocolPtr != NULL) {\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nCallbackProtocolPtr->Revision = %xh ",\r
- Private->CallbackProtocolPtr->Revision)\r
- );\r
-\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nCallbackProtocolPtr->Callback = %xh ",\r
- Private->CallbackProtocolPtr->Callback)\r
- );\r
- }\r
-\r
- return Private->EfiBc.Mode->MakeCallbacks;\r
-}\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-EFI_STATUS\r
-WaitForReceive (\r
- IN PXE_BASECODE_DEVICE *Private,\r
- IN EFI_PXE_BASE_CODE_FUNCTION Function,\r
- IN EFI_EVENT TimeoutEvent,\r
- IN OUT UINTN *HeaderSizePtr,\r
- IN OUT UINTN *BufferSizePtr,\r
- IN OUT UINT16 *ProtocolPtr\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Routine which does an SNP->Receive over a timeout period and doing callbacks\r
-\r
- Arguments:\r
- Private - Pointer to Pxe BaseCode Protocol\r
- Function - What PXE function to callback\r
- TimeoutEvent - Timer event that will trigger when we have waited too\r
- long for an incoming packet\r
- HeaderSizePtr - Pointer to the size of the Header size\r
- BufferSizePtr - Pointer to the size of the Buffer size\r
- ProtocolPtr - The protocol to sniff for (namely, UDP/etc)\r
-\r
- Returns:\r
- 0 - Something was returned\r
- !0 - Like there was nothing to receive (EFI_TIMEOUT/NOT_READY)\r
-\r
---*/\r
-{\r
- EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;\r
- EFI_PXE_CALLBACK CallbackPtr;\r
- EFI_STATUS StatCode;\r
- EFI_EVENT CallbackEvent;\r
-\r
- //\r
- // Initialize pointer to SNP interface\r
- //\r
- SnpPtr = Private->SimpleNetwork;\r
-\r
- //\r
- // Initialize pointer to PxeBc callback routine - if any\r
- //\r
- CallbackPtr = (Private->EfiBc.Mode->MakeCallbacks) ? Private->CallbackProtocolPtr->Callback : NULL;\r
-\r
- //\r
- // Create callback event and set timer\r
- //\r
- StatCode = gBS->CreateEvent (\r
- EVT_TIMER,\r
- TPL_CALLBACK,\r
- NULL,\r
- NULL,\r
- &CallbackEvent\r
- );\r
-\r
- if (EFI_ERROR (StatCode)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- //\r
- // every 100 milliseconds\r
- //\r
- StatCode = gBS->SetTimer (\r
- CallbackEvent,\r
- TimerPeriodic,\r
- 1000000\r
- );\r
-\r
- if (EFI_ERROR (StatCode)) {\r
- gBS->CloseEvent (CallbackEvent);\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // Loop until a packet is received or a receive error is detected or\r
- // a callback abort is detected or a timeout event occurs.\r
- //\r
- for (;;)\r
- {\r
- //\r
- // Poll for received packet.\r
- //\r
- *BufferSizePtr = BUFFER_ALLOCATE_SIZE;\r
-\r
- StatCode = SnpPtr->Receive (\r
- SnpPtr,\r
- HeaderSizePtr,\r
- BufferSizePtr,\r
- Private->ReceiveBufferPtr,\r
- 0,\r
- 0,\r
- ProtocolPtr\r
- );\r
-\r
- if (!EFI_ERROR (StatCode)) {\r
- //\r
- // Packet was received. Make received callback then return.\r
- //\r
- if (CallbackPtr != NULL) {\r
- StatCode = CallbackPtr (\r
- Private->CallbackProtocolPtr,\r
- Function,\r
- TRUE,\r
- (UINT32) *BufferSizePtr,\r
- (EFI_PXE_BASE_CODE_PACKET *) Private->ReceiveBufferPtr\r
- );\r
-\r
- if (StatCode != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) {\r
- StatCode = EFI_ABORTED;\r
- } else {\r
- StatCode = EFI_SUCCESS;\r
- }\r
- }\r
-\r
- break;\r
- }\r
-\r
- if (StatCode != EFI_NOT_READY) {\r
- break;\r
- }\r
-\r
- //\r
- // Check for callback event.\r
- //\r
- if (!EFI_ERROR (gBS->CheckEvent (CallbackEvent))) {\r
- //\r
- // Make periodic callback if callback pointer is initialized.\r
- //\r
- if (CallbackPtr != NULL) {\r
- StatCode = CallbackPtr (\r
- Private->CallbackProtocolPtr,\r
- Function,\r
- FALSE,\r
- 0,\r
- NULL\r
- );\r
-\r
- //\r
- // Abort if directed to by callback routine.\r
- //\r
- if (StatCode != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) {\r
- StatCode = EFI_ABORTED;\r
- break;\r
- }\r
- }\r
- }\r
- //\r
- // Check for timeout event.\r
- //\r
- if (TimeoutEvent == 0) {\r
- StatCode = EFI_TIMEOUT;\r
- break;\r
- }\r
-\r
- if (!EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {\r
- StatCode = EFI_TIMEOUT;\r
- break;\r
- }\r
- //\r
- // Check IGMP timer events.\r
- //\r
- IgmpCheckTimers (Private);\r
- }\r
-\r
- gBS->CloseEvent (CallbackEvent);\r
-\r
- return StatCode;\r
-}\r
-\r
-EFI_STATUS\r
-SendPacket (\r
- PXE_BASECODE_DEVICE *Private,\r
- VOID *HeaderPtr,\r
- VOID *PacketPtr,\r
- INTN PacketLen,\r
- VOID *HardwareAddr,\r
- UINT16 MediaProtocol,\r
- IN EFI_PXE_BASE_CODE_FUNCTION Function\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Routine which does an SNP->Transmit of a buffer\r
-\r
- Arguments:\r
- Private - Pointer to Pxe BaseCode Protocol\r
- HeaderPtr - Pointer to the buffer\r
- PacketPtr - Pointer to the packet to send\r
- PacketLen - The length of the entire packet to send\r
- HardwareAddr - Pointer to the MAC address of the destination\r
- MediaProtocol - What type of frame to create (RFC 1700) - IE. Ethernet\r
- Function - What PXE function to callback\r
-\r
- Returns:\r
- 0 - Something was sent\r
- !0 - An error was encountered during sending of a packet\r
-\r
---*/\r
-{\r
- EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;\r
- EFI_SIMPLE_NETWORK_MODE *SnpModePtr;\r
- EFI_PXE_CALLBACK CallbackPtr;\r
- EFI_STATUS StatCode;\r
- EFI_EVENT TimeoutEvent;\r
- UINT32 IntStatus;\r
- VOID *TxBuf;\r
-\r
- //\r
- //\r
- //\r
- CallbackPtr = Private->EfiBc.Mode->MakeCallbacks ? Private->CallbackProtocolPtr->Callback : 0;\r
-\r
- SnpPtr = Private->SimpleNetwork;\r
- SnpModePtr = SnpPtr->Mode;\r
-\r
- //\r
- // clear prior interrupt status\r
- //\r
- StatCode = SnpPtr->GetStatus (SnpPtr, &IntStatus, 0);\r
-\r
- if (EFI_ERROR (StatCode)) {\r
- DEBUG (\r
- (EFI_D_WARN,\r
- "\nSendPacket() Exit #1 %xh (%r)",\r
- StatCode,\r
- StatCode)\r
- );\r
- return StatCode;\r
- }\r
-\r
- Private->DidTransmit = FALSE;\r
-\r
- if (CallbackPtr != NULL) {\r
- if (CallbackPtr (\r
- Private->CallbackProtocolPtr,\r
- Function,\r
- FALSE,\r
- (UINT32) PacketLen,\r
- PacketPtr\r
- ) != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) {\r
- DEBUG (\r
- (EFI_D_WARN,\r
- "\nSendPacket() Exit #2 %xh (%r)",\r
- EFI_ABORTED,\r
- EFI_ABORTED)\r
- );\r
- return EFI_ABORTED;\r
- }\r
- }\r
- //\r
- // put packet in transmit queue\r
- // headersize should be zero if not filled in\r
- //\r
- StatCode = gBS->CreateEvent (\r
- EVT_TIMER,\r
- TPL_CALLBACK,\r
- NULL,\r
- NULL,\r
- &TimeoutEvent\r
- );\r
-\r
- if (EFI_ERROR (StatCode)) {\r
- DEBUG (\r
- (EFI_D_ERROR,\r
- "Could not create transmit timeout event. %r\n",\r
- StatCode)\r
- );\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- //\r
- // 5 milliseconds\r
- //\r
- StatCode = gBS->SetTimer (\r
- TimeoutEvent,\r
- TimerRelative,\r
- 50000\r
- );\r
-\r
- if (EFI_ERROR (StatCode)) {\r
- DEBUG (\r
- (EFI_D_ERROR,\r
- "Could not set transmit timeout event timer. %r\n",\r
- StatCode)\r
- );\r
- gBS->CloseEvent (TimeoutEvent);\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- for (;;) {\r
- StatCode = SnpPtr->Transmit (\r
- SnpPtr,\r
- (UINTN) SnpPtr->Mode->MediaHeaderSize,\r
- (UINTN) (PacketLen + SnpPtr->Mode->MediaHeaderSize),\r
- HeaderPtr,\r
- &SnpModePtr->CurrentAddress,\r
- (EFI_MAC_ADDRESS *) HardwareAddr,\r
- &MediaProtocol\r
- );\r
-\r
- if (StatCode != EFI_NOT_READY) {\r
- break;\r
- }\r
-\r
- if (!EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {\r
- StatCode = EFI_TIMEOUT;\r
- break;\r
- }\r
- }\r
-\r
- gBS->CloseEvent (TimeoutEvent);\r
-\r
- if (EFI_ERROR (StatCode)) {\r
- DEBUG (\r
- (EFI_D_WARN,\r
- "\nSendPacket() Exit #3 %xh (%r)",\r
- StatCode,\r
- StatCode)\r
- );\r
- return StatCode;\r
- }\r
- //\r
- // remove transmit buffer from snp's unused queue\r
- // done this way in case someday things are buffered and we don't get it back\r
- // immediately\r
- //\r
- StatCode = gBS->CreateEvent (\r
- EVT_TIMER,\r
- TPL_CALLBACK,\r
- NULL,\r
- NULL,\r
- &TimeoutEvent\r
- );\r
-\r
- if (EFI_ERROR (StatCode)) {\r
- DEBUG (\r
- (EFI_D_ERROR,\r
- "Could not create transmit status timeout event. %r\n",\r
- StatCode)\r
- );\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- //\r
- // 5 milliseconds\r
- //\r
- StatCode = gBS->SetTimer (\r
- TimeoutEvent,\r
- TimerRelative,\r
- 50000\r
- );\r
-\r
- if (EFI_ERROR (StatCode)) {\r
- DEBUG (\r
- (EFI_D_ERROR,\r
- "Could not set transmit status timeout event timer. %r\n",\r
- StatCode)\r
- );\r
- gBS->CloseEvent (TimeoutEvent);\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- for (;;) {\r
- StatCode = SnpPtr->GetStatus (SnpPtr, &IntStatus, &TxBuf);\r
-\r
- if (EFI_ERROR (StatCode)) {\r
- DEBUG (\r
- (EFI_D_WARN,\r
- "\nSendPacket() Exit #4 %xh (%r)",\r
- StatCode,\r
- StatCode)\r
- );\r
- break;\r
- }\r
-\r
- if (IntStatus & EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT) {\r
- Private->DidTransmit = TRUE;\r
- }\r
-\r
- if (TxBuf != NULL) {\r
- break;\r
- }\r
-\r
- if (!EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {\r
- StatCode = EFI_TIMEOUT;\r
- break;\r
- }\r
- }\r
-\r
- gBS->CloseEvent (TimeoutEvent);\r
-\r
- return StatCode;\r
-}\r
-//\r
-//\r
-//\r
-EFI_BIS_PROTOCOL *\r
-PxebcBisStart (\r
- IN PXE_BASECODE_DEVICE *Private,\r
- OUT BIS_APPLICATION_HANDLE *BisAppHandle,\r
- OUT OPTIONAL EFI_BIS_DATA **BisDataSigInfo\r
- )\r
-/*++\r
-Routine description:\r
- Locate BIS interface and if found, try to start it.\r
-\r
-Parameters:\r
- Private := Pointer to PxeBc protocol\r
- BisAppHandle := Pointer to BIS application handle storage\r
- BisDataSigInfo := Pointer to BIS signature information storage\r
-Returns:\r
---*/\r
-{\r
- EFI_STATUS EfiStatus;\r
- EFI_HANDLE BisHandleBuffer;\r
- UINTN BisHandleCount;\r
- EFI_BIS_PROTOCOL *BisPtr;\r
- EFI_BIS_VERSION BisInterfaceVersion;\r
- BOOLEAN BisCheckFlag;\r
-\r
- BisHandleCount = sizeof (EFI_HANDLE);\r
- BisCheckFlag = FALSE;\r
-\r
- //\r
- // Locate BIS protocol handle (if present).\r
- // If BIS protocol handle is not found, return NULL.\r
- //\r
- DEBUG ((EFI_D_INFO, "\ngBS->LocateHandle() "));\r
-\r
- EfiStatus = gBS->LocateHandle (\r
- ByProtocol,\r
- &gEfiBisProtocolGuid,\r
- NULL,\r
- &BisHandleCount,\r
- &BisHandleBuffer\r
- );\r
-\r
- if (EFI_ERROR (EfiStatus)) {\r
- //\r
- // Any error means that there is no BIS.\r
- // Note - It could mean that there are more than\r
- // one BIS protocols installed, but that scenario\r
- // is not yet supported.\r
- //\r
- DEBUG (\r
- (EFI_D_WARN,\r
- "\nPxebcBisStart()""\n gBS->LocateHandle() %r (%xh)\n",\r
- EfiStatus,\r
- EfiStatus)\r
- );\r
-\r
- return NULL;\r
- }\r
-\r
- if (BisHandleCount != sizeof (BisHandleBuffer)) {\r
- //\r
- // This really should never happen, but I am paranoid.\r
- //\r
- DEBUG (\r
- (EFI_D_NET,\r
- "\nPxebcBisStart() BisHandleCount != %d\n",\r
- sizeof BisHandleBuffer)\r
- );\r
-\r
- return NULL;\r
- }\r
-\r
- DEBUG ((EFI_D_INFO, "BIS handle found."));\r
-\r
- //\r
- // Locate BIS protocol interface.\r
- // If the BIS protocol interface cannot be found, return NULL.\r
- //\r
- DEBUG ((EFI_D_INFO, "\ngBS->HandleProtocol() "));\r
-\r
- EfiStatus = gBS->HandleProtocol (\r
- BisHandleBuffer,\r
- &gEfiBisProtocolGuid,\r
- (VOID **) &BisPtr\r
- );\r
-\r
- if (EFI_ERROR (EfiStatus)) {\r
- DEBUG (\r
- (EFI_D_WARN,\r
- "\nPxebcBisStart()""\n gBS->HandleProtocol() %r (%xh)\n",\r
- EfiStatus,\r
- EfiStatus)\r
- );\r
-\r
- return NULL;\r
- }\r
-\r
- if (BisPtr == NULL) {\r
- //\r
- // This really should never happen.\r
- //\r
- DEBUG (\r
- (EFI_D_NET,\r
- "\nPxebcBisStart()""\n gBS->HandleProtocoL() ""BIS protocol interface pointer is NULL!\n")\r
- );\r
-\r
- return NULL;\r
- }\r
-\r
- DEBUG ((EFI_D_INFO, "BIS protocol interface found."));\r
-\r
- //\r
- // Check that all of the BIS API function pointers are not NULL.\r
- //\r
- if (BisPtr->Initialize == NULL ||\r
- BisPtr->Shutdown == NULL ||\r
- BisPtr->Free == NULL ||\r
- BisPtr->GetBootObjectAuthorizationCertificate == NULL ||\r
- BisPtr->GetBootObjectAuthorizationCheckFlag == NULL ||\r
- BisPtr->GetBootObjectAuthorizationUpdateToken == NULL ||\r
- BisPtr->GetSignatureInfo == NULL ||\r
- BisPtr->UpdateBootObjectAuthorization == NULL ||\r
- BisPtr->VerifyBootObject == NULL ||\r
- BisPtr->VerifyObjectWithCredential == NULL\r
- ) {\r
- DEBUG (\r
- (\r
- EFI_D_NET,\r
- "\nPxebcBisStart()""\n BIS protocol interface is invalid."\r
- "\n At least one BIS protocol function pointer is NULL.\n"\r
- )\r
- );\r
-\r
- return NULL;\r
- }\r
- //\r
- // Initialize BIS.\r
- // If BIS does not initialize, return NULL.\r
- //\r
- DEBUG ((EFI_D_INFO, "\nBisPtr->Initialize() "));\r
-\r
- BisInterfaceVersion.Major = BIS_VERSION_1;\r
-\r
- EfiStatus = BisPtr->Initialize (\r
- BisPtr,\r
- BisAppHandle,\r
- &BisInterfaceVersion,\r
- NULL\r
- );\r
-\r
- if (EFI_ERROR (EfiStatus)) {\r
- DEBUG (\r
- (EFI_D_WARN,\r
- "\nPxebcBisStart()""\n BisPtr->Initialize() %r (%xh)\n",\r
- EfiStatus,\r
- EfiStatus)\r
- );\r
-\r
- return NULL;\r
- }\r
-\r
- DEBUG (\r
- (EFI_D_INFO,\r
- " BIS version: %d.%d",\r
- BisInterfaceVersion.Major,\r
- BisInterfaceVersion.Minor)\r
- );\r
-\r
- //\r
- // If the requested BIS API version is not supported,\r
- // shutdown BIS and return NULL.\r
- //\r
- if (BisInterfaceVersion.Major != BIS_VERSION_1) {\r
- DEBUG (\r
- (EFI_D_WARN,\r
- "\nPxebcBisStart()""\n BIS version %d.%d not supported by PXE BaseCode.\n",\r
- BisInterfaceVersion.Major,\r
- BisInterfaceVersion.Minor)\r
- );\r
-\r
- BisPtr->Shutdown (*BisAppHandle);\r
- return NULL;\r
- }\r
- //\r
- // Get BIS check flag.\r
- // If the BIS check flag cannot be read, shutdown BIS and return NULL.\r
- //\r
- DEBUG ((EFI_D_INFO, "\nBisPtr->GetBootObjectAuthorizationCheckFlag() "));\r
-\r
- EfiStatus = BisPtr->GetBootObjectAuthorizationCheckFlag (*BisAppHandle, &BisCheckFlag);\r
-\r
- if (EFI_ERROR (EfiStatus)) {\r
- DEBUG (\r
- (EFI_D_WARN,\r
- "\nPxebcBisStart()""\n BisPtr->GetBootObjectAuthorizationCheckFlag() %r (%xh)\n",\r
- EfiStatus,\r
- EfiStatus)\r
- );\r
-\r
- BisPtr->Shutdown (*BisAppHandle);\r
- return NULL;\r
- }\r
- //\r
- // If the BIS check flag is FALSE, shutdown BIS and return NULL.\r
- //\r
- if (!BisCheckFlag) {\r
- DEBUG ((EFI_D_INFO, "\nBIS check flag is FALSE.\n"));\r
- BisPtr->Shutdown (*BisAppHandle);\r
- return NULL;\r
- } else {\r
- DEBUG ((EFI_D_INFO, "\nBIS check flag is TRUE."));\r
- }\r
- //\r
- // Early out if caller does not want signature information.\r
- //\r
- if (BisDataSigInfo == NULL) {\r
- return BisPtr;\r
- }\r
- //\r
- // Get BIS signature information.\r
- // If the signature information cannot be read or is invalid,\r
- // shutdown BIS and return NULL.\r
- //\r
- DEBUG ((EFI_D_INFO, "\nBisPtr->GetSignatureInfo() "));\r
-\r
- EfiStatus = BisPtr->GetSignatureInfo (*BisAppHandle, BisDataSigInfo);\r
-\r
- if (EFI_ERROR (EfiStatus)) {\r
- DEBUG (\r
- (EFI_D_WARN,\r
- "\nPxebcBisStart()""\n BisPtr_GetSignatureInfo() %r (%xh)\n",\r
- EfiStatus,\r
- EfiStatus)\r
- );\r
-\r
- BisPtr->Shutdown (*BisAppHandle);\r
- return NULL;\r
- }\r
-\r
- if (*BisDataSigInfo == NULL) {\r
- //\r
- // This should never happen.\r
- //\r
- DEBUG (\r
- (EFI_D_NET,\r
- "\nPxebcBisStart()""\n BisPtr->GetSignatureInfo() Data pointer is NULL!\n")\r
- );\r
-\r
- BisPtr->Shutdown (*BisAppHandle);\r
- return NULL;\r
- }\r
-\r
- if ((*BisDataSigInfo)->Length < sizeof (EFI_BIS_SIGNATURE_INFO) ||\r
- (*BisDataSigInfo)->Length % sizeof (EFI_BIS_SIGNATURE_INFO) ||\r
- (*BisDataSigInfo)->Length > sizeof (EFI_BIS_SIGNATURE_INFO) * 63\r
- ) {\r
- //\r
- // This should never happen.\r
- //\r
- DEBUG (\r
- (EFI_D_NET,\r
- "\nPxebcBisStart()""\n BisPtr->GetSignatureInfo() Invalid BIS siginfo length.\n")\r
- );\r
-\r
- BisPtr->Free (*BisAppHandle, *BisDataSigInfo);\r
- BisPtr->Shutdown (*BisAppHandle);\r
- return NULL;\r
- }\r
-\r
- return BisPtr;\r
-}\r
-\r
-VOID\r
-PxebcBisStop (\r
- EFI_BIS_PROTOCOL *BisPtr,\r
- BIS_APPLICATION_HANDLE BisAppHandle,\r
- EFI_BIS_DATA *BisDataSigInfo\r
- )\r
-/*++\r
-Routine description:\r
- Stop the BIS interface and release allocations.\r
-\r
-Parameters:\r
- BisPtr := Pointer to BIS interface\r
- BisAppHandle := BIS application handle\r
- BisDataSigInfo := Pointer to BIS signature information data\r
-\r
-Returns:\r
-\r
---*/\r
-{\r
- if (BisPtr == NULL) {\r
- return ;\r
- }\r
- //\r
- // Free BIS allocated resources and shutdown BIS.\r
- // Return TRUE - BIS support is officially detected.\r
- //\r
- if (BisDataSigInfo != NULL) {\r
- BisPtr->Free (BisAppHandle, BisDataSigInfo);\r
- }\r
-\r
- BisPtr->Shutdown (BisAppHandle);\r
-}\r
-\r
-BOOLEAN\r
-PxebcBisVerify (\r
- PXE_BASECODE_DEVICE *Private,\r
- VOID *FileBuffer,\r
- UINTN FileLength,\r
- VOID *CredentialBuffer,\r
- UINTN CredentialLength\r
- )\r
-/*++\r
-Routine description:\r
- Verify image and credential file.\r
-\r
-Parameters:\r
- Private := Pointer to PxeBc interface\r
- FileBuffer := Pointer to image buffer\r
- FileLength := Image length in bytes\r
- CredentialBuffer := Pointer to credential buffer\r
- CredentialLength := Credential length in bytes\r
-\r
-Returns:\r
- TRUE := verified\r
- FALSE := not verified\r
---*/\r
-{\r
- EFI_BIS_PROTOCOL *BisPtr;\r
- BIS_APPLICATION_HANDLE BisAppHandle;\r
- EFI_BIS_DATA FileData;\r
- EFI_BIS_DATA CredentialData;\r
- EFI_STATUS EfiStatus;\r
- BOOLEAN IsVerified;\r
-\r
- if (Private == NULL || FileBuffer == NULL || FileLength == 0 || CredentialBuffer == NULL || CredentialLength == 0) {\r
- return FALSE;\r
- }\r
-\r
- BisPtr = PxebcBisStart (Private, &BisAppHandle, NULL);\r
-\r
- if (BisPtr == NULL) {\r
- return FALSE;\r
- }\r
-\r
- FileData.Length = (UINT32) FileLength;\r
- FileData.Data = FileBuffer;\r
- CredentialData.Length = (UINT32) CredentialLength;\r
- CredentialData.Data = CredentialBuffer;\r
-\r
- EfiStatus = BisPtr->VerifyBootObject (\r
- BisAppHandle,\r
- &CredentialData,\r
- &FileData,\r
- &IsVerified\r
- );\r
-\r
- PxebcBisStop (BisPtr, BisAppHandle, NULL);\r
-\r
- return (BOOLEAN) ((EFI_ERROR (EfiStatus)) ? FALSE : (IsVerified ? TRUE : FALSE));\r
-}\r
-\r
-BOOLEAN\r
-PxebcBisDetect (\r
- PXE_BASECODE_DEVICE *Private\r
- )\r
-/*++\r
-Routine description:\r
- Check for BIS interface presence.\r
-\r
-Parameters:\r
- Private := Pointer to PxeBc interface\r
-\r
-Returns:\r
- TRUE := BIS present\r
- FALSE := BIS not present\r
---*/\r
-{\r
- EFI_BIS_PROTOCOL *BisPtr;\r
- BIS_APPLICATION_HANDLE BisAppHandle;\r
- EFI_BIS_DATA *BisDataSigInfo;\r
-\r
- BisPtr = PxebcBisStart (Private, &BisAppHandle, &BisDataSigInfo);\r
-\r
- if (BisPtr == NULL) {\r
- return FALSE;\r
- }\r
-\r
- PxebcBisStop (BisPtr, BisAppHandle, BisDataSigInfo);\r
-\r
- return TRUE;\r
-}\r
-\r
-VOID *BCNotifyReg;\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-BcStart (\r
- IN EFI_PXE_BASE_CODE_PROTOCOL *This,\r
- IN BOOLEAN UseIPv6\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Start and initialize the BaseCode protocol, Simple Network protocol and UNDI.\r
-\r
- Arguments:\r
- Private - Pointer to Pxe BaseCode Protocol\r
- UseIPv6 - Do we want to support IPv6?\r
-\r
- Returns:\r
- EFI_SUCCESS\r
- EFI_INVALID_PARAMETER\r
- EFI_UNSUPPORTED\r
- EFI_ALREADY_STARTED\r
- EFI_OUT_OF_RESOURCES\r
- Status is also returned from SNP.Start() and SNP.Initialize().\r
-\r
---*/\r
-{\r
- EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;\r
- EFI_SIMPLE_NETWORK_MODE *SnpModePtr;\r
- EFI_STATUS StatCode;\r
- PXE_BASECODE_DEVICE *Private;\r
-\r
- //\r
- // Lock the instance data\r
- //\r
- StatCode = EFI_SUCCESS;\r
-\r
- if (This == NULL) {\r
- DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
-\r
- if (Private == NULL) {\r
- DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE pointer == NULL"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- EfiAcquireLock (&Private->Lock);\r
-\r
- //\r
- // Make sure BaseCode is not already started.\r
- //\r
- if (This->Mode->Started) {\r
- DEBUG ((EFI_D_WARN, "\nBcStart() BC is already started.\n"));\r
- EfiReleaseLock (&Private->Lock);\r
- return EFI_ALREADY_STARTED;\r
- }\r
-\r
- //\r
- // Fail if IPv6 is requested and not supported.\r
- //\r
- if (UseIPv6) {\r
- DEBUG ((EFI_D_WARN, "\nBcStart() IPv6 is not supported.\n"));\r
- EfiReleaseLock (&Private->Lock);\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- //\r
- // Setup shortcuts to SNP protocol and data structure.\r
- //\r
- SnpPtr = Private->SimpleNetwork;\r
- SnpModePtr = SnpPtr->Mode;\r
-\r
- //\r
- // Start and initialize SNP.\r
- //\r
- if (SnpModePtr->State == EfiSimpleNetworkStopped) {\r
- StatCode = (*SnpPtr->Start) (SnpPtr);\r
-\r
- if (SnpModePtr->State != EfiSimpleNetworkStarted) {\r
- DEBUG ((EFI_D_WARN, "\nBcStart() Could not start SNP.\n"));\r
- EfiReleaseLock (&Private->Lock);\r
- return StatCode;\r
- }\r
- }\r
- //\r
- // acquire memory for mode and transmit/receive buffers\r
- //\r
- if (SnpModePtr->State == EfiSimpleNetworkStarted) {\r
- StatCode = (*SnpPtr->Initialize) (SnpPtr, 0, 0);\r
-\r
- if (SnpModePtr->State != EfiSimpleNetworkInitialized) {\r
- DEBUG ((EFI_D_WARN, "\nBcStart() Could not initialize SNP."));\r
- EfiReleaseLock (&Private->Lock);\r
- return StatCode;\r
- }\r
- }\r
- //\r
- // Dump debug info.\r
- //\r
- DEBUG ((EFI_D_INFO, "\nBC Start()"));\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nSnpModePtr->State %Xh",\r
- SnpModePtr->State)\r
- );\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nSnpModePtr->HwAddressSize %Xh",\r
- SnpModePtr->HwAddressSize)\r
- );\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nSnpModePtr->MediaHeaderSize %Xh",\r
- SnpModePtr->MediaHeaderSize)\r
- );\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nSnpModePtr->MaxPacketSize %Xh",\r
- SnpModePtr->MaxPacketSize)\r
- );\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nSnpModePtr->MacAddressChangeable %Xh",\r
- SnpModePtr->MacAddressChangeable)\r
- );\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nSnpModePtr->MultipleTxSupported %Xh",\r
- SnpModePtr->MultipleTxSupported)\r
- );\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nSnpModePtr->CurrentAddress %Xh",\r
- *((UINTN *)&SnpModePtr->CurrentAddress))\r
- );\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nSnpModePtr->BroadcastAddress %Xh",\r
- *((UINTN *)&SnpModePtr->BroadcastAddress))\r
- );\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nSnpModePtr->PermanentAddress %Xh",\r
- *((UINTN *)&SnpModePtr->PermanentAddress))\r
- );\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nSnpModePtr->NvRamSize %Xh",\r
- SnpModePtr->NvRamSize)\r
- );\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nSnpModePtr->NvRamAccessSize %Xh",\r
- SnpModePtr->NvRamAccessSize)\r
- );\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nSnpModePtr->ReceiveFilterMask %Xh",\r
- SnpModePtr->ReceiveFilterMask)\r
- );\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nSnpModePtr->ReceiveFilterSetting %Xh",\r
- SnpModePtr->ReceiveFilterSetting)\r
- );\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nSnpModePtr->MCastFilterCount %Xh",\r
- SnpModePtr->MCastFilterCount)\r
- );\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nSnpModePtr->MCastFilter %Xh",\r
- SnpModePtr->MCastFilter)\r
- );\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nSnpModePtr->IfType %Xh",\r
- SnpModePtr->IfType)\r
- );\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nSnpModePtr->MediaPresentSupported %Xh",\r
- SnpModePtr->MediaPresentSupported)\r
- );\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nSnpModePtr->MediaPresent %Xh",\r
- SnpModePtr->MediaPresent)\r
- );\r
-\r
- //\r
- // If media check is supported and there is no media,\r
- // return error to caller.\r
- //\r
- if (SnpModePtr->MediaPresentSupported && !SnpModePtr->MediaPresent) {\r
- DEBUG ((EFI_D_WARN, "\nBcStart() Media not present.\n"));\r
- EfiReleaseLock (&Private->Lock);\r
- return EFI_NO_MEDIA;\r
- }\r
- //\r
- // Allocate Tx/Rx buffers\r
- //\r
- Private->TransmitBufferPtr = AllocateZeroPool (BUFFER_ALLOCATE_SIZE);\r
- if (Private->TransmitBufferPtr == NULL) {\r
- DEBUG ((EFI_D_NET, "\nBcStart() Could not alloc TxBuf.\n"));\r
- EfiReleaseLock (&Private->Lock);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- Private->ReceiveBufferPtr = AllocateZeroPool (BUFFER_ALLOCATE_SIZE);\r
- if (Private->ReceiveBufferPtr == NULL) {\r
- DEBUG ((EFI_D_NET, "\nBcStart() Could not alloc RxBuf.\n"));\r
- FreePool (Private->TransmitBufferPtr);\r
- EfiReleaseLock (&Private->Lock);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- Private->TftpErrorBuffer = AllocatePool (256);\r
- if (Private->TftpErrorBuffer == NULL) {\r
- FreePool (Private->ReceiveBufferPtr);\r
- FreePool (Private->TransmitBufferPtr);\r
- EfiReleaseLock (&Private->Lock);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- Private->TftpAckBuffer = AllocatePool (256);\r
- if (Private->TftpAckBuffer == NULL) {\r
- FreePool (Private->TftpErrorBuffer);\r
- FreePool (Private->ReceiveBufferPtr);\r
- FreePool (Private->TransmitBufferPtr);\r
- EfiReleaseLock (&Private->Lock);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- //\r
- // Initialize private BaseCode instance data\r
- //\r
- do {\r
- Private->RandomPort = (UINT16) (Private->RandomPort + PXE_RND_PORT_LOW + Random (Private));\r
- } while (Private->RandomPort < PXE_RND_PORT_LOW);\r
-\r
- Private->Igmpv1TimeoutEvent = NULL;\r
- Private->UseIgmpv1Reporting = TRUE;\r
- Private->IpLength = IP_ADDRESS_LENGTH (Private->EfiBc.Mode);\r
-\r
- //\r
- // Initialize Mode structure\r
- //\r
- //\r
- // check for callback protocol and set boolean\r
- //\r
- SetMakeCallback (Private);\r
- Private->EfiBc.Mode->Started = TRUE;\r
- Private->EfiBc.Mode->TTL = DEFAULT_TTL;\r
- Private->EfiBc.Mode->ToS = DEFAULT_ToS;\r
- Private->EfiBc.Mode->UsingIpv6 = UseIPv6;\r
- Private->EfiBc.Mode->DhcpDiscoverValid = FALSE;\r
- Private->EfiBc.Mode->DhcpAckReceived = FALSE;\r
- Private->EfiBc.Mode->ProxyOfferReceived = FALSE;\r
- Private->EfiBc.Mode->PxeDiscoverValid = FALSE;\r
- Private->EfiBc.Mode->PxeReplyReceived = FALSE;\r
- Private->EfiBc.Mode->PxeBisReplyReceived = FALSE;\r
- Private->EfiBc.Mode->IcmpErrorReceived = FALSE;\r
- Private->EfiBc.Mode->TftpErrorReceived = FALSE;\r
- ZeroMem (&Private->EfiBc.Mode->StationIp, sizeof (EFI_IP_ADDRESS));\r
- ZeroMem (&Private->EfiBc.Mode->SubnetMask, sizeof (EFI_IP_ADDRESS));\r
- Private->EfiBc.Mode->IpFilter.Filters = 0;\r
- Private->EfiBc.Mode->IpFilter.IpCnt = 0;\r
- Private->EfiBc.Mode->ArpCacheEntries = 0;\r
- Private->EfiBc.Mode->RouteTableEntries = 0;\r
- ZeroMem (&Private->EfiBc.Mode->IcmpError, sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR));\r
- ZeroMem (&Private->EfiBc.Mode->TftpError, sizeof (EFI_PXE_BASE_CODE_TFTP_ERROR));\r
-\r
- //\r
- // Set to PXE_TRUE by the BC constructor if this BC implementation\r
- // supports IPv6.\r
- //\r
- Private->EfiBc.Mode->Ipv6Supported = SUPPORT_IPV6;\r
- Private->EfiBc.Mode->Ipv6Available = FALSE;\r
-\r
- //\r
- // Set to TRUE by the BC constructor if this BC implementation\r
- // supports BIS.\r
- //\r
- Private->EfiBc.Mode->BisSupported = TRUE;\r
- Private->EfiBc.Mode->BisDetected = PxebcBisDetect (Private);\r
-\r
- //\r
- // This field is set to PXE_TRUE by the BC Start() function. When this\r
- // field is PXE_TRUE, ARP packets are sent as needed to get IP and MAC\r
- // addresses. This can cause unexpected delays in the DHCP(), Discover()\r
- // and MTFTP() functions. Setting this to PXE_FALSE will cause these\r
- // functions to fail if the required IP/MAC information is not in the\r
- // ARP cache. The value of this field can be changed by an application\r
- // at any time.\r
- //\r
- Private->EfiBc.Mode->AutoArp = TRUE;\r
-\r
- //\r
- // Unlock the instance data\r
- //\r
- EfiReleaseLock (&Private->Lock);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-BcStop (\r
- IN EFI_PXE_BASE_CODE_PROTOCOL *This\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Stop the BaseCode protocol, Simple Network protocol and UNDI.\r
-\r
- Arguments:\r
- Private - Pointer to Pxe BaseCode Protocol\r
-\r
- Returns:\r
-\r
- 0 - Successfully stopped\r
- !0 - Failed\r
---*/\r
-{\r
- //\r
- // Lock the instance data\r
- //\r
- EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;\r
- EFI_SIMPLE_NETWORK_MODE *SnpModePtr;\r
- EFI_STATUS StatCode;\r
- PXE_BASECODE_DEVICE *Private;\r
-\r
- StatCode = EFI_SUCCESS;\r
-\r
- if (This == NULL) {\r
- DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
-\r
- if (Private == NULL) {\r
- DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- EfiAcquireLock (&Private->Lock);\r
-\r
- SnpPtr = Private->SimpleNetwork;\r
- SnpModePtr = SnpPtr->Mode;\r
-\r
- //\r
- // Issue BC command\r
- //\r
- StatCode = EFI_NOT_STARTED;\r
-\r
- if (SnpModePtr->State == EfiSimpleNetworkInitialized) {\r
- StatCode = (*SnpPtr->Shutdown) (SnpPtr);\r
- }\r
-\r
- if (SnpModePtr->State == EfiSimpleNetworkStarted) {\r
- StatCode = (*SnpPtr->Stop) (SnpPtr);\r
- }\r
-\r
- if (Private->TransmitBufferPtr != NULL) {\r
- FreePool (Private->TransmitBufferPtr);\r
- Private->TransmitBufferPtr = NULL;\r
- }\r
-\r
- if (Private->ReceiveBufferPtr != NULL) {\r
- FreePool (Private->ReceiveBufferPtr);\r
- Private->ReceiveBufferPtr = NULL;\r
- }\r
-\r
- if (Private->ArpBuffer != NULL) {\r
- FreePool (Private->ArpBuffer);\r
- Private->ArpBuffer = NULL;\r
- }\r
-\r
- if (Private->TftpErrorBuffer != NULL) {\r
- FreePool (Private->TftpErrorBuffer);\r
- Private->TftpErrorBuffer = NULL;\r
- }\r
-\r
- if (Private->TftpAckBuffer != NULL) {\r
- FreePool (Private->TftpAckBuffer);\r
- Private->TftpAckBuffer = NULL;\r
- }\r
-\r
- if (Private->Igmpv1TimeoutEvent != NULL) {\r
- gBS->CloseEvent (Private->Igmpv1TimeoutEvent);\r
- Private->Igmpv1TimeoutEvent = NULL;\r
- }\r
-\r
- Private->FileSize = 0;\r
- Private->EfiBc.Mode->Started = FALSE;\r
-\r
- //\r
- // Unlock the instance data\r
- //\r
- EfiReleaseLock (&Private->Lock);\r
- return StatCode;\r
-}\r
-\r
-const IPV4_ADDR AllSystemsGroup = { { 224, 0, 0, 1 } };\r
-\r
-EFI_STATUS\r
-IpFilter (\r
- IN PXE_BASECODE_DEVICE *Private,\r
- IN EFI_PXE_BASE_CODE_IP_FILTER *Filter\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Set up the IP filter\r
-\r
- Arguments:\r
- Private - Pointer to Pxe BaseCode Protocol\r
- Filter - Pointer to the filter\r
-\r
- Returns:\r
-\r
- 0 - Successfully set the filter\r
- !0 - Failed\r
---*/\r
-{\r
- EFI_STATUS StatCode;\r
- EFI_MAC_ADDRESS MACadds[PXE_IP_FILTER_SIZE];\r
- EFI_PXE_BASE_CODE_MODE *PxebcMode;\r
- EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;\r
- EFI_SIMPLE_NETWORK_MODE *SnpModePtr;\r
- UINT32 Enable;\r
- UINT32 Disable;\r
- UINTN Index;\r
- UINTN Index2;\r
-\r
- PxebcMode = Private->EfiBc.Mode;\r
- SnpPtr = Private->SimpleNetwork;\r
- SnpModePtr = SnpPtr->Mode;\r
-\r
- //\r
- // validate input parameters\r
- // must have a filter\r
- // must not have any extra filter bits set\r
- //\r
- if (Filter == NULL ||\r
- (Filter->Filters &~FILTER_BITS)\r
- //\r
- // must not have a count which is too large or with no IP list\r
- //\r
- ||\r
- (Filter->IpCnt && (!Filter->IpList || Filter->IpCnt > PXE_IP_FILTER_SIZE))\r
- //\r
- // must not have incompatible filters - promiscuous incompatible with anything else\r
- //\r
- ||\r
- (\r
- (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) &&\r
- ((Filter->Filters &~EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) || Filter->IpCnt)\r
- )\r
- ) {\r
- DEBUG ((EFI_D_INFO, "\nIpFilter() Exit #1"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- //\r
- // promiscuous multicast incompatible with multicast in IP list\r
- //\r
- if (Filter->IpCnt && (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST)) {\r
- for (Index = 0; Index < Filter->IpCnt; ++Index) {\r
- if (IS_MULTICAST (&Filter->IpList[Index])) {\r
- DEBUG ((EFI_D_INFO, "\nIpFilter() Exit #2"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- }\r
- }\r
- //\r
- // leave groups for all those multicast which are no longer enabled\r
- //\r
- for (Index = 0; Index < PxebcMode->IpFilter.IpCnt; ++Index) {\r
- if (!IS_MULTICAST (&PxebcMode->IpFilter.IpList[Index])) {\r
- continue;\r
- }\r
-\r
- for (Index2 = 0; Index2 < Filter->IpCnt; ++Index2) {\r
- if (!CompareMem (&PxebcMode->IpFilter.IpList[Index], &Filter->IpList[Index2], IP_ADDRESS_LENGTH (PxebcMode))) {\r
- //\r
- // still enabled\r
- //\r
- break;\r
- }\r
- }\r
- //\r
- // if we didn't find it, remove from group\r
- //\r
- if (Index2 == Filter->IpCnt) {\r
- IgmpLeaveGroup (Private, &PxebcMode->IpFilter.IpList[Index]);\r
- }\r
- }\r
- //\r
- // set enable bits, convert multicast ip adds, join groups\r
- // allways leave receive broadcast enabled at hardware layer\r
- //\r
- Index2 = 0;\r
-\r
- if (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) {\r
- Enable = EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
- } else {\r
- if (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST) {\r
- Enable = EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
- } else {\r
- Enable = EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;\r
-\r
- for (Index = 0; Index < Filter->IpCnt; ++Index) {\r
- CopyMem (&(PxebcMode->IpFilter.IpList[Index]), &(Filter->IpList[Index]), sizeof (EFI_IP_ADDRESS));\r
-\r
- if (IS_MULTICAST (&Filter->IpList[Index])) {\r
- EFI_IP_ADDRESS *TmpIp;\r
-\r
- Enable |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;\r
-\r
- //\r
- // if this is the first group, add the all systems group to mcast list\r
- //\r
- if (!Index2)\r
- {\r
- TmpIp = (EFI_IP_ADDRESS *) &AllSystemsGroup;\r
- --Index;\r
- } else {\r
- TmpIp = (EFI_IP_ADDRESS *) &Filter->IpList[Index];\r
- }\r
- //\r
- // get MAC address of IP\r
- //\r
- StatCode = (*SnpPtr->MCastIpToMac) (SnpPtr, PxebcMode->UsingIpv6, TmpIp, &MACadds[Index2++]);\r
-\r
- if (EFI_ERROR (StatCode)) {\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nIpFilter() Exit #2 %Xh (%r)",\r
- StatCode,\r
- StatCode)\r
- );\r
- return StatCode;\r
- }\r
- } else {\r
- Enable |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;\r
- }\r
- }\r
- }\r
-\r
- if (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) {\r
- Enable |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;\r
- }\r
- }\r
- //\r
- // if nothing changed, just return\r
- //\r
- DEBUG (\r
- (EFI_D_INFO,\r
- "\nsnp->ReceiveFilterSetting == %Xh Filter->IpCnt == %Xh",\r
- SnpModePtr->ReceiveFilterSetting,\r
- Filter->IpCnt)\r
- );\r
-\r
- if (SnpModePtr->ReceiveFilterSetting == Enable && !Filter->IpCnt) {\r
- DEBUG ((EFI_D_INFO, "\nIpFilter() Exit #4"));\r
- return EFI_SUCCESS;\r
- }\r
- //\r
- // disable those currently set but not set in new filter\r
- //\r
- Disable = SnpModePtr->ReceiveFilterSetting &~Enable;\r
-\r
- StatCode = SnpPtr->ReceiveFilters (SnpPtr, Enable, Disable, FALSE, Index2, MACadds);\r
-\r
- PxebcMode->IpFilter.IpCnt = Filter->IpCnt;\r
-\r
- //\r
- // join groups for all multicast in list\r
- //\r
- for (Index = 0; Index < Filter->IpCnt; ++Index) {\r
- if (IS_MULTICAST (&Filter->IpList[Index])) {\r
- IgmpJoinGroup (Private, &Filter->IpList[Index]);\r
- }\r
- }\r
-\r
- DEBUG ((EFI_D_INFO, "\nIpFilter() Exit #5 %Xh (%r)", StatCode, StatCode));\r
-\r
- return StatCode;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-BcIpFilter (\r
- IN EFI_PXE_BASE_CODE_PROTOCOL *This,\r
- IN EFI_PXE_BASE_CODE_IP_FILTER *Filter\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Call the IP filter\r
-\r
- Arguments:\r
- Private - Pointer to Pxe BaseCode Protocol\r
- Filter - Pointer to the filter\r
-\r
- Returns:\r
-\r
- 0 - Successfully set the filter\r
- !0 - Failed\r
---*/\r
-{\r
- EFI_STATUS StatCode;\r
- PXE_BASECODE_DEVICE *Private;\r
-\r
- //\r
- // Lock the instance data and make sure started\r
- //\r
- StatCode = EFI_SUCCESS;\r
-\r
- if (This == NULL) {\r
- DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
-\r
- if (Private == NULL) {\r
- DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- EfiAcquireLock (&Private->Lock);\r
-\r
- if (This->Mode == NULL || !This->Mode->Started) {\r
- DEBUG ((EFI_D_ERROR, "BC was not started."));\r
- EfiReleaseLock (&Private->Lock);\r
- return EFI_NOT_STARTED;\r
- }\r
-\r
- if (Filter == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- //\r
- // Issue BC command\r
- //\r
- StatCode = IpFilter (Private, Filter);\r
-\r
- //\r
- // Unlock the instance data\r
- //\r
- EfiReleaseLock (&Private->Lock);\r
- return StatCode;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-BcSetParameters (\r
- EFI_PXE_BASE_CODE_PROTOCOL *This,\r
- BOOLEAN *AutoArpPtr,\r
- BOOLEAN *SendGuidPtr,\r
- UINT8 *TimeToLivePtr,\r
- UINT8 *TypeOfServicePtr,\r
- BOOLEAN *MakeCallbackPtr\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Set the Base Code behavior parameters\r
-\r
- Arguments:\r
- This - Pointer to Pxe BaseCode Protocol\r
- AutoArpPtr - Boolean to do ARP stuff\r
- SendGuidPtr - Boolean whether or not to send GUID info\r
- TimeToLivePtr - Value for Total time to live\r
- TypeOfServicePtr - Value for Type of Service\r
- MakeCallbackPtr - Boolean to determine if we make callbacks\r
-\r
- Returns:\r
-\r
- 0 - Successfully set the parameters\r
- !0 - Failed\r
---*/\r
-{\r
- EFI_PXE_BASE_CODE_MODE *PxebcMode;\r
- EFI_GUID TmpGuid;\r
- CHAR8 *SerialNumberPtr;\r
- EFI_STATUS StatCode;\r
- PXE_BASECODE_DEVICE *Private;\r
-\r
- //\r
- // Lock the instance data and make sure started\r
- //\r
- StatCode = EFI_SUCCESS;\r
-\r
- if (This == NULL) {\r
- DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
-\r
- if (Private == NULL) {\r
- DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- EfiAcquireLock (&Private->Lock);\r
-\r
- if (This->Mode == NULL || !This->Mode->Started) {\r
- DEBUG ((EFI_D_ERROR, "BC was not started."));\r
- EfiReleaseLock (&Private->Lock);\r
- return EFI_NOT_STARTED;\r
- }\r
-\r
- DEBUG ((EFI_D_INFO, "\nSetParameters() Entry. "));\r
-\r
- PxebcMode = Private->EfiBc.Mode;\r
- StatCode = EFI_SUCCESS;\r
-\r
- if (SendGuidPtr != NULL) {\r
- if (*SendGuidPtr) {\r
- if (PxeBcLibGetSmbiosSystemGuidAndSerialNumber (&TmpGuid, &SerialNumberPtr) != EFI_SUCCESS) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- }\r
- }\r
-\r
- if (MakeCallbackPtr != NULL) {\r
- if (*MakeCallbackPtr) {\r
- if (!SetMakeCallback (Private)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- }\r
-\r
- PxebcMode->MakeCallbacks = *MakeCallbackPtr;\r
- }\r
-\r
- if (AutoArpPtr != NULL) {\r
- PxebcMode->AutoArp = *AutoArpPtr;\r
- }\r
-\r
- if (SendGuidPtr != NULL) {\r
- PxebcMode->SendGUID = *SendGuidPtr;\r
- }\r
-\r
- if (TimeToLivePtr != NULL) {\r
- PxebcMode->TTL = *TimeToLivePtr;\r
- }\r
-\r
- if (TypeOfServicePtr != NULL) {\r
- PxebcMode->ToS = *TypeOfServicePtr;\r
- }\r
- //\r
- // Unlock the instance data\r
- //\r
- DEBUG ((EFI_D_INFO, "\nSetparameters() Exit = %xh ", StatCode));\r
-\r
- EfiReleaseLock (&Private->Lock);\r
- return StatCode;\r
-}\r
-//\r
-// //////////////////////////////////////////////////////////\r
-//\r
-// BC Set Station IP Routine\r
-//\r
-EFI_STATUS\r
-EFIAPI\r
-BcSetStationIP (\r
- IN EFI_PXE_BASE_CODE_PROTOCOL *This,\r
- IN EFI_IP_ADDRESS *StationIpPtr,\r
- IN EFI_IP_ADDRESS *SubnetMaskPtr\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Set the station IP address\r
-\r
- Arguments:\r
- This - Pointer to Pxe BaseCode Protocol\r
- StationIpPtr - Pointer to the requested IP address to set in base code\r
- SubnetMaskPtr - Pointer to the requested subnet mask for the base code\r
-\r
- Returns:\r
-\r
- EFI_SUCCESS - Successfully set the parameters\r
- EFI_NOT_STARTED - BC has not started\r
---*/\r
-{\r
- EFI_PXE_BASE_CODE_MODE *PxebcMode;\r
- EFI_STATUS StatCode;\r
- PXE_BASECODE_DEVICE *Private;\r
- UINT32 SubnetMask;\r
-\r
- //\r
- // Lock the instance data and make sure started\r
- //\r
- StatCode = EFI_SUCCESS;\r
-\r
- if (This == NULL) {\r
- DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
-\r
- if (Private == NULL) {\r
- DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- EfiAcquireLock (&Private->Lock);\r
-\r
- if (This->Mode == NULL || !This->Mode->Started) {\r
- DEBUG ((EFI_D_ERROR, "BC was not started."));\r
- StatCode = EFI_NOT_STARTED;\r
- goto RELEASE_LOCK;\r
- }\r
-\r
- PxebcMode = Private->EfiBc.Mode;\r
-\r
- if (!Private->GoodStationIp && ((StationIpPtr == NULL) || (SubnetMaskPtr == NULL))) {\r
- //\r
- // It's not allowed to only set one of the two addresses while there isn't a previous\r
- // GOOD address configuration.\r
- //\r
- StatCode = EFI_INVALID_PARAMETER;\r
- goto RELEASE_LOCK;\r
- }\r
-\r
- if (SubnetMaskPtr != NULL) {\r
- SubnetMask = SubnetMaskPtr->Addr[0];\r
-\r
- if (SubnetMask & (SubnetMask + 1)) {\r
- //\r
- // the subnet mask is valid if it's with leading continuous 1 bits.\r
- //\r
- StatCode = EFI_INVALID_PARAMETER;\r
- goto RELEASE_LOCK;\r
- }\r
- } else {\r
- SubnetMaskPtr = &PxebcMode->SubnetMask;\r
- SubnetMask = SubnetMaskPtr->Addr[0];\r
- }\r
-\r
- if (StationIpPtr == NULL) {\r
- StationIpPtr = &PxebcMode->StationIp;\r
- }\r
-\r
- if (!IS_INADDR_UNICAST (StationIpPtr) ||\r
- ((StationIpPtr->Addr[0] | SubnetMask) == BROADCAST_IPv4)) {\r
- //\r
- // The station IP is not a unicast address.\r
- //\r
- StatCode = EFI_INVALID_PARAMETER;\r
- goto RELEASE_LOCK;\r
- }\r
-\r
- CopyMem (&PxebcMode->StationIp, StationIpPtr, sizeof (EFI_IP_ADDRESS));\r
- CopyMem (&PxebcMode->SubnetMask, SubnetMaskPtr, sizeof (EFI_IP_ADDRESS));\r
-\r
- Private->GoodStationIp = TRUE;\r
-\r
-RELEASE_LOCK:\r
- //\r
- // Unlock the instance data\r
- //\r
- EfiReleaseLock (&Private->Lock);\r
-\r
- return StatCode;\r
-}\r
-\r
-EFI_DRIVER_BINDING_PROTOCOL gPxeBcDriverBinding = {\r
- PxeBcDriverSupported,\r
- PxeBcDriverStart,\r
- PxeBcDriverStop,\r
- 0xa,\r
- NULL,\r
- NULL\r
-};\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-PxeBcDriverSupported (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Test to see if this driver supports Controller. Any Controller\r
- than contains a Snp protocol can be supported.\r
-\r
- Arguments:\r
- This - Protocol instance pointer.\r
- Controller - Handle of device to test.\r
- RemainingDevicePath - Not used.\r
-\r
- Returns:\r
- EFI_SUCCESS - This driver supports this device.\r
- EFI_ALREADY_STARTED - This driver is already running on this device.\r
- other - This driver does not support this device.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;\r
-\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiDevicePathProtocolGuid,\r
- NULL,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiSimpleNetworkProtocolGuid,\r
- (VOID **) &SnpPtr,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiSimpleNetworkProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-PxeBcDriverStart (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Start the Base code driver.\r
-\r
- Arguments:\r
- This - Protocol instance pointer.\r
- Controller - Handle of device to test.\r
- RemainingDevicePath - Not used.\r
-\r
- Returns:\r
- EFI_SUCCESS - This driver supports this device.\r
- EFI_ALREADY_STARTED - This driver is already running on this device.\r
- other - This driver does not support this device.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- PXE_BASECODE_DEVICE *Private;\r
- LOADFILE_DEVICE *pLF;\r
-\r
- //\r
- // Allocate structures needed by BaseCode and LoadFile protocols.\r
- //\r
- Private = AllocateZeroPool (sizeof (PXE_BASECODE_DEVICE));\r
-\r
- if (Private == NULL ) {\r
- DEBUG ((EFI_D_NET, "\nBcNotifySnp() Could not alloc PXE_BASECODE_DEVICE structure.\n"));\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- pLF = AllocateZeroPool (sizeof (LOADFILE_DEVICE));\r
- if (pLF == NULL) {\r
- DEBUG ((EFI_D_NET, "\nBcNotifySnp() Could not alloc LOADFILE_DEVICE structure.\n"));\r
- FreePool (Private);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- Private->EfiBc.Mode = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_MODE));\r
- if (Private->EfiBc.Mode == NULL) {\r
- DEBUG ((EFI_D_NET, "\nBcNotifySnp() Could not alloc Mode structure.\n"));\r
- FreePool (Private);\r
- FreePool (pLF);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- //\r
- // Lock access, just in case\r
- //\r
- EfiInitializeLock (&Private->Lock, TPL_CALLBACK);\r
- EfiAcquireLock (&Private->Lock);\r
-\r
- EfiInitializeLock (&pLF->Lock, TPL_CALLBACK);\r
- EfiAcquireLock (&pLF->Lock);\r
-\r
- //\r
- // Initialize PXE structure\r
- //\r
- //\r
- // First initialize the internal 'private' data that the application\r
- // does not see.\r
- //\r
- Private->Signature = PXE_BASECODE_DEVICE_SIGNATURE;\r
- Private->Handle = Controller;\r
-\r
- //\r
- // Get the NII interface\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
- (VOID **) &Private->NiiPtr,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiNetworkInterfaceIdentifierProtocolGuid,\r
- (VOID **) &Private->NiiPtr,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto PxeBcError;\r
- }\r
- }\r
- //\r
- // Get the Snp interface\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiSimpleNetworkProtocolGuid,\r
- (VOID **) &Private->SimpleNetwork,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto PxeBcError;\r
- }\r
-\r
- //\r
- // Next, initialize the external 'public' data that\r
- // the application does see.\r
- //\r
- Private->EfiBc.Revision = EFI_PXE_BASE_CODE_INTERFACE_REVISION;\r
- Private->EfiBc.Start = BcStart;\r
- Private->EfiBc.Stop = BcStop;\r
- Private->EfiBc.Dhcp = BcDhcp;\r
- Private->EfiBc.Discover = BcDiscover;\r
- Private->EfiBc.Mtftp = BcMtftp;\r
- Private->EfiBc.UdpWrite = BcUdpWrite;\r
- Private->EfiBc.UdpRead = BcUdpRead;\r
- Private->EfiBc.Arp = BcArp;\r
- Private->EfiBc.SetIpFilter = BcIpFilter;\r
- Private->EfiBc.SetParameters = BcSetParameters;\r
- Private->EfiBc.SetStationIp = BcSetStationIP;\r
- Private->EfiBc.SetPackets = BcSetPackets;\r
-\r
- //\r
- // Initialize BaseCode Mode structure\r
- //\r
- Private->EfiBc.Mode->Started = FALSE;\r
- Private->EfiBc.Mode->TTL = DEFAULT_TTL;\r
- Private->EfiBc.Mode->ToS = DEFAULT_ToS;\r
- Private->EfiBc.Mode->UsingIpv6 = FALSE;\r
- Private->EfiBc.Mode->AutoArp = TRUE;\r
-\r
- //\r
- // Set to PXE_TRUE by the BC constructor if this BC\r
- // implementation supports IPv6.\r
- //\r
- Private->EfiBc.Mode->Ipv6Supported = SUPPORT_IPV6;\r
- Private->EfiBc.Mode->Ipv6Available = FALSE;\r
-\r
- //\r
- // Set to TRUE by the BC constructor if this BC\r
- // implementation supports BIS.\r
- //\r
- Private->EfiBc.Mode->BisSupported = TRUE;\r
- Private->EfiBc.Mode->BisDetected = PxebcBisDetect (Private);\r
-\r
- //\r
- // Initialize LoadFile structure.\r
- //\r
- pLF->Signature = LOADFILE_DEVICE_SIGNATURE;\r
- pLF->LoadFile.LoadFile = LoadFile;\r
- pLF->Private = Private;\r
-\r
- //\r
- // Install protocol interfaces.\r
- //\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &Controller,\r
- &gEfiPxeBaseCodeProtocolGuid,\r
- &Private->EfiBc,\r
- &gEfiLoadFileProtocolGuid,\r
- &pLF->LoadFile,\r
- NULL\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiSimpleNetworkProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- goto PxeBcError;\r
- }\r
- //\r
- // Release locks.\r
- //\r
- EfiReleaseLock (&pLF->Lock);\r
- EfiReleaseLock (&Private->Lock);\r
- return Status;\r
-\r
-PxeBcError: ;\r
- FreePool (Private->EfiBc.Mode);\r
- FreePool (Private);\r
- FreePool (pLF);\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-PxeBcDriverStop (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN UINTN NumberOfChildren,\r
- IN EFI_HANDLE *ChildHandleBuffer\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Stop the Base code driver.\r
-\r
- Arguments:\r
- This - Protocol instance pointer.\r
- Controller - Handle of device to test.\r
- NumberOfChildren - Not used\r
- ChildHandleBuffer - Not used\r
-\r
- Returns:\r
- EFI_SUCCESS - This driver supports this device.\r
- EFI_ALREADY_STARTED - This driver is already running on this device.\r
- other - This driver does not support this device.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
- EFI_LOAD_FILE_PROTOCOL *LfProtocol;\r
- LOADFILE_DEVICE *LoadDevice;\r
-\r
- //\r
- // Get our context back.\r
- //\r
- Status = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiLoadFileProtocolGuid,\r
- (VOID **) &LfProtocol,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- LoadDevice = EFI_LOAD_FILE_DEV_FROM_THIS (LfProtocol);\r
-\r
- Status = gBS->UninstallMultipleProtocolInterfaces (\r
- Controller,\r
- &gEfiLoadFileProtocolGuid,\r
- &LoadDevice->LoadFile,\r
- &gEfiPxeBaseCodeProtocolGuid,\r
- &LoadDevice->Private->EfiBc,\r
- NULL\r
- );\r
-\r
- if (!EFI_ERROR (Status)) {\r
-\r
- Status = gBS->CloseProtocol (\r
- Controller,\r
- &gEfiSimpleNetworkProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
-\r
- FreePool (LoadDevice->Private->EfiBc.Mode);\r
- FreePool (LoadDevice->Private);\r
- FreePool (LoadDevice);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-InitializeBCDriver (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-/*++\r
-\r
- Routine Description:\r
- Initialize the base code drivers and install the driver binding\r
-\r
- Arguments:\r
- Standard EFI Image Entry\r
-\r
- Returns:\r
- EFI_SUCCESS - This driver was successfully bound\r
-\r
---*/\r
-{\r
- InitArpHeader ();\r
- OptionsStrucInit ();\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/* eof - bc.c */\r