3 Copyright (c) 2004 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
28 PxeBcDriverSupported (
29 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
30 IN EFI_HANDLE Controller
,
31 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
37 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
38 IN EFI_HANDLE Controller
,
39 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
45 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
46 IN EFI_HANDLE Controller
,
47 IN UINTN NumberOfChildren
,
48 IN EFI_HANDLE
*ChildHandleBuffer
67 Convert number to ASCII value
69 @param Number Numeric value to convert to decimal ASCII value.
70 @param Buffer Buffer to place ASCII version of the Number
71 @param Length Length of Buffer.
86 Remainder
= Number
% 10;
88 Buffer
[Length
] = (UINT8
) ('0' + Remainder
);
94 Convert number to decimal ASCII value at Buffer location
96 @param Number Numeric value to convert to decimal ASCII value.
97 @param Buffer Buffer to place ASCII version of the Number
112 CvtNum (Number
, BuffArray
, 30);
114 for (Index
= 0; Index
< 30; ++Index
) {
115 if (BuffArray
[Index
] != '0') {
120 CopyMem (Buffer
, BuffArray
+ Index
, 31 - Index
);
125 Convert ASCII numeric string to a UINTN value
127 @param Number Numeric value to convert to decimal ASCII value.
128 @param Buffer Buffer to place ASCII version of the Number
130 @retval Value UINTN value of the ASCII string.
142 Character
= *Buffer
++;
144 Value
= Value
* 10 + Character
- '0';
145 Character
= *Buffer
++;
153 Convert ASCII numeric string to a UINTN value
155 @param Number Numeric value to convert to decimal ASCII value.
156 @param Buffer Buffer to place ASCII version of the Number
158 @retval Value UINTN value of the ASCII string.
170 while ((Character
= *Buffer
++) != '\0') {
171 Value
= MultU64x32 (Value
, 10) + (Character
- '0');
177 // random number generator
179 #define RANDOM_MULTIPLIER 2053
180 #define RANDOM_ADD_IN_VALUE 19
184 IN PXE_BASECODE_DEVICE
*Private
,
185 IN UINT16 InitialSeed
190 Initialize the Seed for the random number generator
199 if (Private
!= NULL
) {
200 Private
->RandomSeed
= InitialSeed
;
206 Generate and return a pseudo-random number
209 @retval Number UINT16 random number
214 IN PXE_BASECODE_DEVICE
*Private
219 if (Private
!= NULL
) {
220 Number
= -(INTN
) Private
->RandomSeed
* RANDOM_MULTIPLIER
+ RANDOM_ADD_IN_VALUE
;
222 return Private
->RandomSeed
= (UINT16
) Number
;
228 // calculate the internet checksum (RFC 1071)
229 // return 16 bit ones complement of ones complement sum of 16 bit words
233 Calculate the internet checksum (see RFC 1071)
235 @param Packet Buffer which contains the data to be checksummed
236 @param Length Length to be checksummed
238 @retval Checksum Returns the 16 bit ones complement of ones
239 complement sum of 16 bit words
252 Odd
= (UINT8
) (Length
& 1);
259 Sum
+= *(UINT8
*) Packet
;
262 Sum
= (Sum
& 0xffff) + (Sum
>> 16);
264 // in case above carried
268 return (UINT16
) (~ (UINT16
) Sum
);
273 Calculate the internet checksum (see RFC 1071)
274 on a non contiguous header and data
276 @param Header Buffer which contains the data to be checksummed
277 @param HeaderLen Length to be checksummed
278 @param Message Buffer which contains the data to be checksummed
279 @param MessageLen Length to be checksummed
281 @retval Checksum Returns the 16 bit ones complement of ones
282 complement sum of 16 bit words
294 UINT16 HeaderChecksum
;
295 UINT16 MessageChecksum
;
297 HeaderChecksum
= (UINT16
)~IpChecksum (Header
, HeaderLen
);
298 MessageChecksum
= (UINT16
)~IpChecksum (Message
, MessageLen
);
299 Sum
= HeaderChecksum
+ MessageChecksum
;
302 // in case above carried
306 return (UINT16
) (~ (UINT16
) Sum
);
311 Adjust the internet checksum (see RFC 1071) on a single word update.
313 @param OldChkSum Checksum previously calculated
315 @param NewWord New Value
317 @retval Checksum Returns the 16 bit ones complement of ones
318 complement sum of 16 bit words
330 sum
= ~OldChksum
+ NewWord
- OldWord
;
332 // in case above carried
335 return (UINT16
) (~ (UINT16
) sum
);
340 See if a callback is in play
342 @param Private Pointer to Pxe BaseCode Protocol
344 @retval 0 Callbacks are active on the handle
345 @retval 1 Callbacks are not active on the handle
350 IN PXE_BASECODE_DEVICE
*Private
353 Private
->EfiBc
.Mode
->MakeCallbacks
= (BOOLEAN
) (gBS
->HandleProtocol (
355 &gEfiPxeBaseCodeCallbackProtocolGuid
,
356 (VOID
*) &Private
->CallbackProtocolPtr
361 "\nMode->MakeCallbacks == %d ",
362 Private
->EfiBc
.Mode
->MakeCallbacks
)
367 "\nPrivate->CallbackProtocolPtr == %xh ",
368 Private
->CallbackProtocolPtr
)
371 if (Private
->CallbackProtocolPtr
!= NULL
) {
374 "\nCallbackProtocolPtr->Revision = %xh ",
375 Private
->CallbackProtocolPtr
->Revision
)
380 "\nCallbackProtocolPtr->Callback = %xh ",
381 Private
->CallbackProtocolPtr
->Callback
)
385 return Private
->EfiBc
.Mode
->MakeCallbacks
;
388 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
391 Routine which does an SNP->Receive over a timeout period and doing callbacks
393 @param Private Pointer to Pxe BaseCode Protocol
394 @param Function What PXE function to callback
395 @param TimeoutEvent Timer event that will trigger when we have waited
396 too long for an incoming packet
397 @param HeaderSizePtr Pointer to the size of the Header size
398 @param BufferSizePtr Pointer to the size of the Buffer size
399 @param ProtocolPtr The protocol to sniff for (namely, UDP/TCP/etc)
401 @retval 0 Something was returned
402 @retval !0 Like there was nothing to receive
403 (EFI_TIMEOUT/NOT_READY)
408 IN PXE_BASECODE_DEVICE
*Private
,
409 IN EFI_PXE_BASE_CODE_FUNCTION Function
,
410 IN EFI_EVENT TimeoutEvent
,
411 IN OUT UINTN
*HeaderSizePtr
,
412 IN OUT UINTN
*BufferSizePtr
,
413 IN OUT UINT16
*ProtocolPtr
416 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
417 EFI_PXE_CALLBACK CallbackPtr
;
419 EFI_EVENT CallbackEvent
;
422 // Initialize pointer to SNP interface
424 SnpPtr
= Private
->SimpleNetwork
;
427 // Initialize pointer to PxeBc callback routine - if any
429 CallbackPtr
= (Private
->EfiBc
.Mode
->MakeCallbacks
) ? Private
->CallbackProtocolPtr
->Callback
: NULL
;
432 // Create callback event and set timer
434 StatCode
= gBS
->CreateEvent (
442 if (EFI_ERROR (StatCode
)) {
443 return EFI_DEVICE_ERROR
;
447 // every 100 milliseconds
449 StatCode
= gBS
->SetTimer (
455 if (EFI_ERROR (StatCode
)) {
456 gBS
->CloseEvent (CallbackEvent
);
457 return EFI_DEVICE_ERROR
;
460 // Loop until a packet is received or a receive error is detected or
461 // a callback abort is detected or a timeout event occurs.
466 // Poll for received packet.
468 *BufferSizePtr
= BUFFER_ALLOCATE_SIZE
;
470 StatCode
= SnpPtr
->Receive (
474 Private
->ReceiveBufferPtr
,
480 if (!EFI_ERROR (StatCode
)) {
482 // Packet was received. Make received callback then return.
484 if (CallbackPtr
!= NULL
) {
485 StatCode
= CallbackPtr (
486 Private
->CallbackProtocolPtr
,
489 (UINT32
) *BufferSizePtr
,
490 (EFI_PXE_BASE_CODE_PACKET
*) Private
->ReceiveBufferPtr
493 if (StatCode
!= EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
) {
494 StatCode
= EFI_ABORTED
;
496 StatCode
= EFI_SUCCESS
;
503 if (StatCode
!= EFI_NOT_READY
) {
507 // Check for callback event.
509 if (!EFI_ERROR (gBS
->CheckEvent (CallbackEvent
))) {
511 // Make periodic callback if callback pointer is initialized.
513 if (CallbackPtr
!= NULL
) {
514 StatCode
= CallbackPtr (
515 Private
->CallbackProtocolPtr
,
523 // Abort if directed to by callback routine.
525 if (StatCode
!= EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
) {
526 StatCode
= EFI_ABORTED
;
532 // Check for timeout event.
534 if (TimeoutEvent
== 0) {
535 StatCode
= EFI_TIMEOUT
;
539 if (!EFI_ERROR (gBS
->CheckEvent (TimeoutEvent
))) {
540 StatCode
= EFI_TIMEOUT
;
544 // Check IGMP timer events.
546 IgmpCheckTimers (Private
);
549 gBS
->CloseEvent (CallbackEvent
);
556 Routine which does an SNP->Transmit of a buffer
558 @param Private Pointer to Pxe BaseCode Protocol
559 @param HeaderPtr Pointer to the buffer
560 @param PacketPtr Pointer to the packet to send
561 @param PacketLen The length of the entire packet to send
562 @param HardwareAddr Pointer to the MAC address of the destination
563 @param MediaProtocol What type of frame to create (RFC 1700) - IE.
565 @param Function What PXE function to callback
567 @retval 0 Something was sent
568 @retval !0 An error was encountered during sending of a packet
573 PXE_BASECODE_DEVICE
*Private
,
578 UINT16 MediaProtocol
,
579 IN EFI_PXE_BASE_CODE_FUNCTION Function
582 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
583 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
584 EFI_PXE_CALLBACK CallbackPtr
;
586 EFI_EVENT TimeoutEvent
;
593 CallbackPtr
= Private
->EfiBc
.Mode
->MakeCallbacks
? Private
->CallbackProtocolPtr
->Callback
: 0;
595 SnpPtr
= Private
->SimpleNetwork
;
596 SnpModePtr
= SnpPtr
->Mode
;
599 // clear prior interrupt status
601 StatCode
= SnpPtr
->GetStatus (SnpPtr
, &IntStatus
, 0);
603 if (EFI_ERROR (StatCode
)) {
606 "\nSendPacket() Exit #1 %xh (%r)",
613 Private
->DidTransmit
= FALSE
;
615 if (CallbackPtr
!= NULL
) {
617 Private
->CallbackProtocolPtr
,
622 ) != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
) {
625 "\nSendPacket() Exit #2 %xh (%r)",
633 // put packet in transmit queue
634 // headersize should be zero if not filled in
636 StatCode
= gBS
->CreateEvent (
644 if (EFI_ERROR (StatCode
)) {
647 "Could not create transmit timeout event. %r\n",
650 return EFI_DEVICE_ERROR
;
656 StatCode
= gBS
->SetTimer (
662 if (EFI_ERROR (StatCode
)) {
665 "Could not set transmit timeout event timer. %r\n",
668 gBS
->CloseEvent (TimeoutEvent
);
669 return EFI_DEVICE_ERROR
;
673 StatCode
= SnpPtr
->Transmit (
675 (UINTN
) SnpPtr
->Mode
->MediaHeaderSize
,
676 (UINTN
) (PacketLen
+ SnpPtr
->Mode
->MediaHeaderSize
),
678 &SnpModePtr
->CurrentAddress
,
679 (EFI_MAC_ADDRESS
*) HardwareAddr
,
683 if (StatCode
!= EFI_NOT_READY
) {
687 if (!EFI_ERROR (gBS
->CheckEvent (TimeoutEvent
))) {
688 StatCode
= EFI_TIMEOUT
;
693 gBS
->CloseEvent (TimeoutEvent
);
695 if (EFI_ERROR (StatCode
)) {
698 "\nSendPacket() Exit #3 %xh (%r)",
705 // remove transmit buffer from snp's unused queue
706 // done this way in case someday things are buffered and we don't get it back
709 StatCode
= gBS
->CreateEvent (
717 if (EFI_ERROR (StatCode
)) {
720 "Could not create transmit status timeout event. %r\n",
723 return EFI_DEVICE_ERROR
;
729 StatCode
= gBS
->SetTimer (
735 if (EFI_ERROR (StatCode
)) {
738 "Could not set transmit status timeout event timer. %r\n",
741 gBS
->CloseEvent (TimeoutEvent
);
742 return EFI_DEVICE_ERROR
;
746 StatCode
= SnpPtr
->GetStatus (SnpPtr
, &IntStatus
, &TxBuf
);
748 if (EFI_ERROR (StatCode
)) {
751 "\nSendPacket() Exit #4 %xh (%r)",
758 if (IntStatus
& EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT
) {
759 Private
->DidTransmit
= TRUE
;
766 if (!EFI_ERROR (gBS
->CheckEvent (TimeoutEvent
))) {
767 StatCode
= EFI_TIMEOUT
;
772 gBS
->CloseEvent (TimeoutEvent
);
786 IN PXE_BASECODE_DEVICE
*Private
,
787 OUT BIS_APPLICATION_HANDLE
*BisAppHandle
,
788 OUT OPTIONAL EFI_BIS_DATA
**BisDataSigInfo
791 EFI_STATUS EfiStatus
;
792 EFI_HANDLE BisHandleBuffer
;
793 UINTN BisHandleCount
;
794 EFI_BIS_PROTOCOL
*BisPtr
;
795 EFI_BIS_VERSION BisInterfaceVersion
;
796 BOOLEAN BisCheckFlag
;
798 BisHandleCount
= sizeof (EFI_HANDLE
);
799 BisCheckFlag
= FALSE
;
802 // Locate BIS protocol handle (if present).
803 // If BIS protocol handle is not found, return NULL.
805 DEBUG ((DEBUG_INFO
, "\ngBS->LocateHandle() "));
807 EfiStatus
= gBS
->LocateHandle (
809 &gEfiBisProtocolGuid
,
815 if (EFI_ERROR (EfiStatus
)) {
817 // Any error means that there is no BIS.
818 // Note - It could mean that there are more than
819 // one BIS protocols installed, but that scenario
820 // is not yet supported.
824 "\nPxebcBisStart()""\n gBS->LocateHandle() %r (%xh)\n",
832 if (BisHandleCount
!= sizeof BisHandleBuffer
) {
834 // This really should never happen, but I am paranoid.
838 "\nPxebcBisStart() BisHandleCount != %d\n",
839 sizeof BisHandleBuffer
)
845 DEBUG ((DEBUG_INFO
, "BIS handle found."));
848 // Locate BIS protocol interface.
849 // If the BIS protocol interface cannot be found, return NULL.
851 DEBUG ((DEBUG_INFO
, "\ngBS->HandleProtocol() "));
853 EfiStatus
= gBS
->HandleProtocol (
855 &gEfiBisProtocolGuid
,
859 if (EFI_ERROR (EfiStatus
)) {
862 "\nPxebcBisStart()""\n gBS->HandleProtocol() %r (%xh)\n",
870 if (BisPtr
== NULL
) {
872 // This really should never happen.
876 "\nPxebcBisStart()""\n gBS->HandleProtocoL() ""BIS protocol interface pointer is NULL!\n")
882 DEBUG ((DEBUG_INFO
, "BIS protocol interface found."));
885 // Check that all of the BIS API function pointers are not NULL.
887 if (BisPtr
->Initialize
== NULL
||
888 BisPtr
->Shutdown
== NULL
||
889 BisPtr
->Free
== NULL
||
890 BisPtr
->GetBootObjectAuthorizationCertificate
== NULL
||
891 BisPtr
->GetBootObjectAuthorizationCheckFlag
== NULL
||
892 BisPtr
->GetBootObjectAuthorizationUpdateToken
== NULL
||
893 BisPtr
->GetSignatureInfo
== NULL
||
894 BisPtr
->UpdateBootObjectAuthorization
== NULL
||
895 BisPtr
->VerifyBootObject
== NULL
||
896 BisPtr
->VerifyObjectWithCredential
== NULL
901 "\nPxebcBisStart()""\n BIS protocol interface is invalid."
902 "\n At least one BIS protocol function pointer is NULL.\n"
910 // If BIS does not initialize, return NULL.
912 DEBUG ((DEBUG_INFO
, "\nBisPtr->Initialize() "));
914 BisInterfaceVersion
.Major
= BIS_VERSION_1
;
916 EfiStatus
= BisPtr
->Initialize (
919 &BisInterfaceVersion
,
923 if (EFI_ERROR (EfiStatus
)) {
926 "\nPxebcBisStart()""\n BisPtr->Initialize() %r (%xh)\n",
936 " BIS version: %d.%d",
937 BisInterfaceVersion
.Major
,
938 BisInterfaceVersion
.Minor
)
942 // If the requested BIS API version is not supported,
943 // shutdown BIS and return NULL.
945 if (BisInterfaceVersion
.Major
!= BIS_VERSION_1
) {
948 "\nPxebcBisStart()""\n BIS version %d.%d not supported by PXE BaseCode.\n",
949 BisInterfaceVersion
.Major
,
950 BisInterfaceVersion
.Minor
)
953 BisPtr
->Shutdown (*BisAppHandle
);
957 // Get BIS check flag.
958 // If the BIS check flag cannot be read, shutdown BIS and return NULL.
960 DEBUG ((DEBUG_INFO
, "\nBisPtr->GetBootObjectAuthorizationCheckFlag() "));
962 EfiStatus
= BisPtr
->GetBootObjectAuthorizationCheckFlag (*BisAppHandle
, &BisCheckFlag
);
964 if (EFI_ERROR (EfiStatus
)) {
967 "\nPxebcBisStart()""\n BisPtr->GetBootObjectAuthorizationCheckFlag() %r (%xh)\n",
972 BisPtr
->Shutdown (*BisAppHandle
);
976 // If the BIS check flag is FALSE, shutdown BIS and return NULL.
979 DEBUG ((DEBUG_INFO
, "\nBIS check flag is FALSE.\n"));
980 BisPtr
->Shutdown (*BisAppHandle
);
983 DEBUG ((DEBUG_INFO
, "\nBIS check flag is TRUE."));
986 // Early out if caller does not want signature information.
988 if (BisDataSigInfo
== NULL
) {
992 // Get BIS signature information.
993 // If the signature information cannot be read or is invalid,
994 // shutdown BIS and return NULL.
996 DEBUG ((DEBUG_INFO
, "\nBisPtr->GetSignatureInfo() "));
998 EfiStatus
= BisPtr
->GetSignatureInfo (*BisAppHandle
, BisDataSigInfo
);
1000 if (EFI_ERROR (EfiStatus
)) {
1003 "\nPxebcBisStart()""\n BisPtr_GetSignatureInfo() %r (%xh)\n",
1008 BisPtr
->Shutdown (*BisAppHandle
);
1012 if (*BisDataSigInfo
== NULL
) {
1014 // This should never happen.
1018 "\nPxebcBisStart()""\n BisPtr->GetSignatureInfo() Data pointer is NULL!\n")
1021 BisPtr
->Shutdown (*BisAppHandle
);
1025 if ((*BisDataSigInfo
)->Length
< sizeof (EFI_BIS_SIGNATURE_INFO
) ||
1026 (*BisDataSigInfo
)->Length
% sizeof (EFI_BIS_SIGNATURE_INFO
) ||
1027 (*BisDataSigInfo
)->Length
> sizeof (EFI_BIS_SIGNATURE_INFO
) * 63
1030 // This should never happen.
1034 "\nPxebcBisStart()""\n BisPtr->GetSignatureInfo() Invalid BIS siginfo length.\n")
1037 BisPtr
->Free (*BisAppHandle
, *BisDataSigInfo
);
1038 BisPtr
->Shutdown (*BisAppHandle
);
1052 EFI_BIS_PROTOCOL
*BisPtr
,
1053 BIS_APPLICATION_HANDLE BisAppHandle
,
1054 EFI_BIS_DATA
*BisDataSigInfo
1057 if (BisPtr
== NULL
) {
1061 // Free BIS allocated resources and shutdown BIS.
1062 // Return TRUE - BIS support is officially detected.
1064 if (BisDataSigInfo
!= NULL
) {
1065 BisPtr
->Free (BisAppHandle
, BisDataSigInfo
);
1068 BisPtr
->Shutdown (BisAppHandle
);
1074 @return TRUE := verified
1075 @return FALSE := not verified
1080 PXE_BASECODE_DEVICE
*Private
,
1083 VOID
*CredentialBuffer
,
1084 UINTN CredentialLength
1087 EFI_BIS_PROTOCOL
*BisPtr
;
1088 BIS_APPLICATION_HANDLE BisAppHandle
;
1089 EFI_BIS_DATA FileData
;
1090 EFI_BIS_DATA CredentialData
;
1091 EFI_STATUS EfiStatus
;
1094 if (Private
== NULL
|| FileBuffer
== NULL
|| FileLength
== 0 || CredentialBuffer
== NULL
|| CredentialLength
== 0) {
1098 BisPtr
= PxebcBisStart (Private
, &BisAppHandle
, NULL
);
1100 if (BisPtr
== NULL
) {
1104 FileData
.Length
= (UINT32
) FileLength
;
1105 FileData
.Data
= FileBuffer
;
1106 CredentialData
.Length
= (UINT32
) CredentialLength
;
1107 CredentialData
.Data
= CredentialBuffer
;
1109 EfiStatus
= BisPtr
->VerifyBootObject (
1116 PxebcBisStop (BisPtr
, BisAppHandle
, NULL
);
1118 return (BOOLEAN
) ((EFI_ERROR (EfiStatus
)) ? FALSE
: (IsVerified
? TRUE
: FALSE
));
1124 @return TRUE := BIS present
1125 @return FALSE := BIS not present
1130 PXE_BASECODE_DEVICE
*Private
1133 EFI_BIS_PROTOCOL
*BisPtr
;
1134 BIS_APPLICATION_HANDLE BisAppHandle
;
1135 EFI_BIS_DATA
*BisDataSigInfo
;
1137 BisPtr
= PxebcBisStart (Private
, &BisAppHandle
, &BisDataSigInfo
);
1139 if (BisPtr
== NULL
) {
1143 PxebcBisStop (BisPtr
, BisAppHandle
, BisDataSigInfo
);
1149 Start and initialize the BaseCode protocol, Simple Network protocol and UNDI.
1151 @param Private Pointer to Pxe BaseCode Protocol
1152 @param UseIPv6 Do we want to support IPv6?
1155 @return EFI_INVALID_PARAMETER
1156 @return EFI_UNSUPPORTED
1157 @return EFI_ALREADY_STARTED
1158 @return EFI_OUT_OF_RESOURCES
1159 @return Status is also returned from SNP.Start() and SNP.Initialize().
1165 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1169 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
1170 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
1172 EFI_STATUS StatCode
;
1173 PXE_BASECODE_DEVICE
*Private
;
1176 // Lock the instance data
1178 StatCode
= EFI_SUCCESS
;
1181 DEBUG ((DEBUG_ERROR
, "BC *This pointer == NULL"));
1182 return EFI_INVALID_PARAMETER
;
1185 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1187 if (Private
== NULL
) {
1188 DEBUG ((DEBUG_ERROR
, "PXE_BASECODE_DEVICE pointer == NULL"));
1189 return EFI_INVALID_PARAMETER
;
1192 EfiAcquireLock (&Private
->Lock
);
1195 // Make sure BaseCode is not already started.
1197 if (This
->Mode
->Started
) {
1198 DEBUG ((DEBUG_WARN
, "\nBcStart() BC is already started.\n"));
1199 EfiReleaseLock (&Private
->Lock
);
1200 return EFI_ALREADY_STARTED
;
1204 // Fail if IPv6 is requested and not supported.
1207 DEBUG ((DEBUG_WARN
, "\nBcStart() IPv6 is not supported.\n"));
1208 EfiReleaseLock (&Private
->Lock
);
1209 return EFI_UNSUPPORTED
;
1212 // Setup shortcuts to SNP protocol and data structure.
1214 SnpPtr
= Private
->SimpleNetwork
;
1215 SnpModePtr
= SnpPtr
->Mode
;
1218 // Start and initialize SNP.
1220 if (SnpModePtr
->State
== EfiSimpleNetworkStopped
) {
1221 StatCode
= (*SnpPtr
->Start
) (SnpPtr
);
1223 if (SnpModePtr
->State
!= EfiSimpleNetworkStarted
) {
1224 DEBUG ((DEBUG_WARN
, "\nBcStart() Could not start SNP.\n"));
1225 EfiReleaseLock (&Private
->Lock
);
1230 // acquire memory for mode and transmit/receive buffers
1232 if (SnpModePtr
->State
== EfiSimpleNetworkStarted
) {
1233 StatCode
= (*SnpPtr
->Initialize
) (SnpPtr
, 0, 0);
1235 if (SnpModePtr
->State
!= EfiSimpleNetworkInitialized
) {
1236 DEBUG ((DEBUG_WARN
, "\nBcStart() Could not initialize SNP."));
1237 EfiReleaseLock (&Private
->Lock
);
1244 DEBUG ((DEBUG_INFO
, "\nBC Start()"));
1247 "\nSnpModePtr->State %Xh",
1252 "\nSnpModePtr->HwAddressSize %Xh",
1253 SnpModePtr
->HwAddressSize
)
1257 "\nSnpModePtr->MediaHeaderSize %Xh",
1258 SnpModePtr
->MediaHeaderSize
)
1262 "\nSnpModePtr->MaxPacketSize %Xh",
1263 SnpModePtr
->MaxPacketSize
)
1267 "\nSnpModePtr->MacAddressChangeable %Xh",
1268 SnpModePtr
->MacAddressChangeable
)
1272 "\nSnpModePtr->MultipleTxSupported %Xh",
1273 SnpModePtr
->MultipleTxSupported
)
1277 "\nSnpModePtr->CurrentAddress %Xh",
1278 *((UINTN
*)&SnpModePtr
->CurrentAddress
))
1282 "\nSnpModePtr->BroadcastAddress %Xh",
1283 *((UINTN
*)&SnpModePtr
->BroadcastAddress
))
1287 "\nSnpModePtr->PermanentAddress %Xh",
1288 *((UINTN
*)&SnpModePtr
->PermanentAddress
))
1292 "\nSnpModePtr->NvRamSize %Xh",
1293 SnpModePtr
->NvRamSize
)
1297 "\nSnpModePtr->NvRamAccessSize %Xh",
1298 SnpModePtr
->NvRamAccessSize
)
1302 "\nSnpModePtr->ReceiveFilterMask %Xh",
1303 SnpModePtr
->ReceiveFilterMask
)
1307 "\nSnpModePtr->ReceiveFilterSetting %Xh",
1308 SnpModePtr
->ReceiveFilterSetting
)
1312 "\nSnpModePtr->MCastFilterCount %Xh",
1313 SnpModePtr
->MCastFilterCount
)
1317 "\nSnpModePtr->MCastFilter %Xh",
1318 SnpModePtr
->MCastFilter
)
1322 "\nSnpModePtr->IfType %Xh",
1327 "\nSnpModePtr->MediaPresentSupported %Xh",
1328 SnpModePtr
->MediaPresentSupported
)
1332 "\nSnpModePtr->MediaPresent %Xh",
1333 SnpModePtr
->MediaPresent
)
1337 // If media check is supported and there is no media,
1338 // return error to caller.
1340 if (SnpModePtr
->MediaPresentSupported
&& !SnpModePtr
->MediaPresent
) {
1341 DEBUG ((DEBUG_WARN
, "\nBcStart() Media not present.\n"));
1342 EfiReleaseLock (&Private
->Lock
);
1343 return EFI_NO_MEDIA
;
1346 // Allocate Tx/Rx buffers
1348 Status
= gBS
->AllocatePool (
1349 EfiBootServicesData
,
1350 BUFFER_ALLOCATE_SIZE
,
1351 (VOID
**) &Private
->TransmitBufferPtr
1354 if (!EFI_ERROR (Status
)) {
1355 ZeroMem (Private
->TransmitBufferPtr
, BUFFER_ALLOCATE_SIZE
);
1357 DEBUG ((DEBUG_NET
, "\nBcStart() Could not alloc TxBuf.\n"));
1358 EfiReleaseLock (&Private
->Lock
);
1359 return EFI_OUT_OF_RESOURCES
;
1362 Status
= gBS
->AllocatePool (
1363 EfiBootServicesData
,
1364 BUFFER_ALLOCATE_SIZE
,
1365 (VOID
**) &Private
->ReceiveBufferPtr
1368 if (!EFI_ERROR (Status
)) {
1369 ZeroMem (Private
->ReceiveBufferPtr
, BUFFER_ALLOCATE_SIZE
);
1371 DEBUG ((DEBUG_NET
, "\nBcStart() Could not alloc RxBuf.\n"));
1372 gBS
->FreePool (Private
->TransmitBufferPtr
);
1373 EfiReleaseLock (&Private
->Lock
);
1374 return EFI_OUT_OF_RESOURCES
;
1377 Status
= gBS
->AllocatePool (
1378 EfiBootServicesData
,
1380 (VOID
**) &Private
->TftpErrorBuffer
1383 if (EFI_ERROR (Status
)) {
1384 gBS
->FreePool (Private
->ReceiveBufferPtr
);
1385 gBS
->FreePool (Private
->TransmitBufferPtr
);
1386 EfiReleaseLock (&Private
->Lock
);
1387 return EFI_OUT_OF_RESOURCES
;
1390 Status
= gBS
->AllocatePool (EfiBootServicesData
, 256, (VOID
**) &Private
->TftpAckBuffer
);
1392 if (EFI_ERROR (Status
)) {
1393 gBS
->FreePool (Private
->TftpErrorBuffer
);
1394 gBS
->FreePool (Private
->ReceiveBufferPtr
);
1395 gBS
->FreePool (Private
->TransmitBufferPtr
);
1396 EfiReleaseLock (&Private
->Lock
);
1397 return EFI_OUT_OF_RESOURCES
;
1400 // Initialize private BaseCode instance data
1403 Private
->RandomPort
= (UINT16
) (Private
->RandomPort
+ PXE_RND_PORT_LOW
+ Random (Private
));
1404 } while (Private
->RandomPort
< PXE_RND_PORT_LOW
);
1406 Private
->Igmpv1TimeoutEvent
= NULL
;
1407 Private
->UseIgmpv1Reporting
= TRUE
;
1408 Private
->IpLength
= IP_ADDRESS_LENGTH (Private
->EfiBc
.Mode
);
1411 // Initialize Mode structure
1413 ZeroMem (Private
->EfiBc
.Mode
, sizeof (EFI_PXE_BASE_CODE_MODE
));
1415 // check for callback protocol and set boolean
1417 SetMakeCallback (Private
);
1418 Private
->EfiBc
.Mode
->Started
= TRUE
;
1419 Private
->EfiBc
.Mode
->TTL
= DEFAULT_TTL
;
1420 Private
->EfiBc
.Mode
->ToS
= DEFAULT_ToS
;
1421 Private
->EfiBc
.Mode
->UsingIpv6
= UseIPv6
;
1424 // Set to PXE_TRUE by the BC constructor if this BC implementation
1427 Private
->EfiBc
.Mode
->Ipv6Supported
= SUPPORT_IPV6
;
1429 Private
->EfiBc
.Mode
->Ipv6Available
= FALSE
;
1431 // Set to TRUE by the BC constructor if this BC implementation
1434 Private
->EfiBc
.Mode
->BisSupported
= TRUE
;
1435 Private
->EfiBc
.Mode
->BisDetected
= PxebcBisDetect (Private
);
1438 // This field is set to PXE_TRUE by the BC Start() function. When this
1439 // field is PXE_TRUE, ARP packets are sent as needed to get IP and MAC
1440 // addresses. This can cause unexpected delays in the DHCP(), Discover()
1441 // and MTFTP() functions. Setting this to PXE_FALSE will cause these
1442 // functions to fail if the required IP/MAC information is not in the
1443 // ARP cache. The value of this field can be changed by an application
1446 Private
->EfiBc
.Mode
->AutoArp
= TRUE
;
1449 // Unlock the instance data
1451 EfiReleaseLock (&Private
->Lock
);
1457 Stop the BaseCode protocol, Simple Network protocol and UNDI.
1459 @param Private Pointer to Pxe BaseCode Protocol
1461 @retval 0 Successfully stopped
1468 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
1472 // Lock the instance data
1474 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
1475 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
1476 EFI_STATUS StatCode
;
1477 PXE_BASECODE_DEVICE
*Private
;
1479 StatCode
= EFI_SUCCESS
;
1482 DEBUG ((DEBUG_ERROR
, "BC *This pointer == NULL"));
1483 return EFI_INVALID_PARAMETER
;
1486 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1488 if (Private
== NULL
) {
1489 DEBUG ((DEBUG_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1490 return EFI_INVALID_PARAMETER
;
1493 EfiAcquireLock (&Private
->Lock
);
1495 SnpPtr
= Private
->SimpleNetwork
;
1496 SnpModePtr
= SnpPtr
->Mode
;
1501 StatCode
= EFI_NOT_STARTED
;
1503 if (SnpModePtr
->State
== EfiSimpleNetworkInitialized
) {
1504 StatCode
= (*SnpPtr
->Shutdown
) (SnpPtr
);
1507 if (SnpModePtr
->State
== EfiSimpleNetworkStarted
) {
1508 StatCode
= (*SnpPtr
->Stop
) (SnpPtr
);
1511 if (Private
->TransmitBufferPtr
!= NULL
) {
1512 gBS
->FreePool (Private
->TransmitBufferPtr
);
1513 Private
->TransmitBufferPtr
= NULL
;
1516 if (Private
->ReceiveBufferPtr
!= NULL
) {
1517 gBS
->FreePool (Private
->ReceiveBufferPtr
);
1518 Private
->ReceiveBufferPtr
= NULL
;
1521 if (Private
->ArpBuffer
!= NULL
) {
1522 gBS
->FreePool (Private
->ArpBuffer
);
1523 Private
->ArpBuffer
= NULL
;
1526 if (Private
->TftpErrorBuffer
!= NULL
) {
1527 gBS
->FreePool (Private
->TftpErrorBuffer
);
1528 Private
->TftpErrorBuffer
= NULL
;
1531 if (Private
->TftpAckBuffer
!= NULL
) {
1532 gBS
->FreePool (Private
->TftpAckBuffer
);
1533 Private
->TftpAckBuffer
= NULL
;
1536 if (Private
->Igmpv1TimeoutEvent
!= NULL
) {
1537 gBS
->CloseEvent (Private
->Igmpv1TimeoutEvent
);
1538 Private
->Igmpv1TimeoutEvent
= NULL
;
1541 Private
->FileSize
= 0;
1543 if (!Private
->EfiBc
.Mode
->Started
) {
1544 StatCode
= EFI_NOT_STARTED
;
1546 Private
->EfiBc
.Mode
->Started
= FALSE
;
1550 // Unlock the instance data
1552 EfiReleaseLock (&Private
->Lock
);
1556 const IPV4_ADDR AllSystemsGroup
= {{224, 0, 0, 1}};
1560 Set up the IP filter
1562 @param Private Pointer to Pxe BaseCode Protocol
1563 @param Filter Pointer to the filter
1565 @retval 0 Successfully set the filter
1571 IN PXE_BASECODE_DEVICE
*Private
,
1572 IN EFI_PXE_BASE_CODE_IP_FILTER
*Filter
1575 EFI_STATUS StatCode
;
1576 EFI_MAC_ADDRESS MACadds
[PXE_IP_FILTER_SIZE
];
1577 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1578 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
1579 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
1585 PxebcMode
= Private
->EfiBc
.Mode
;
1586 SnpPtr
= Private
->SimpleNetwork
;
1587 SnpModePtr
= SnpPtr
->Mode
;
1590 // validate input parameters
1591 // must have a filter
1592 // must not have any extra filter bits set
1594 if (Filter
== NULL
||
1595 (Filter
->Filters
&~FILTER_BITS
)
1597 // must not have a count which is too large or with no IP list
1600 (Filter
->IpCnt
&& (!Filter
->IpList
|| Filter
->IpCnt
> PXE_IP_FILTER_SIZE
))
1602 // must not have incompatible filters - promiscuous incompatible with anything else
1606 (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) &&
1607 ((Filter
->Filters
&~EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) || Filter
->IpCnt
)
1610 DEBUG ((DEBUG_INFO
, "\nIpFilter() Exit #1"));
1611 return EFI_INVALID_PARAMETER
;
1614 // promiscuous multicast incompatible with multicast in IP list
1616 if (Filter
->IpCnt
&& (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
)) {
1617 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1618 if (IS_MULTICAST (&Filter
->IpList
[Index
])) {
1619 DEBUG ((DEBUG_INFO
, "\nIpFilter() Exit #2"));
1620 return EFI_INVALID_PARAMETER
;
1625 // leave groups for all those multicast which are no longer enabled
1627 for (Index
= 0; Index
< PxebcMode
->IpFilter
.IpCnt
; ++Index
) {
1628 if (!IS_MULTICAST (&PxebcMode
->IpFilter
.IpList
[Index
])) {
1632 for (Index2
= 0; Index2
< Filter
->IpCnt
; ++Index2
) {
1633 if (!CompareMem (&PxebcMode
->IpFilter
.IpList
[Index
], &Filter
->IpList
[Index2
], IP_ADDRESS_LENGTH (PxebcMode
))) {
1641 // if we didn't find it, remove from group
1643 if (Index2
== Filter
->IpCnt
) {
1644 IgmpLeaveGroup (Private
, &PxebcMode
->IpFilter
.IpList
[Index
]);
1648 // set enable bits, convert multicast ip adds, join groups
1649 // allways leave receive broadcast enabled at hardware layer
1653 if (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) {
1654 Enable
= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
1656 if (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
) {
1657 Enable
= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
1659 Enable
= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
1661 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1662 CopyMem (&PxebcMode
->IpFilter
.IpList
[Index
], &Filter
->IpList
[Index
], sizeof (EFI_IP_ADDRESS
));
1664 if (IS_MULTICAST (&Filter
->IpList
[Index
])) {
1665 EFI_IP_ADDRESS
*TmpIp
;
1667 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
1670 // if this is the first group, add the all systems group to mcast list
1674 TmpIp
= (EFI_IP_ADDRESS
*) &AllSystemsGroup
;
1677 TmpIp
= (EFI_IP_ADDRESS
*) &Filter
->IpList
[Index
];
1680 // get MAC address of IP
1682 StatCode
= (*SnpPtr
->MCastIpToMac
) (SnpPtr
, PxebcMode
->UsingIpv6
, TmpIp
, &MACadds
[Index2
++]);
1684 if (EFI_ERROR (StatCode
)) {
1687 "\nIpFilter() Exit #2 %Xh (%r)",
1694 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
1699 if (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
) {
1700 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
1704 // if nothing changed, just return
1708 "\nsnp->ReceiveFilterSetting == %Xh Filter->IpCnt == %Xh",
1709 SnpModePtr
->ReceiveFilterSetting
,
1713 if (SnpModePtr
->ReceiveFilterSetting
== Enable
&& !Filter
->IpCnt
) {
1714 DEBUG ((DEBUG_INFO
, "\nIpFilter() Exit #4"));
1718 // disable those currently set but not set in new filter
1720 Disable
= SnpModePtr
->ReceiveFilterSetting
&~Enable
;
1722 StatCode
= SnpPtr
->ReceiveFilters (SnpPtr
, Enable
, Disable
, FALSE
, Index2
, MACadds
);
1724 PxebcMode
->IpFilter
.IpCnt
= Filter
->IpCnt
;
1727 // join groups for all multicast in list
1729 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1730 if (IS_MULTICAST (&Filter
->IpList
[Index
])) {
1731 IgmpJoinGroup (Private
, &Filter
->IpList
[Index
]);
1735 DEBUG ((DEBUG_INFO
, "\nIpFilter() Exit #5 %Xh (%r)", StatCode
, StatCode
));
1744 @param Private Pointer to Pxe BaseCode Protocol
1745 @param Filter Pointer to the filter
1747 @retval 0 Successfully set the filter
1754 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1755 IN EFI_PXE_BASE_CODE_IP_FILTER
*Filter
1758 EFI_STATUS StatCode
;
1759 PXE_BASECODE_DEVICE
*Private
;
1762 // Lock the instance data and make sure started
1764 StatCode
= EFI_SUCCESS
;
1767 DEBUG ((DEBUG_ERROR
, "BC *This pointer == NULL"));
1768 return EFI_INVALID_PARAMETER
;
1771 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1773 if (Private
== NULL
) {
1774 DEBUG ((DEBUG_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1775 return EFI_INVALID_PARAMETER
;
1778 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1779 if ((Filter
->IpList
[Index
].Addr
[0]) == BROADCAST_IPv4
) {
1781 // The IP is a broadcast address.
1783 return EFI_INVALID_PARAMETER
;
1787 EfiAcquireLock (&Private
->Lock
);
1789 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
1790 DEBUG ((DEBUG_ERROR
, "BC was not started."));
1791 EfiReleaseLock (&Private
->Lock
);
1792 return EFI_NOT_STARTED
;
1795 if (Filter
== NULL
) {
1796 return EFI_INVALID_PARAMETER
;
1801 StatCode
= IpFilter (Private
, Filter
);
1804 // Unlock the instance data
1806 EfiReleaseLock (&Private
->Lock
);
1812 Set the Base Code behavior parameters
1814 @param This Pointer to Pxe BaseCode Protocol
1815 @param AutoArpPtr Boolean to do ARP stuff
1816 @param SendGuidPtr Boolean whether or not to send GUID info
1817 @param TimeToLivePtr Value for Total time to live
1818 @param TypeOfServicePtr Value for Type of Service
1819 @param MakeCallbackPtr Boolean to determine if we make callbacks
1821 @retval 0 Successfully set the parameters
1828 EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1829 BOOLEAN
*AutoArpPtr
,
1830 BOOLEAN
*SendGuidPtr
,
1831 UINT8
*TimeToLivePtr
,
1832 UINT8
*TypeOfServicePtr
,
1833 BOOLEAN
*MakeCallbackPtr
1836 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1838 UINT8
*SerialNumberPtr
;
1839 EFI_STATUS StatCode
;
1840 PXE_BASECODE_DEVICE
*Private
;
1843 // Lock the instance data and make sure started
1845 StatCode
= EFI_SUCCESS
;
1848 DEBUG ((DEBUG_ERROR
, "BC *This pointer == NULL"));
1849 return EFI_INVALID_PARAMETER
;
1852 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1854 if (Private
== NULL
) {
1855 DEBUG ((DEBUG_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1856 return EFI_INVALID_PARAMETER
;
1859 EfiAcquireLock (&Private
->Lock
);
1861 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
1862 DEBUG ((DEBUG_ERROR
, "BC was not started."));
1863 EfiReleaseLock (&Private
->Lock
);
1864 return EFI_NOT_STARTED
;
1867 DEBUG ((DEBUG_INFO
, "\nSetParameters() Entry. "));
1869 PxebcMode
= Private
->EfiBc
.Mode
;
1870 StatCode
= EFI_SUCCESS
;
1872 if (SendGuidPtr
!= NULL
) {
1874 if (PxeBcLibGetSmbiosSystemGuidAndSerialNumber (&TmpGuid
, (CHAR8
**) &SerialNumberPtr
) != EFI_SUCCESS
) {
1875 return EFI_INVALID_PARAMETER
;
1880 if (MakeCallbackPtr
!= NULL
) {
1881 if (*MakeCallbackPtr
) {
1882 if (!SetMakeCallback (Private
)) {
1883 return EFI_INVALID_PARAMETER
;
1887 PxebcMode
->MakeCallbacks
= *MakeCallbackPtr
;
1890 if (AutoArpPtr
!= NULL
) {
1891 PxebcMode
->AutoArp
= *AutoArpPtr
;
1894 if (SendGuidPtr
!= NULL
) {
1895 PxebcMode
->SendGUID
= *SendGuidPtr
;
1898 if (TimeToLivePtr
!= NULL
) {
1899 PxebcMode
->TTL
= *TimeToLivePtr
;
1902 if (TypeOfServicePtr
!= NULL
) {
1903 PxebcMode
->ToS
= *TypeOfServicePtr
;
1906 // Unlock the instance data
1908 DEBUG ((DEBUG_INFO
, "\nSetparameters() Exit = %xh ", StatCode
));
1910 EfiReleaseLock (&Private
->Lock
);
1914 // //////////////////////////////////////////////////////////
1916 // BC Set Station IP Routine
1920 Set the station IP address
1922 @param This Pointer to Pxe BaseCode Protocol
1923 @param StationIpPtr Pointer to the requested IP address to set in base
1925 @param SubnetMaskPtr Pointer to the requested subnet mask for the base
1928 @retval EFI_SUCCESS Successfully set the parameters
1929 @retval EFI_NOT_STARTED BC has not started
1935 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1936 IN EFI_IP_ADDRESS
*StationIpPtr
,
1937 IN EFI_IP_ADDRESS
*SubnetMaskPtr
1940 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1941 EFI_STATUS StatCode
;
1942 PXE_BASECODE_DEVICE
*Private
;
1946 // Lock the instance data and make sure started
1948 StatCode
= EFI_SUCCESS
;
1951 DEBUG ((DEBUG_ERROR
, "BC *This pointer == NULL"));
1952 return EFI_INVALID_PARAMETER
;
1955 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1957 if (Private
== NULL
) {
1958 DEBUG ((DEBUG_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1959 return EFI_INVALID_PARAMETER
;
1962 EfiAcquireLock (&Private
->Lock
);
1964 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
1965 DEBUG ((DEBUG_ERROR
, "BC was not started."));
1966 StatCode
= EFI_NOT_STARTED
;
1970 PxebcMode
= Private
->EfiBc
.Mode
;
1972 if (!Private
->GoodStationIp
&& ((StationIpPtr
== NULL
) || (SubnetMaskPtr
== NULL
))) {
1974 // It's not allowed to only set one of the two addresses while there isn't a previous
1975 // GOOD address configuration.
1977 StatCode
= EFI_INVALID_PARAMETER
;
1981 if (SubnetMaskPtr
!= NULL
) {
1982 SubnetMask
= SubnetMaskPtr
->Addr
[0];
1984 if (SubnetMask
& (SubnetMask
+ 1)) {
1986 // the subnet mask is valid if it's with leading continuous 1 bits.
1988 StatCode
= EFI_INVALID_PARAMETER
;
1992 SubnetMaskPtr
= &PxebcMode
->SubnetMask
;
1993 SubnetMask
= SubnetMaskPtr
->Addr
[0];
1996 if (StationIpPtr
== NULL
) {
1997 StationIpPtr
= &PxebcMode
->StationIp
;
2000 if (!IS_INADDR_UNICAST (StationIpPtr
) ||
2001 ((StationIpPtr
->Addr
[0] | SubnetMask
) == BROADCAST_IPv4
)) {
2003 // The station IP is not a unicast address.
2005 StatCode
= EFI_INVALID_PARAMETER
;
2009 CopyMem (&PxebcMode
->StationIp
, StationIpPtr
, sizeof (EFI_IP_ADDRESS
));
2010 CopyMem (&PxebcMode
->SubnetMask
, SubnetMaskPtr
, sizeof (EFI_IP_ADDRESS
));
2011 Private
->GoodStationIp
= TRUE
;
2015 // Unlock the instance data
2017 EfiReleaseLock (&Private
->Lock
);
2022 EFI_DRIVER_BINDING_PROTOCOL mPxeBcDriverBinding
= {
2023 PxeBcDriverSupported
,
2033 Test to see if this driver supports Controller. Any Controller
2034 than contains a Snp protocol can be supported.
2036 @param This Protocol instance pointer.
2037 @param Controller Handle of device to test.
2038 @param RemainingDevicePath Not used.
2040 @retval EFI_SUCCESS This driver supports this device.
2041 @retval EFI_ALREADY_STARTED This driver is already running on this device.
2042 @retval other This driver does not support this device.
2047 PxeBcDriverSupported (
2048 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2049 IN EFI_HANDLE Controller
,
2050 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
2054 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
2056 Status
= gBS
->OpenProtocol (
2058 &gEfiDevicePathProtocolGuid
,
2060 This
->DriverBindingHandle
,
2062 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
2065 if (EFI_ERROR (Status
)) {
2069 Status
= gBS
->OpenProtocol (
2071 &gEfiSimpleNetworkProtocolGuid
,
2073 This
->DriverBindingHandle
,
2075 EFI_OPEN_PROTOCOL_BY_DRIVER
2077 if (EFI_ERROR (Status
)) {
2081 gBS
->CloseProtocol (
2083 &gEfiSimpleNetworkProtocolGuid
,
2084 This
->DriverBindingHandle
,
2093 Start the Base code driver.
2095 @param This Protocol instance pointer.
2096 @param Controller Handle of device to test.
2097 @param RemainingDevicePath Not used.
2099 @retval EFI_SUCCESS This driver supports this device.
2100 @retval EFI_ALREADY_STARTED This driver is already running on this device.
2101 @retval other This driver does not support this device.
2107 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2108 IN EFI_HANDLE Controller
,
2109 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
2113 PXE_BASECODE_DEVICE
*Private
;
2114 LOADFILE_DEVICE
*pLF
;
2117 // Allocate structures needed by BaseCode and LoadFile protocols.
2119 Private
= AllocateZeroPool (sizeof (PXE_BASECODE_DEVICE
));
2121 if (Private
== NULL
) {
2122 DEBUG ((EFI_D_NET
, "\nBcNotifySnp() Could not alloc PXE_BASECODE_DEVICE structure.\n"));
2123 return EFI_OUT_OF_RESOURCES
;
2126 pLF
= AllocateZeroPool (sizeof (LOADFILE_DEVICE
));
2128 DEBUG ((EFI_D_NET
, "\nBcNotifySnp() Could not alloc LOADFILE_DEVICE structure.\n"));
2130 return EFI_OUT_OF_RESOURCES
;
2133 Private
->EfiBc
.Mode
= AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_MODE
));
2134 if (Private
->EfiBc
.Mode
== NULL
) {
2135 DEBUG ((EFI_D_NET
, "\nBcNotifySnp() Could not alloc Mode structure.\n"));
2138 return EFI_OUT_OF_RESOURCES
;
2141 // Lock access, just in case
2143 EfiInitializeLock (&Private
->Lock
, TPL_CALLBACK
);
2144 EfiAcquireLock (&Private
->Lock
);
2146 EfiInitializeLock (&pLF
->Lock
, TPL_CALLBACK
);
2147 EfiAcquireLock (&pLF
->Lock
);
2150 // Initialize PXE structure
2153 // First initialize the internal 'private' data that the application
2156 Private
->Signature
= PXE_BASECODE_DEVICE_SIGNATURE
;
2157 Private
->Handle
= Controller
;
2160 // Get the NII interface
2162 Status
= gBS
->OpenProtocol (
2164 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
2165 (VOID
**) &Private
->NiiPtr
,
2166 This
->DriverBindingHandle
,
2168 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2171 if (EFI_ERROR (Status
)) {
2176 // Get the Snp interface
2178 Status
= gBS
->OpenProtocol (
2180 &gEfiSimpleNetworkProtocolGuid
,
2181 (VOID
**) &Private
->SimpleNetwork
,
2182 This
->DriverBindingHandle
,
2184 EFI_OPEN_PROTOCOL_BY_DRIVER
2187 if (EFI_ERROR (Status
)) {
2192 // Next, initialize the external 'public' data that
2193 // the application does see.
2195 Private
->EfiBc
.Revision
= EFI_PXE_BASE_CODE_PROTOCOL_REVISION
;
2196 Private
->EfiBc
.Start
= BcStart
;
2197 Private
->EfiBc
.Stop
= BcStop
;
2198 Private
->EfiBc
.Dhcp
= BcDhcp
;
2199 Private
->EfiBc
.Discover
= BcDiscover
;
2200 Private
->EfiBc
.Mtftp
= BcMtftp
;
2201 Private
->EfiBc
.UdpWrite
= BcUdpWrite
;
2202 Private
->EfiBc
.UdpRead
= BcUdpRead
;
2203 Private
->EfiBc
.Arp
= BcArp
;
2204 Private
->EfiBc
.SetIpFilter
= BcIpFilter
;
2205 Private
->EfiBc
.SetParameters
= BcSetParameters
;
2206 Private
->EfiBc
.SetStationIp
= BcSetStationIP
;
2207 Private
->EfiBc
.SetPackets
= BcSetPackets
;
2210 // Initialize BaseCode Mode structure
2212 Private
->EfiBc
.Mode
->Started
= FALSE
;
2213 Private
->EfiBc
.Mode
->TTL
= DEFAULT_TTL
;
2214 Private
->EfiBc
.Mode
->ToS
= DEFAULT_ToS
;
2215 Private
->EfiBc
.Mode
->UsingIpv6
= FALSE
;
2216 Private
->EfiBc
.Mode
->AutoArp
= TRUE
;
2219 // Set to PXE_TRUE by the BC constructor if this BC
2220 // implementation supports IPv6.
2222 Private
->EfiBc
.Mode
->Ipv6Supported
= SUPPORT_IPV6
;
2223 Private
->EfiBc
.Mode
->Ipv6Available
= FALSE
;
2226 // Set to TRUE by the BC constructor if this BC
2227 // implementation supports BIS.
2229 Private
->EfiBc
.Mode
->BisSupported
= TRUE
;
2230 Private
->EfiBc
.Mode
->BisDetected
= PxebcBisDetect (Private
);
2233 // Initialize LoadFile structure.
2235 pLF
->Signature
= LOADFILE_DEVICE_SIGNATURE
;
2236 pLF
->LoadFile
.LoadFile
= LoadFile
;
2237 pLF
->Private
= Private
;
2240 // Install protocol interfaces.
2242 Status
= gBS
->InstallMultipleProtocolInterfaces (
2244 &gEfiPxeBaseCodeProtocolGuid
,
2246 &gEfiLoadFileProtocolGuid
,
2251 if (EFI_ERROR (Status
)) {
2252 gBS
->CloseProtocol (
2254 &gEfiSimpleNetworkProtocolGuid
,
2255 This
->DriverBindingHandle
,
2264 EfiReleaseLock (&pLF
->Lock
);
2265 EfiReleaseLock (&Private
->Lock
);
2269 gBS
->FreePool (Private
->EfiBc
.Mode
);
2270 gBS
->FreePool (Private
);
2271 gBS
->FreePool (pLF
);
2277 Stop the Base code driver.
2279 @param This Protocol instance pointer.
2280 @param Controller Handle of device to test.
2281 @param NumberOfChildren Not used
2282 @param ChildHandleBuffer Not used
2284 @retval EFI_SUCCESS This driver supports this device.
2285 @retval EFI_ALREADY_STARTED This driver is already running on this device.
2286 @retval other This driver does not support this device.
2292 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2293 IN EFI_HANDLE Controller
,
2294 IN UINTN NumberOfChildren
,
2295 IN EFI_HANDLE
*ChildHandleBuffer
2299 EFI_LOAD_FILE_PROTOCOL
*LfProtocol
;
2300 LOADFILE_DEVICE
*LoadDevice
;
2303 // Get our context back.
2305 Status
= gBS
->OpenProtocol (
2307 &gEfiLoadFileProtocolGuid
,
2308 (VOID
**) &LfProtocol
,
2309 This
->DriverBindingHandle
,
2311 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2314 if (EFI_ERROR (Status
)) {
2315 return EFI_UNSUPPORTED
;
2318 LoadDevice
= EFI_LOAD_FILE_DEV_FROM_THIS (LfProtocol
);
2320 Status
= gBS
->UninstallMultipleProtocolInterfaces (
2322 &gEfiLoadFileProtocolGuid
,
2323 &LoadDevice
->LoadFile
,
2324 &gEfiPxeBaseCodeProtocolGuid
,
2325 &LoadDevice
->Private
->EfiBc
,
2329 if (!EFI_ERROR (Status
)) {
2331 Status
= gBS
->CloseProtocol (
2333 &gEfiSimpleNetworkProtocolGuid
,
2334 This
->DriverBindingHandle
,
2338 gBS
->FreePool (LoadDevice
->Private
->EfiBc
.Mode
);
2339 gBS
->FreePool (LoadDevice
->Private
);
2340 gBS
->FreePool (LoadDevice
);
2349 IN EFI_HANDLE ImageHandle
2353 UINTN DeviceHandleCount
;
2354 EFI_HANDLE
*DeviceHandleBuffer
;
2357 Status
= gBS
->LocateHandleBuffer (
2364 if (!EFI_ERROR (Status
)) {
2365 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
2366 Status
= gBS
->DisconnectController (
2367 DeviceHandleBuffer
[Index
],
2368 mPxeBcDriverBinding
.DriverBindingHandle
,
2373 if (DeviceHandleBuffer
!= NULL
) {
2374 gBS
->FreePool (DeviceHandleBuffer
);
2383 Initialize the base code drivers and install the driver binding
2385 Standard EFI Image Entry
2387 @retval EFI_SUCCESS This driver was successfully bound
2392 InitializeBCDriver (
2393 IN EFI_HANDLE ImageHandle
,
2394 IN EFI_SYSTEM_TABLE
*SystemTable
2398 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
2401 // Initialize EFI library
2403 Status
= EfiLibInstallDriverBindingComponentName2 (
2406 &mPxeBcDriverBinding
,
2408 &gPxeBcComponentName
,
2409 &gPxeBcComponentName2
2412 Status
= gBS
->HandleProtocol (
2414 &gEfiLoadedImageProtocolGuid
,
2415 (VOID
**) &LoadedImage
2417 if (EFI_ERROR (Status
)) {
2420 LoadedImage
->Unload
= PxeBcUnload
;
2424 OptionsStrucInit ();