2 Copyright (c) 2006, Intel Corporation
3 All rights reserved. This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution. The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
25 PxeBcDriverSupported (
26 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
27 IN EFI_HANDLE Controller
,
28 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
34 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
35 IN EFI_HANDLE Controller
,
36 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
42 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
43 IN EFI_HANDLE Controller
,
44 IN UINTN NumberOfChildren
,
45 IN EFI_HANDLE
*ChildHandleBuffer
60 Convert number to ASCII value
63 Number - Numeric value to convert to decimal ASCII value.
64 Buffer - Buffer to place ASCII version of the Number
65 Length - Length of Buffer.
75 Remainder
= Number
% 10;
77 Buffer
[Length
] = (UINT8
) ('0' + Remainder
);
89 Convert number to decimal ASCII value at Buffer location
92 Number - Numeric value to convert to decimal ASCII value.
93 Buffer - Buffer to place ASCII version of the Number
104 CvtNum (Number
, BuffArray
, 30);
106 for (Index
= 0; Index
< 30; ++Index
) {
107 if (BuffArray
[Index
] != '0') {
112 CopyMem (Buffer
, BuffArray
+ Index
, 31 - Index
);
122 Convert ASCII numeric string to a UINTN value
125 Number - Numeric value to convert to decimal ASCII value.
126 Buffer - Buffer to place ASCII version of the Number
129 Value - UINTN value of the ASCII string.
137 Character
= *Buffer
++;
139 Value
= Value
* 10 + Character
- '0';
140 Character
= *Buffer
++;
153 Convert ASCII numeric string to a UINTN value
156 Number - Numeric value to convert to decimal ASCII value.
157 Buffer - Buffer to place ASCII version of the Number
160 Value - UINTN value of the ASCII string.
168 while ((Character
= *Buffer
++) != '\0') {
169 Value
= MultU64x32 (Value
, 10) + (Character
- '0');
175 // random number generator
177 #define RANDOM_MULTIPLIER 2053
178 #define RANDOM_ADD_IN_VALUE 19
182 IN PXE_BASECODE_DEVICE
*Private
,
183 IN UINT16 InitialSeed
188 Initialize the Seed for the random number generator
197 if (Private
!= NULL
) {
198 Private
->RandomSeed
= InitialSeed
;
204 IN PXE_BASECODE_DEVICE
*Private
209 Generate and return a pseudo-random number
214 Number - UINT16 random number
220 if (Private
!= NULL
) {
221 Number
= -(INTN
) Private
->RandomSeed
* RANDOM_MULTIPLIER
+ RANDOM_ADD_IN_VALUE
;
223 return Private
->RandomSeed
= (UINT16
) Number
;
229 // calculate the internet checksum (RFC 1071)
230 // return 16 bit ones complement of ones complement sum of 16 bit words
240 Calculate the internet checksum (see RFC 1071)
243 Packet - Buffer which contains the data to be checksummed
244 Length - Length to be checksummed
247 Checksum - Returns the 16 bit ones complement of
248 ones complement sum of 16 bit words
256 Odd
= (UINT8
) (Length
& 1);
263 Sum
+= *(UINT8
*) Packet
;
266 Sum
= (Sum
& 0xffff) + (Sum
>> 16);
268 // in case above carried
272 return (UINT16
) (~ (UINT16
) Sum
);
285 Calculate the internet checksum (see RFC 1071)
286 on a non contiguous header and data
289 Header - Buffer which contains the data to be checksummed
290 HeaderLen - Length to be checksummed
291 Message - Buffer which contains the data to be checksummed
292 MessageLen - Length to be checksummed
295 Checksum - Returns the 16 bit ones complement of
296 ones complement sum of 16 bit words
302 Sum
= (UINT16
)~IpChecksum (Header
, HeaderLen
);
303 Sum
= Sum
+ (UINT16
)~IpChecksum (Message
, MessageLen
);
305 // in case above carried
309 return (UINT16
) (~ (UINT16
) Sum
);
321 Adjust the internet checksum (see RFC 1071) on a single word update.
324 OldChkSum - Checksum previously calculated
329 Checksum - Returns the 16 bit ones complement of
330 ones complement sum of 16 bit words
336 sum
= ~OldChksum
+ NewWord
- OldWord
;
338 // in case above carried
341 return (UINT16
) (~ (UINT16
) sum
);
347 IN PXE_BASECODE_DEVICE
*Private
352 See if a callback is in play
355 Private - Pointer to Pxe BaseCode Protocol
358 0 - Callbacks are active on the handle
359 1 - Callbacks are not active on the handle
363 Private
->EfiBc
.Mode
->MakeCallbacks
= (BOOLEAN
) (gBS
->HandleProtocol (
365 &gEfiPxeBaseCodeCallbackProtocolGuid
,
366 (VOID
*) &Private
->CallbackProtocolPtr
371 "\nMode->MakeCallbacks == %d ",
372 Private
->EfiBc
.Mode
->MakeCallbacks
)
377 "\nPrivate->CallbackProtocolPtr == %xh ",
378 Private
->CallbackProtocolPtr
)
381 if (Private
->CallbackProtocolPtr
!= NULL
) {
384 "\nCallbackProtocolPtr->Revision = %xh ",
385 Private
->CallbackProtocolPtr
->Revision
)
390 "\nCallbackProtocolPtr->Callback = %xh ",
391 Private
->CallbackProtocolPtr
->Callback
)
395 return Private
->EfiBc
.Mode
->MakeCallbacks
;
398 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
401 IN PXE_BASECODE_DEVICE
*Private
,
402 IN EFI_PXE_BASE_CODE_FUNCTION Function
,
403 IN EFI_EVENT TimeoutEvent
,
404 IN OUT UINTN
*HeaderSizePtr
,
405 IN OUT UINTN
*BufferSizePtr
,
406 IN OUT UINT16
*ProtocolPtr
411 Routine which does an SNP->Receive over a timeout period and doing callbacks
414 Private - Pointer to Pxe BaseCode Protocol
415 Function - What PXE function to callback
416 TimeoutEvent - Timer event that will trigger when we have waited too
417 long for an incoming packet
418 HeaderSizePtr - Pointer to the size of the Header size
419 BufferSizePtr - Pointer to the size of the Buffer size
420 ProtocolPtr - The protocol to sniff for (namely, UDP/etc)
423 0 - Something was returned
424 !0 - Like there was nothing to receive (EFI_TIMEOUT/NOT_READY)
428 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
429 EFI_PXE_CALLBACK CallbackPtr
;
431 EFI_EVENT CallbackEvent
;
434 // Initialize pointer to SNP interface
436 SnpPtr
= Private
->SimpleNetwork
;
439 // Initialize pointer to PxeBc callback routine - if any
441 CallbackPtr
= (Private
->EfiBc
.Mode
->MakeCallbacks
) ? Private
->CallbackProtocolPtr
->Callback
: NULL
;
444 // Create callback event and set timer
446 StatCode
= gBS
->CreateEvent (
454 if (EFI_ERROR (StatCode
)) {
455 return EFI_DEVICE_ERROR
;
459 // every 100 milliseconds
461 StatCode
= gBS
->SetTimer (
467 if (EFI_ERROR (StatCode
)) {
468 gBS
->CloseEvent (CallbackEvent
);
469 return EFI_DEVICE_ERROR
;
472 // Loop until a packet is received or a receive error is detected or
473 // a callback abort is detected or a timeout event occurs.
479 // Check for received packet event.
481 if (!EFI_ERROR (gBS
->CheckEvent (SnpPtr
->WaitForPacket
))) {
483 // Packet should be available. Attempt to read it.
485 *BufferSizePtr
= BUFFER_ALLOCATE_SIZE
;
487 StatCode
= SnpPtr
->Receive (
491 Private
->ReceiveBufferPtr
,
497 if (EFI_ERROR (StatCode
)) {
501 // Packet was received. Make received callback then return.
503 if (CallbackPtr
!= NULL
) {
504 StatCode
= CallbackPtr (
505 Private
->CallbackProtocolPtr
,
508 (UINT32
) *BufferSizePtr
,
509 (EFI_PXE_BASE_CODE_PACKET
*) Private
->ReceiveBufferPtr
512 if (StatCode
!= EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
) {
513 StatCode
= EFI_ABORTED
;
515 StatCode
= EFI_SUCCESS
;
524 // Poll for received packet.
526 *BufferSizePtr
= BUFFER_ALLOCATE_SIZE
;
528 StatCode
= SnpPtr
->Receive (
532 Private
->ReceiveBufferPtr
,
538 if (!EFI_ERROR (StatCode
)) {
540 // Packet was received. Make received callback then return.
542 if (CallbackPtr
!= NULL
) {
543 StatCode
= CallbackPtr (
544 Private
->CallbackProtocolPtr
,
547 (UINT32
) *BufferSizePtr
,
548 (EFI_PXE_BASE_CODE_PACKET
*) Private
->ReceiveBufferPtr
551 if (StatCode
!= EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
) {
552 StatCode
= EFI_ABORTED
;
554 StatCode
= EFI_SUCCESS
;
561 if (StatCode
!= EFI_NOT_READY
) {
566 // Check for callback event.
568 if (!EFI_ERROR (gBS
->CheckEvent (CallbackEvent
))) {
570 // Make periodic callback if callback pointer is initialized.
572 if (CallbackPtr
!= NULL
) {
573 StatCode
= CallbackPtr (
574 Private
->CallbackProtocolPtr
,
582 // Abort if directed to by callback routine.
584 if (StatCode
!= EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
) {
585 StatCode
= EFI_ABORTED
;
591 // Check for timeout event.
593 if (TimeoutEvent
== 0) {
594 StatCode
= EFI_TIMEOUT
;
598 if (!EFI_ERROR (gBS
->CheckEvent (TimeoutEvent
))) {
599 StatCode
= EFI_TIMEOUT
;
603 // Check IGMP timer events.
605 IgmpCheckTimers (Private
);
608 gBS
->CloseEvent (CallbackEvent
);
615 PXE_BASECODE_DEVICE
*Private
,
620 UINT16 MediaProtocol
,
621 IN EFI_PXE_BASE_CODE_FUNCTION Function
626 Routine which does an SNP->Transmit of a buffer
629 Private - Pointer to Pxe BaseCode Protocol
630 HeaderPtr - Pointer to the buffer
631 PacketPtr - Pointer to the packet to send
632 PacketLen - The length of the entire packet to send
633 HardwareAddr - Pointer to the MAC address of the destination
634 MediaProtocol - What type of frame to create (RFC 1700) - IE. Ethernet
635 Function - What PXE function to callback
638 0 - Something was sent
639 !0 - An error was encountered during sending of a packet
643 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
644 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
645 EFI_PXE_CALLBACK CallbackPtr
;
647 EFI_EVENT TimeoutEvent
;
654 CallbackPtr
= Private
->EfiBc
.Mode
->MakeCallbacks
? Private
->CallbackProtocolPtr
->Callback
: 0;
656 SnpPtr
= Private
->SimpleNetwork
;
657 SnpModePtr
= SnpPtr
->Mode
;
660 // clear prior interrupt status
662 StatCode
= SnpPtr
->GetStatus (SnpPtr
, &IntStatus
, 0);
664 if (EFI_ERROR (StatCode
)) {
667 "\nSendPacket() Exit #1 %xh (%r)",
674 Private
->DidTransmit
= FALSE
;
676 if (CallbackPtr
!= NULL
) {
678 Private
->CallbackProtocolPtr
,
683 ) != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
) {
686 "\nSendPacket() Exit #2 %xh (%r)",
694 // put packet in transmit queue
695 // headersize should be zero if not filled in
697 StatCode
= gBS
->CreateEvent (
705 if (EFI_ERROR (StatCode
)) {
708 "Could not create transmit timeout event. %r\n",
711 return EFI_DEVICE_ERROR
;
717 StatCode
= gBS
->SetTimer (
723 if (EFI_ERROR (StatCode
)) {
726 "Could not set transmit timeout event timer. %r\n",
729 gBS
->CloseEvent (TimeoutEvent
);
730 return EFI_DEVICE_ERROR
;
734 StatCode
= SnpPtr
->Transmit (
736 (UINTN
) SnpPtr
->Mode
->MediaHeaderSize
,
737 (UINTN
) (PacketLen
+ SnpPtr
->Mode
->MediaHeaderSize
),
739 &SnpModePtr
->CurrentAddress
,
740 (EFI_MAC_ADDRESS
*) HardwareAddr
,
744 if (StatCode
!= EFI_NOT_READY
) {
748 if (!EFI_ERROR (gBS
->CheckEvent (TimeoutEvent
))) {
749 StatCode
= EFI_TIMEOUT
;
754 gBS
->CloseEvent (TimeoutEvent
);
756 if (EFI_ERROR (StatCode
)) {
759 "\nSendPacket() Exit #3 %xh (%r)",
766 // remove transmit buffer from snp's unused queue
767 // done this way in case someday things are buffered and we don't get it back
770 StatCode
= gBS
->CreateEvent (
778 if (EFI_ERROR (StatCode
)) {
781 "Could not create transmit status timeout event. %r\n",
784 return EFI_DEVICE_ERROR
;
790 StatCode
= gBS
->SetTimer (
796 if (EFI_ERROR (StatCode
)) {
799 "Could not set transmit status timeout event timer. %r\n",
802 gBS
->CloseEvent (TimeoutEvent
);
803 return EFI_DEVICE_ERROR
;
807 StatCode
= SnpPtr
->GetStatus (SnpPtr
, &IntStatus
, &TxBuf
);
809 if (EFI_ERROR (StatCode
)) {
812 "\nSendPacket() Exit #4 %xh (%r)",
819 if (IntStatus
& EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT
) {
820 Private
->DidTransmit
= TRUE
;
827 if (!EFI_ERROR (gBS
->CheckEvent (TimeoutEvent
))) {
828 StatCode
= EFI_TIMEOUT
;
833 gBS
->CloseEvent (TimeoutEvent
);
842 IN PXE_BASECODE_DEVICE
*Private
,
843 OUT BIS_APPLICATION_HANDLE
*BisAppHandle
,
844 OUT OPTIONAL EFI_BIS_DATA
**BisDataSigInfo
848 Locate BIS interface and if found, try to start it.
851 Private := Pointer to PxeBc protocol
852 BisAppHandle := Pointer to BIS application handle storage
853 BisDataSigInfo := Pointer to BIS signature information storage
857 EFI_STATUS EfiStatus
;
858 EFI_HANDLE BisHandleBuffer
;
859 UINTN BisHandleCount
;
860 EFI_BIS_PROTOCOL
*BisPtr
;
861 EFI_BIS_VERSION BisInterfaceVersion
;
862 BOOLEAN BisCheckFlag
;
864 BisHandleCount
= sizeof (EFI_HANDLE
);
865 BisCheckFlag
= FALSE
;
868 // Locate BIS protocol handle (if present).
869 // If BIS protocol handle is not found, return NULL.
871 DEBUG ((EFI_D_INFO
, "\ngBS->LocateHandle() "));
873 EfiStatus
= gBS
->LocateHandle (
875 &gEfiBisProtocolGuid
,
881 if (EFI_ERROR (EfiStatus
)) {
883 // Any error means that there is no BIS.
884 // Note - It could mean that there are more than
885 // one BIS protocols installed, but that scenario
886 // is not yet supported.
890 "\nPxebcBisStart()""\n gBS->LocateHandle() %r (%xh)\n",
898 if (BisHandleCount
!= sizeof BisHandleBuffer
) {
900 // This really should never happen, but I am paranoid.
904 "\nPxebcBisStart() BisHandleCount != %d\n",
905 sizeof BisHandleBuffer
)
911 DEBUG ((EFI_D_INFO
, "BIS handle found."));
914 // Locate BIS protocol interface.
915 // If the BIS protocol interface cannot be found, return NULL.
917 DEBUG ((EFI_D_INFO
, "\ngBS->HandleProtocol() "));
919 EfiStatus
= gBS
->HandleProtocol (
921 &gEfiBisProtocolGuid
,
925 if (EFI_ERROR (EfiStatus
)) {
928 "\nPxebcBisStart()""\n gBS->HandleProtocol() %r (%xh)\n",
936 if (BisPtr
== NULL
) {
938 // This really should never happen.
942 "\nPxebcBisStart()""\n gBS->HandleProtocoL() ""BIS protocol interface pointer is NULL!\n")
948 DEBUG ((EFI_D_INFO
, "BIS protocol interface found."));
951 // Check that all of the BIS API function pointers are not NULL.
953 if (BisPtr
->Initialize
== NULL
||
954 BisPtr
->Shutdown
== NULL
||
955 BisPtr
->Free
== NULL
||
956 BisPtr
->GetBootObjectAuthorizationCertificate
== NULL
||
957 BisPtr
->GetBootObjectAuthorizationCheckFlag
== NULL
||
958 BisPtr
->GetBootObjectAuthorizationUpdateToken
== NULL
||
959 BisPtr
->GetSignatureInfo
== NULL
||
960 BisPtr
->UpdateBootObjectAuthorization
== NULL
||
961 BisPtr
->VerifyBootObject
== NULL
||
962 BisPtr
->VerifyObjectWithCredential
== NULL
967 "\nPxebcBisStart()""\n BIS protocol interface is invalid."
968 "\n At least one BIS protocol function pointer is NULL.\n"
976 // If BIS does not initialize, return NULL.
978 DEBUG ((EFI_D_INFO
, "\nBisPtr->Initialize() "));
980 BisInterfaceVersion
.Major
= BIS_VERSION_1
;
982 EfiStatus
= BisPtr
->Initialize (
985 &BisInterfaceVersion
,
989 if (EFI_ERROR (EfiStatus
)) {
992 "\nPxebcBisStart()""\n BisPtr->Initialize() %r (%xh)\n",
1002 " BIS version: %d.%d",
1003 BisInterfaceVersion
.Major
,
1004 BisInterfaceVersion
.Minor
)
1008 // If the requested BIS API version is not supported,
1009 // shutdown BIS and return NULL.
1011 if (BisInterfaceVersion
.Major
!= BIS_VERSION_1
) {
1014 "\nPxebcBisStart()""\n BIS version %d.%d not supported by PXE BaseCode.\n",
1015 BisInterfaceVersion
.Major
,
1016 BisInterfaceVersion
.Minor
)
1019 BisPtr
->Shutdown (*BisAppHandle
);
1023 // Get BIS check flag.
1024 // If the BIS check flag cannot be read, shutdown BIS and return NULL.
1026 DEBUG ((EFI_D_INFO
, "\nBisPtr->GetBootObjectAuthorizationCheckFlag() "));
1028 EfiStatus
= BisPtr
->GetBootObjectAuthorizationCheckFlag (*BisAppHandle
, &BisCheckFlag
);
1030 if (EFI_ERROR (EfiStatus
)) {
1033 "\nPxebcBisStart()""\n BisPtr->GetBootObjectAuthorizationCheckFlag() %r (%xh)\n",
1038 BisPtr
->Shutdown (*BisAppHandle
);
1042 // If the BIS check flag is FALSE, shutdown BIS and return NULL.
1044 if (!BisCheckFlag
) {
1045 DEBUG ((EFI_D_INFO
, "\nBIS check flag is FALSE.\n"));
1046 BisPtr
->Shutdown (*BisAppHandle
);
1049 DEBUG ((EFI_D_INFO
, "\nBIS check flag is TRUE."));
1052 // Early out if caller does not want signature information.
1054 if (BisDataSigInfo
== NULL
) {
1058 // Get BIS signature information.
1059 // If the signature information cannot be read or is invalid,
1060 // shutdown BIS and return NULL.
1062 DEBUG ((EFI_D_INFO
, "\nBisPtr->GetSignatureInfo() "));
1064 EfiStatus
= BisPtr
->GetSignatureInfo (*BisAppHandle
, BisDataSigInfo
);
1066 if (EFI_ERROR (EfiStatus
)) {
1069 "\nPxebcBisStart()""\n BisPtr_GetSignatureInfo() %r (%xh)\n",
1074 BisPtr
->Shutdown (*BisAppHandle
);
1078 if (*BisDataSigInfo
== NULL
) {
1080 // This should never happen.
1084 "\nPxebcBisStart()""\n BisPtr->GetSignatureInfo() Data pointer is NULL!\n")
1087 BisPtr
->Shutdown (*BisAppHandle
);
1091 if ((*BisDataSigInfo
)->Length
< sizeof (EFI_BIS_SIGNATURE_INFO
) ||
1092 (*BisDataSigInfo
)->Length
% sizeof (EFI_BIS_SIGNATURE_INFO
) ||
1093 (*BisDataSigInfo
)->Length
> sizeof (EFI_BIS_SIGNATURE_INFO
) * 63
1096 // This should never happen.
1100 "\nPxebcBisStart()""\n BisPtr->GetSignatureInfo() Invalid BIS siginfo length.\n")
1103 BisPtr
->Free (*BisAppHandle
, *BisDataSigInfo
);
1104 BisPtr
->Shutdown (*BisAppHandle
);
1113 EFI_BIS_PROTOCOL
*BisPtr
,
1114 BIS_APPLICATION_HANDLE BisAppHandle
,
1115 EFI_BIS_DATA
*BisDataSigInfo
1118 Routine description:
1119 Stop the BIS interface and release allocations.
1122 BisPtr := Pointer to BIS interface
1123 BisAppHandle := BIS application handle
1124 BisDataSigInfo := Pointer to BIS signature information data
1130 if (BisPtr
== NULL
) {
1134 // Free BIS allocated resources and shutdown BIS.
1135 // Return TRUE - BIS support is officially detected.
1137 if (BisDataSigInfo
!= NULL
) {
1138 BisPtr
->Free (BisAppHandle
, BisDataSigInfo
);
1141 BisPtr
->Shutdown (BisAppHandle
);
1146 PXE_BASECODE_DEVICE
*Private
,
1149 VOID
*CredentialBuffer
,
1150 UINTN CredentialLength
1153 Routine description:
1154 Verify image and credential file.
1157 Private := Pointer to PxeBc interface
1158 FileBuffer := Pointer to image buffer
1159 FileLength := Image length in bytes
1160 CredentialBuffer := Pointer to credential buffer
1161 CredentialLength := Credential length in bytes
1165 FALSE := not verified
1168 EFI_BIS_PROTOCOL
*BisPtr
;
1169 BIS_APPLICATION_HANDLE BisAppHandle
;
1170 EFI_BIS_DATA FileData
;
1171 EFI_BIS_DATA CredentialData
;
1172 EFI_STATUS EfiStatus
;
1175 if (Private
== NULL
|| FileBuffer
== NULL
|| FileLength
== 0 || CredentialBuffer
== NULL
|| CredentialLength
== 0) {
1179 BisPtr
= PxebcBisStart (Private
, &BisAppHandle
, NULL
);
1181 if (BisPtr
== NULL
) {
1185 FileData
.Length
= (UINT32
) FileLength
;
1186 FileData
.Data
= FileBuffer
;
1187 CredentialData
.Length
= (UINT32
) CredentialLength
;
1188 CredentialData
.Data
= CredentialBuffer
;
1190 EfiStatus
= BisPtr
->VerifyBootObject (
1197 PxebcBisStop (BisPtr
, BisAppHandle
, NULL
);
1199 return (BOOLEAN
) ((EFI_ERROR (EfiStatus
)) ? FALSE
: (IsVerified
? TRUE
: FALSE
));
1204 PXE_BASECODE_DEVICE
*Private
1207 Routine description:
1208 Check for BIS interface presence.
1211 Private := Pointer to PxeBc interface
1215 FALSE := BIS not present
1218 EFI_BIS_PROTOCOL
*BisPtr
;
1219 BIS_APPLICATION_HANDLE BisAppHandle
;
1220 EFI_BIS_DATA
*BisDataSigInfo
;
1222 BisPtr
= PxebcBisStart (Private
, &BisAppHandle
, &BisDataSigInfo
);
1224 if (BisPtr
== NULL
) {
1228 PxebcBisStop (BisPtr
, BisAppHandle
, BisDataSigInfo
);
1238 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1243 Routine Description:
1244 Start and initialize the BaseCode protocol, Simple Network protocol and UNDI.
1247 Private - Pointer to Pxe BaseCode Protocol
1248 UseIPv6 - Do we want to support IPv6?
1252 EFI_INVALID_PARAMETER
1255 EFI_OUT_OF_RESOURCES
1256 Status is also returned from SNP.Start() and SNP.Initialize().
1260 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
1261 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
1263 EFI_STATUS StatCode
;
1264 PXE_BASECODE_DEVICE
*Private
;
1267 // Lock the instance data
1269 StatCode
= EFI_SUCCESS
;
1272 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1273 return EFI_INVALID_PARAMETER
;
1276 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1278 if (Private
== NULL
) {
1279 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE pointer == NULL"));
1280 return EFI_INVALID_PARAMETER
;
1283 EfiAcquireLock (&Private
->Lock
);
1286 // Make sure BaseCode is not already started.
1288 if (This
->Mode
->Started
) {
1289 DEBUG ((EFI_D_WARN
, "\nBcStart() BC is already started.\n"));
1290 EfiReleaseLock (&Private
->Lock
);
1291 return EFI_ALREADY_STARTED
;
1296 // Fail if IPv6 is requested and not supported.
1299 DEBUG ((EFI_D_WARN
, "\nBcStart() IPv6 is not supported.\n"));
1300 EfiReleaseLock (&Private
->Lock
);
1301 return EFI_UNSUPPORTED
;
1305 // Setup shortcuts to SNP protocol and data structure.
1307 SnpPtr
= Private
->SimpleNetwork
;
1308 SnpModePtr
= SnpPtr
->Mode
;
1311 // Start and initialize SNP.
1313 if (SnpModePtr
->State
== EfiSimpleNetworkStopped
) {
1314 StatCode
= (*SnpPtr
->Start
) (SnpPtr
);
1316 if (SnpModePtr
->State
!= EfiSimpleNetworkStarted
) {
1317 DEBUG ((EFI_D_WARN
, "\nBcStart() Could not start SNP.\n"));
1318 EfiReleaseLock (&Private
->Lock
);
1323 // acquire memory for mode and transmit/receive buffers
1325 if (SnpModePtr
->State
== EfiSimpleNetworkStarted
) {
1326 StatCode
= (*SnpPtr
->Initialize
) (SnpPtr
, 0, 0);
1328 if (SnpModePtr
->State
!= EfiSimpleNetworkInitialized
) {
1329 DEBUG ((EFI_D_WARN
, "\nBcStart() Could not initialize SNP."));
1330 EfiReleaseLock (&Private
->Lock
);
1337 DEBUG ((EFI_D_INFO
, "\nBC Start()"));
1340 "\nSnpModePtr->State %Xh",
1345 "\nSnpModePtr->HwAddressSize %Xh",
1346 SnpModePtr
->HwAddressSize
)
1350 "\nSnpModePtr->MediaHeaderSize %Xh",
1351 SnpModePtr
->MediaHeaderSize
)
1355 "\nSnpModePtr->MaxPacketSize %Xh",
1356 SnpModePtr
->MaxPacketSize
)
1360 "\nSnpModePtr->MacAddressChangeable %Xh",
1361 SnpModePtr
->MacAddressChangeable
)
1365 "\nSnpModePtr->MultipleTxSupported %Xh",
1366 SnpModePtr
->MultipleTxSupported
)
1370 "\nSnpModePtr->CurrentAddress %Xh",
1371 *((UINTN
*)&SnpModePtr
->CurrentAddress
))
1375 "\nSnpModePtr->BroadcastAddress %Xh",
1376 *((UINTN
*)&SnpModePtr
->BroadcastAddress
))
1380 "\nSnpModePtr->PermanentAddress %Xh",
1381 *((UINTN
*)&SnpModePtr
->PermanentAddress
))
1385 "\nSnpModePtr->NvRamSize %Xh",
1386 SnpModePtr
->NvRamSize
)
1390 "\nSnpModePtr->NvRamAccessSize %Xh",
1391 SnpModePtr
->NvRamAccessSize
)
1395 "\nSnpModePtr->ReceiveFilterMask %Xh",
1396 SnpModePtr
->ReceiveFilterMask
)
1400 "\nSnpModePtr->ReceiveFilterSetting %Xh",
1401 SnpModePtr
->ReceiveFilterSetting
)
1405 "\nSnpModePtr->MCastFilterCount %Xh",
1406 SnpModePtr
->MCastFilterCount
)
1410 "\nSnpModePtr->MCastFilter %Xh",
1411 SnpModePtr
->MCastFilter
)
1415 "\nSnpModePtr->IfType %Xh",
1420 "\nSnpModePtr->MediaPresentSupported %Xh",
1421 SnpModePtr
->MediaPresentSupported
)
1425 "\nSnpModePtr->MediaPresent %Xh",
1426 SnpModePtr
->MediaPresent
)
1430 // If media check is supported and there is no media,
1431 // return error to caller.
1433 if (SnpModePtr
->MediaPresentSupported
&& !SnpModePtr
->MediaPresent
) {
1434 DEBUG ((EFI_D_WARN
, "\nBcStart() Media not present.\n"));
1435 EfiReleaseLock (&Private
->Lock
);
1436 return EFI_NO_MEDIA
;
1439 // Allocate Tx/Rx buffers
1441 Status
= gBS
->AllocatePool (
1442 EfiBootServicesData
,
1443 BUFFER_ALLOCATE_SIZE
,
1444 (VOID
**) &Private
->TransmitBufferPtr
1447 if (!EFI_ERROR (Status
)) {
1448 ZeroMem (Private
->TransmitBufferPtr
, BUFFER_ALLOCATE_SIZE
);
1450 DEBUG ((EFI_D_NET
, "\nBcStart() Could not alloc TxBuf.\n"));
1451 EfiReleaseLock (&Private
->Lock
);
1452 return EFI_OUT_OF_RESOURCES
;
1455 Status
= gBS
->AllocatePool (
1456 EfiBootServicesData
,
1457 BUFFER_ALLOCATE_SIZE
,
1458 (VOID
**) &Private
->ReceiveBufferPtr
1461 if (!EFI_ERROR (Status
)) {
1462 ZeroMem (Private
->ReceiveBufferPtr
, BUFFER_ALLOCATE_SIZE
);
1464 DEBUG ((EFI_D_NET
, "\nBcStart() Could not alloc RxBuf.\n"));
1465 gBS
->FreePool (Private
->TransmitBufferPtr
);
1466 EfiReleaseLock (&Private
->Lock
);
1467 return EFI_OUT_OF_RESOURCES
;
1470 Status
= gBS
->AllocatePool (
1471 EfiBootServicesData
,
1473 (VOID
**) &Private
->TftpErrorBuffer
1476 if (EFI_ERROR (Status
)) {
1477 gBS
->FreePool (Private
->ReceiveBufferPtr
);
1478 gBS
->FreePool (Private
->TransmitBufferPtr
);
1479 EfiReleaseLock (&Private
->Lock
);
1480 return EFI_OUT_OF_RESOURCES
;
1483 Status
= gBS
->AllocatePool (EfiBootServicesData
, 256, (VOID
**) &Private
->TftpAckBuffer
);
1485 if (EFI_ERROR (Status
)) {
1486 gBS
->FreePool (Private
->TftpErrorBuffer
);
1487 gBS
->FreePool (Private
->ReceiveBufferPtr
);
1488 gBS
->FreePool (Private
->TransmitBufferPtr
);
1489 EfiReleaseLock (&Private
->Lock
);
1490 return EFI_OUT_OF_RESOURCES
;
1493 // Initialize private BaseCode instance data
1496 Private
->RandomPort
= (UINT16
) (Private
->RandomPort
+ PXE_RND_PORT_LOW
+ Random (Private
));
1497 } while (Private
->RandomPort
< PXE_RND_PORT_LOW
);
1499 Private
->Igmpv1TimeoutEvent
= NULL
;
1500 Private
->UseIgmpv1Reporting
= TRUE
;
1501 Private
->IpLength
= IP_ADDRESS_LENGTH (Private
->EfiBc
.Mode
);
1504 // Initialize Mode structure
1507 // check for callback protocol and set boolean
1509 SetMakeCallback (Private
);
1510 Private
->EfiBc
.Mode
->Started
= TRUE
;
1511 Private
->EfiBc
.Mode
->TTL
= DEFAULT_TTL
;
1512 Private
->EfiBc
.Mode
->ToS
= DEFAULT_ToS
;
1513 Private
->EfiBc
.Mode
->UsingIpv6
= UseIPv6
;
1514 Private
->EfiBc
.Mode
->DhcpDiscoverValid
= FALSE
;
1515 Private
->EfiBc
.Mode
->DhcpAckReceived
= FALSE
;
1516 Private
->EfiBc
.Mode
->ProxyOfferReceived
= FALSE
;
1517 Private
->EfiBc
.Mode
->PxeDiscoverValid
= FALSE
;
1518 Private
->EfiBc
.Mode
->PxeReplyReceived
= FALSE
;
1519 Private
->EfiBc
.Mode
->PxeBisReplyReceived
= FALSE
;
1520 Private
->EfiBc
.Mode
->IcmpErrorReceived
= FALSE
;
1521 Private
->EfiBc
.Mode
->TftpErrorReceived
= FALSE
;
1522 ZeroMem (&Private
->EfiBc
.Mode
->StationIp
, sizeof (EFI_IP_ADDRESS
));
1523 ZeroMem (&Private
->EfiBc
.Mode
->SubnetMask
, sizeof (EFI_IP_ADDRESS
));
1524 Private
->EfiBc
.Mode
->IpFilter
.Filters
= 0;
1525 Private
->EfiBc
.Mode
->IpFilter
.IpCnt
= 0;
1526 Private
->EfiBc
.Mode
->ArpCacheEntries
= 0;
1527 Private
->EfiBc
.Mode
->RouteTableEntries
= 0;
1528 ZeroMem (&Private
->EfiBc
.Mode
->IcmpError
, sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR
));
1529 ZeroMem (&Private
->EfiBc
.Mode
->TftpError
, sizeof (EFI_PXE_BASE_CODE_TFTP_ERROR
));
1532 // Set to PXE_TRUE by the BC constructor if this BC implementation
1535 Private
->EfiBc
.Mode
->Ipv6Supported
= SUPPORT_IPV6
;
1538 Private
->EfiBc
.Mode
->Ipv6Available
= Private
->NiiPtr
->Ipv6Supported
;
1540 Private
->EfiBc
.Mode
->Ipv6Available
= FALSE
;
1543 // Set to TRUE by the BC constructor if this BC implementation
1546 Private
->EfiBc
.Mode
->BisSupported
= TRUE
;
1547 Private
->EfiBc
.Mode
->BisDetected
= PxebcBisDetect (Private
);
1550 // This field is set to PXE_TRUE by the BC Start() function. When this
1551 // field is PXE_TRUE, ARP packets are sent as needed to get IP and MAC
1552 // addresses. This can cause unexpected delays in the DHCP(), Discover()
1553 // and MTFTP() functions. Setting this to PXE_FALSE will cause these
1554 // functions to fail if the required IP/MAC information is not in the
1555 // ARP cache. The value of this field can be changed by an application
1558 Private
->EfiBc
.Mode
->AutoArp
= TRUE
;
1561 // Unlock the instance data
1563 EfiReleaseLock (&Private
->Lock
);
1570 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
1574 Routine Description:
1575 Stop the BaseCode protocol, Simple Network protocol and UNDI.
1578 Private - Pointer to Pxe BaseCode Protocol
1582 0 - Successfully stopped
1587 // Lock the instance data
1589 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
1590 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
1591 EFI_STATUS StatCode
;
1592 PXE_BASECODE_DEVICE
*Private
;
1594 StatCode
= EFI_SUCCESS
;
1597 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1598 return EFI_INVALID_PARAMETER
;
1601 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1603 if (Private
== NULL
) {
1604 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1605 return EFI_INVALID_PARAMETER
;
1608 EfiAcquireLock (&Private
->Lock
);
1610 SnpPtr
= Private
->SimpleNetwork
;
1611 SnpModePtr
= SnpPtr
->Mode
;
1616 StatCode
= EFI_NOT_STARTED
;
1618 if (SnpModePtr
->State
== EfiSimpleNetworkInitialized
) {
1619 StatCode
= (*SnpPtr
->Shutdown
) (SnpPtr
);
1622 if (SnpModePtr
->State
== EfiSimpleNetworkStarted
) {
1623 StatCode
= (*SnpPtr
->Stop
) (SnpPtr
);
1626 if (Private
->TransmitBufferPtr
!= NULL
) {
1627 gBS
->FreePool (Private
->TransmitBufferPtr
);
1628 Private
->TransmitBufferPtr
= NULL
;
1631 if (Private
->ReceiveBufferPtr
!= NULL
) {
1632 gBS
->FreePool (Private
->ReceiveBufferPtr
);
1633 Private
->ReceiveBufferPtr
= NULL
;
1636 if (Private
->ArpBuffer
!= NULL
) {
1637 gBS
->FreePool (Private
->ArpBuffer
);
1638 Private
->ArpBuffer
= NULL
;
1641 if (Private
->TftpErrorBuffer
!= NULL
) {
1642 gBS
->FreePool (Private
->TftpErrorBuffer
);
1643 Private
->TftpErrorBuffer
= NULL
;
1646 if (Private
->TftpAckBuffer
!= NULL
) {
1647 gBS
->FreePool (Private
->TftpAckBuffer
);
1648 Private
->TftpAckBuffer
= NULL
;
1651 if (Private
->Igmpv1TimeoutEvent
!= NULL
) {
1652 gBS
->CloseEvent (Private
->Igmpv1TimeoutEvent
);
1653 Private
->Igmpv1TimeoutEvent
= NULL
;
1656 Private
->FileSize
= 0;
1657 Private
->EfiBc
.Mode
->Started
= FALSE
;
1660 // Unlock the instance data
1662 EfiReleaseLock (&Private
->Lock
);
1666 const IPV4_ADDR AllSystemsGroup
= { { 224, 0, 0, 1 } };
1670 IN PXE_BASECODE_DEVICE
*Private
,
1671 IN EFI_PXE_BASE_CODE_IP_FILTER
*Filter
1675 Routine Description:
1676 Set up the IP filter
1679 Private - Pointer to Pxe BaseCode Protocol
1680 Filter - Pointer to the filter
1684 0 - Successfully set the filter
1688 EFI_STATUS StatCode
;
1689 EFI_MAC_ADDRESS MACadds
[PXE_IP_FILTER_SIZE
];
1690 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1691 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
1692 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
1698 PxebcMode
= Private
->EfiBc
.Mode
;
1699 SnpPtr
= Private
->SimpleNetwork
;
1700 SnpModePtr
= SnpPtr
->Mode
;
1703 // validate input parameters
1704 // must have a filter
1705 // must not have any extra filter bits set
1707 if (Filter
== NULL
||
1708 (Filter
->Filters
&~FILTER_BITS
)
1710 // must not have a count which is too large or with no IP list
1713 (Filter
->IpCnt
&& (!Filter
->IpList
|| Filter
->IpCnt
> PXE_IP_FILTER_SIZE
))
1715 // must not have incompatible filters - promiscuous incompatible with anything else
1719 (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) &&
1720 ((Filter
->Filters
&~EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) || Filter
->IpCnt
)
1723 DEBUG ((EFI_D_INFO
, "\nIpFilter() Exit #1"));
1724 return EFI_INVALID_PARAMETER
;
1727 // promiscuous multicast incompatible with multicast in IP list
1729 if (Filter
->IpCnt
&& (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
)) {
1730 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1731 if (IS_MULTICAST (&Filter
->IpList
[Index
])) {
1732 DEBUG ((EFI_D_INFO
, "\nIpFilter() Exit #2"));
1733 return EFI_INVALID_PARAMETER
;
1738 // leave groups for all those multicast which are no longer enabled
1740 for (Index
= 0; Index
< PxebcMode
->IpFilter
.IpCnt
; ++Index
) {
1741 if (!IS_MULTICAST (&PxebcMode
->IpFilter
.IpList
[Index
])) {
1745 for (Index2
= 0; Index2
< Filter
->IpCnt
; ++Index2
) {
1746 if (!CompareMem (&PxebcMode
->IpFilter
.IpList
[Index
], &Filter
->IpList
[Index2
], IP_ADDRESS_LENGTH (PxebcMode
))) {
1754 // if we didn't find it, remove from group
1756 if (Index2
== Filter
->IpCnt
) {
1757 IgmpLeaveGroup (Private
, &PxebcMode
->IpFilter
.IpList
[Index
]);
1761 // set enable bits, convert multicast ip adds, join groups
1762 // allways leave receive broadcast enabled at hardware layer
1766 if (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) {
1767 Enable
= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
1769 if (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
) {
1770 Enable
= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
1772 Enable
= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
1774 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1775 CopyMem (&(PxebcMode
->IpFilter
.IpList
[Index
]), &(Filter
->IpList
[Index
]), sizeof (EFI_IP_ADDRESS
));
1777 if (IS_MULTICAST (&Filter
->IpList
[Index
])) {
1778 EFI_IP_ADDRESS
*TmpIp
;
1780 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
1783 // if this is the first group, add the all systems group to mcast list
1788 if (PxebcMode
->UsingIpv6
) {
1794 TmpIp
= (EFI_IP_ADDRESS
*) &AllSystemsGroup
;
1797 TmpIp
= (EFI_IP_ADDRESS
*) &Filter
->IpList
[Index
];
1800 // get MAC address of IP
1802 StatCode
= (*SnpPtr
->MCastIpToMac
) (SnpPtr
, PxebcMode
->UsingIpv6
, TmpIp
, &MACadds
[Index2
++]);
1804 if (EFI_ERROR (StatCode
)) {
1807 "\nIpFilter() Exit #2 %Xh (%r)",
1814 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
1819 if (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
) {
1820 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
1824 // if nothing changed, just return
1828 "\nsnp->ReceiveFilterSetting == %Xh Filter->IpCnt == %Xh",
1829 SnpModePtr
->ReceiveFilterSetting
,
1833 if (SnpModePtr
->ReceiveFilterSetting
== Enable
&& !Filter
->IpCnt
) {
1834 DEBUG ((EFI_D_INFO
, "\nIpFilter() Exit #4"));
1838 // disable those currently set but not set in new filter
1840 Disable
= SnpModePtr
->ReceiveFilterSetting
&~Enable
;
1842 StatCode
= SnpPtr
->ReceiveFilters (SnpPtr
, Enable
, Disable
, FALSE
, Index2
, MACadds
);
1844 PxebcMode
->IpFilter
.IpCnt
= Filter
->IpCnt
;
1847 // join groups for all multicast in list
1849 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1850 if (IS_MULTICAST (&Filter
->IpList
[Index
])) {
1851 IgmpJoinGroup (Private
, &Filter
->IpList
[Index
]);
1855 DEBUG ((EFI_D_INFO
, "\nIpFilter() Exit #5 %Xh (%r)", StatCode
, StatCode
));
1863 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1864 IN EFI_PXE_BASE_CODE_IP_FILTER
*Filter
1868 Routine Description:
1872 Private - Pointer to Pxe BaseCode Protocol
1873 Filter - Pointer to the filter
1877 0 - Successfully set the filter
1881 EFI_STATUS StatCode
;
1882 PXE_BASECODE_DEVICE
*Private
;
1885 // Lock the instance data and make sure started
1887 StatCode
= EFI_SUCCESS
;
1890 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1891 return EFI_INVALID_PARAMETER
;
1894 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1896 if (Private
== NULL
) {
1897 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1898 return EFI_INVALID_PARAMETER
;
1901 EfiAcquireLock (&Private
->Lock
);
1903 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
1904 DEBUG ((EFI_D_ERROR
, "BC was not started."));
1905 EfiReleaseLock (&Private
->Lock
);
1906 return EFI_NOT_STARTED
;
1909 if (Filter
== NULL
) {
1910 return EFI_INVALID_PARAMETER
;
1915 StatCode
= IpFilter (Private
, Filter
);
1918 // Unlock the instance data
1920 EfiReleaseLock (&Private
->Lock
);
1927 EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1928 BOOLEAN
*AutoArpPtr
,
1929 BOOLEAN
*SendGuidPtr
,
1930 UINT8
*TimeToLivePtr
,
1931 UINT8
*TypeOfServicePtr
,
1932 BOOLEAN
*MakeCallbackPtr
1936 Routine Description:
1937 Set the Base Code behavior parameters
1940 This - Pointer to Pxe BaseCode Protocol
1941 AutoArpPtr - Boolean to do ARP stuff
1942 SendGuidPtr - Boolean whether or not to send GUID info
1943 TimeToLivePtr - Value for Total time to live
1944 TypeOfServicePtr - Value for Type of Service
1945 MakeCallbackPtr - Boolean to determine if we make callbacks
1949 0 - Successfully set the parameters
1953 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1955 CHAR8
*SerialNumberPtr
;
1956 EFI_STATUS StatCode
;
1957 PXE_BASECODE_DEVICE
*Private
;
1960 // Lock the instance data and make sure started
1962 StatCode
= EFI_SUCCESS
;
1965 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1966 return EFI_INVALID_PARAMETER
;
1969 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1971 if (Private
== NULL
) {
1972 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1973 return EFI_INVALID_PARAMETER
;
1976 EfiAcquireLock (&Private
->Lock
);
1978 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
1979 DEBUG ((EFI_D_ERROR
, "BC was not started."));
1980 EfiReleaseLock (&Private
->Lock
);
1981 return EFI_NOT_STARTED
;
1984 DEBUG ((EFI_D_INFO
, "\nSetParameters() Entry. "));
1986 PxebcMode
= Private
->EfiBc
.Mode
;
1987 StatCode
= EFI_SUCCESS
;
1989 if (SendGuidPtr
!= NULL
) {
1991 if (PxeBcLibGetSmbiosSystemGuidAndSerialNumber (&TmpGuid
, &SerialNumberPtr
) != EFI_SUCCESS
) {
1992 return EFI_INVALID_PARAMETER
;
1997 if (MakeCallbackPtr
!= NULL
) {
1998 if (*MakeCallbackPtr
) {
1999 if (!SetMakeCallback (Private
)) {
2000 return EFI_INVALID_PARAMETER
;
2004 PxebcMode
->MakeCallbacks
= *MakeCallbackPtr
;
2007 if (AutoArpPtr
!= NULL
) {
2008 PxebcMode
->AutoArp
= *AutoArpPtr
;
2011 if (SendGuidPtr
!= NULL
) {
2012 PxebcMode
->SendGUID
= *SendGuidPtr
;
2015 if (TimeToLivePtr
!= NULL
) {
2016 PxebcMode
->TTL
= *TimeToLivePtr
;
2019 if (TypeOfServicePtr
!= NULL
) {
2020 PxebcMode
->ToS
= *TypeOfServicePtr
;
2023 // Unlock the instance data
2025 DEBUG ((EFI_D_INFO
, "\nSetparameters() Exit = %xh ", StatCode
));
2027 EfiReleaseLock (&Private
->Lock
);
2031 // //////////////////////////////////////////////////////////
2033 // BC Set Station IP Routine
2038 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
2039 IN EFI_IP_ADDRESS
*StationIpPtr
,
2040 IN EFI_IP_ADDRESS
*SubnetMaskPtr
2044 Routine Description:
2045 Set the station IP address
2048 This - Pointer to Pxe BaseCode Protocol
2049 StationIpPtr - Pointer to the requested IP address to set in base code
2050 SubnetMaskPtr - Pointer to the requested subnet mask for the base code
2054 EFI_SUCCESS - Successfully set the parameters
2055 EFI_NOT_STARTED - BC has not started
2058 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
2059 PXE_BASECODE_DEVICE
*Private
;
2062 // Lock the instance data and make sure started
2066 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
2067 return EFI_INVALID_PARAMETER
;
2070 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
2072 if (Private
== NULL
) {
2073 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
2074 return EFI_INVALID_PARAMETER
;
2077 EfiAcquireLock (&Private
->Lock
);
2079 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
2080 DEBUG ((EFI_D_ERROR
, "BC was not started."));
2081 EfiReleaseLock (&Private
->Lock
);
2082 return EFI_NOT_STARTED
;
2085 PxebcMode
= Private
->EfiBc
.Mode
;
2087 if (StationIpPtr
!= NULL
) {
2088 CopyMem (&PxebcMode
->StationIp
, StationIpPtr
, sizeof (EFI_IP_ADDRESS
));
2089 Private
->GoodStationIp
= TRUE
;
2092 if (SubnetMaskPtr
!= NULL
) {
2093 CopyMem (&PxebcMode
->SubnetMask
, SubnetMaskPtr
, sizeof (EFI_IP_ADDRESS
));
2096 // Unlock the instance data
2098 EfiReleaseLock (&Private
->Lock
);
2103 EFI_DRIVER_BINDING_PROTOCOL gPxeBcDriverBinding
= {
2104 PxeBcDriverSupported
,
2114 PxeBcDriverSupported (
2115 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2116 IN EFI_HANDLE Controller
,
2117 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
2121 Routine Description:
2122 Test to see if this driver supports Controller. Any Controller
2123 than contains a Snp protocol can be supported.
2126 This - Protocol instance pointer.
2127 Controller - Handle of device to test.
2128 RemainingDevicePath - Not used.
2131 EFI_SUCCESS - This driver supports this device.
2132 EFI_ALREADY_STARTED - This driver is already running on this device.
2133 other - This driver does not support this device.
2138 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
2140 Status
= gBS
->OpenProtocol (
2142 &gEfiDevicePathProtocolGuid
,
2144 This
->DriverBindingHandle
,
2146 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
2149 if (EFI_ERROR (Status
)) {
2153 Status
= gBS
->OpenProtocol (
2155 &gEfiSimpleNetworkProtocolGuid
,
2157 This
->DriverBindingHandle
,
2159 EFI_OPEN_PROTOCOL_BY_DRIVER
2161 if (EFI_ERROR (Status
)) {
2165 gBS
->CloseProtocol (
2167 &gEfiSimpleNetworkProtocolGuid
,
2168 This
->DriverBindingHandle
,
2178 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2179 IN EFI_HANDLE Controller
,
2180 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
2184 Routine Description:
2185 Start the Base code driver.
2188 This - Protocol instance pointer.
2189 Controller - Handle of device to test.
2190 RemainingDevicePath - Not used.
2193 EFI_SUCCESS - This driver supports this device.
2194 EFI_ALREADY_STARTED - This driver is already running on this device.
2195 other - This driver does not support this device.
2200 PXE_BASECODE_DEVICE
*Private
;
2201 LOADFILE_DEVICE
*pLF
;
2204 // Allocate structures needed by BaseCode and LoadFile protocols.
2206 Status
= gBS
->AllocatePool (
2207 EfiBootServicesData
,
2208 sizeof (PXE_BASECODE_DEVICE
),
2212 if (!EFI_ERROR (Status
)) {
2213 ZeroMem (Private
, sizeof (PXE_BASECODE_DEVICE
));
2215 DEBUG ((EFI_D_NET
, "\nBcNotifySnp() Could not alloc PXE_BASECODE_DEVICE structure.\n"));
2219 Status
= gBS
->AllocatePool (
2220 EfiBootServicesData
,
2221 sizeof (LOADFILE_DEVICE
),
2225 if (!EFI_ERROR (Status
)) {
2226 ZeroMem (pLF
, sizeof (LOADFILE_DEVICE
));
2228 DEBUG ((EFI_D_NET
, "\nBcNotifySnp() Could not alloc LOADFILE_DEVICE structure.\n"));
2229 gBS
->FreePool (Private
);
2233 Status
= gBS
->AllocatePool (
2234 EfiBootServicesData
,
2235 sizeof (EFI_PXE_BASE_CODE_MODE
),
2236 (VOID
**) &Private
->EfiBc
.Mode
2239 if (!EFI_ERROR (Status
)) {
2240 ZeroMem (Private
->EfiBc
.Mode
, sizeof (EFI_PXE_BASE_CODE_MODE
));
2242 DEBUG ((EFI_D_NET
, "\nBcNotifySnp() Could not alloc Mode structure.\n"));
2243 gBS
->FreePool (Private
);
2244 gBS
->FreePool (pLF
);
2248 // Lock access, just in case
2250 EfiInitializeLock (&Private
->Lock
, EFI_TPL_CALLBACK
);
2251 EfiAcquireLock (&Private
->Lock
);
2253 EfiInitializeLock (&pLF
->Lock
, EFI_TPL_CALLBACK
);
2254 EfiAcquireLock (&pLF
->Lock
);
2257 // Initialize PXE structure
2260 // First initialize the internal 'private' data that the application
2263 Private
->Signature
= PXE_BASECODE_DEVICE_SIGNATURE
;
2264 Private
->Handle
= Controller
;
2267 // Get the NII interface
2269 Status
= gBS
->OpenProtocol (
2271 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
2272 (VOID
**) &Private
->NiiPtr
,
2273 This
->DriverBindingHandle
,
2275 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2278 if (EFI_ERROR (Status
)) {
2279 Status
= gBS
->OpenProtocol (
2281 &gEfiNetworkInterfaceIdentifierProtocolGuid
,
2282 (VOID
**) &Private
->NiiPtr
,
2283 This
->DriverBindingHandle
,
2285 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2288 if (EFI_ERROR (Status
)) {
2293 // Get the Snp interface
2295 Status
= gBS
->OpenProtocol (
2297 &gEfiSimpleNetworkProtocolGuid
,
2298 (VOID
**) &Private
->SimpleNetwork
,
2299 This
->DriverBindingHandle
,
2301 EFI_OPEN_PROTOCOL_BY_DRIVER
2304 if (EFI_ERROR (Status
)) {
2309 // Next, initialize the external 'public' data that
2310 // the application does see.
2312 Private
->EfiBc
.Revision
= EFI_PXE_BASE_CODE_INTERFACE_REVISION
;
2313 Private
->EfiBc
.Start
= BcStart
;
2314 Private
->EfiBc
.Stop
= BcStop
;
2315 Private
->EfiBc
.Dhcp
= BcDhcp
;
2316 Private
->EfiBc
.Discover
= BcDiscover
;
2317 Private
->EfiBc
.Mtftp
= BcMtftp
;
2318 Private
->EfiBc
.UdpWrite
= BcUdpWrite
;
2319 Private
->EfiBc
.UdpRead
= BcUdpRead
;
2320 Private
->EfiBc
.Arp
= BcArp
;
2321 Private
->EfiBc
.SetIpFilter
= BcIpFilter
;
2322 Private
->EfiBc
.SetParameters
= BcSetParameters
;
2323 Private
->EfiBc
.SetStationIp
= BcSetStationIP
;
2324 Private
->EfiBc
.SetPackets
= BcSetPackets
;
2327 // Initialize BaseCode Mode structure
2329 Private
->EfiBc
.Mode
->Started
= FALSE
;
2330 Private
->EfiBc
.Mode
->TTL
= DEFAULT_TTL
;
2331 Private
->EfiBc
.Mode
->ToS
= DEFAULT_ToS
;
2332 Private
->EfiBc
.Mode
->UsingIpv6
= FALSE
;
2333 Private
->EfiBc
.Mode
->AutoArp
= TRUE
;
2336 // Set to PXE_TRUE by the BC constructor if this BC
2337 // implementation supports IPv6.
2339 Private
->EfiBc
.Mode
->Ipv6Supported
= SUPPORT_IPV6
;
2342 Private
->EfiBc
.Mode
->Ipv6Available
= Private
->NiiPtr
->Ipv6Supported
;
2344 Private
->EfiBc
.Mode
->Ipv6Available
= FALSE
;
2347 // Set to TRUE by the BC constructor if this BC
2348 // implementation supports BIS.
2350 Private
->EfiBc
.Mode
->BisSupported
= TRUE
;
2351 Private
->EfiBc
.Mode
->BisDetected
= PxebcBisDetect (Private
);
2354 // Initialize LoadFile structure.
2356 pLF
->Signature
= LOADFILE_DEVICE_SIGNATURE
;
2357 pLF
->LoadFile
.LoadFile
= LoadFile
;
2358 pLF
->Private
= Private
;
2361 // Install protocol interfaces.
2363 Status
= gBS
->InstallMultipleProtocolInterfaces (
2365 &gEfiPxeBaseCodeProtocolGuid
,
2367 &gEfiLoadFileProtocolGuid
,
2372 if (EFI_ERROR (Status
)) {
2373 gBS
->CloseProtocol (
2375 &gEfiSimpleNetworkProtocolGuid
,
2376 This
->DriverBindingHandle
,
2385 EfiReleaseLock (&pLF
->Lock
);
2386 EfiReleaseLock (&Private
->Lock
);
2390 gBS
->FreePool (Private
->EfiBc
.Mode
);
2391 gBS
->FreePool (Private
);
2392 gBS
->FreePool (pLF
);
2399 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2400 IN EFI_HANDLE Controller
,
2401 IN UINTN NumberOfChildren
,
2402 IN EFI_HANDLE
*ChildHandleBuffer
2406 Routine Description:
2407 Stop the Base code driver.
2410 This - Protocol instance pointer.
2411 Controller - Handle of device to test.
2412 NumberOfChildren - Not used
2413 ChildHandleBuffer - Not used
2416 EFI_SUCCESS - This driver supports this device.
2417 EFI_ALREADY_STARTED - This driver is already running on this device.
2418 other - This driver does not support this device.
2423 EFI_LOAD_FILE_PROTOCOL
*LfProtocol
;
2424 LOADFILE_DEVICE
*LoadDevice
;
2427 // Get our context back.
2429 Status
= gBS
->OpenProtocol (
2431 &gEfiLoadFileProtocolGuid
,
2432 (VOID
**) &LfProtocol
,
2433 This
->DriverBindingHandle
,
2435 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2438 if (EFI_ERROR (Status
)) {
2439 return EFI_UNSUPPORTED
;
2442 LoadDevice
= EFI_LOAD_FILE_DEV_FROM_THIS (LfProtocol
);
2444 Status
= gBS
->UninstallMultipleProtocolInterfaces (
2446 &gEfiLoadFileProtocolGuid
,
2447 &LoadDevice
->LoadFile
,
2448 &gEfiPxeBaseCodeProtocolGuid
,
2449 &LoadDevice
->Private
->EfiBc
,
2453 if (!EFI_ERROR (Status
)) {
2455 Status
= gBS
->CloseProtocol (
2457 &gEfiSimpleNetworkProtocolGuid
,
2458 This
->DriverBindingHandle
,
2462 gBS
->FreePool (LoadDevice
->Private
->EfiBc
.Mode
);
2463 gBS
->FreePool (LoadDevice
->Private
);
2464 gBS
->FreePool (LoadDevice
);
2472 InitializeBCDriver (
2473 IN EFI_HANDLE ImageHandle
,
2474 IN EFI_SYSTEM_TABLE
*SystemTable
2478 Routine Description:
2479 Initialize the base code drivers and install the driver binding
2482 Standard EFI Image Entry
2485 EFI_SUCCESS - This driver was successfully bound
2490 OptionsStrucInit ();