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
71 Convert number to ASCII value
74 Number - Numeric value to convert to decimal ASCII value.
75 Buffer - Buffer to place ASCII version of the Number
76 Length - Length of Buffer.
86 Remainder
= Number
% 10;
88 Buffer
[Length
] = (UINT8
) ('0' + Remainder
);
100 Convert number to decimal ASCII value at Buffer location
103 Number - Numeric value to convert to decimal ASCII value.
104 Buffer - Buffer to place ASCII version of the Number
115 CvtNum (Number
, BuffArray
, 30);
117 for (Index
= 0; Index
< 30; ++Index
) {
118 if (BuffArray
[Index
] != '0') {
123 CopyMem (Buffer
, BuffArray
+ Index
, 31 - Index
);
133 Convert ASCII numeric string to a UINTN value
136 Number - Numeric value to convert to decimal ASCII value.
137 Buffer - Buffer to place ASCII version of the Number
140 Value - UINTN value of the ASCII string.
148 Character
= *Buffer
++;
150 Value
= Value
* 10 + Character
- '0';
151 Character
= *Buffer
++;
164 Convert ASCII numeric string to a UINTN value
167 Number - Numeric value to convert to decimal ASCII value.
168 Buffer - Buffer to place ASCII version of the Number
171 Value - UINTN value of the ASCII string.
179 while ((Character
= *Buffer
++) != '\0') {
180 Value
= MultU64x32 (Value
, 10) + (Character
- '0');
186 // random number generator
188 #define RANDOM_MULTIPLIER 2053
189 #define RANDOM_ADD_IN_VALUE 19
193 IN PXE_BASECODE_DEVICE
*Private
,
194 IN UINT16 InitialSeed
199 Initialize the Seed for the random number generator
208 if (Private
!= NULL
) {
209 Private
->RandomSeed
= InitialSeed
;
215 IN PXE_BASECODE_DEVICE
*Private
220 Generate and return a pseudo-random number
225 Number - UINT16 random number
231 if (Private
!= NULL
) {
232 Number
= -(INTN
) Private
->RandomSeed
* RANDOM_MULTIPLIER
+ RANDOM_ADD_IN_VALUE
;
234 return Private
->RandomSeed
= (UINT16
) Number
;
240 // calculate the internet checksum (RFC 1071)
241 // return 16 bit ones complement of ones complement sum of 16 bit words
251 Calculate the internet checksum (see RFC 1071)
254 Packet - Buffer which contains the data to be checksummed
255 Length - Length to be checksummed
258 Checksum - Returns the 16 bit ones complement of
259 ones complement sum of 16 bit words
267 Odd
= (UINT8
) (Length
& 1);
274 Sum
+= *(UINT8
*) Packet
;
277 Sum
= (Sum
& 0xffff) + (Sum
>> 16);
279 // in case above carried
283 return (UINT16
) (~ (UINT16
) Sum
);
296 Calculate the internet checksum (see RFC 1071)
297 on a non contiguous header and data
300 Header - Buffer which contains the data to be checksummed
301 HeaderLen - Length to be checksummed
302 Message - Buffer which contains the data to be checksummed
303 MessageLen - Length to be checksummed
306 Checksum - Returns the 16 bit ones complement of
307 ones complement sum of 16 bit words
313 Sum
= (UINT16
)~IpChecksum (Header
, HeaderLen
) + (UINT16
)~IpChecksum (Message
, MessageLen
);
316 // in case above carried
320 return (UINT16
) (~ (UINT16
) Sum
);
332 Adjust the internet checksum (see RFC 1071) on a single word update.
335 OldChkSum - Checksum previously calculated
340 Checksum - Returns the 16 bit ones complement of
341 ones complement sum of 16 bit words
347 sum
= ~OldChksum
+ NewWord
- OldWord
;
349 // in case above carried
352 return (UINT16
) (~ (UINT16
) sum
);
358 IN PXE_BASECODE_DEVICE
*Private
363 See if a callback is in play
366 Private - Pointer to Pxe BaseCode Protocol
369 0 - Callbacks are active on the handle
370 1 - Callbacks are not active on the handle
374 Private
->EfiBc
.Mode
->MakeCallbacks
= (BOOLEAN
) (gBS
->HandleProtocol (
376 &gEfiPxeBaseCodeCallbackProtocolGuid
,
377 (VOID
*) &Private
->CallbackProtocolPtr
382 "\nMode->MakeCallbacks == %d ",
383 Private
->EfiBc
.Mode
->MakeCallbacks
)
388 "\nPrivate->CallbackProtocolPtr == %xh ",
389 Private
->CallbackProtocolPtr
)
392 if (Private
->CallbackProtocolPtr
!= NULL
) {
395 "\nCallbackProtocolPtr->Revision = %xh ",
396 Private
->CallbackProtocolPtr
->Revision
)
401 "\nCallbackProtocolPtr->Callback = %xh ",
402 Private
->CallbackProtocolPtr
->Callback
)
406 return Private
->EfiBc
.Mode
->MakeCallbacks
;
409 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
412 IN PXE_BASECODE_DEVICE
*Private
,
413 IN EFI_PXE_BASE_CODE_FUNCTION Function
,
414 IN EFI_EVENT TimeoutEvent
,
415 IN OUT UINTN
*HeaderSizePtr
,
416 IN OUT UINTN
*BufferSizePtr
,
417 IN OUT UINT16
*ProtocolPtr
422 Routine which does an SNP->Receive over a timeout period and doing callbacks
425 Private - Pointer to Pxe BaseCode Protocol
426 Function - What PXE function to callback
427 TimeoutEvent - Timer event that will trigger when we have waited too
428 long for an incoming packet
429 HeaderSizePtr - Pointer to the size of the Header size
430 BufferSizePtr - Pointer to the size of the Buffer size
431 ProtocolPtr - The protocol to sniff for (namely, UDP/etc)
434 0 - Something was returned
435 !0 - Like there was nothing to receive (EFI_TIMEOUT/NOT_READY)
439 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
440 EFI_PXE_CALLBACK CallbackPtr
;
442 EFI_EVENT CallbackEvent
;
445 // Initialize pointer to SNP interface
447 SnpPtr
= Private
->SimpleNetwork
;
450 // Initialize pointer to PxeBc callback routine - if any
452 CallbackPtr
= (Private
->EfiBc
.Mode
->MakeCallbacks
) ? Private
->CallbackProtocolPtr
->Callback
: NULL
;
455 // Create callback event and set timer
457 StatCode
= gBS
->CreateEvent (
465 if (EFI_ERROR (StatCode
)) {
466 return EFI_DEVICE_ERROR
;
470 // every 100 milliseconds
472 StatCode
= gBS
->SetTimer (
478 if (EFI_ERROR (StatCode
)) {
479 gBS
->CloseEvent (CallbackEvent
);
480 return EFI_DEVICE_ERROR
;
483 // Loop until a packet is received or a receive error is detected or
484 // a callback abort is detected or a timeout event occurs.
490 // Check for received packet event.
492 if (!EFI_ERROR (gBS
->CheckEvent (SnpPtr
->WaitForPacket
))) {
494 // Packet should be available. Attempt to read it.
496 *BufferSizePtr
= BUFFER_ALLOCATE_SIZE
;
498 StatCode
= SnpPtr
->Receive (
502 Private
->ReceiveBufferPtr
,
508 if (EFI_ERROR (StatCode
)) {
512 // Packet was received. Make received callback then return.
514 if (CallbackPtr
!= NULL
) {
515 StatCode
= CallbackPtr (
516 Private
->CallbackProtocolPtr
,
519 (UINT32
) *BufferSizePtr
,
520 (EFI_PXE_BASE_CODE_PACKET
*) Private
->ReceiveBufferPtr
523 if (StatCode
!= EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
) {
524 StatCode
= EFI_ABORTED
;
526 StatCode
= EFI_SUCCESS
;
535 // Poll for received packet.
537 *BufferSizePtr
= BUFFER_ALLOCATE_SIZE
;
539 StatCode
= SnpPtr
->Receive (
543 Private
->ReceiveBufferPtr
,
549 if (!EFI_ERROR (StatCode
)) {
551 // Packet was received. Make received callback then return.
553 if (CallbackPtr
!= NULL
) {
554 StatCode
= CallbackPtr (
555 Private
->CallbackProtocolPtr
,
558 (UINT32
) *BufferSizePtr
,
559 (EFI_PXE_BASE_CODE_PACKET
*) Private
->ReceiveBufferPtr
562 if (StatCode
!= EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
) {
563 StatCode
= EFI_ABORTED
;
565 StatCode
= EFI_SUCCESS
;
572 if (StatCode
!= EFI_NOT_READY
) {
577 // Check for callback event.
579 if (!EFI_ERROR (gBS
->CheckEvent (CallbackEvent
))) {
581 // Make periodic callback if callback pointer is initialized.
583 if (CallbackPtr
!= NULL
) {
584 StatCode
= CallbackPtr (
585 Private
->CallbackProtocolPtr
,
593 // Abort if directed to by callback routine.
595 if (StatCode
!= EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
) {
596 StatCode
= EFI_ABORTED
;
602 // Check for timeout event.
604 if (TimeoutEvent
== 0) {
605 StatCode
= EFI_TIMEOUT
;
609 if (!EFI_ERROR (gBS
->CheckEvent (TimeoutEvent
))) {
610 StatCode
= EFI_TIMEOUT
;
614 // Check IGMP timer events.
616 IgmpCheckTimers (Private
);
619 gBS
->CloseEvent (CallbackEvent
);
626 PXE_BASECODE_DEVICE
*Private
,
631 UINT16 MediaProtocol
,
632 IN EFI_PXE_BASE_CODE_FUNCTION Function
637 Routine which does an SNP->Transmit of a buffer
640 Private - Pointer to Pxe BaseCode Protocol
641 HeaderPtr - Pointer to the buffer
642 PacketPtr - Pointer to the packet to send
643 PacketLen - The length of the entire packet to send
644 HardwareAddr - Pointer to the MAC address of the destination
645 MediaProtocol - What type of frame to create (RFC 1700) - IE. Ethernet
646 Function - What PXE function to callback
649 0 - Something was sent
650 !0 - An error was encountered during sending of a packet
654 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
655 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
656 EFI_PXE_CALLBACK CallbackPtr
;
658 EFI_EVENT TimeoutEvent
;
665 CallbackPtr
= Private
->EfiBc
.Mode
->MakeCallbacks
? Private
->CallbackProtocolPtr
->Callback
: 0;
667 SnpPtr
= Private
->SimpleNetwork
;
668 SnpModePtr
= SnpPtr
->Mode
;
671 // clear prior interrupt status
673 StatCode
= SnpPtr
->GetStatus (SnpPtr
, &IntStatus
, 0);
675 if (EFI_ERROR (StatCode
)) {
678 "\nSendPacket() Exit #1 %xh (%r)",
685 Private
->DidTransmit
= FALSE
;
687 if (CallbackPtr
!= NULL
) {
689 Private
->CallbackProtocolPtr
,
694 ) != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
) {
697 "\nSendPacket() Exit #2 %xh (%r)",
705 // put packet in transmit queue
706 // headersize should be zero if not filled in
708 StatCode
= gBS
->CreateEvent (
716 if (EFI_ERROR (StatCode
)) {
719 "Could not create transmit timeout event. %r\n",
722 return EFI_DEVICE_ERROR
;
728 StatCode
= gBS
->SetTimer (
734 if (EFI_ERROR (StatCode
)) {
737 "Could not set transmit timeout event timer. %r\n",
740 gBS
->CloseEvent (TimeoutEvent
);
741 return EFI_DEVICE_ERROR
;
745 StatCode
= SnpPtr
->Transmit (
747 (UINTN
) SnpPtr
->Mode
->MediaHeaderSize
,
748 (UINTN
) (PacketLen
+ SnpPtr
->Mode
->MediaHeaderSize
),
750 &SnpModePtr
->CurrentAddress
,
751 (EFI_MAC_ADDRESS
*) HardwareAddr
,
755 if (StatCode
!= EFI_NOT_READY
) {
759 if (!EFI_ERROR (gBS
->CheckEvent (TimeoutEvent
))) {
760 StatCode
= EFI_TIMEOUT
;
765 gBS
->CloseEvent (TimeoutEvent
);
767 if (EFI_ERROR (StatCode
)) {
770 "\nSendPacket() Exit #3 %xh (%r)",
777 // remove transmit buffer from snp's unused queue
778 // done this way in case someday things are buffered and we don't get it back
781 StatCode
= gBS
->CreateEvent (
789 if (EFI_ERROR (StatCode
)) {
792 "Could not create transmit status timeout event. %r\n",
795 return EFI_DEVICE_ERROR
;
801 StatCode
= gBS
->SetTimer (
807 if (EFI_ERROR (StatCode
)) {
810 "Could not set transmit status timeout event timer. %r\n",
813 gBS
->CloseEvent (TimeoutEvent
);
814 return EFI_DEVICE_ERROR
;
818 StatCode
= SnpPtr
->GetStatus (SnpPtr
, &IntStatus
, &TxBuf
);
820 if (EFI_ERROR (StatCode
)) {
823 "\nSendPacket() Exit #4 %xh (%r)",
830 if (IntStatus
& EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT
) {
831 Private
->DidTransmit
= TRUE
;
838 if (!EFI_ERROR (gBS
->CheckEvent (TimeoutEvent
))) {
839 StatCode
= EFI_TIMEOUT
;
844 gBS
->CloseEvent (TimeoutEvent
);
853 IN PXE_BASECODE_DEVICE
*Private
,
854 OUT BIS_APPLICATION_HANDLE
*BisAppHandle
,
855 OUT OPTIONAL EFI_BIS_DATA
**BisDataSigInfo
859 Locate BIS interface and if found, try to start it.
862 Private := Pointer to PxeBc protocol
863 BisAppHandle := Pointer to BIS application handle storage
864 BisDataSigInfo := Pointer to BIS signature information storage
868 EFI_STATUS EfiStatus
;
869 EFI_HANDLE BisHandleBuffer
;
870 UINTN BisHandleCount
;
871 EFI_BIS_PROTOCOL
*BisPtr
;
872 EFI_BIS_VERSION BisInterfaceVersion
;
873 BOOLEAN BisCheckFlag
;
875 BisHandleCount
= sizeof (EFI_HANDLE
);
876 BisCheckFlag
= FALSE
;
879 // Locate BIS protocol handle (if present).
880 // If BIS protocol handle is not found, return NULL.
882 DEBUG ((EFI_D_INFO
, "\ngBS->LocateHandle() "));
884 EfiStatus
= gBS
->LocateHandle (
886 &gEfiBisProtocolGuid
,
892 if (EFI_ERROR (EfiStatus
)) {
894 // Any error means that there is no BIS.
895 // Note - It could mean that there are more than
896 // one BIS protocols installed, but that scenario
897 // is not yet supported.
901 "\nPxebcBisStart()""\n gBS->LocateHandle() %r (%xh)\n",
909 if (BisHandleCount
!= sizeof BisHandleBuffer
) {
911 // This really should never happen, but I am paranoid.
915 "\nPxebcBisStart() BisHandleCount != %d\n",
916 sizeof BisHandleBuffer
)
922 DEBUG ((EFI_D_INFO
, "BIS handle found."));
925 // Locate BIS protocol interface.
926 // If the BIS protocol interface cannot be found, return NULL.
928 DEBUG ((EFI_D_INFO
, "\ngBS->HandleProtocol() "));
930 EfiStatus
= gBS
->HandleProtocol (
932 &gEfiBisProtocolGuid
,
936 if (EFI_ERROR (EfiStatus
)) {
939 "\nPxebcBisStart()""\n gBS->HandleProtocol() %r (%xh)\n",
947 if (BisPtr
== NULL
) {
949 // This really should never happen.
953 "\nPxebcBisStart()""\n gBS->HandleProtocoL() ""BIS protocol interface pointer is NULL!\n")
959 DEBUG ((EFI_D_INFO
, "BIS protocol interface found."));
962 // Check that all of the BIS API function pointers are not NULL.
964 if (BisPtr
->Initialize
== NULL
||
965 BisPtr
->Shutdown
== NULL
||
966 BisPtr
->Free
== NULL
||
967 BisPtr
->GetBootObjectAuthorizationCertificate
== NULL
||
968 BisPtr
->GetBootObjectAuthorizationCheckFlag
== NULL
||
969 BisPtr
->GetBootObjectAuthorizationUpdateToken
== NULL
||
970 BisPtr
->GetSignatureInfo
== NULL
||
971 BisPtr
->UpdateBootObjectAuthorization
== NULL
||
972 BisPtr
->VerifyBootObject
== NULL
||
973 BisPtr
->VerifyObjectWithCredential
== NULL
978 "\nPxebcBisStart()""\n BIS protocol interface is invalid."
979 "\n At least one BIS protocol function pointer is NULL.\n"
987 // If BIS does not initialize, return NULL.
989 DEBUG ((EFI_D_INFO
, "\nBisPtr->Initialize() "));
991 BisInterfaceVersion
.Major
= BIS_VERSION_1
;
993 EfiStatus
= BisPtr
->Initialize (
996 &BisInterfaceVersion
,
1000 if (EFI_ERROR (EfiStatus
)) {
1003 "\nPxebcBisStart()""\n BisPtr->Initialize() %r (%xh)\n",
1013 " BIS version: %d.%d",
1014 BisInterfaceVersion
.Major
,
1015 BisInterfaceVersion
.Minor
)
1019 // If the requested BIS API version is not supported,
1020 // shutdown BIS and return NULL.
1022 if (BisInterfaceVersion
.Major
!= BIS_VERSION_1
) {
1025 "\nPxebcBisStart()""\n BIS version %d.%d not supported by PXE BaseCode.\n",
1026 BisInterfaceVersion
.Major
,
1027 BisInterfaceVersion
.Minor
)
1030 BisPtr
->Shutdown (*BisAppHandle
);
1034 // Get BIS check flag.
1035 // If the BIS check flag cannot be read, shutdown BIS and return NULL.
1037 DEBUG ((EFI_D_INFO
, "\nBisPtr->GetBootObjectAuthorizationCheckFlag() "));
1039 EfiStatus
= BisPtr
->GetBootObjectAuthorizationCheckFlag (*BisAppHandle
, &BisCheckFlag
);
1041 if (EFI_ERROR (EfiStatus
)) {
1044 "\nPxebcBisStart()""\n BisPtr->GetBootObjectAuthorizationCheckFlag() %r (%xh)\n",
1049 BisPtr
->Shutdown (*BisAppHandle
);
1053 // If the BIS check flag is FALSE, shutdown BIS and return NULL.
1055 if (!BisCheckFlag
) {
1056 DEBUG ((EFI_D_INFO
, "\nBIS check flag is FALSE.\n"));
1057 BisPtr
->Shutdown (*BisAppHandle
);
1060 DEBUG ((EFI_D_INFO
, "\nBIS check flag is TRUE."));
1063 // Early out if caller does not want signature information.
1065 if (BisDataSigInfo
== NULL
) {
1069 // Get BIS signature information.
1070 // If the signature information cannot be read or is invalid,
1071 // shutdown BIS and return NULL.
1073 DEBUG ((EFI_D_INFO
, "\nBisPtr->GetSignatureInfo() "));
1075 EfiStatus
= BisPtr
->GetSignatureInfo (*BisAppHandle
, BisDataSigInfo
);
1077 if (EFI_ERROR (EfiStatus
)) {
1080 "\nPxebcBisStart()""\n BisPtr_GetSignatureInfo() %r (%xh)\n",
1085 BisPtr
->Shutdown (*BisAppHandle
);
1089 if (*BisDataSigInfo
== NULL
) {
1091 // This should never happen.
1095 "\nPxebcBisStart()""\n BisPtr->GetSignatureInfo() Data pointer is NULL!\n")
1098 BisPtr
->Shutdown (*BisAppHandle
);
1102 if ((*BisDataSigInfo
)->Length
< sizeof (EFI_BIS_SIGNATURE_INFO
) ||
1103 (*BisDataSigInfo
)->Length
% sizeof (EFI_BIS_SIGNATURE_INFO
) ||
1104 (*BisDataSigInfo
)->Length
> sizeof (EFI_BIS_SIGNATURE_INFO
) * 63
1107 // This should never happen.
1111 "\nPxebcBisStart()""\n BisPtr->GetSignatureInfo() Invalid BIS siginfo length.\n")
1114 BisPtr
->Free (*BisAppHandle
, *BisDataSigInfo
);
1115 BisPtr
->Shutdown (*BisAppHandle
);
1124 EFI_BIS_PROTOCOL
*BisPtr
,
1125 BIS_APPLICATION_HANDLE BisAppHandle
,
1126 EFI_BIS_DATA
*BisDataSigInfo
1129 Routine description:
1130 Stop the BIS interface and release allocations.
1133 BisPtr := Pointer to BIS interface
1134 BisAppHandle := BIS application handle
1135 BisDataSigInfo := Pointer to BIS signature information data
1141 if (BisPtr
== NULL
) {
1145 // Free BIS allocated resources and shutdown BIS.
1146 // Return TRUE - BIS support is officially detected.
1148 if (BisDataSigInfo
!= NULL
) {
1149 BisPtr
->Free (BisAppHandle
, BisDataSigInfo
);
1152 BisPtr
->Shutdown (BisAppHandle
);
1157 PXE_BASECODE_DEVICE
*Private
,
1160 VOID
*CredentialBuffer
,
1161 UINTN CredentialLength
1164 Routine description:
1165 Verify image and credential file.
1168 Private := Pointer to PxeBc interface
1169 FileBuffer := Pointer to image buffer
1170 FileLength := Image length in bytes
1171 CredentialBuffer := Pointer to credential buffer
1172 CredentialLength := Credential length in bytes
1176 FALSE := not verified
1179 EFI_BIS_PROTOCOL
*BisPtr
;
1180 BIS_APPLICATION_HANDLE BisAppHandle
;
1181 EFI_BIS_DATA FileData
;
1182 EFI_BIS_DATA CredentialData
;
1183 EFI_STATUS EfiStatus
;
1186 if (Private
== NULL
|| FileBuffer
== NULL
|| FileLength
== 0 || CredentialBuffer
== NULL
|| CredentialLength
== 0) {
1190 BisPtr
= PxebcBisStart (Private
, &BisAppHandle
, NULL
);
1192 if (BisPtr
== NULL
) {
1196 FileData
.Length
= (UINT32
) FileLength
;
1197 FileData
.Data
= FileBuffer
;
1198 CredentialData
.Length
= (UINT32
) CredentialLength
;
1199 CredentialData
.Data
= CredentialBuffer
;
1201 EfiStatus
= BisPtr
->VerifyBootObject (
1208 PxebcBisStop (BisPtr
, BisAppHandle
, NULL
);
1210 return (BOOLEAN
) ((EFI_ERROR (EfiStatus
)) ? FALSE
: (IsVerified
? TRUE
: FALSE
));
1215 PXE_BASECODE_DEVICE
*Private
1218 Routine description:
1219 Check for BIS interface presence.
1222 Private := Pointer to PxeBc interface
1226 FALSE := BIS not present
1229 EFI_BIS_PROTOCOL
*BisPtr
;
1230 BIS_APPLICATION_HANDLE BisAppHandle
;
1231 EFI_BIS_DATA
*BisDataSigInfo
;
1233 BisPtr
= PxebcBisStart (Private
, &BisAppHandle
, &BisDataSigInfo
);
1235 if (BisPtr
== NULL
) {
1239 PxebcBisStop (BisPtr
, BisAppHandle
, BisDataSigInfo
);
1249 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1254 Routine Description:
1255 Start and initialize the BaseCode protocol, Simple Network protocol and UNDI.
1258 Private - Pointer to Pxe BaseCode Protocol
1259 UseIPv6 - Do we want to support IPv6?
1263 EFI_INVALID_PARAMETER
1266 EFI_OUT_OF_RESOURCES
1267 Status is also returned from SNP.Start() and SNP.Initialize().
1271 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
1272 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
1274 EFI_STATUS StatCode
;
1275 PXE_BASECODE_DEVICE
*Private
;
1278 // Lock the instance data
1280 StatCode
= EFI_SUCCESS
;
1283 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1284 return EFI_INVALID_PARAMETER
;
1287 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1289 if (Private
== NULL
) {
1290 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE pointer == NULL"));
1291 return EFI_INVALID_PARAMETER
;
1294 EfiAcquireLock (&Private
->Lock
);
1297 // Make sure BaseCode is not already started.
1299 if (This
->Mode
->Started
) {
1300 DEBUG ((EFI_D_WARN
, "\nBcStart() BC is already started.\n"));
1301 EfiReleaseLock (&Private
->Lock
);
1302 return EFI_ALREADY_STARTED
;
1307 // Fail if IPv6 is requested and not supported.
1310 DEBUG ((EFI_D_WARN
, "\nBcStart() IPv6 is not supported.\n"));
1311 EfiReleaseLock (&Private
->Lock
);
1312 return EFI_UNSUPPORTED
;
1316 // Setup shortcuts to SNP protocol and data structure.
1318 SnpPtr
= Private
->SimpleNetwork
;
1319 SnpModePtr
= SnpPtr
->Mode
;
1322 // Start and initialize SNP.
1324 if (SnpModePtr
->State
== EfiSimpleNetworkStopped
) {
1325 StatCode
= (*SnpPtr
->Start
) (SnpPtr
);
1327 if (SnpModePtr
->State
!= EfiSimpleNetworkStarted
) {
1328 DEBUG ((EFI_D_WARN
, "\nBcStart() Could not start SNP.\n"));
1329 EfiReleaseLock (&Private
->Lock
);
1334 // acquire memory for mode and transmit/receive buffers
1336 if (SnpModePtr
->State
== EfiSimpleNetworkStarted
) {
1337 StatCode
= (*SnpPtr
->Initialize
) (SnpPtr
, 0, 0);
1339 if (SnpModePtr
->State
!= EfiSimpleNetworkInitialized
) {
1340 DEBUG ((EFI_D_WARN
, "\nBcStart() Could not initialize SNP."));
1341 EfiReleaseLock (&Private
->Lock
);
1348 DEBUG ((EFI_D_INFO
, "\nBC Start()"));
1351 "\nSnpModePtr->State %Xh",
1356 "\nSnpModePtr->HwAddressSize %Xh",
1357 SnpModePtr
->HwAddressSize
)
1361 "\nSnpModePtr->MediaHeaderSize %Xh",
1362 SnpModePtr
->MediaHeaderSize
)
1366 "\nSnpModePtr->MaxPacketSize %Xh",
1367 SnpModePtr
->MaxPacketSize
)
1371 "\nSnpModePtr->MacAddressChangeable %Xh",
1372 SnpModePtr
->MacAddressChangeable
)
1376 "\nSnpModePtr->MultipleTxSupported %Xh",
1377 SnpModePtr
->MultipleTxSupported
)
1381 "\nSnpModePtr->CurrentAddress %Xh",
1382 *((UINTN
*)&SnpModePtr
->CurrentAddress
))
1386 "\nSnpModePtr->BroadcastAddress %Xh",
1387 *((UINTN
*)&SnpModePtr
->BroadcastAddress
))
1391 "\nSnpModePtr->PermanentAddress %Xh",
1392 *((UINTN
*)&SnpModePtr
->PermanentAddress
))
1396 "\nSnpModePtr->NvRamSize %Xh",
1397 SnpModePtr
->NvRamSize
)
1401 "\nSnpModePtr->NvRamAccessSize %Xh",
1402 SnpModePtr
->NvRamAccessSize
)
1406 "\nSnpModePtr->ReceiveFilterMask %Xh",
1407 SnpModePtr
->ReceiveFilterMask
)
1411 "\nSnpModePtr->ReceiveFilterSetting %Xh",
1412 SnpModePtr
->ReceiveFilterSetting
)
1416 "\nSnpModePtr->MCastFilterCount %Xh",
1417 SnpModePtr
->MCastFilterCount
)
1421 "\nSnpModePtr->MCastFilter %Xh",
1422 SnpModePtr
->MCastFilter
)
1426 "\nSnpModePtr->IfType %Xh",
1431 "\nSnpModePtr->MediaPresentSupported %Xh",
1432 SnpModePtr
->MediaPresentSupported
)
1436 "\nSnpModePtr->MediaPresent %Xh",
1437 SnpModePtr
->MediaPresent
)
1441 // If media check is supported and there is no media,
1442 // return error to caller.
1444 if (SnpModePtr
->MediaPresentSupported
&& !SnpModePtr
->MediaPresent
) {
1445 DEBUG ((EFI_D_WARN
, "\nBcStart() Media not present.\n"));
1446 EfiReleaseLock (&Private
->Lock
);
1447 return EFI_NO_MEDIA
;
1450 // Allocate Tx/Rx buffers
1452 Status
= gBS
->AllocatePool (
1453 EfiBootServicesData
,
1454 BUFFER_ALLOCATE_SIZE
,
1455 (VOID
**) &Private
->TransmitBufferPtr
1458 if (!EFI_ERROR (Status
)) {
1459 ZeroMem (Private
->TransmitBufferPtr
, BUFFER_ALLOCATE_SIZE
);
1461 DEBUG ((EFI_D_NET
, "\nBcStart() Could not alloc TxBuf.\n"));
1462 EfiReleaseLock (&Private
->Lock
);
1463 return EFI_OUT_OF_RESOURCES
;
1466 Status
= gBS
->AllocatePool (
1467 EfiBootServicesData
,
1468 BUFFER_ALLOCATE_SIZE
,
1469 (VOID
**) &Private
->ReceiveBufferPtr
1472 if (!EFI_ERROR (Status
)) {
1473 ZeroMem (Private
->ReceiveBufferPtr
, BUFFER_ALLOCATE_SIZE
);
1475 DEBUG ((EFI_D_NET
, "\nBcStart() Could not alloc RxBuf.\n"));
1476 gBS
->FreePool (Private
->TransmitBufferPtr
);
1477 EfiReleaseLock (&Private
->Lock
);
1478 return EFI_OUT_OF_RESOURCES
;
1481 Status
= gBS
->AllocatePool (
1482 EfiBootServicesData
,
1484 (VOID
**) &Private
->TftpErrorBuffer
1487 if (EFI_ERROR (Status
)) {
1488 gBS
->FreePool (Private
->ReceiveBufferPtr
);
1489 gBS
->FreePool (Private
->TransmitBufferPtr
);
1490 EfiReleaseLock (&Private
->Lock
);
1491 return EFI_OUT_OF_RESOURCES
;
1494 Status
= gBS
->AllocatePool (EfiBootServicesData
, 256, (VOID
**) &Private
->TftpAckBuffer
);
1496 if (EFI_ERROR (Status
)) {
1497 gBS
->FreePool (Private
->TftpErrorBuffer
);
1498 gBS
->FreePool (Private
->ReceiveBufferPtr
);
1499 gBS
->FreePool (Private
->TransmitBufferPtr
);
1500 EfiReleaseLock (&Private
->Lock
);
1501 return EFI_OUT_OF_RESOURCES
;
1504 // Initialize private BaseCode instance data
1507 Private
->RandomPort
= (UINT16
) (Private
->RandomPort
+ PXE_RND_PORT_LOW
+ Random (Private
));
1508 } while (Private
->RandomPort
< PXE_RND_PORT_LOW
);
1510 Private
->Igmpv1TimeoutEvent
= NULL
;
1511 Private
->UseIgmpv1Reporting
= TRUE
;
1512 Private
->IpLength
= IP_ADDRESS_LENGTH (Private
->EfiBc
.Mode
);
1515 // Initialize Mode structure
1518 // check for callback protocol and set boolean
1520 SetMakeCallback (Private
);
1521 Private
->EfiBc
.Mode
->Started
= TRUE
;
1522 Private
->EfiBc
.Mode
->TTL
= DEFAULT_TTL
;
1523 Private
->EfiBc
.Mode
->ToS
= DEFAULT_ToS
;
1524 Private
->EfiBc
.Mode
->UsingIpv6
= UseIPv6
;
1525 Private
->EfiBc
.Mode
->DhcpDiscoverValid
= FALSE
;
1526 Private
->EfiBc
.Mode
->DhcpAckReceived
= FALSE
;
1527 Private
->EfiBc
.Mode
->ProxyOfferReceived
= FALSE
;
1528 Private
->EfiBc
.Mode
->PxeDiscoverValid
= FALSE
;
1529 Private
->EfiBc
.Mode
->PxeReplyReceived
= FALSE
;
1530 Private
->EfiBc
.Mode
->PxeBisReplyReceived
= FALSE
;
1531 Private
->EfiBc
.Mode
->IcmpErrorReceived
= FALSE
;
1532 Private
->EfiBc
.Mode
->TftpErrorReceived
= FALSE
;
1533 ZeroMem (&Private
->EfiBc
.Mode
->StationIp
, sizeof (EFI_IP_ADDRESS
));
1534 ZeroMem (&Private
->EfiBc
.Mode
->SubnetMask
, sizeof (EFI_IP_ADDRESS
));
1535 Private
->EfiBc
.Mode
->IpFilter
.Filters
= 0;
1536 Private
->EfiBc
.Mode
->IpFilter
.IpCnt
= 0;
1537 Private
->EfiBc
.Mode
->ArpCacheEntries
= 0;
1538 Private
->EfiBc
.Mode
->RouteTableEntries
= 0;
1539 ZeroMem (&Private
->EfiBc
.Mode
->IcmpError
, sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR
));
1540 ZeroMem (&Private
->EfiBc
.Mode
->TftpError
, sizeof (EFI_PXE_BASE_CODE_TFTP_ERROR
));
1543 // Set to PXE_TRUE by the BC constructor if this BC implementation
1546 Private
->EfiBc
.Mode
->Ipv6Supported
= SUPPORT_IPV6
;
1549 Private
->EfiBc
.Mode
->Ipv6Available
= Private
->NiiPtr
->Ipv6Supported
;
1551 Private
->EfiBc
.Mode
->Ipv6Available
= FALSE
;
1554 // Set to TRUE by the BC constructor if this BC implementation
1557 Private
->EfiBc
.Mode
->BisSupported
= TRUE
;
1558 Private
->EfiBc
.Mode
->BisDetected
= PxebcBisDetect (Private
);
1561 // This field is set to PXE_TRUE by the BC Start() function. When this
1562 // field is PXE_TRUE, ARP packets are sent as needed to get IP and MAC
1563 // addresses. This can cause unexpected delays in the DHCP(), Discover()
1564 // and MTFTP() functions. Setting this to PXE_FALSE will cause these
1565 // functions to fail if the required IP/MAC information is not in the
1566 // ARP cache. The value of this field can be changed by an application
1569 Private
->EfiBc
.Mode
->AutoArp
= TRUE
;
1572 // Unlock the instance data
1574 EfiReleaseLock (&Private
->Lock
);
1581 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
1585 Routine Description:
1586 Stop the BaseCode protocol, Simple Network protocol and UNDI.
1589 Private - Pointer to Pxe BaseCode Protocol
1593 0 - Successfully stopped
1598 // Lock the instance data
1600 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1601 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
1602 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
1603 EFI_STATUS StatCode
;
1604 PXE_BASECODE_DEVICE
*Private
;
1606 StatCode
= EFI_SUCCESS
;
1609 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1610 return EFI_INVALID_PARAMETER
;
1613 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1615 if (Private
== NULL
) {
1616 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1617 return EFI_INVALID_PARAMETER
;
1620 EfiAcquireLock (&Private
->Lock
);
1622 PxebcMode
= Private
->EfiBc
.Mode
;
1623 SnpPtr
= Private
->SimpleNetwork
;
1624 SnpModePtr
= SnpPtr
->Mode
;
1629 StatCode
= EFI_NOT_STARTED
;
1631 if (SnpModePtr
->State
== EfiSimpleNetworkInitialized
) {
1632 StatCode
= (*SnpPtr
->Shutdown
) (SnpPtr
);
1635 if (SnpModePtr
->State
== EfiSimpleNetworkStarted
) {
1636 StatCode
= (*SnpPtr
->Stop
) (SnpPtr
);
1639 if (Private
->TransmitBufferPtr
!= NULL
) {
1640 gBS
->FreePool (Private
->TransmitBufferPtr
);
1641 Private
->TransmitBufferPtr
= NULL
;
1644 if (Private
->ReceiveBufferPtr
!= NULL
) {
1645 gBS
->FreePool (Private
->ReceiveBufferPtr
);
1646 Private
->ReceiveBufferPtr
= NULL
;
1649 if (Private
->ArpBuffer
!= NULL
) {
1650 gBS
->FreePool (Private
->ArpBuffer
);
1651 Private
->ArpBuffer
= NULL
;
1654 if (Private
->TftpErrorBuffer
!= NULL
) {
1655 gBS
->FreePool (Private
->TftpErrorBuffer
);
1656 Private
->TftpErrorBuffer
= NULL
;
1659 if (Private
->TftpAckBuffer
!= NULL
) {
1660 gBS
->FreePool (Private
->TftpAckBuffer
);
1661 Private
->TftpAckBuffer
= NULL
;
1664 if (Private
->Igmpv1TimeoutEvent
!= NULL
) {
1665 gBS
->CloseEvent (Private
->Igmpv1TimeoutEvent
);
1666 Private
->Igmpv1TimeoutEvent
= NULL
;
1669 Private
->FileSize
= 0;
1670 Private
->EfiBc
.Mode
->Started
= FALSE
;
1673 // Unlock the instance data
1675 EfiReleaseLock (&Private
->Lock
);
1679 const IPV4_ADDR AllSystemsGroup
= { { 224, 0, 0, 1 } };
1683 IN PXE_BASECODE_DEVICE
*Private
,
1684 IN EFI_PXE_BASE_CODE_IP_FILTER
*Filter
1688 Routine Description:
1689 Set up the IP filter
1692 Private - Pointer to Pxe BaseCode Protocol
1693 Filter - Pointer to the filter
1697 0 - Successfully set the filter
1701 EFI_STATUS StatCode
;
1702 EFI_MAC_ADDRESS MACadds
[PXE_IP_FILTER_SIZE
];
1703 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1704 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
1705 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
1711 PxebcMode
= Private
->EfiBc
.Mode
;
1712 SnpPtr
= Private
->SimpleNetwork
;
1713 SnpModePtr
= SnpPtr
->Mode
;
1716 // validate input parameters
1717 // must have a filter
1718 // must not have any extra filter bits set
1720 if (Filter
== NULL
||
1721 (Filter
->Filters
&~FILTER_BITS
)
1723 // must not have a count which is too large or with no IP list
1726 (Filter
->IpCnt
&& (!Filter
->IpList
|| Filter
->IpCnt
> PXE_IP_FILTER_SIZE
))
1728 // must not have incompatible filters - promiscuous incompatible with anything else
1732 (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) &&
1733 ((Filter
->Filters
&~EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) || Filter
->IpCnt
)
1736 DEBUG ((EFI_D_INFO
, "\nIpFilter() Exit #1"));
1737 return EFI_INVALID_PARAMETER
;
1740 // promiscuous multicast incompatible with multicast in IP list
1742 if (Filter
->IpCnt
&& (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
)) {
1743 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1744 if (IS_MULTICAST (&Filter
->IpList
[Index
])) {
1745 DEBUG ((EFI_D_INFO
, "\nIpFilter() Exit #2"));
1746 return EFI_INVALID_PARAMETER
;
1751 // leave groups for all those multicast which are no longer enabled
1753 for (Index
= 0; Index
< PxebcMode
->IpFilter
.IpCnt
; ++Index
) {
1754 if (!IS_MULTICAST (&PxebcMode
->IpFilter
.IpList
[Index
])) {
1758 for (Index2
= 0; Index2
< Filter
->IpCnt
; ++Index2
) {
1759 if (!CompareMem (&PxebcMode
->IpFilter
.IpList
[Index
], &Filter
->IpList
[Index2
], IP_ADDRESS_LENGTH (PxebcMode
))) {
1767 // if we didn't find it, remove from group
1769 if (Index2
== Filter
->IpCnt
) {
1770 IgmpLeaveGroup (Private
, &PxebcMode
->IpFilter
.IpList
[Index
]);
1774 // set enable bits, convert multicast ip adds, join groups
1775 // allways leave receive broadcast enabled at hardware layer
1779 if (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) {
1780 Enable
= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
1782 if (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
) {
1783 Enable
= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
1785 Enable
= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
1787 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1788 CopyMem (&(PxebcMode
->IpFilter
.IpList
[Index
]), &(Filter
->IpList
[Index
]), sizeof (EFI_IP_ADDRESS
));
1790 if (IS_MULTICAST (&Filter
->IpList
[Index
])) {
1791 EFI_IP_ADDRESS
*TmpIp
;
1793 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
1796 // if this is the first group, add the all systems group to mcast list
1801 if (PxebcMode
->UsingIpv6
) {
1807 TmpIp
= (EFI_IP_ADDRESS
*) &AllSystemsGroup
;
1810 TmpIp
= (EFI_IP_ADDRESS
*) &Filter
->IpList
[Index
];
1813 // get MAC address of IP
1815 StatCode
= (*SnpPtr
->MCastIpToMac
) (SnpPtr
, PxebcMode
->UsingIpv6
, TmpIp
, &MACadds
[Index2
++]);
1817 if (EFI_ERROR (StatCode
)) {
1820 "\nIpFilter() Exit #2 %Xh (%r)",
1827 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
1832 if (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
) {
1833 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
1837 // if nothing changed, just return
1841 "\nsnp->ReceiveFilterSetting == %Xh Filter->IpCnt == %Xh",
1842 SnpModePtr
->ReceiveFilterSetting
,
1846 if (SnpModePtr
->ReceiveFilterSetting
== Enable
&& !Filter
->IpCnt
) {
1847 DEBUG ((EFI_D_INFO
, "\nIpFilter() Exit #4"));
1851 // disable those currently set but not set in new filter
1853 Disable
= SnpModePtr
->ReceiveFilterSetting
&~Enable
;
1855 StatCode
= SnpPtr
->ReceiveFilters (SnpPtr
, Enable
, Disable
, FALSE
, Index2
, MACadds
);
1857 PxebcMode
->IpFilter
.IpCnt
= Filter
->IpCnt
;
1860 // join groups for all multicast in list
1862 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1863 if (IS_MULTICAST (&Filter
->IpList
[Index
])) {
1864 IgmpJoinGroup (Private
, &Filter
->IpList
[Index
]);
1868 DEBUG ((EFI_D_INFO
, "\nIpFilter() Exit #5 %Xh (%r)", StatCode
, StatCode
));
1876 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1877 IN EFI_PXE_BASE_CODE_IP_FILTER
*Filter
1881 Routine Description:
1885 Private - Pointer to Pxe BaseCode Protocol
1886 Filter - Pointer to the filter
1890 0 - Successfully set the filter
1894 EFI_STATUS StatCode
;
1895 PXE_BASECODE_DEVICE
*Private
;
1898 // Lock the instance data and make sure started
1900 StatCode
= EFI_SUCCESS
;
1903 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1904 return EFI_INVALID_PARAMETER
;
1907 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1909 if (Private
== NULL
) {
1910 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1911 return EFI_INVALID_PARAMETER
;
1914 EfiAcquireLock (&Private
->Lock
);
1916 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
1917 DEBUG ((EFI_D_ERROR
, "BC was not started."));
1918 EfiReleaseLock (&Private
->Lock
);
1919 return EFI_NOT_STARTED
;
1922 if (Filter
== NULL
) {
1923 return EFI_INVALID_PARAMETER
;
1928 StatCode
= IpFilter (Private
, Filter
);
1931 // Unlock the instance data
1933 EfiReleaseLock (&Private
->Lock
);
1940 EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1941 BOOLEAN
*AutoArpPtr
,
1942 BOOLEAN
*SendGuidPtr
,
1943 UINT8
*TimeToLivePtr
,
1944 UINT8
*TypeOfServicePtr
,
1945 BOOLEAN
*MakeCallbackPtr
1949 Routine Description:
1950 Set the Base Code behavior parameters
1953 This - Pointer to Pxe BaseCode Protocol
1954 AutoArpPtr - Boolean to do ARP stuff
1955 SendGuidPtr - Boolean whether or not to send GUID info
1956 TimeToLivePtr - Value for Total time to live
1957 TypeOfServicePtr - Value for Type of Service
1958 MakeCallbackPtr - Boolean to determine if we make callbacks
1962 0 - Successfully set the parameters
1966 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1968 CHAR8
*SerialNumberPtr
;
1969 EFI_STATUS StatCode
;
1970 PXE_BASECODE_DEVICE
*Private
;
1973 // Lock the instance data and make sure started
1975 StatCode
= EFI_SUCCESS
;
1978 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1979 return EFI_INVALID_PARAMETER
;
1982 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1984 if (Private
== NULL
) {
1985 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1986 return EFI_INVALID_PARAMETER
;
1989 EfiAcquireLock (&Private
->Lock
);
1991 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
1992 DEBUG ((EFI_D_ERROR
, "BC was not started."));
1993 EfiReleaseLock (&Private
->Lock
);
1994 return EFI_NOT_STARTED
;
1997 DEBUG ((EFI_D_INFO
, "\nSetParameters() Entry. "));
1999 PxebcMode
= Private
->EfiBc
.Mode
;
2000 StatCode
= EFI_SUCCESS
;
2002 if (SendGuidPtr
!= NULL
) {
2004 if (PxeBcLibGetSmbiosSystemGuidAndSerialNumber (&TmpGuid
, &SerialNumberPtr
) != EFI_SUCCESS
) {
2005 return EFI_INVALID_PARAMETER
;
2010 if (MakeCallbackPtr
!= NULL
) {
2011 if (*MakeCallbackPtr
) {
2012 if (!SetMakeCallback (Private
)) {
2013 return EFI_INVALID_PARAMETER
;
2017 PxebcMode
->MakeCallbacks
= *MakeCallbackPtr
;
2020 if (AutoArpPtr
!= NULL
) {
2021 PxebcMode
->AutoArp
= *AutoArpPtr
;
2024 if (SendGuidPtr
!= NULL
) {
2025 PxebcMode
->SendGUID
= *SendGuidPtr
;
2028 if (TimeToLivePtr
!= NULL
) {
2029 PxebcMode
->TTL
= *TimeToLivePtr
;
2032 if (TypeOfServicePtr
!= NULL
) {
2033 PxebcMode
->ToS
= *TypeOfServicePtr
;
2036 // Unlock the instance data
2038 DEBUG ((EFI_D_INFO
, "\nSetparameters() Exit = %xh ", StatCode
));
2040 EfiReleaseLock (&Private
->Lock
);
2044 // //////////////////////////////////////////////////////////
2046 // BC Set Station IP Routine
2051 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
2052 IN EFI_IP_ADDRESS
*StationIpPtr
,
2053 IN EFI_IP_ADDRESS
*SubnetMaskPtr
2057 Routine Description:
2058 Set the station IP address
2061 This - Pointer to Pxe BaseCode Protocol
2062 StationIpPtr - Pointer to the requested IP address to set in base code
2063 SubnetMaskPtr - Pointer to the requested subnet mask for the base code
2067 EFI_SUCCESS - Successfully set the parameters
2068 EFI_NOT_STARTED - BC has not started
2071 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
2072 EFI_STATUS StatCode
;
2073 PXE_BASECODE_DEVICE
*Private
;
2076 // Lock the instance data and make sure started
2078 StatCode
= EFI_SUCCESS
;
2081 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
2082 return EFI_INVALID_PARAMETER
;
2085 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
2087 if (Private
== NULL
) {
2088 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
2089 return EFI_INVALID_PARAMETER
;
2092 EfiAcquireLock (&Private
->Lock
);
2094 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
2095 DEBUG ((EFI_D_ERROR
, "BC was not started."));
2096 EfiReleaseLock (&Private
->Lock
);
2097 return EFI_NOT_STARTED
;
2100 PxebcMode
= Private
->EfiBc
.Mode
;
2102 if (StationIpPtr
!= NULL
) {
2103 CopyMem (&PxebcMode
->StationIp
, StationIpPtr
, sizeof (EFI_IP_ADDRESS
));
2104 Private
->GoodStationIp
= TRUE
;
2107 if (SubnetMaskPtr
!= NULL
) {
2108 CopyMem (&PxebcMode
->SubnetMask
, SubnetMaskPtr
, sizeof (EFI_IP_ADDRESS
));
2111 // Unlock the instance data
2113 EfiReleaseLock (&Private
->Lock
);
2118 EFI_DRIVER_BINDING_PROTOCOL gPxeBcDriverBinding
= {
2119 PxeBcDriverSupported
,
2129 PxeBcDriverSupported (
2130 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2131 IN EFI_HANDLE Controller
,
2132 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
2136 Routine Description:
2137 Test to see if this driver supports Controller. Any Controller
2138 than contains a Snp protocol can be supported.
2141 This - Protocol instance pointer.
2142 Controller - Handle of device to test.
2143 RemainingDevicePath - Not used.
2146 EFI_SUCCESS - This driver supports this device.
2147 EFI_ALREADY_STARTED - This driver is already running on this device.
2148 other - This driver does not support this device.
2153 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
2155 Status
= gBS
->OpenProtocol (
2157 &gEfiDevicePathProtocolGuid
,
2159 This
->DriverBindingHandle
,
2161 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
2164 if (EFI_ERROR (Status
)) {
2168 Status
= gBS
->OpenProtocol (
2170 &gEfiSimpleNetworkProtocolGuid
,
2172 This
->DriverBindingHandle
,
2174 EFI_OPEN_PROTOCOL_BY_DRIVER
2176 if (EFI_ERROR (Status
)) {
2180 gBS
->CloseProtocol (
2182 &gEfiSimpleNetworkProtocolGuid
,
2183 This
->DriverBindingHandle
,
2193 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2194 IN EFI_HANDLE Controller
,
2195 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
2199 Routine Description:
2200 Start the Base code driver.
2203 This - Protocol instance pointer.
2204 Controller - Handle of device to test.
2205 RemainingDevicePath - Not used.
2208 EFI_SUCCESS - This driver supports this device.
2209 EFI_ALREADY_STARTED - This driver is already running on this device.
2210 other - This driver does not support this device.
2215 PXE_BASECODE_DEVICE
*Private
;
2216 LOADFILE_DEVICE
*pLF
;
2219 // Allocate structures needed by BaseCode and LoadFile protocols.
2221 Status
= gBS
->AllocatePool (
2222 EfiBootServicesData
,
2223 sizeof (PXE_BASECODE_DEVICE
),
2227 if (!EFI_ERROR (Status
)) {
2228 ZeroMem (Private
, sizeof (PXE_BASECODE_DEVICE
));
2230 DEBUG ((EFI_D_NET
, "\nBcNotifySnp() Could not alloc PXE_BASECODE_DEVICE structure.\n"));
2234 Status
= gBS
->AllocatePool (
2235 EfiBootServicesData
,
2236 sizeof (LOADFILE_DEVICE
),
2240 if (!EFI_ERROR (Status
)) {
2241 ZeroMem (pLF
, sizeof (LOADFILE_DEVICE
));
2243 DEBUG ((EFI_D_NET
, "\nBcNotifySnp() Could not alloc LOADFILE_DEVICE structure.\n"));
2244 gBS
->FreePool (Private
);
2248 Status
= gBS
->AllocatePool (
2249 EfiBootServicesData
,
2250 sizeof (EFI_PXE_BASE_CODE_MODE
),
2251 (VOID
**) &Private
->EfiBc
.Mode
2254 if (!EFI_ERROR (Status
)) {
2255 ZeroMem (Private
->EfiBc
.Mode
, sizeof (EFI_PXE_BASE_CODE_MODE
));
2257 DEBUG ((EFI_D_NET
, "\nBcNotifySnp() Could not alloc Mode structure.\n"));
2258 gBS
->FreePool (Private
);
2259 gBS
->FreePool (pLF
);
2263 // Lock access, just in case
2265 EfiInitializeLock (&Private
->Lock
, EFI_TPL_CALLBACK
);
2266 EfiAcquireLock (&Private
->Lock
);
2268 EfiInitializeLock (&pLF
->Lock
, EFI_TPL_CALLBACK
);
2269 EfiAcquireLock (&pLF
->Lock
);
2272 // Initialize PXE structure
2275 // First initialize the internal 'private' data that the application
2278 Private
->Signature
= PXE_BASECODE_DEVICE_SIGNATURE
;
2279 Private
->Handle
= Controller
;
2282 // Get the NII interface
2284 Status
= gBS
->OpenProtocol (
2286 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
2287 (VOID
**) &Private
->NiiPtr
,
2288 This
->DriverBindingHandle
,
2290 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2293 if (EFI_ERROR (Status
)) {
2294 Status
= gBS
->OpenProtocol (
2296 &gEfiNetworkInterfaceIdentifierProtocolGuid
,
2297 (VOID
**) &Private
->NiiPtr
,
2298 This
->DriverBindingHandle
,
2300 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2303 if (EFI_ERROR (Status
)) {
2308 // Get the Snp interface
2310 Status
= gBS
->OpenProtocol (
2312 &gEfiSimpleNetworkProtocolGuid
,
2313 (VOID
**) &Private
->SimpleNetwork
,
2314 This
->DriverBindingHandle
,
2316 EFI_OPEN_PROTOCOL_BY_DRIVER
2319 if (EFI_ERROR (Status
)) {
2324 // Next, initialize the external 'public' data that
2325 // the application does see.
2327 Private
->EfiBc
.Revision
= EFI_PXE_BASE_CODE_INTERFACE_REVISION
;
2328 Private
->EfiBc
.Start
= BcStart
;
2329 Private
->EfiBc
.Stop
= BcStop
;
2330 Private
->EfiBc
.Dhcp
= BcDhcp
;
2331 Private
->EfiBc
.Discover
= BcDiscover
;
2332 Private
->EfiBc
.Mtftp
= BcMtftp
;
2333 Private
->EfiBc
.UdpWrite
= BcUdpWrite
;
2334 Private
->EfiBc
.UdpRead
= BcUdpRead
;
2335 Private
->EfiBc
.Arp
= BcArp
;
2336 Private
->EfiBc
.SetIpFilter
= BcIpFilter
;
2337 Private
->EfiBc
.SetParameters
= BcSetParameters
;
2338 Private
->EfiBc
.SetStationIp
= BcSetStationIP
;
2339 Private
->EfiBc
.SetPackets
= BcSetPackets
;
2342 // Initialize BaseCode Mode structure
2344 Private
->EfiBc
.Mode
->Started
= FALSE
;
2345 Private
->EfiBc
.Mode
->TTL
= DEFAULT_TTL
;
2346 Private
->EfiBc
.Mode
->ToS
= DEFAULT_ToS
;
2347 Private
->EfiBc
.Mode
->UsingIpv6
= FALSE
;
2348 Private
->EfiBc
.Mode
->AutoArp
= TRUE
;
2351 // Set to PXE_TRUE by the BC constructor if this BC
2352 // implementation supports IPv6.
2354 Private
->EfiBc
.Mode
->Ipv6Supported
= SUPPORT_IPV6
;
2357 Private
->EfiBc
.Mode
->Ipv6Available
= Private
->NiiPtr
->Ipv6Supported
;
2359 Private
->EfiBc
.Mode
->Ipv6Available
= FALSE
;
2362 // Set to TRUE by the BC constructor if this BC
2363 // implementation supports BIS.
2365 Private
->EfiBc
.Mode
->BisSupported
= TRUE
;
2366 Private
->EfiBc
.Mode
->BisDetected
= PxebcBisDetect (Private
);
2369 // Initialize LoadFile structure.
2371 pLF
->Signature
= LOADFILE_DEVICE_SIGNATURE
;
2372 pLF
->LoadFile
.LoadFile
= LoadFile
;
2373 pLF
->Private
= Private
;
2376 // Install protocol interfaces.
2378 Status
= gBS
->InstallMultipleProtocolInterfaces (
2380 &gEfiPxeBaseCodeProtocolGuid
,
2382 &gEfiLoadFileProtocolGuid
,
2387 if (EFI_ERROR (Status
)) {
2388 gBS
->CloseProtocol (
2390 &gEfiSimpleNetworkProtocolGuid
,
2391 This
->DriverBindingHandle
,
2400 EfiReleaseLock (&pLF
->Lock
);
2401 EfiReleaseLock (&Private
->Lock
);
2405 gBS
->FreePool (Private
->EfiBc
.Mode
);
2406 gBS
->FreePool (Private
);
2407 gBS
->FreePool (pLF
);
2414 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2415 IN EFI_HANDLE Controller
,
2416 IN UINTN NumberOfChildren
,
2417 IN EFI_HANDLE
*ChildHandleBuffer
2421 Routine Description:
2422 Stop the Base code driver.
2425 This - Protocol instance pointer.
2426 Controller - Handle of device to test.
2427 NumberOfChildren - Not used
2428 ChildHandleBuffer - Not used
2431 EFI_SUCCESS - This driver supports this device.
2432 EFI_ALREADY_STARTED - This driver is already running on this device.
2433 other - This driver does not support this device.
2438 EFI_LOAD_FILE_PROTOCOL
*LfProtocol
;
2439 LOADFILE_DEVICE
*LoadDevice
;
2442 // Get our context back.
2444 Status
= gBS
->OpenProtocol (
2446 &gEfiLoadFileProtocolGuid
,
2447 (VOID
**) &LfProtocol
,
2448 This
->DriverBindingHandle
,
2450 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2453 if (EFI_ERROR (Status
)) {
2454 return EFI_UNSUPPORTED
;
2457 LoadDevice
= EFI_LOAD_FILE_DEV_FROM_THIS (LfProtocol
);
2459 Status
= gBS
->UninstallMultipleProtocolInterfaces (
2461 &gEfiLoadFileProtocolGuid
,
2462 &LoadDevice
->LoadFile
,
2463 &gEfiPxeBaseCodeProtocolGuid
,
2464 &LoadDevice
->Private
->EfiBc
,
2468 if (!EFI_ERROR (Status
)) {
2470 Status
= gBS
->CloseProtocol (
2472 &gEfiSimpleNetworkProtocolGuid
,
2473 This
->DriverBindingHandle
,
2477 gBS
->FreePool (LoadDevice
->Private
->EfiBc
.Mode
);
2478 gBS
->FreePool (LoadDevice
->Private
);
2479 gBS
->FreePool (LoadDevice
);
2487 InitializeBCDriver (
2488 IN EFI_HANDLE ImageHandle
,
2489 IN EFI_SYSTEM_TABLE
*SystemTable
2493 Routine Description:
2494 Initialize the base code drivers and install the driver binding
2497 Standard EFI Image Entry
2500 EFI_SUCCESS - This driver was successfully bound
2505 OptionsStrucInit ();