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
295 Sum
= (UINT16
)~IpChecksum (Header
, HeaderLen
) + (UINT16
)~IpChecksum (Message
, MessageLen
);
298 // in case above carried
302 return (UINT16
) (~ (UINT16
) Sum
);
307 Adjust the internet checksum (see RFC 1071) on a single word update.
309 @param OldChkSum Checksum previously calculated
311 @param NewWord New Value
313 @retval Checksum Returns the 16 bit ones complement of ones
314 complement sum of 16 bit words
326 sum
= ~OldChksum
+ NewWord
- OldWord
;
328 // in case above carried
331 return (UINT16
) (~ (UINT16
) sum
);
336 See if a callback is in play
338 @param Private Pointer to Pxe BaseCode Protocol
340 @retval 0 Callbacks are active on the handle
341 @retval 1 Callbacks are not active on the handle
347 IN PXE_BASECODE_DEVICE
*Private
350 Private
->EfiBc
.Mode
->MakeCallbacks
= (BOOLEAN
) (gBS
->HandleProtocol (
352 &gEfiPxeBaseCodeCallbackProtocolGuid
,
353 (VOID
*) &Private
->CallbackProtocolPtr
358 "\nMode->MakeCallbacks == %d ",
359 Private
->EfiBc
.Mode
->MakeCallbacks
)
364 "\nPrivate->CallbackProtocolPtr == %xh ",
365 Private
->CallbackProtocolPtr
)
368 if (Private
->CallbackProtocolPtr
!= NULL
) {
371 "\nCallbackProtocolPtr->Revision = %xh ",
372 Private
->CallbackProtocolPtr
->Revision
)
377 "\nCallbackProtocolPtr->Callback = %xh ",
378 Private
->CallbackProtocolPtr
->Callback
)
382 return Private
->EfiBc
.Mode
->MakeCallbacks
;
385 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
388 Routine which does an SNP->Receive over a timeout period and doing callbacks
390 @param Private Pointer to Pxe BaseCode Protocol
391 @param Function What PXE function to callback
392 @param TimeoutEvent Timer event that will trigger when we have waited
393 too long for an incoming packet
394 @param HeaderSizePtr Pointer to the size of the Header size
395 @param BufferSizePtr Pointer to the size of the Buffer size
396 @param ProtocolPtr The protocol to sniff for (namely, UDP/TCP/etc)
398 @retval 0 Something was returned
399 @retval !0 Like there was nothing to receive
400 (EFI_TIMEOUT/NOT_READY)
405 IN PXE_BASECODE_DEVICE
*Private
,
406 IN EFI_PXE_BASE_CODE_FUNCTION Function
,
407 IN EFI_EVENT TimeoutEvent
,
408 IN OUT UINTN
*HeaderSizePtr
,
409 IN OUT UINTN
*BufferSizePtr
,
410 IN OUT UINT16
*ProtocolPtr
413 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
414 EFI_PXE_CALLBACK CallbackPtr
;
416 EFI_EVENT CallbackEvent
;
419 // Initialize pointer to SNP interface
421 SnpPtr
= Private
->SimpleNetwork
;
424 // Initialize pointer to PxeBc callback routine - if any
426 CallbackPtr
= (Private
->EfiBc
.Mode
->MakeCallbacks
) ? Private
->CallbackProtocolPtr
->Callback
: NULL
;
429 // Create callback event and set timer
431 StatCode
= gBS
->CreateEvent (
439 if (EFI_ERROR (StatCode
)) {
440 return EFI_DEVICE_ERROR
;
444 // every 100 milliseconds
446 StatCode
= gBS
->SetTimer (
452 if (EFI_ERROR (StatCode
)) {
453 gBS
->CloseEvent (CallbackEvent
);
454 return EFI_DEVICE_ERROR
;
457 // Loop until a packet is received or a receive error is detected or
458 // a callback abort is detected or a timeout event occurs.
463 // Poll for received packet.
465 *BufferSizePtr
= BUFFER_ALLOCATE_SIZE
;
467 StatCode
= SnpPtr
->Receive (
471 Private
->ReceiveBufferPtr
,
477 if (!EFI_ERROR (StatCode
)) {
479 // Packet was received. Make received callback then return.
481 if (CallbackPtr
!= NULL
) {
482 StatCode
= CallbackPtr (
483 Private
->CallbackProtocolPtr
,
486 (UINT32
) *BufferSizePtr
,
487 (EFI_PXE_BASE_CODE_PACKET
*) Private
->ReceiveBufferPtr
490 if (StatCode
!= EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
) {
491 StatCode
= EFI_ABORTED
;
493 StatCode
= EFI_SUCCESS
;
500 if (StatCode
!= EFI_NOT_READY
) {
504 // Check for callback event.
506 if (!EFI_ERROR (gBS
->CheckEvent (CallbackEvent
))) {
508 // Make periodic callback if callback pointer is initialized.
510 if (CallbackPtr
!= NULL
) {
511 StatCode
= CallbackPtr (
512 Private
->CallbackProtocolPtr
,
520 // Abort if directed to by callback routine.
522 if (StatCode
!= EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
) {
523 StatCode
= EFI_ABORTED
;
529 // Check for timeout event.
531 if (TimeoutEvent
== 0) {
532 StatCode
= EFI_TIMEOUT
;
536 if (!EFI_ERROR (gBS
->CheckEvent (TimeoutEvent
))) {
537 StatCode
= EFI_TIMEOUT
;
541 // Check IGMP timer events.
543 IgmpCheckTimers (Private
);
546 gBS
->CloseEvent (CallbackEvent
);
553 Routine which does an SNP->Transmit of a buffer
555 @param Private Pointer to Pxe BaseCode Protocol
556 @param HeaderPtr Pointer to the buffer
557 @param PacketPtr Pointer to the packet to send
558 @param PacketLen The length of the entire packet to send
559 @param HardwareAddr Pointer to the MAC address of the destination
560 @param MediaProtocol What type of frame to create (RFC 1700) - IE.
562 @param Function What PXE function to callback
564 @retval 0 Something was sent
565 @retval !0 An error was encountered during sending of a packet
570 PXE_BASECODE_DEVICE
*Private
,
575 UINT16 MediaProtocol
,
576 IN EFI_PXE_BASE_CODE_FUNCTION Function
579 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
580 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
581 EFI_PXE_CALLBACK CallbackPtr
;
583 EFI_EVENT TimeoutEvent
;
590 CallbackPtr
= Private
->EfiBc
.Mode
->MakeCallbacks
? Private
->CallbackProtocolPtr
->Callback
: 0;
592 SnpPtr
= Private
->SimpleNetwork
;
593 SnpModePtr
= SnpPtr
->Mode
;
596 // clear prior interrupt status
598 StatCode
= SnpPtr
->GetStatus (SnpPtr
, &IntStatus
, 0);
600 if (EFI_ERROR (StatCode
)) {
603 "\nSendPacket() Exit #1 %xh (%r)",
610 Private
->DidTransmit
= FALSE
;
612 if (CallbackPtr
!= NULL
) {
614 Private
->CallbackProtocolPtr
,
619 ) != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
) {
622 "\nSendPacket() Exit #2 %xh (%r)",
630 // put packet in transmit queue
631 // headersize should be zero if not filled in
633 StatCode
= gBS
->CreateEvent (
641 if (EFI_ERROR (StatCode
)) {
644 "Could not create transmit timeout event. %r\n",
647 return EFI_DEVICE_ERROR
;
653 StatCode
= gBS
->SetTimer (
659 if (EFI_ERROR (StatCode
)) {
662 "Could not set transmit timeout event timer. %r\n",
665 gBS
->CloseEvent (TimeoutEvent
);
666 return EFI_DEVICE_ERROR
;
670 StatCode
= SnpPtr
->Transmit (
672 (UINTN
) SnpPtr
->Mode
->MediaHeaderSize
,
673 (UINTN
) (PacketLen
+ SnpPtr
->Mode
->MediaHeaderSize
),
675 &SnpModePtr
->CurrentAddress
,
676 (EFI_MAC_ADDRESS
*) HardwareAddr
,
680 if (StatCode
!= EFI_NOT_READY
) {
684 if (!EFI_ERROR (gBS
->CheckEvent (TimeoutEvent
))) {
685 StatCode
= EFI_TIMEOUT
;
690 gBS
->CloseEvent (TimeoutEvent
);
692 if (EFI_ERROR (StatCode
)) {
695 "\nSendPacket() Exit #3 %xh (%r)",
702 // remove transmit buffer from snp's unused queue
703 // done this way in case someday things are buffered and we don't get it back
706 StatCode
= gBS
->CreateEvent (
714 if (EFI_ERROR (StatCode
)) {
717 "Could not create transmit status timeout event. %r\n",
720 return EFI_DEVICE_ERROR
;
726 StatCode
= gBS
->SetTimer (
732 if (EFI_ERROR (StatCode
)) {
735 "Could not set transmit status timeout event timer. %r\n",
738 gBS
->CloseEvent (TimeoutEvent
);
739 return EFI_DEVICE_ERROR
;
743 StatCode
= SnpPtr
->GetStatus (SnpPtr
, &IntStatus
, &TxBuf
);
745 if (EFI_ERROR (StatCode
)) {
748 "\nSendPacket() Exit #4 %xh (%r)",
755 if (IntStatus
& EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT
) {
756 Private
->DidTransmit
= TRUE
;
763 if (!EFI_ERROR (gBS
->CheckEvent (TimeoutEvent
))) {
764 StatCode
= EFI_TIMEOUT
;
769 gBS
->CloseEvent (TimeoutEvent
);
783 IN PXE_BASECODE_DEVICE
*Private
,
784 OUT BIS_APPLICATION_HANDLE
*BisAppHandle
,
785 OUT OPTIONAL EFI_BIS_DATA
**BisDataSigInfo
788 EFI_STATUS EfiStatus
;
789 EFI_HANDLE BisHandleBuffer
;
790 UINTN BisHandleCount
;
791 EFI_BIS_PROTOCOL
*BisPtr
;
792 EFI_BIS_VERSION BisInterfaceVersion
;
793 BOOLEAN BisCheckFlag
;
795 BisHandleCount
= sizeof (EFI_HANDLE
);
796 BisCheckFlag
= FALSE
;
799 // Locate BIS protocol handle (if present).
800 // If BIS protocol handle is not found, return NULL.
802 DEBUG ((DEBUG_INFO
, "\ngBS->LocateHandle() "));
804 EfiStatus
= gBS
->LocateHandle (
806 &gEfiBisProtocolGuid
,
812 if (EFI_ERROR (EfiStatus
)) {
814 // Any error means that there is no BIS.
815 // Note - It could mean that there are more than
816 // one BIS protocols installed, but that scenario
817 // is not yet supported.
821 "\nPxebcBisStart()""\n gBS->LocateHandle() %r (%xh)\n",
829 if (BisHandleCount
!= sizeof BisHandleBuffer
) {
831 // This really should never happen, but I am paranoid.
835 "\nPxebcBisStart() BisHandleCount != %d\n",
836 sizeof BisHandleBuffer
)
842 DEBUG ((DEBUG_INFO
, "BIS handle found."));
845 // Locate BIS protocol interface.
846 // If the BIS protocol interface cannot be found, return NULL.
848 DEBUG ((DEBUG_INFO
, "\ngBS->HandleProtocol() "));
850 EfiStatus
= gBS
->HandleProtocol (
852 &gEfiBisProtocolGuid
,
856 if (EFI_ERROR (EfiStatus
)) {
859 "\nPxebcBisStart()""\n gBS->HandleProtocol() %r (%xh)\n",
867 if (BisPtr
== NULL
) {
869 // This really should never happen.
873 "\nPxebcBisStart()""\n gBS->HandleProtocoL() ""BIS protocol interface pointer is NULL!\n")
879 DEBUG ((DEBUG_INFO
, "BIS protocol interface found."));
882 // Check that all of the BIS API function pointers are not NULL.
884 if (BisPtr
->Initialize
== NULL
||
885 BisPtr
->Shutdown
== NULL
||
886 BisPtr
->Free
== NULL
||
887 BisPtr
->GetBootObjectAuthorizationCertificate
== NULL
||
888 BisPtr
->GetBootObjectAuthorizationCheckFlag
== NULL
||
889 BisPtr
->GetBootObjectAuthorizationUpdateToken
== NULL
||
890 BisPtr
->GetSignatureInfo
== NULL
||
891 BisPtr
->UpdateBootObjectAuthorization
== NULL
||
892 BisPtr
->VerifyBootObject
== NULL
||
893 BisPtr
->VerifyObjectWithCredential
== NULL
898 "\nPxebcBisStart()""\n BIS protocol interface is invalid."
899 "\n At least one BIS protocol function pointer is NULL.\n"
907 // If BIS does not initialize, return NULL.
909 DEBUG ((DEBUG_INFO
, "\nBisPtr->Initialize() "));
911 BisInterfaceVersion
.Major
= BIS_VERSION_1
;
913 EfiStatus
= BisPtr
->Initialize (
916 &BisInterfaceVersion
,
920 if (EFI_ERROR (EfiStatus
)) {
923 "\nPxebcBisStart()""\n BisPtr->Initialize() %r (%xh)\n",
933 " BIS version: %d.%d",
934 BisInterfaceVersion
.Major
,
935 BisInterfaceVersion
.Minor
)
939 // If the requested BIS API version is not supported,
940 // shutdown BIS and return NULL.
942 if (BisInterfaceVersion
.Major
!= BIS_VERSION_1
) {
945 "\nPxebcBisStart()""\n BIS version %d.%d not supported by PXE BaseCode.\n",
946 BisInterfaceVersion
.Major
,
947 BisInterfaceVersion
.Minor
)
950 BisPtr
->Shutdown (*BisAppHandle
);
954 // Get BIS check flag.
955 // If the BIS check flag cannot be read, shutdown BIS and return NULL.
957 DEBUG ((DEBUG_INFO
, "\nBisPtr->GetBootObjectAuthorizationCheckFlag() "));
959 EfiStatus
= BisPtr
->GetBootObjectAuthorizationCheckFlag (*BisAppHandle
, &BisCheckFlag
);
961 if (EFI_ERROR (EfiStatus
)) {
964 "\nPxebcBisStart()""\n BisPtr->GetBootObjectAuthorizationCheckFlag() %r (%xh)\n",
969 BisPtr
->Shutdown (*BisAppHandle
);
973 // If the BIS check flag is FALSE, shutdown BIS and return NULL.
976 DEBUG ((DEBUG_INFO
, "\nBIS check flag is FALSE.\n"));
977 BisPtr
->Shutdown (*BisAppHandle
);
980 DEBUG ((DEBUG_INFO
, "\nBIS check flag is TRUE."));
983 // Early out if caller does not want signature information.
985 if (BisDataSigInfo
== NULL
) {
989 // Get BIS signature information.
990 // If the signature information cannot be read or is invalid,
991 // shutdown BIS and return NULL.
993 DEBUG ((DEBUG_INFO
, "\nBisPtr->GetSignatureInfo() "));
995 EfiStatus
= BisPtr
->GetSignatureInfo (*BisAppHandle
, BisDataSigInfo
);
997 if (EFI_ERROR (EfiStatus
)) {
1000 "\nPxebcBisStart()""\n BisPtr_GetSignatureInfo() %r (%xh)\n",
1005 BisPtr
->Shutdown (*BisAppHandle
);
1009 if (*BisDataSigInfo
== NULL
) {
1011 // This should never happen.
1015 "\nPxebcBisStart()""\n BisPtr->GetSignatureInfo() Data pointer is NULL!\n")
1018 BisPtr
->Shutdown (*BisAppHandle
);
1022 if ((*BisDataSigInfo
)->Length
< sizeof (EFI_BIS_SIGNATURE_INFO
) ||
1023 (*BisDataSigInfo
)->Length
% sizeof (EFI_BIS_SIGNATURE_INFO
) ||
1024 (*BisDataSigInfo
)->Length
> sizeof (EFI_BIS_SIGNATURE_INFO
) * 63
1027 // This should never happen.
1031 "\nPxebcBisStart()""\n BisPtr->GetSignatureInfo() Invalid BIS siginfo length.\n")
1034 BisPtr
->Free (*BisAppHandle
, *BisDataSigInfo
);
1035 BisPtr
->Shutdown (*BisAppHandle
);
1049 EFI_BIS_PROTOCOL
*BisPtr
,
1050 BIS_APPLICATION_HANDLE BisAppHandle
,
1051 EFI_BIS_DATA
*BisDataSigInfo
1054 if (BisPtr
== NULL
) {
1058 // Free BIS allocated resources and shutdown BIS.
1059 // Return TRUE - BIS support is officially detected.
1061 if (BisDataSigInfo
!= NULL
) {
1062 BisPtr
->Free (BisAppHandle
, BisDataSigInfo
);
1065 BisPtr
->Shutdown (BisAppHandle
);
1071 @return TRUE := verified
1072 @return FALSE := not verified
1077 PXE_BASECODE_DEVICE
*Private
,
1080 VOID
*CredentialBuffer
,
1081 UINTN CredentialLength
1084 EFI_BIS_PROTOCOL
*BisPtr
;
1085 BIS_APPLICATION_HANDLE BisAppHandle
;
1086 EFI_BIS_DATA FileData
;
1087 EFI_BIS_DATA CredentialData
;
1088 EFI_STATUS EfiStatus
;
1091 if (Private
== NULL
|| FileBuffer
== NULL
|| FileLength
== 0 || CredentialBuffer
== NULL
|| CredentialLength
== 0) {
1095 BisPtr
= PxebcBisStart (Private
, &BisAppHandle
, NULL
);
1097 if (BisPtr
== NULL
) {
1101 FileData
.Length
= (UINT32
) FileLength
;
1102 FileData
.Data
= FileBuffer
;
1103 CredentialData
.Length
= (UINT32
) CredentialLength
;
1104 CredentialData
.Data
= CredentialBuffer
;
1106 EfiStatus
= BisPtr
->VerifyBootObject (
1113 PxebcBisStop (BisPtr
, BisAppHandle
, NULL
);
1115 return (BOOLEAN
) ((EFI_ERROR (EfiStatus
)) ? FALSE
: (IsVerified
? TRUE
: FALSE
));
1121 @return TRUE := BIS present
1122 @return FALSE := BIS not present
1127 PXE_BASECODE_DEVICE
*Private
1130 EFI_BIS_PROTOCOL
*BisPtr
;
1131 BIS_APPLICATION_HANDLE BisAppHandle
;
1132 EFI_BIS_DATA
*BisDataSigInfo
;
1134 BisPtr
= PxebcBisStart (Private
, &BisAppHandle
, &BisDataSigInfo
);
1136 if (BisPtr
== NULL
) {
1140 PxebcBisStop (BisPtr
, BisAppHandle
, BisDataSigInfo
);
1145 static VOID
*BCNotifyReg
;
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
;
1205 // Fail if IPv6 is requested and not supported.
1208 DEBUG ((DEBUG_WARN
, "\nBcStart() IPv6 is not supported.\n"));
1209 EfiReleaseLock (&Private
->Lock
);
1210 return EFI_UNSUPPORTED
;
1214 // Setup shortcuts to SNP protocol and data structure.
1216 SnpPtr
= Private
->SimpleNetwork
;
1217 SnpModePtr
= SnpPtr
->Mode
;
1220 // Start and initialize SNP.
1222 if (SnpModePtr
->State
== EfiSimpleNetworkStopped
) {
1223 StatCode
= (*SnpPtr
->Start
) (SnpPtr
);
1225 if (SnpModePtr
->State
!= EfiSimpleNetworkStarted
) {
1226 DEBUG ((DEBUG_WARN
, "\nBcStart() Could not start SNP.\n"));
1227 EfiReleaseLock (&Private
->Lock
);
1232 // acquire memory for mode and transmit/receive buffers
1234 if (SnpModePtr
->State
== EfiSimpleNetworkStarted
) {
1235 StatCode
= (*SnpPtr
->Initialize
) (SnpPtr
, 0, 0);
1237 if (SnpModePtr
->State
!= EfiSimpleNetworkInitialized
) {
1238 DEBUG ((DEBUG_WARN
, "\nBcStart() Could not initialize SNP."));
1239 EfiReleaseLock (&Private
->Lock
);
1246 DEBUG ((DEBUG_INFO
, "\nBC Start()"));
1249 "\nSnpModePtr->State %Xh",
1254 "\nSnpModePtr->HwAddressSize %Xh",
1255 SnpModePtr
->HwAddressSize
)
1259 "\nSnpModePtr->MediaHeaderSize %Xh",
1260 SnpModePtr
->MediaHeaderSize
)
1264 "\nSnpModePtr->MaxPacketSize %Xh",
1265 SnpModePtr
->MaxPacketSize
)
1269 "\nSnpModePtr->MacAddressChangeable %Xh",
1270 SnpModePtr
->MacAddressChangeable
)
1274 "\nSnpModePtr->MultipleTxSupported %Xh",
1275 SnpModePtr
->MultipleTxSupported
)
1279 "\nSnpModePtr->CurrentAddress %Xh",
1280 *((UINTN
*)&SnpModePtr
->CurrentAddress
))
1284 "\nSnpModePtr->BroadcastAddress %Xh",
1285 *((UINTN
*)&SnpModePtr
->BroadcastAddress
))
1289 "\nSnpModePtr->PermanentAddress %Xh",
1290 *((UINTN
*)&SnpModePtr
->PermanentAddress
))
1294 "\nSnpModePtr->NvRamSize %Xh",
1295 SnpModePtr
->NvRamSize
)
1299 "\nSnpModePtr->NvRamAccessSize %Xh",
1300 SnpModePtr
->NvRamAccessSize
)
1304 "\nSnpModePtr->ReceiveFilterMask %Xh",
1305 SnpModePtr
->ReceiveFilterMask
)
1309 "\nSnpModePtr->ReceiveFilterSetting %Xh",
1310 SnpModePtr
->ReceiveFilterSetting
)
1314 "\nSnpModePtr->MCastFilterCount %Xh",
1315 SnpModePtr
->MCastFilterCount
)
1319 "\nSnpModePtr->MCastFilter %Xh",
1320 SnpModePtr
->MCastFilter
)
1324 "\nSnpModePtr->IfType %Xh",
1329 "\nSnpModePtr->MediaPresentSupported %Xh",
1330 SnpModePtr
->MediaPresentSupported
)
1334 "\nSnpModePtr->MediaPresent %Xh",
1335 SnpModePtr
->MediaPresent
)
1339 // If media check is supported and there is no media,
1340 // return error to caller.
1342 if (SnpModePtr
->MediaPresentSupported
&& !SnpModePtr
->MediaPresent
) {
1343 DEBUG ((DEBUG_WARN
, "\nBcStart() Media not present.\n"));
1344 EfiReleaseLock (&Private
->Lock
);
1345 return EFI_NO_MEDIA
;
1348 // Allocate Tx/Rx buffers
1350 Status
= gBS
->AllocatePool (
1351 EfiBootServicesData
,
1352 BUFFER_ALLOCATE_SIZE
,
1353 &Private
->TransmitBufferPtr
1356 if (!EFI_ERROR (Status
)) {
1357 ZeroMem (Private
->TransmitBufferPtr
, BUFFER_ALLOCATE_SIZE
);
1359 DEBUG ((DEBUG_NET
, "\nBcStart() Could not alloc TxBuf.\n"));
1360 EfiReleaseLock (&Private
->Lock
);
1361 return EFI_OUT_OF_RESOURCES
;
1364 Status
= gBS
->AllocatePool (
1365 EfiBootServicesData
,
1366 BUFFER_ALLOCATE_SIZE
,
1367 &Private
->ReceiveBufferPtr
1370 if (!EFI_ERROR (Status
)) {
1371 ZeroMem (Private
->ReceiveBufferPtr
, BUFFER_ALLOCATE_SIZE
);
1373 DEBUG ((DEBUG_NET
, "\nBcStart() Could not alloc RxBuf.\n"));
1374 gBS
->FreePool (Private
->TransmitBufferPtr
);
1375 EfiReleaseLock (&Private
->Lock
);
1376 return EFI_OUT_OF_RESOURCES
;
1379 Status
= gBS
->AllocatePool (
1380 EfiBootServicesData
,
1382 &Private
->TftpErrorBuffer
1385 if (EFI_ERROR (Status
)) {
1386 gBS
->FreePool (Private
->ReceiveBufferPtr
);
1387 gBS
->FreePool (Private
->TransmitBufferPtr
);
1388 EfiReleaseLock (&Private
->Lock
);
1389 return EFI_OUT_OF_RESOURCES
;
1392 Status
= gBS
->AllocatePool (EfiBootServicesData
, 256, &Private
->TftpAckBuffer
);
1394 if (EFI_ERROR (Status
)) {
1395 gBS
->FreePool (Private
->TftpErrorBuffer
);
1396 gBS
->FreePool (Private
->ReceiveBufferPtr
);
1397 gBS
->FreePool (Private
->TransmitBufferPtr
);
1398 EfiReleaseLock (&Private
->Lock
);
1399 return EFI_OUT_OF_RESOURCES
;
1402 // Initialize private BaseCode instance data
1405 Private
->RandomPort
= (UINT16
) (Private
->RandomPort
+ PXE_RND_PORT_LOW
+ Random (Private
));
1406 } while (Private
->RandomPort
< PXE_RND_PORT_LOW
);
1408 Private
->Igmpv1TimeoutEvent
= NULL
;
1409 Private
->UseIgmpv1Reporting
= TRUE
;
1410 Private
->IpLength
= IP_ADDRESS_LENGTH (Private
->EfiBc
.Mode
);
1413 // Initialize Mode structure
1415 ZeroMem (Private
->EfiBc
.Mode
, sizeof (EFI_PXE_BASE_CODE_MODE
));
1417 // check for callback protocol and set boolean
1419 SetMakeCallback (Private
);
1420 Private
->EfiBc
.Mode
->Started
= TRUE
;
1421 Private
->EfiBc
.Mode
->TTL
= DEFAULT_TTL
;
1422 Private
->EfiBc
.Mode
->ToS
= DEFAULT_ToS
;
1423 Private
->EfiBc
.Mode
->UsingIpv6
= UseIPv6
;
1426 // Set to PXE_TRUE by the BC constructor if this BC implementation
1429 Private
->EfiBc
.Mode
->Ipv6Supported
= SUPPORT_IPV6
;
1431 Private
->EfiBc
.Mode
->Ipv6Available
= FALSE
;
1433 // Set to TRUE by the BC constructor if this BC implementation
1436 Private
->EfiBc
.Mode
->BisSupported
= TRUE
;
1437 Private
->EfiBc
.Mode
->BisDetected
= PxebcBisDetect (Private
);
1440 // This field is set to PXE_TRUE by the BC Start() function. When this
1441 // field is PXE_TRUE, ARP packets are sent as needed to get IP and MAC
1442 // addresses. This can cause unexpected delays in the DHCP(), Discover()
1443 // and MTFTP() functions. Setting this to PXE_FALSE will cause these
1444 // functions to fail if the required IP/MAC information is not in the
1445 // ARP cache. The value of this field can be changed by an application
1448 Private
->EfiBc
.Mode
->AutoArp
= TRUE
;
1451 // Unlock the instance data
1453 EfiReleaseLock (&Private
->Lock
);
1459 Stop the BaseCode protocol, Simple Network protocol and UNDI.
1461 @param Private Pointer to Pxe BaseCode Protocol
1463 @retval 0 Successfully stopped
1470 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
1474 // Lock the instance data
1476 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1477 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
1478 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
1479 EFI_STATUS StatCode
;
1480 PXE_BASECODE_DEVICE
*Private
;
1482 StatCode
= EFI_SUCCESS
;
1485 DEBUG ((DEBUG_ERROR
, "BC *This pointer == NULL"));
1486 return EFI_INVALID_PARAMETER
;
1489 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1491 if (Private
== NULL
) {
1492 DEBUG ((DEBUG_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1493 return EFI_INVALID_PARAMETER
;
1496 EfiAcquireLock (&Private
->Lock
);
1498 PxebcMode
= Private
->EfiBc
.Mode
;
1499 SnpPtr
= Private
->SimpleNetwork
;
1500 SnpModePtr
= SnpPtr
->Mode
;
1505 StatCode
= EFI_NOT_STARTED
;
1507 if (SnpModePtr
->State
== EfiSimpleNetworkInitialized
) {
1508 StatCode
= (*SnpPtr
->Shutdown
) (SnpPtr
);
1511 if (SnpModePtr
->State
== EfiSimpleNetworkStarted
) {
1512 StatCode
= (*SnpPtr
->Stop
) (SnpPtr
);
1515 if (Private
->TransmitBufferPtr
!= NULL
) {
1516 gBS
->FreePool (Private
->TransmitBufferPtr
);
1517 Private
->TransmitBufferPtr
= NULL
;
1520 if (Private
->ReceiveBufferPtr
!= NULL
) {
1521 gBS
->FreePool (Private
->ReceiveBufferPtr
);
1522 Private
->ReceiveBufferPtr
= NULL
;
1525 if (Private
->ArpBuffer
!= NULL
) {
1526 gBS
->FreePool (Private
->ArpBuffer
);
1527 Private
->ArpBuffer
= NULL
;
1530 if (Private
->TftpErrorBuffer
!= NULL
) {
1531 gBS
->FreePool (Private
->TftpErrorBuffer
);
1532 Private
->TftpErrorBuffer
= NULL
;
1535 if (Private
->TftpAckBuffer
!= NULL
) {
1536 gBS
->FreePool (Private
->TftpAckBuffer
);
1537 Private
->TftpAckBuffer
= NULL
;
1540 if (Private
->Igmpv1TimeoutEvent
!= NULL
) {
1541 gBS
->CloseEvent (Private
->Igmpv1TimeoutEvent
);
1542 Private
->Igmpv1TimeoutEvent
= NULL
;
1545 Private
->FileSize
= 0;
1547 if (!Private
->EfiBc
.Mode
->Started
) {
1548 StatCode
= EFI_NOT_STARTED
;
1550 Private
->EfiBc
.Mode
->Started
= FALSE
;
1554 // Unlock the instance data
1556 EfiReleaseLock (&Private
->Lock
);
1560 const IPV4_ADDR AllSystemsGroup
= { 224, 0, 0, 1 };
1564 Set up the IP filter
1566 @param Private Pointer to Pxe BaseCode Protocol
1567 @param Filter Pointer to the filter
1569 @retval 0 Successfully set the filter
1575 IN PXE_BASECODE_DEVICE
*Private
,
1576 IN EFI_PXE_BASE_CODE_IP_FILTER
*Filter
1579 EFI_STATUS StatCode
;
1580 EFI_MAC_ADDRESS MACadds
[PXE_IP_FILTER_SIZE
];
1581 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1582 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
1583 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
1589 PxebcMode
= Private
->EfiBc
.Mode
;
1590 SnpPtr
= Private
->SimpleNetwork
;
1591 SnpModePtr
= SnpPtr
->Mode
;
1594 // validate input parameters
1595 // must have a filter
1596 // must not have any extra filter bits set
1598 if (Filter
== NULL
||
1599 (Filter
->Filters
&~FILTER_BITS
)
1601 // must not have a count which is too large or with no IP list
1604 (Filter
->IpCnt
&& (!Filter
->IpList
|| Filter
->IpCnt
> PXE_IP_FILTER_SIZE
))
1606 // must not have incompatible filters - promiscuous incompatible with anything else
1610 (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) &&
1611 ((Filter
->Filters
&~EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) || Filter
->IpCnt
)
1614 DEBUG ((DEBUG_INFO
, "\nIpFilter() Exit #1"));
1615 return EFI_INVALID_PARAMETER
;
1618 // promiscuous multicast incompatible with multicast in IP list
1620 if (Filter
->IpCnt
&& (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
)) {
1621 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1622 if (IS_MULTICAST (&Filter
->IpList
[Index
])) {
1623 DEBUG ((DEBUG_INFO
, "\nIpFilter() Exit #2"));
1624 return EFI_INVALID_PARAMETER
;
1629 // leave groups for all those multicast which are no longer enabled
1631 for (Index
= 0; Index
< PxebcMode
->IpFilter
.IpCnt
; ++Index
) {
1632 if (!IS_MULTICAST (&PxebcMode
->IpFilter
.IpList
[Index
])) {
1636 for (Index2
= 0; Index2
< Filter
->IpCnt
; ++Index2
) {
1637 if (!CompareMem (&PxebcMode
->IpFilter
.IpList
[Index
], &Filter
->IpList
[Index2
], IP_ADDRESS_LENGTH (PxebcMode
))) {
1645 // if we didn't find it, remove from group
1647 if (Index2
== Filter
->IpCnt
) {
1648 IgmpLeaveGroup (Private
, &PxebcMode
->IpFilter
.IpList
[Index
]);
1652 // set enable bits, convert multicast ip adds, join groups
1653 // allways leave receive broadcast enabled at hardware layer
1657 if (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) {
1658 Enable
= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
1660 if (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
) {
1661 Enable
= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
1663 Enable
= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
1665 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1666 PxebcMode
->IpFilter
.IpList
[Index
] = Filter
->IpList
[Index
];
1668 if (IS_MULTICAST (&Filter
->IpList
[Index
])) {
1669 EFI_IP_ADDRESS
*TmpIp
;
1671 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
1674 // if this is the first group, add the all systems group to mcast list
1678 TmpIp
= (EFI_IP_ADDRESS
*) &AllSystemsGroup
;
1681 TmpIp
= (EFI_IP_ADDRESS
*) &Filter
->IpList
[Index
];
1684 // get MAC address of IP
1686 StatCode
= (*SnpPtr
->MCastIpToMac
) (SnpPtr
, PxebcMode
->UsingIpv6
, TmpIp
, &MACadds
[Index2
++]);
1688 if (EFI_ERROR (StatCode
)) {
1691 "\nIpFilter() Exit #2 %Xh (%r)",
1698 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
1703 if (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
) {
1704 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
1708 // if nothing changed, just return
1712 "\nsnp->ReceiveFilterSetting == %Xh Filter->IpCnt == %Xh",
1713 SnpModePtr
->ReceiveFilterSetting
,
1717 if (SnpModePtr
->ReceiveFilterSetting
== Enable
&& !Filter
->IpCnt
) {
1718 DEBUG ((DEBUG_INFO
, "\nIpFilter() Exit #4"));
1722 // disable those currently set but not set in new filter
1724 Disable
= SnpModePtr
->ReceiveFilterSetting
&~Enable
;
1726 StatCode
= SnpPtr
->ReceiveFilters (SnpPtr
, Enable
, Disable
, FALSE
, Index2
, MACadds
);
1728 PxebcMode
->IpFilter
.IpCnt
= Filter
->IpCnt
;
1731 // join groups for all multicast in list
1733 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1734 if (IS_MULTICAST (&Filter
->IpList
[Index
])) {
1735 IgmpJoinGroup (Private
, &Filter
->IpList
[Index
]);
1739 DEBUG ((DEBUG_INFO
, "\nIpFilter() Exit #5 %Xh (%r)", StatCode
, StatCode
));
1748 @param Private Pointer to Pxe BaseCode Protocol
1749 @param Filter Pointer to the filter
1751 @retval 0 Successfully set the filter
1758 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1759 IN EFI_PXE_BASE_CODE_IP_FILTER
*Filter
1762 EFI_STATUS StatCode
;
1763 PXE_BASECODE_DEVICE
*Private
;
1766 // Lock the instance data and make sure started
1768 StatCode
= EFI_SUCCESS
;
1771 DEBUG ((DEBUG_ERROR
, "BC *This pointer == NULL"));
1772 return EFI_INVALID_PARAMETER
;
1775 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1777 if (Private
== NULL
) {
1778 DEBUG ((DEBUG_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1779 return EFI_INVALID_PARAMETER
;
1782 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1783 if ((Filter
->IpList
[Index
].Addr
[0]) == BROADCAST_IPv4
) {
1785 // The IP is a broadcast address.
1787 return EFI_INVALID_PARAMETER
;
1791 EfiAcquireLock (&Private
->Lock
);
1793 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
1794 DEBUG ((DEBUG_ERROR
, "BC was not started."));
1795 EfiReleaseLock (&Private
->Lock
);
1796 return EFI_NOT_STARTED
;
1799 if (Filter
== NULL
) {
1800 return EFI_INVALID_PARAMETER
;
1805 StatCode
= IpFilter (Private
, Filter
);
1808 // Unlock the instance data
1810 EfiReleaseLock (&Private
->Lock
);
1816 Set the Base Code behavior parameters
1818 @param This Pointer to Pxe BaseCode Protocol
1819 @param AutoArpPtr Boolean to do ARP stuff
1820 @param SendGuidPtr Boolean whether or not to send GUID info
1821 @param TimeToLivePtr Value for Total time to live
1822 @param TypeOfServicePtr Value for Type of Service
1823 @param MakeCallbackPtr Boolean to determine if we make callbacks
1825 @retval 0 Successfully set the parameters
1832 EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1833 BOOLEAN
*AutoArpPtr
,
1834 BOOLEAN
*SendGuidPtr
,
1835 UINT8
*TimeToLivePtr
,
1836 UINT8
*TypeOfServicePtr
,
1837 BOOLEAN
*MakeCallbackPtr
1840 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1842 UINT8
*SerialNumberPtr
;
1843 EFI_STATUS StatCode
;
1844 PXE_BASECODE_DEVICE
*Private
;
1847 // Lock the instance data and make sure started
1849 StatCode
= EFI_SUCCESS
;
1852 DEBUG ((DEBUG_ERROR
, "BC *This pointer == NULL"));
1853 return EFI_INVALID_PARAMETER
;
1856 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1858 if (Private
== NULL
) {
1859 DEBUG ((DEBUG_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1860 return EFI_INVALID_PARAMETER
;
1863 EfiAcquireLock (&Private
->Lock
);
1865 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
1866 DEBUG ((DEBUG_ERROR
, "BC was not started."));
1867 EfiReleaseLock (&Private
->Lock
);
1868 return EFI_NOT_STARTED
;
1871 DEBUG ((DEBUG_INFO
, "\nSetParameters() Entry. "));
1873 PxebcMode
= Private
->EfiBc
.Mode
;
1874 StatCode
= EFI_SUCCESS
;
1876 if (SendGuidPtr
!= NULL
) {
1878 if (PxeBcLibGetSmbiosSystemGuidAndSerialNumber (&TmpGuid
, &SerialNumberPtr
) != EFI_SUCCESS
) {
1879 return EFI_INVALID_PARAMETER
;
1884 if (MakeCallbackPtr
!= NULL
) {
1885 if (*MakeCallbackPtr
) {
1886 if (!SetMakeCallback (Private
)) {
1887 return EFI_INVALID_PARAMETER
;
1891 PxebcMode
->MakeCallbacks
= *MakeCallbackPtr
;
1894 if (AutoArpPtr
!= NULL
) {
1895 PxebcMode
->AutoArp
= *AutoArpPtr
;
1898 if (SendGuidPtr
!= NULL
) {
1899 PxebcMode
->SendGUID
= *SendGuidPtr
;
1902 if (TimeToLivePtr
!= NULL
) {
1903 PxebcMode
->TTL
= *TimeToLivePtr
;
1906 if (TypeOfServicePtr
!= NULL
) {
1907 PxebcMode
->ToS
= *TypeOfServicePtr
;
1910 // Unlock the instance data
1912 DEBUG ((DEBUG_INFO
, "\nSetparameters() Exit = %xh ", StatCode
));
1914 EfiReleaseLock (&Private
->Lock
);
1918 // //////////////////////////////////////////////////////////
1920 // BC Set Station IP Routine
1924 Set the station IP address
1926 @param This Pointer to Pxe BaseCode Protocol
1927 @param StationIpPtr Pointer to the requested IP address to set in base
1929 @param SubnetMaskPtr Pointer to the requested subnet mask for the base
1932 @retval EFI_SUCCESS Successfully set the parameters
1933 @retval EFI_NOT_STARTED BC has not started
1939 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1940 IN EFI_IP_ADDRESS
*StationIpPtr
,
1941 IN EFI_IP_ADDRESS
*SubnetMaskPtr
1944 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1945 EFI_STATUS StatCode
;
1946 PXE_BASECODE_DEVICE
*Private
;
1950 // Lock the instance data and make sure started
1952 StatCode
= EFI_SUCCESS
;
1955 DEBUG ((DEBUG_ERROR
, "BC *This pointer == NULL"));
1956 return EFI_INVALID_PARAMETER
;
1959 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1961 if (Private
== NULL
) {
1962 DEBUG ((DEBUG_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1963 return EFI_INVALID_PARAMETER
;
1966 EfiAcquireLock (&Private
->Lock
);
1968 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
1969 DEBUG ((DEBUG_ERROR
, "BC was not started."));
1970 StatCode
= EFI_NOT_STARTED
;
1974 PxebcMode
= Private
->EfiBc
.Mode
;
1976 if (!Private
->GoodStationIp
&& ((StationIpPtr
== NULL
) || (SubnetMaskPtr
== NULL
))) {
1978 // It's not allowed to only set one of the two addresses while there isn't a previous
1979 // GOOD address configuration.
1981 StatCode
= EFI_INVALID_PARAMETER
;
1985 if (SubnetMaskPtr
!= NULL
) {
1986 SubnetMask
= SubnetMaskPtr
->Addr
[0];
1988 if (SubnetMask
& (SubnetMask
+ 1)) {
1990 // the subnet mask is valid if it's with leading continuous 1 bits.
1992 StatCode
= EFI_INVALID_PARAMETER
;
1996 SubnetMaskPtr
= &PxebcMode
->SubnetMask
;
1997 SubnetMask
= SubnetMaskPtr
->Addr
[0];
2000 if (StationIpPtr
== NULL
) {
2001 StationIpPtr
= &PxebcMode
->StationIp
;
2004 if (!IS_INADDR_UNICAST (StationIpPtr
) ||
2005 ((StationIpPtr
->Addr
[0] | SubnetMask
) == BROADCAST_IPv4
)) {
2007 // The station IP is not a unicast address.
2009 StatCode
= EFI_INVALID_PARAMETER
;
2013 PxebcMode
->StationIp
= *StationIpPtr
;
2014 PxebcMode
->SubnetMask
= *SubnetMaskPtr
;
2015 Private
->GoodStationIp
= TRUE
;
2019 // Unlock the instance data
2021 EfiReleaseLock (&Private
->Lock
);
2026 EFI_DRIVER_BINDING_PROTOCOL mPxeBcDriverBinding
= {
2027 PxeBcDriverSupported
,
2037 Test to see if this driver supports Controller. Any Controller
2038 than contains a Snp protocol can be supported.
2040 @param This Protocol instance pointer.
2041 @param Controller Handle of device to test.
2042 @param RemainingDevicePath Not used.
2044 @retval EFI_SUCCESS This driver supports this device.
2045 @retval EFI_ALREADY_STARTED This driver is already running on this device.
2046 @retval other This driver does not support this device.
2051 PxeBcDriverSupported (
2052 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2053 IN EFI_HANDLE Controller
,
2054 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
2058 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
2060 Status
= gBS
->OpenProtocol (
2062 &gEfiDevicePathProtocolGuid
,
2064 This
->DriverBindingHandle
,
2066 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
2069 if (EFI_ERROR (Status
)) {
2073 Status
= gBS
->OpenProtocol (
2075 &gEfiSimpleNetworkProtocolGuid
,
2077 This
->DriverBindingHandle
,
2079 EFI_OPEN_PROTOCOL_BY_DRIVER
2081 if (EFI_ERROR (Status
)) {
2085 gBS
->CloseProtocol (
2087 &gEfiSimpleNetworkProtocolGuid
,
2088 This
->DriverBindingHandle
,
2097 Start the Base code driver.
2099 @param This Protocol instance pointer.
2100 @param Controller Handle of device to test.
2101 @param RemainingDevicePath Not used.
2103 @retval EFI_SUCCESS This driver supports this device.
2104 @retval EFI_ALREADY_STARTED This driver is already running on this device.
2105 @retval other This driver does not support this device.
2111 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2112 IN EFI_HANDLE Controller
,
2113 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
2117 PXE_BASECODE_DEVICE
*Private
;
2118 LOADFILE_DEVICE
*pLF
;
2121 // Allocate structures needed by BaseCode and LoadFile protocols.
2123 Private
= AllocateZeroPool (sizeof (PXE_BASECODE_DEVICE
));
2125 if (Private
== NULL
) {
2126 DEBUG ((EFI_D_NET
, "\nBcNotifySnp() Could not alloc PXE_BASECODE_DEVICE structure.\n"));
2127 return EFI_OUT_OF_RESOURCES
;
2130 pLF
= AllocateZeroPool (sizeof (LOADFILE_DEVICE
));
2132 DEBUG ((EFI_D_NET
, "\nBcNotifySnp() Could not alloc LOADFILE_DEVICE structure.\n"));
2134 return EFI_OUT_OF_RESOURCES
;
2137 Private
->EfiBc
.Mode
= AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_MODE
));
2138 if (Private
->EfiBc
.Mode
== NULL
) {
2139 DEBUG ((EFI_D_NET
, "\nBcNotifySnp() Could not alloc Mode structure.\n"));
2142 return EFI_OUT_OF_RESOURCES
;
2145 // Lock access, just in case
2147 EfiInitializeLock (&Private
->Lock
, TPL_CALLBACK
);
2148 EfiAcquireLock (&Private
->Lock
);
2150 EfiInitializeLock (&pLF
->Lock
, TPL_CALLBACK
);
2151 EfiAcquireLock (&pLF
->Lock
);
2154 // Initialize PXE structure
2157 // First initialize the internal 'private' data that the application
2160 Private
->Signature
= PXE_BASECODE_DEVICE_SIGNATURE
;
2161 Private
->Handle
= Controller
;
2164 // Get the NII interface
2166 Status
= gBS
->OpenProtocol (
2168 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
2169 (VOID
**) &Private
->NiiPtr
,
2170 This
->DriverBindingHandle
,
2172 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2175 if (EFI_ERROR (Status
)) {
2176 Status
= gBS
->OpenProtocol (
2178 &gEfiNetworkInterfaceIdentifierProtocolGuid
,
2179 (VOID
**) &Private
->NiiPtr
,
2180 This
->DriverBindingHandle
,
2182 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2185 if (EFI_ERROR (Status
)) {
2190 // Get the Snp interface
2192 Status
= gBS
->OpenProtocol (
2194 &gEfiSimpleNetworkProtocolGuid
,
2195 (VOID
**) &Private
->SimpleNetwork
,
2196 This
->DriverBindingHandle
,
2198 EFI_OPEN_PROTOCOL_BY_DRIVER
2201 if (EFI_ERROR (Status
)) {
2206 // Next, initialize the external 'public' data that
2207 // the application does see.
2209 Private
->EfiBc
.Revision
= EFI_PXE_BASE_CODE_PROTOCOL_REVISION
;
2210 Private
->EfiBc
.Start
= BcStart
;
2211 Private
->EfiBc
.Stop
= BcStop
;
2212 Private
->EfiBc
.Dhcp
= BcDhcp
;
2213 Private
->EfiBc
.Discover
= BcDiscover
;
2214 Private
->EfiBc
.Mtftp
= BcMtftp
;
2215 Private
->EfiBc
.UdpWrite
= BcUdpWrite
;
2216 Private
->EfiBc
.UdpRead
= BcUdpRead
;
2217 Private
->EfiBc
.Arp
= BcArp
;
2218 Private
->EfiBc
.SetIpFilter
= BcIpFilter
;
2219 Private
->EfiBc
.SetParameters
= BcSetParameters
;
2220 Private
->EfiBc
.SetStationIp
= BcSetStationIP
;
2221 Private
->EfiBc
.SetPackets
= BcSetPackets
;
2224 // Initialize BaseCode Mode structure
2226 Private
->EfiBc
.Mode
->Started
= FALSE
;
2227 Private
->EfiBc
.Mode
->TTL
= DEFAULT_TTL
;
2228 Private
->EfiBc
.Mode
->ToS
= DEFAULT_ToS
;
2229 Private
->EfiBc
.Mode
->UsingIpv6
= FALSE
;
2230 Private
->EfiBc
.Mode
->AutoArp
= TRUE
;
2233 // Set to PXE_TRUE by the BC constructor if this BC
2234 // implementation supports IPv6.
2236 Private
->EfiBc
.Mode
->Ipv6Supported
= SUPPORT_IPV6
;
2239 Private
->EfiBc
.Mode
->Ipv6Available
= Private
->NiiPtr
->Ipv6Supported
;
2241 Private
->EfiBc
.Mode
->Ipv6Available
= FALSE
;
2244 // Set to TRUE by the BC constructor if this BC
2245 // implementation supports BIS.
2247 Private
->EfiBc
.Mode
->BisSupported
= TRUE
;
2248 Private
->EfiBc
.Mode
->BisDetected
= PxebcBisDetect (Private
);
2251 // Initialize LoadFile structure.
2253 pLF
->Signature
= LOADFILE_DEVICE_SIGNATURE
;
2254 pLF
->LoadFile
.LoadFile
= LoadFile
;
2255 pLF
->Private
= Private
;
2258 // Install protocol interfaces.
2260 Status
= gBS
->InstallMultipleProtocolInterfaces (
2262 &gEfiPxeBaseCodeProtocolGuid
,
2264 &gEfiLoadFileProtocolGuid
,
2269 if (EFI_ERROR (Status
)) {
2270 gBS
->CloseProtocol (
2272 &gEfiSimpleNetworkProtocolGuid
,
2273 This
->DriverBindingHandle
,
2282 EfiReleaseLock (&pLF
->Lock
);
2283 EfiReleaseLock (&Private
->Lock
);
2287 gBS
->FreePool (Private
->EfiBc
.Mode
);
2288 gBS
->FreePool (Private
);
2289 gBS
->FreePool (pLF
);
2295 Stop the Base code driver.
2297 @param This Protocol instance pointer.
2298 @param Controller Handle of device to test.
2299 @param NumberOfChildren Not used
2300 @param ChildHandleBuffer Not used
2302 @retval EFI_SUCCESS This driver supports this device.
2303 @retval EFI_ALREADY_STARTED This driver is already running on this device.
2304 @retval other This driver does not support this device.
2310 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2311 IN EFI_HANDLE Controller
,
2312 IN UINTN NumberOfChildren
,
2313 IN EFI_HANDLE
*ChildHandleBuffer
2317 EFI_LOAD_FILE_PROTOCOL
*LfProtocol
;
2318 LOADFILE_DEVICE
*LoadDevice
;
2321 // Get our context back.
2323 Status
= gBS
->OpenProtocol (
2325 &gEfiLoadFileProtocolGuid
,
2326 (VOID
**) &LfProtocol
,
2327 This
->DriverBindingHandle
,
2329 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2332 if (EFI_ERROR (Status
)) {
2333 return EFI_UNSUPPORTED
;
2336 LoadDevice
= EFI_LOAD_FILE_DEV_FROM_THIS (LfProtocol
);
2338 Status
= gBS
->UninstallMultipleProtocolInterfaces (
2340 &gEfiLoadFileProtocolGuid
,
2341 &LoadDevice
->LoadFile
,
2342 &gEfiPxeBaseCodeProtocolGuid
,
2343 &LoadDevice
->Private
->EfiBc
,
2347 if (!EFI_ERROR (Status
)) {
2349 Status
= gBS
->CloseProtocol (
2351 &gEfiSimpleNetworkProtocolGuid
,
2352 This
->DriverBindingHandle
,
2356 gBS
->FreePool (LoadDevice
->Private
->EfiBc
.Mode
);
2357 gBS
->FreePool (LoadDevice
->Private
);
2358 gBS
->FreePool (LoadDevice
);
2366 Initialize the base code drivers and install the driver binding
2368 Standard EFI Image Entry
2370 @retval EFI_SUCCESS This driver was successfully bound
2375 InitializeBCDriver (
2376 IN EFI_HANDLE ImageHandle
,
2377 IN EFI_SYSTEM_TABLE
*SystemTable
2383 // Initialize EFI library
2385 Status
= EfiLibInstallAllDriverProtocols (
2388 &mPxeBcDriverBinding
,
2396 OptionsStrucInit ();