3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
33 Convert number to ASCII value
36 Number - Numeric value to convert to decimal ASCII value.
37 Buffer - Buffer to place ASCII version of the Number
38 Length - Length of Buffer.
48 Remainder
= Number
% 10;
50 Buffer
[Length
] = (UINT8
) ('0' + Remainder
);
62 Convert number to decimal ASCII value at Buffer location
65 Number - Numeric value to convert to decimal ASCII value.
66 Buffer - Buffer to place ASCII version of the Number
77 CvtNum (Number
, BuffArray
, 30);
79 for (Index
= 0; Index
< 30; ++Index
) {
80 if (BuffArray
[Index
] != '0') {
85 CopyMem (Buffer
, BuffArray
+ Index
, 31 - Index
);
95 Convert ASCII numeric string to a UINTN value
98 Number - Numeric value to convert to decimal ASCII value.
99 Buffer - Buffer to place ASCII version of the Number
102 Value - UINTN value of the ASCII string.
110 Character
= *Buffer
++;
112 Value
= Value
* 10 + Character
- '0';
113 Character
= *Buffer
++;
126 Convert ASCII numeric string to a UINTN value
129 Number - Numeric value to convert to decimal ASCII value.
130 Buffer - Buffer to place ASCII version of the Number
133 Value - UINTN value of the ASCII string.
141 while ((Character
= *Buffer
++) != '\0') {
142 Value
= MultU64x32 (Value
, 10) + (Character
- '0');
148 // random number generator
150 #define RANDOM_MULTIPLIER 2053
151 #define RANDOM_ADD_IN_VALUE 19
155 IN PXE_BASECODE_DEVICE
*Private
,
156 IN UINT16 InitialSeed
161 Initialize the Seed for the random number generator
170 if (Private
!= NULL
) {
171 Private
->RandomSeed
= InitialSeed
;
177 IN PXE_BASECODE_DEVICE
*Private
182 Generate and return a pseudo-random number
187 Number - UINT16 random number
193 if (Private
!= NULL
) {
194 Number
= -(INTN
) Private
->RandomSeed
* RANDOM_MULTIPLIER
+ RANDOM_ADD_IN_VALUE
;
196 return Private
->RandomSeed
= (UINT16
) Number
;
202 // calculate the internet checksum (RFC 1071)
203 // return 16 bit ones complement of ones complement sum of 16 bit words
213 Calculate the internet checksum (see RFC 1071)
216 Packet - Buffer which contains the data to be checksummed
217 Length - Length to be checksummed
220 Checksum - Returns the 16 bit ones complement of
221 ones complement sum of 16 bit words
229 Odd
= (UINT8
) (Length
& 1);
236 Sum
+= *(UINT8
*) Packet
;
239 Sum
= (Sum
& 0xffff) + (Sum
>> 16);
241 // in case above carried
245 return (UINT16
) (~ (UINT16
) Sum
);
258 Calculate the internet checksum (see RFC 1071)
259 on a non contiguous header and data
262 Header - Buffer which contains the data to be checksummed
263 HeaderLen - Length to be checksummed
264 Message - Buffer which contains the data to be checksummed
265 MessageLen - Length to be checksummed
268 Checksum - Returns the 16 bit ones complement of
269 ones complement sum of 16 bit words
275 Sum
= (UINT16
)~IpChecksum (Header
, HeaderLen
);
276 Sum
= Sum
+ (UINT16
)~IpChecksum (Message
, MessageLen
);
278 // in case above carried
282 return (UINT16
) (~ (UINT16
) Sum
);
294 Adjust the internet checksum (see RFC 1071) on a single word update.
297 OldChkSum - Checksum previously calculated
302 Checksum - Returns the 16 bit ones complement of
303 ones complement sum of 16 bit words
309 sum
= ~OldChksum
+ NewWord
- OldWord
;
311 // in case above carried
314 return (UINT16
) (~ (UINT16
) sum
);
320 IN PXE_BASECODE_DEVICE
*Private
325 See if a callback is in play
328 Private - Pointer to Pxe BaseCode Protocol
331 0 - Callbacks are active on the handle
332 1 - Callbacks are not active on the handle
336 Private
->EfiBc
.Mode
->MakeCallbacks
= (BOOLEAN
) (gBS
->HandleProtocol (
338 &gEfiPxeBaseCodeCallbackProtocolGuid
,
339 (VOID
*) &Private
->CallbackProtocolPtr
344 "\nMode->MakeCallbacks == %d ",
345 Private
->EfiBc
.Mode
->MakeCallbacks
)
350 "\nPrivate->CallbackProtocolPtr == %xh ",
351 Private
->CallbackProtocolPtr
)
354 if (Private
->CallbackProtocolPtr
!= NULL
) {
357 "\nCallbackProtocolPtr->Revision = %xh ",
358 Private
->CallbackProtocolPtr
->Revision
)
363 "\nCallbackProtocolPtr->Callback = %xh ",
364 Private
->CallbackProtocolPtr
->Callback
)
368 return Private
->EfiBc
.Mode
->MakeCallbacks
;
371 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
374 IN PXE_BASECODE_DEVICE
*Private
,
375 IN EFI_PXE_BASE_CODE_FUNCTION Function
,
376 IN EFI_EVENT TimeoutEvent
,
377 IN OUT UINTN
*HeaderSizePtr
,
378 IN OUT UINTN
*BufferSizePtr
,
379 IN OUT UINT16
*ProtocolPtr
384 Routine which does an SNP->Receive over a timeout period and doing callbacks
387 Private - Pointer to Pxe BaseCode Protocol
388 Function - What PXE function to callback
389 TimeoutEvent - Timer event that will trigger when we have waited too
390 long for an incoming packet
391 HeaderSizePtr - Pointer to the size of the Header size
392 BufferSizePtr - Pointer to the size of the Buffer size
393 ProtocolPtr - The protocol to sniff for (namely, UDP/etc)
396 0 - Something was returned
397 !0 - Like there was nothing to receive (EFI_TIMEOUT/NOT_READY)
401 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
402 EFI_PXE_CALLBACK CallbackPtr
;
404 EFI_EVENT CallbackEvent
;
407 // Initialize pointer to SNP interface
409 SnpPtr
= Private
->SimpleNetwork
;
412 // Initialize pointer to PxeBc callback routine - if any
414 CallbackPtr
= (Private
->EfiBc
.Mode
->MakeCallbacks
) ? Private
->CallbackProtocolPtr
->Callback
: NULL
;
417 // Create callback event and set timer
419 StatCode
= gBS
->CreateEvent (
427 if (EFI_ERROR (StatCode
)) {
428 return EFI_DEVICE_ERROR
;
432 // every 100 milliseconds
434 StatCode
= gBS
->SetTimer (
440 if (EFI_ERROR (StatCode
)) {
441 gBS
->CloseEvent (CallbackEvent
);
442 return EFI_DEVICE_ERROR
;
445 // Loop until a packet is received or a receive error is detected or
446 // a callback abort is detected or a timeout event occurs.
451 // Poll for received packet.
453 *BufferSizePtr
= BUFFER_ALLOCATE_SIZE
;
455 StatCode
= SnpPtr
->Receive (
459 Private
->ReceiveBufferPtr
,
465 if (!EFI_ERROR (StatCode
)) {
467 // Packet was received. Make received callback then return.
469 if (CallbackPtr
!= NULL
) {
470 StatCode
= CallbackPtr (
471 Private
->CallbackProtocolPtr
,
474 (UINT32
) *BufferSizePtr
,
475 (EFI_PXE_BASE_CODE_PACKET
*) Private
->ReceiveBufferPtr
478 if (StatCode
!= EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
) {
479 StatCode
= EFI_ABORTED
;
481 StatCode
= EFI_SUCCESS
;
488 if (StatCode
!= EFI_NOT_READY
) {
493 // Check for callback event.
495 if (!EFI_ERROR (gBS
->CheckEvent (CallbackEvent
))) {
497 // Make periodic callback if callback pointer is initialized.
499 if (CallbackPtr
!= NULL
) {
500 StatCode
= CallbackPtr (
501 Private
->CallbackProtocolPtr
,
509 // Abort if directed to by callback routine.
511 if (StatCode
!= EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
) {
512 StatCode
= EFI_ABORTED
;
518 // Check for timeout event.
520 if (TimeoutEvent
== 0) {
521 StatCode
= EFI_TIMEOUT
;
525 if (!EFI_ERROR (gBS
->CheckEvent (TimeoutEvent
))) {
526 StatCode
= EFI_TIMEOUT
;
530 // Check IGMP timer events.
532 IgmpCheckTimers (Private
);
535 gBS
->CloseEvent (CallbackEvent
);
542 PXE_BASECODE_DEVICE
*Private
,
547 UINT16 MediaProtocol
,
548 IN EFI_PXE_BASE_CODE_FUNCTION Function
553 Routine which does an SNP->Transmit of a buffer
556 Private - Pointer to Pxe BaseCode Protocol
557 HeaderPtr - Pointer to the buffer
558 PacketPtr - Pointer to the packet to send
559 PacketLen - The length of the entire packet to send
560 HardwareAddr - Pointer to the MAC address of the destination
561 MediaProtocol - What type of frame to create (RFC 1700) - IE. Ethernet
562 Function - What PXE function to callback
565 0 - Something was sent
566 !0 - An error was encountered during sending of a packet
570 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
571 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
572 EFI_PXE_CALLBACK CallbackPtr
;
574 EFI_EVENT TimeoutEvent
;
581 CallbackPtr
= Private
->EfiBc
.Mode
->MakeCallbacks
? Private
->CallbackProtocolPtr
->Callback
: 0;
583 SnpPtr
= Private
->SimpleNetwork
;
584 SnpModePtr
= SnpPtr
->Mode
;
587 // clear prior interrupt status
589 StatCode
= SnpPtr
->GetStatus (SnpPtr
, &IntStatus
, 0);
591 if (EFI_ERROR (StatCode
)) {
594 "\nSendPacket() Exit #1 %xh (%r)",
601 Private
->DidTransmit
= FALSE
;
603 if (CallbackPtr
!= NULL
) {
605 Private
->CallbackProtocolPtr
,
610 ) != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
) {
613 "\nSendPacket() Exit #2 %xh (%r)",
621 // put packet in transmit queue
622 // headersize should be zero if not filled in
624 StatCode
= gBS
->CreateEvent (
632 if (EFI_ERROR (StatCode
)) {
635 "Could not create transmit timeout event. %r\n",
638 return EFI_DEVICE_ERROR
;
644 StatCode
= gBS
->SetTimer (
650 if (EFI_ERROR (StatCode
)) {
653 "Could not set transmit timeout event timer. %r\n",
656 gBS
->CloseEvent (TimeoutEvent
);
657 return EFI_DEVICE_ERROR
;
661 StatCode
= SnpPtr
->Transmit (
663 (UINTN
) SnpPtr
->Mode
->MediaHeaderSize
,
664 (UINTN
) (PacketLen
+ SnpPtr
->Mode
->MediaHeaderSize
),
666 &SnpModePtr
->CurrentAddress
,
667 (EFI_MAC_ADDRESS
*) HardwareAddr
,
671 if (StatCode
!= EFI_NOT_READY
) {
675 if (!EFI_ERROR (gBS
->CheckEvent (TimeoutEvent
))) {
676 StatCode
= EFI_TIMEOUT
;
681 gBS
->CloseEvent (TimeoutEvent
);
683 if (EFI_ERROR (StatCode
)) {
686 "\nSendPacket() Exit #3 %xh (%r)",
693 // remove transmit buffer from snp's unused queue
694 // done this way in case someday things are buffered and we don't get it back
697 StatCode
= gBS
->CreateEvent (
705 if (EFI_ERROR (StatCode
)) {
708 "Could not create transmit status timeout event. %r\n",
711 return EFI_DEVICE_ERROR
;
717 StatCode
= gBS
->SetTimer (
723 if (EFI_ERROR (StatCode
)) {
726 "Could not set transmit status timeout event timer. %r\n",
729 gBS
->CloseEvent (TimeoutEvent
);
730 return EFI_DEVICE_ERROR
;
734 StatCode
= SnpPtr
->GetStatus (SnpPtr
, &IntStatus
, &TxBuf
);
736 if (EFI_ERROR (StatCode
)) {
739 "\nSendPacket() Exit #4 %xh (%r)",
746 if (IntStatus
& EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT
) {
747 Private
->DidTransmit
= TRUE
;
754 if (!EFI_ERROR (gBS
->CheckEvent (TimeoutEvent
))) {
755 StatCode
= EFI_TIMEOUT
;
760 gBS
->CloseEvent (TimeoutEvent
);
769 IN PXE_BASECODE_DEVICE
*Private
,
770 OUT BIS_APPLICATION_HANDLE
*BisAppHandle
,
771 OUT OPTIONAL EFI_BIS_DATA
**BisDataSigInfo
775 Locate BIS interface and if found, try to start it.
778 Private := Pointer to PxeBc protocol
779 BisAppHandle := Pointer to BIS application handle storage
780 BisDataSigInfo := Pointer to BIS signature information storage
784 EFI_STATUS EfiStatus
;
785 EFI_HANDLE BisHandleBuffer
;
786 UINTN BisHandleCount
;
787 EFI_BIS_PROTOCOL
*BisPtr
;
788 EFI_BIS_VERSION BisInterfaceVersion
;
789 BOOLEAN BisCheckFlag
;
791 BisHandleCount
= sizeof (EFI_HANDLE
);
792 BisCheckFlag
= FALSE
;
795 // Locate BIS protocol handle (if present).
796 // If BIS protocol handle is not found, return NULL.
798 DEBUG ((EFI_D_INFO
, "\ngBS->LocateHandle() "));
800 EfiStatus
= gBS
->LocateHandle (
802 &gEfiBisProtocolGuid
,
808 if (EFI_ERROR (EfiStatus
)) {
810 // Any error means that there is no BIS.
811 // Note - It could mean that there are more than
812 // one BIS protocols installed, but that scenario
813 // is not yet supported.
817 "\nPxebcBisStart()""\n gBS->LocateHandle() %r (%xh)\n",
825 if (BisHandleCount
!= sizeof (BisHandleBuffer
)) {
827 // This really should never happen, but I am paranoid.
831 "\nPxebcBisStart() BisHandleCount != %d\n",
832 sizeof BisHandleBuffer
)
838 DEBUG ((EFI_D_INFO
, "BIS handle found."));
841 // Locate BIS protocol interface.
842 // If the BIS protocol interface cannot be found, return NULL.
844 DEBUG ((EFI_D_INFO
, "\ngBS->HandleProtocol() "));
846 EfiStatus
= gBS
->HandleProtocol (
848 &gEfiBisProtocolGuid
,
852 if (EFI_ERROR (EfiStatus
)) {
855 "\nPxebcBisStart()""\n gBS->HandleProtocol() %r (%xh)\n",
863 if (BisPtr
== NULL
) {
865 // This really should never happen.
869 "\nPxebcBisStart()""\n gBS->HandleProtocoL() ""BIS protocol interface pointer is NULL!\n")
875 DEBUG ((EFI_D_INFO
, "BIS protocol interface found."));
878 // Check that all of the BIS API function pointers are not NULL.
880 if (BisPtr
->Initialize
== NULL
||
881 BisPtr
->Shutdown
== NULL
||
882 BisPtr
->Free
== NULL
||
883 BisPtr
->GetBootObjectAuthorizationCertificate
== NULL
||
884 BisPtr
->GetBootObjectAuthorizationCheckFlag
== NULL
||
885 BisPtr
->GetBootObjectAuthorizationUpdateToken
== NULL
||
886 BisPtr
->GetSignatureInfo
== NULL
||
887 BisPtr
->UpdateBootObjectAuthorization
== NULL
||
888 BisPtr
->VerifyBootObject
== NULL
||
889 BisPtr
->VerifyObjectWithCredential
== NULL
894 "\nPxebcBisStart()""\n BIS protocol interface is invalid."
895 "\n At least one BIS protocol function pointer is NULL.\n"
903 // If BIS does not initialize, return NULL.
905 DEBUG ((EFI_D_INFO
, "\nBisPtr->Initialize() "));
907 BisInterfaceVersion
.Major
= BIS_VERSION_1
;
909 EfiStatus
= BisPtr
->Initialize (
912 &BisInterfaceVersion
,
916 if (EFI_ERROR (EfiStatus
)) {
919 "\nPxebcBisStart()""\n BisPtr->Initialize() %r (%xh)\n",
929 " BIS version: %d.%d",
930 BisInterfaceVersion
.Major
,
931 BisInterfaceVersion
.Minor
)
935 // If the requested BIS API version is not supported,
936 // shutdown BIS and return NULL.
938 if (BisInterfaceVersion
.Major
!= BIS_VERSION_1
) {
941 "\nPxebcBisStart()""\n BIS version %d.%d not supported by PXE BaseCode.\n",
942 BisInterfaceVersion
.Major
,
943 BisInterfaceVersion
.Minor
)
946 BisPtr
->Shutdown (*BisAppHandle
);
950 // Get BIS check flag.
951 // If the BIS check flag cannot be read, shutdown BIS and return NULL.
953 DEBUG ((EFI_D_INFO
, "\nBisPtr->GetBootObjectAuthorizationCheckFlag() "));
955 EfiStatus
= BisPtr
->GetBootObjectAuthorizationCheckFlag (*BisAppHandle
, &BisCheckFlag
);
957 if (EFI_ERROR (EfiStatus
)) {
960 "\nPxebcBisStart()""\n BisPtr->GetBootObjectAuthorizationCheckFlag() %r (%xh)\n",
965 BisPtr
->Shutdown (*BisAppHandle
);
969 // If the BIS check flag is FALSE, shutdown BIS and return NULL.
972 DEBUG ((EFI_D_INFO
, "\nBIS check flag is FALSE.\n"));
973 BisPtr
->Shutdown (*BisAppHandle
);
976 DEBUG ((EFI_D_INFO
, "\nBIS check flag is TRUE."));
979 // Early out if caller does not want signature information.
981 if (BisDataSigInfo
== NULL
) {
985 // Get BIS signature information.
986 // If the signature information cannot be read or is invalid,
987 // shutdown BIS and return NULL.
989 DEBUG ((EFI_D_INFO
, "\nBisPtr->GetSignatureInfo() "));
991 EfiStatus
= BisPtr
->GetSignatureInfo (*BisAppHandle
, BisDataSigInfo
);
993 if (EFI_ERROR (EfiStatus
)) {
996 "\nPxebcBisStart()""\n BisPtr_GetSignatureInfo() %r (%xh)\n",
1001 BisPtr
->Shutdown (*BisAppHandle
);
1005 if (*BisDataSigInfo
== NULL
) {
1007 // This should never happen.
1011 "\nPxebcBisStart()""\n BisPtr->GetSignatureInfo() Data pointer is NULL!\n")
1014 BisPtr
->Shutdown (*BisAppHandle
);
1018 if ((*BisDataSigInfo
)->Length
< sizeof (EFI_BIS_SIGNATURE_INFO
) ||
1019 (*BisDataSigInfo
)->Length
% sizeof (EFI_BIS_SIGNATURE_INFO
) ||
1020 (*BisDataSigInfo
)->Length
> sizeof (EFI_BIS_SIGNATURE_INFO
) * 63
1023 // This should never happen.
1027 "\nPxebcBisStart()""\n BisPtr->GetSignatureInfo() Invalid BIS siginfo length.\n")
1030 BisPtr
->Free (*BisAppHandle
, *BisDataSigInfo
);
1031 BisPtr
->Shutdown (*BisAppHandle
);
1040 EFI_BIS_PROTOCOL
*BisPtr
,
1041 BIS_APPLICATION_HANDLE BisAppHandle
,
1042 EFI_BIS_DATA
*BisDataSigInfo
1045 Routine description:
1046 Stop the BIS interface and release allocations.
1049 BisPtr := Pointer to BIS interface
1050 BisAppHandle := BIS application handle
1051 BisDataSigInfo := Pointer to BIS signature information data
1057 if (BisPtr
== NULL
) {
1061 // Free BIS allocated resources and shutdown BIS.
1062 // Return TRUE - BIS support is officially detected.
1064 if (BisDataSigInfo
!= NULL
) {
1065 BisPtr
->Free (BisAppHandle
, BisDataSigInfo
);
1068 BisPtr
->Shutdown (BisAppHandle
);
1073 PXE_BASECODE_DEVICE
*Private
,
1076 VOID
*CredentialBuffer
,
1077 UINTN CredentialLength
1080 Routine description:
1081 Verify image and credential file.
1084 Private := Pointer to PxeBc interface
1085 FileBuffer := Pointer to image buffer
1086 FileLength := Image length in bytes
1087 CredentialBuffer := Pointer to credential buffer
1088 CredentialLength := Credential length in bytes
1092 FALSE := not verified
1095 EFI_BIS_PROTOCOL
*BisPtr
;
1096 BIS_APPLICATION_HANDLE BisAppHandle
;
1097 EFI_BIS_DATA FileData
;
1098 EFI_BIS_DATA CredentialData
;
1099 EFI_STATUS EfiStatus
;
1102 if (Private
== NULL
|| FileBuffer
== NULL
|| FileLength
== 0 || CredentialBuffer
== NULL
|| CredentialLength
== 0) {
1106 BisPtr
= PxebcBisStart (Private
, &BisAppHandle
, NULL
);
1108 if (BisPtr
== NULL
) {
1112 FileData
.Length
= (UINT32
) FileLength
;
1113 FileData
.Data
= FileBuffer
;
1114 CredentialData
.Length
= (UINT32
) CredentialLength
;
1115 CredentialData
.Data
= CredentialBuffer
;
1117 EfiStatus
= BisPtr
->VerifyBootObject (
1124 PxebcBisStop (BisPtr
, BisAppHandle
, NULL
);
1126 return (BOOLEAN
) ((EFI_ERROR (EfiStatus
)) ? FALSE
: (IsVerified
? TRUE
: FALSE
));
1131 PXE_BASECODE_DEVICE
*Private
1134 Routine description:
1135 Check for BIS interface presence.
1138 Private := Pointer to PxeBc interface
1142 FALSE := BIS not present
1145 EFI_BIS_PROTOCOL
*BisPtr
;
1146 BIS_APPLICATION_HANDLE BisAppHandle
;
1147 EFI_BIS_DATA
*BisDataSigInfo
;
1149 BisPtr
= PxebcBisStart (Private
, &BisAppHandle
, &BisDataSigInfo
);
1151 if (BisPtr
== NULL
) {
1155 PxebcBisStop (BisPtr
, BisAppHandle
, BisDataSigInfo
);
1165 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1170 Routine Description:
1171 Start and initialize the BaseCode protocol, Simple Network protocol and UNDI.
1174 Private - Pointer to Pxe BaseCode Protocol
1175 UseIPv6 - Do we want to support IPv6?
1179 EFI_INVALID_PARAMETER
1182 EFI_OUT_OF_RESOURCES
1183 Status is also returned from SNP.Start() and SNP.Initialize().
1187 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
1188 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
1189 EFI_STATUS StatCode
;
1190 PXE_BASECODE_DEVICE
*Private
;
1193 // Lock the instance data
1195 StatCode
= EFI_SUCCESS
;
1198 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1199 return EFI_INVALID_PARAMETER
;
1202 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1204 if (Private
== NULL
) {
1205 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE pointer == NULL"));
1206 return EFI_INVALID_PARAMETER
;
1209 EfiAcquireLock (&Private
->Lock
);
1212 // Make sure BaseCode is not already started.
1214 if (This
->Mode
->Started
) {
1215 DEBUG ((EFI_D_WARN
, "\nBcStart() BC is already started.\n"));
1216 EfiReleaseLock (&Private
->Lock
);
1217 return EFI_ALREADY_STARTED
;
1221 // Fail if IPv6 is requested and not supported.
1224 DEBUG ((EFI_D_WARN
, "\nBcStart() IPv6 is not supported.\n"));
1225 EfiReleaseLock (&Private
->Lock
);
1226 return EFI_UNSUPPORTED
;
1230 // Setup shortcuts to SNP protocol and data structure.
1232 SnpPtr
= Private
->SimpleNetwork
;
1233 SnpModePtr
= SnpPtr
->Mode
;
1236 // Start and initialize SNP.
1238 if (SnpModePtr
->State
== EfiSimpleNetworkStopped
) {
1239 StatCode
= (*SnpPtr
->Start
) (SnpPtr
);
1241 if (SnpModePtr
->State
!= EfiSimpleNetworkStarted
) {
1242 DEBUG ((EFI_D_WARN
, "\nBcStart() Could not start SNP.\n"));
1243 EfiReleaseLock (&Private
->Lock
);
1248 // acquire memory for mode and transmit/receive buffers
1250 if (SnpModePtr
->State
== EfiSimpleNetworkStarted
) {
1251 StatCode
= (*SnpPtr
->Initialize
) (SnpPtr
, 0, 0);
1253 if (SnpModePtr
->State
!= EfiSimpleNetworkInitialized
) {
1254 DEBUG ((EFI_D_WARN
, "\nBcStart() Could not initialize SNP."));
1255 EfiReleaseLock (&Private
->Lock
);
1262 DEBUG ((EFI_D_INFO
, "\nBC Start()"));
1265 "\nSnpModePtr->State %Xh",
1270 "\nSnpModePtr->HwAddressSize %Xh",
1271 SnpModePtr
->HwAddressSize
)
1275 "\nSnpModePtr->MediaHeaderSize %Xh",
1276 SnpModePtr
->MediaHeaderSize
)
1280 "\nSnpModePtr->MaxPacketSize %Xh",
1281 SnpModePtr
->MaxPacketSize
)
1285 "\nSnpModePtr->MacAddressChangeable %Xh",
1286 SnpModePtr
->MacAddressChangeable
)
1290 "\nSnpModePtr->MultipleTxSupported %Xh",
1291 SnpModePtr
->MultipleTxSupported
)
1295 "\nSnpModePtr->CurrentAddress %Xh",
1296 *((UINTN
*)&SnpModePtr
->CurrentAddress
))
1300 "\nSnpModePtr->BroadcastAddress %Xh",
1301 *((UINTN
*)&SnpModePtr
->BroadcastAddress
))
1305 "\nSnpModePtr->PermanentAddress %Xh",
1306 *((UINTN
*)&SnpModePtr
->PermanentAddress
))
1310 "\nSnpModePtr->NvRamSize %Xh",
1311 SnpModePtr
->NvRamSize
)
1315 "\nSnpModePtr->NvRamAccessSize %Xh",
1316 SnpModePtr
->NvRamAccessSize
)
1320 "\nSnpModePtr->ReceiveFilterMask %Xh",
1321 SnpModePtr
->ReceiveFilterMask
)
1325 "\nSnpModePtr->ReceiveFilterSetting %Xh",
1326 SnpModePtr
->ReceiveFilterSetting
)
1330 "\nSnpModePtr->MCastFilterCount %Xh",
1331 SnpModePtr
->MCastFilterCount
)
1335 "\nSnpModePtr->MCastFilter %Xh",
1336 SnpModePtr
->MCastFilter
)
1340 "\nSnpModePtr->IfType %Xh",
1345 "\nSnpModePtr->MediaPresentSupported %Xh",
1346 SnpModePtr
->MediaPresentSupported
)
1350 "\nSnpModePtr->MediaPresent %Xh",
1351 SnpModePtr
->MediaPresent
)
1355 // If media check is supported and there is no media,
1356 // return error to caller.
1358 if (SnpModePtr
->MediaPresentSupported
&& !SnpModePtr
->MediaPresent
) {
1359 DEBUG ((EFI_D_WARN
, "\nBcStart() Media not present.\n"));
1360 EfiReleaseLock (&Private
->Lock
);
1361 return EFI_NO_MEDIA
;
1364 // Allocate Tx/Rx buffers
1366 Private
->TransmitBufferPtr
= AllocateZeroPool (BUFFER_ALLOCATE_SIZE
);
1367 if (Private
->TransmitBufferPtr
== NULL
) {
1368 DEBUG ((EFI_D_NET
, "\nBcStart() Could not alloc TxBuf.\n"));
1369 EfiReleaseLock (&Private
->Lock
);
1370 return EFI_OUT_OF_RESOURCES
;
1373 Private
->ReceiveBufferPtr
= AllocateZeroPool (BUFFER_ALLOCATE_SIZE
);
1374 if (Private
->ReceiveBufferPtr
== NULL
) {
1375 DEBUG ((EFI_D_NET
, "\nBcStart() Could not alloc RxBuf.\n"));
1376 FreePool (Private
->TransmitBufferPtr
);
1377 EfiReleaseLock (&Private
->Lock
);
1378 return EFI_OUT_OF_RESOURCES
;
1381 Private
->TftpErrorBuffer
= AllocatePool (256);
1382 if (Private
->TftpErrorBuffer
== NULL
) {
1383 FreePool (Private
->ReceiveBufferPtr
);
1384 FreePool (Private
->TransmitBufferPtr
);
1385 EfiReleaseLock (&Private
->Lock
);
1386 return EFI_OUT_OF_RESOURCES
;
1389 Private
->TftpAckBuffer
= AllocatePool (256);
1390 if (Private
->TftpAckBuffer
== NULL
) {
1391 FreePool (Private
->TftpErrorBuffer
);
1392 FreePool (Private
->ReceiveBufferPtr
);
1393 FreePool (Private
->TransmitBufferPtr
);
1394 EfiReleaseLock (&Private
->Lock
);
1395 return EFI_OUT_OF_RESOURCES
;
1398 // Initialize private BaseCode instance data
1401 Private
->RandomPort
= (UINT16
) (Private
->RandomPort
+ PXE_RND_PORT_LOW
+ Random (Private
));
1402 } while (Private
->RandomPort
< PXE_RND_PORT_LOW
);
1404 Private
->Igmpv1TimeoutEvent
= NULL
;
1405 Private
->UseIgmpv1Reporting
= TRUE
;
1406 Private
->IpLength
= IP_ADDRESS_LENGTH (Private
->EfiBc
.Mode
);
1409 // Initialize Mode structure
1412 // check for callback protocol and set boolean
1414 SetMakeCallback (Private
);
1415 Private
->EfiBc
.Mode
->Started
= TRUE
;
1416 Private
->EfiBc
.Mode
->TTL
= DEFAULT_TTL
;
1417 Private
->EfiBc
.Mode
->ToS
= DEFAULT_ToS
;
1418 Private
->EfiBc
.Mode
->UsingIpv6
= UseIPv6
;
1419 Private
->EfiBc
.Mode
->DhcpDiscoverValid
= FALSE
;
1420 Private
->EfiBc
.Mode
->DhcpAckReceived
= FALSE
;
1421 Private
->EfiBc
.Mode
->ProxyOfferReceived
= FALSE
;
1422 Private
->EfiBc
.Mode
->PxeDiscoverValid
= FALSE
;
1423 Private
->EfiBc
.Mode
->PxeReplyReceived
= FALSE
;
1424 Private
->EfiBc
.Mode
->PxeBisReplyReceived
= FALSE
;
1425 Private
->EfiBc
.Mode
->IcmpErrorReceived
= FALSE
;
1426 Private
->EfiBc
.Mode
->TftpErrorReceived
= FALSE
;
1427 ZeroMem (&Private
->EfiBc
.Mode
->StationIp
, sizeof (EFI_IP_ADDRESS
));
1428 ZeroMem (&Private
->EfiBc
.Mode
->SubnetMask
, sizeof (EFI_IP_ADDRESS
));
1429 Private
->EfiBc
.Mode
->IpFilter
.Filters
= 0;
1430 Private
->EfiBc
.Mode
->IpFilter
.IpCnt
= 0;
1431 Private
->EfiBc
.Mode
->ArpCacheEntries
= 0;
1432 Private
->EfiBc
.Mode
->RouteTableEntries
= 0;
1433 ZeroMem (&Private
->EfiBc
.Mode
->IcmpError
, sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR
));
1434 ZeroMem (&Private
->EfiBc
.Mode
->TftpError
, sizeof (EFI_PXE_BASE_CODE_TFTP_ERROR
));
1437 // Set to PXE_TRUE by the BC constructor if this BC implementation
1440 Private
->EfiBc
.Mode
->Ipv6Supported
= SUPPORT_IPV6
;
1441 Private
->EfiBc
.Mode
->Ipv6Available
= FALSE
;
1444 // Set to TRUE by the BC constructor if this BC implementation
1447 Private
->EfiBc
.Mode
->BisSupported
= TRUE
;
1448 Private
->EfiBc
.Mode
->BisDetected
= PxebcBisDetect (Private
);
1451 // This field is set to PXE_TRUE by the BC Start() function. When this
1452 // field is PXE_TRUE, ARP packets are sent as needed to get IP and MAC
1453 // addresses. This can cause unexpected delays in the DHCP(), Discover()
1454 // and MTFTP() functions. Setting this to PXE_FALSE will cause these
1455 // functions to fail if the required IP/MAC information is not in the
1456 // ARP cache. The value of this field can be changed by an application
1459 Private
->EfiBc
.Mode
->AutoArp
= TRUE
;
1462 // Unlock the instance data
1464 EfiReleaseLock (&Private
->Lock
);
1471 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
1475 Routine Description:
1476 Stop the BaseCode protocol, Simple Network protocol and UNDI.
1479 Private - Pointer to Pxe BaseCode Protocol
1483 0 - Successfully stopped
1488 // Lock the instance data
1490 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
1491 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
1492 EFI_STATUS StatCode
;
1493 PXE_BASECODE_DEVICE
*Private
;
1495 StatCode
= EFI_SUCCESS
;
1498 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1499 return EFI_INVALID_PARAMETER
;
1502 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1504 if (Private
== NULL
) {
1505 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1506 return EFI_INVALID_PARAMETER
;
1509 EfiAcquireLock (&Private
->Lock
);
1511 SnpPtr
= Private
->SimpleNetwork
;
1512 SnpModePtr
= SnpPtr
->Mode
;
1517 StatCode
= EFI_NOT_STARTED
;
1519 if (SnpModePtr
->State
== EfiSimpleNetworkInitialized
) {
1520 StatCode
= (*SnpPtr
->Shutdown
) (SnpPtr
);
1523 if (SnpModePtr
->State
== EfiSimpleNetworkStarted
) {
1524 StatCode
= (*SnpPtr
->Stop
) (SnpPtr
);
1527 if (Private
->TransmitBufferPtr
!= NULL
) {
1528 FreePool (Private
->TransmitBufferPtr
);
1529 Private
->TransmitBufferPtr
= NULL
;
1532 if (Private
->ReceiveBufferPtr
!= NULL
) {
1533 FreePool (Private
->ReceiveBufferPtr
);
1534 Private
->ReceiveBufferPtr
= NULL
;
1537 if (Private
->ArpBuffer
!= NULL
) {
1538 FreePool (Private
->ArpBuffer
);
1539 Private
->ArpBuffer
= NULL
;
1542 if (Private
->TftpErrorBuffer
!= NULL
) {
1543 FreePool (Private
->TftpErrorBuffer
);
1544 Private
->TftpErrorBuffer
= NULL
;
1547 if (Private
->TftpAckBuffer
!= NULL
) {
1548 FreePool (Private
->TftpAckBuffer
);
1549 Private
->TftpAckBuffer
= NULL
;
1552 if (Private
->Igmpv1TimeoutEvent
!= NULL
) {
1553 gBS
->CloseEvent (Private
->Igmpv1TimeoutEvent
);
1554 Private
->Igmpv1TimeoutEvent
= NULL
;
1557 Private
->FileSize
= 0;
1558 Private
->EfiBc
.Mode
->Started
= FALSE
;
1561 // Unlock the instance data
1563 EfiReleaseLock (&Private
->Lock
);
1567 const IPV4_ADDR AllSystemsGroup
= { { 224, 0, 0, 1 } };
1571 IN PXE_BASECODE_DEVICE
*Private
,
1572 IN EFI_PXE_BASE_CODE_IP_FILTER
*Filter
1576 Routine Description:
1577 Set up the IP filter
1580 Private - Pointer to Pxe BaseCode Protocol
1581 Filter - Pointer to the filter
1585 0 - Successfully set the filter
1589 EFI_STATUS StatCode
;
1590 EFI_MAC_ADDRESS MACadds
[PXE_IP_FILTER_SIZE
];
1591 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1592 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
1593 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
1599 PxebcMode
= Private
->EfiBc
.Mode
;
1600 SnpPtr
= Private
->SimpleNetwork
;
1601 SnpModePtr
= SnpPtr
->Mode
;
1604 // validate input parameters
1605 // must have a filter
1606 // must not have any extra filter bits set
1608 if (Filter
== NULL
||
1609 (Filter
->Filters
&~FILTER_BITS
)
1611 // must not have a count which is too large or with no IP list
1614 (Filter
->IpCnt
&& (!Filter
->IpList
|| Filter
->IpCnt
> PXE_IP_FILTER_SIZE
))
1616 // must not have incompatible filters - promiscuous incompatible with anything else
1620 (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) &&
1621 ((Filter
->Filters
&~EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) || Filter
->IpCnt
)
1624 DEBUG ((EFI_D_INFO
, "\nIpFilter() Exit #1"));
1625 return EFI_INVALID_PARAMETER
;
1628 // promiscuous multicast incompatible with multicast in IP list
1630 if (Filter
->IpCnt
&& (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
)) {
1631 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1632 if (IS_MULTICAST (&Filter
->IpList
[Index
])) {
1633 DEBUG ((EFI_D_INFO
, "\nIpFilter() Exit #2"));
1634 return EFI_INVALID_PARAMETER
;
1639 // leave groups for all those multicast which are no longer enabled
1641 for (Index
= 0; Index
< PxebcMode
->IpFilter
.IpCnt
; ++Index
) {
1642 if (!IS_MULTICAST (&PxebcMode
->IpFilter
.IpList
[Index
])) {
1646 for (Index2
= 0; Index2
< Filter
->IpCnt
; ++Index2
) {
1647 if (!CompareMem (&PxebcMode
->IpFilter
.IpList
[Index
], &Filter
->IpList
[Index2
], IP_ADDRESS_LENGTH (PxebcMode
))) {
1655 // if we didn't find it, remove from group
1657 if (Index2
== Filter
->IpCnt
) {
1658 IgmpLeaveGroup (Private
, &PxebcMode
->IpFilter
.IpList
[Index
]);
1662 // set enable bits, convert multicast ip adds, join groups
1663 // allways leave receive broadcast enabled at hardware layer
1667 if (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) {
1668 Enable
= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
1670 if (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
) {
1671 Enable
= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
1673 Enable
= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
1675 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1676 CopyMem (&(PxebcMode
->IpFilter
.IpList
[Index
]), &(Filter
->IpList
[Index
]), sizeof (EFI_IP_ADDRESS
));
1678 if (IS_MULTICAST (&Filter
->IpList
[Index
])) {
1679 EFI_IP_ADDRESS
*TmpIp
;
1681 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
1684 // if this is the first group, add the all systems group to mcast list
1688 TmpIp
= (EFI_IP_ADDRESS
*) &AllSystemsGroup
;
1691 TmpIp
= (EFI_IP_ADDRESS
*) &Filter
->IpList
[Index
];
1694 // get MAC address of IP
1696 StatCode
= (*SnpPtr
->MCastIpToMac
) (SnpPtr
, PxebcMode
->UsingIpv6
, TmpIp
, &MACadds
[Index2
++]);
1698 if (EFI_ERROR (StatCode
)) {
1701 "\nIpFilter() Exit #2 %Xh (%r)",
1708 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
1713 if (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
) {
1714 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
1718 // if nothing changed, just return
1722 "\nsnp->ReceiveFilterSetting == %Xh Filter->IpCnt == %Xh",
1723 SnpModePtr
->ReceiveFilterSetting
,
1727 if (SnpModePtr
->ReceiveFilterSetting
== Enable
&& !Filter
->IpCnt
) {
1728 DEBUG ((EFI_D_INFO
, "\nIpFilter() Exit #4"));
1732 // disable those currently set but not set in new filter
1734 Disable
= SnpModePtr
->ReceiveFilterSetting
&~Enable
;
1736 StatCode
= SnpPtr
->ReceiveFilters (SnpPtr
, Enable
, Disable
, FALSE
, Index2
, MACadds
);
1738 PxebcMode
->IpFilter
.IpCnt
= Filter
->IpCnt
;
1741 // join groups for all multicast in list
1743 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1744 if (IS_MULTICAST (&Filter
->IpList
[Index
])) {
1745 IgmpJoinGroup (Private
, &Filter
->IpList
[Index
]);
1749 DEBUG ((EFI_D_INFO
, "\nIpFilter() Exit #5 %Xh (%r)", StatCode
, StatCode
));
1757 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1758 IN EFI_PXE_BASE_CODE_IP_FILTER
*Filter
1762 Routine Description:
1766 Private - Pointer to Pxe BaseCode Protocol
1767 Filter - Pointer to the filter
1771 0 - Successfully set the filter
1775 EFI_STATUS StatCode
;
1776 PXE_BASECODE_DEVICE
*Private
;
1779 // Lock the instance data and make sure started
1781 StatCode
= EFI_SUCCESS
;
1784 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1785 return EFI_INVALID_PARAMETER
;
1788 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1790 if (Private
== NULL
) {
1791 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1792 return EFI_INVALID_PARAMETER
;
1795 EfiAcquireLock (&Private
->Lock
);
1797 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
1798 DEBUG ((EFI_D_ERROR
, "BC was not started."));
1799 EfiReleaseLock (&Private
->Lock
);
1800 return EFI_NOT_STARTED
;
1803 if (Filter
== NULL
) {
1804 return EFI_INVALID_PARAMETER
;
1809 StatCode
= IpFilter (Private
, Filter
);
1812 // Unlock the instance data
1814 EfiReleaseLock (&Private
->Lock
);
1821 EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1822 BOOLEAN
*AutoArpPtr
,
1823 BOOLEAN
*SendGuidPtr
,
1824 UINT8
*TimeToLivePtr
,
1825 UINT8
*TypeOfServicePtr
,
1826 BOOLEAN
*MakeCallbackPtr
1830 Routine Description:
1831 Set the Base Code behavior parameters
1834 This - Pointer to Pxe BaseCode Protocol
1835 AutoArpPtr - Boolean to do ARP stuff
1836 SendGuidPtr - Boolean whether or not to send GUID info
1837 TimeToLivePtr - Value for Total time to live
1838 TypeOfServicePtr - Value for Type of Service
1839 MakeCallbackPtr - Boolean to determine if we make callbacks
1843 0 - Successfully set the parameters
1847 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1849 CHAR8
*SerialNumberPtr
;
1850 EFI_STATUS StatCode
;
1851 PXE_BASECODE_DEVICE
*Private
;
1854 // Lock the instance data and make sure started
1856 StatCode
= EFI_SUCCESS
;
1859 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1860 return EFI_INVALID_PARAMETER
;
1863 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1865 if (Private
== NULL
) {
1866 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1867 return EFI_INVALID_PARAMETER
;
1870 EfiAcquireLock (&Private
->Lock
);
1872 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
1873 DEBUG ((EFI_D_ERROR
, "BC was not started."));
1874 EfiReleaseLock (&Private
->Lock
);
1875 return EFI_NOT_STARTED
;
1878 DEBUG ((EFI_D_INFO
, "\nSetParameters() Entry. "));
1880 PxebcMode
= Private
->EfiBc
.Mode
;
1881 StatCode
= EFI_SUCCESS
;
1883 if (SendGuidPtr
!= NULL
) {
1885 if (PxeBcLibGetSmbiosSystemGuidAndSerialNumber (&TmpGuid
, &SerialNumberPtr
) != EFI_SUCCESS
) {
1886 return EFI_INVALID_PARAMETER
;
1891 if (MakeCallbackPtr
!= NULL
) {
1892 if (*MakeCallbackPtr
) {
1893 if (!SetMakeCallback (Private
)) {
1894 return EFI_INVALID_PARAMETER
;
1898 PxebcMode
->MakeCallbacks
= *MakeCallbackPtr
;
1901 if (AutoArpPtr
!= NULL
) {
1902 PxebcMode
->AutoArp
= *AutoArpPtr
;
1905 if (SendGuidPtr
!= NULL
) {
1906 PxebcMode
->SendGUID
= *SendGuidPtr
;
1909 if (TimeToLivePtr
!= NULL
) {
1910 PxebcMode
->TTL
= *TimeToLivePtr
;
1913 if (TypeOfServicePtr
!= NULL
) {
1914 PxebcMode
->ToS
= *TypeOfServicePtr
;
1917 // Unlock the instance data
1919 DEBUG ((EFI_D_INFO
, "\nSetparameters() Exit = %xh ", StatCode
));
1921 EfiReleaseLock (&Private
->Lock
);
1925 // //////////////////////////////////////////////////////////
1927 // BC Set Station IP Routine
1932 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1933 IN EFI_IP_ADDRESS
*StationIpPtr
,
1934 IN EFI_IP_ADDRESS
*SubnetMaskPtr
1938 Routine Description:
1939 Set the station IP address
1942 This - Pointer to Pxe BaseCode Protocol
1943 StationIpPtr - Pointer to the requested IP address to set in base code
1944 SubnetMaskPtr - Pointer to the requested subnet mask for the base code
1948 EFI_SUCCESS - Successfully set the parameters
1949 EFI_NOT_STARTED - BC has not started
1952 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1953 PXE_BASECODE_DEVICE
*Private
;
1956 // Lock the instance data and make sure started
1960 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1961 return EFI_INVALID_PARAMETER
;
1964 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1966 if (Private
== NULL
) {
1967 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1968 return EFI_INVALID_PARAMETER
;
1971 EfiAcquireLock (&Private
->Lock
);
1973 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
1974 DEBUG ((EFI_D_ERROR
, "BC was not started."));
1975 EfiReleaseLock (&Private
->Lock
);
1976 return EFI_NOT_STARTED
;
1979 PxebcMode
= Private
->EfiBc
.Mode
;
1981 if (StationIpPtr
!= NULL
) {
1982 CopyMem (&PxebcMode
->StationIp
, StationIpPtr
, sizeof (EFI_IP_ADDRESS
));
1983 Private
->GoodStationIp
= TRUE
;
1986 if (SubnetMaskPtr
!= NULL
) {
1987 CopyMem (&PxebcMode
->SubnetMask
, SubnetMaskPtr
, sizeof (EFI_IP_ADDRESS
));
1990 // Unlock the instance data
1992 EfiReleaseLock (&Private
->Lock
);
1997 EFI_DRIVER_BINDING_PROTOCOL gPxeBcDriverBinding
= {
1998 PxeBcDriverSupported
,
2008 PxeBcDriverSupported (
2009 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2010 IN EFI_HANDLE Controller
,
2011 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
2015 Routine Description:
2016 Test to see if this driver supports Controller. Any Controller
2017 than contains a Snp protocol can be supported.
2020 This - Protocol instance pointer.
2021 Controller - Handle of device to test.
2022 RemainingDevicePath - Not used.
2025 EFI_SUCCESS - This driver supports this device.
2026 EFI_ALREADY_STARTED - This driver is already running on this device.
2027 other - This driver does not support this device.
2032 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
2034 Status
= gBS
->OpenProtocol (
2036 &gEfiDevicePathProtocolGuid
,
2038 This
->DriverBindingHandle
,
2040 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
2043 if (EFI_ERROR (Status
)) {
2047 Status
= gBS
->OpenProtocol (
2049 &gEfiSimpleNetworkProtocolGuid
,
2051 This
->DriverBindingHandle
,
2053 EFI_OPEN_PROTOCOL_BY_DRIVER
2055 if (EFI_ERROR (Status
)) {
2059 gBS
->CloseProtocol (
2061 &gEfiSimpleNetworkProtocolGuid
,
2062 This
->DriverBindingHandle
,
2072 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2073 IN EFI_HANDLE Controller
,
2074 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
2078 Routine Description:
2079 Start the Base code driver.
2082 This - Protocol instance pointer.
2083 Controller - Handle of device to test.
2084 RemainingDevicePath - Not used.
2087 EFI_SUCCESS - This driver supports this device.
2088 EFI_ALREADY_STARTED - This driver is already running on this device.
2089 other - This driver does not support this device.
2094 PXE_BASECODE_DEVICE
*Private
;
2095 LOADFILE_DEVICE
*pLF
;
2098 // Allocate structures needed by BaseCode and LoadFile protocols.
2100 Private
= AllocateZeroPool (sizeof (PXE_BASECODE_DEVICE
));
2102 if (Private
== NULL
) {
2103 DEBUG ((EFI_D_NET
, "\nBcNotifySnp() Could not alloc PXE_BASECODE_DEVICE structure.\n"));
2104 return EFI_OUT_OF_RESOURCES
;
2107 pLF
= AllocateZeroPool (sizeof (LOADFILE_DEVICE
));
2109 DEBUG ((EFI_D_NET
, "\nBcNotifySnp() Could not alloc LOADFILE_DEVICE structure.\n"));
2111 return EFI_OUT_OF_RESOURCES
;
2114 Private
->EfiBc
.Mode
= AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_MODE
));
2115 if (Private
->EfiBc
.Mode
== NULL
) {
2116 DEBUG ((EFI_D_NET
, "\nBcNotifySnp() Could not alloc Mode structure.\n"));
2119 return EFI_OUT_OF_RESOURCES
;
2122 // Lock access, just in case
2124 EfiInitializeLock (&Private
->Lock
, EFI_TPL_CALLBACK
);
2125 EfiAcquireLock (&Private
->Lock
);
2127 EfiInitializeLock (&pLF
->Lock
, EFI_TPL_CALLBACK
);
2128 EfiAcquireLock (&pLF
->Lock
);
2131 // Initialize PXE structure
2134 // First initialize the internal 'private' data that the application
2137 Private
->Signature
= PXE_BASECODE_DEVICE_SIGNATURE
;
2138 Private
->Handle
= Controller
;
2141 // Get the NII interface
2143 Status
= gBS
->OpenProtocol (
2145 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
2146 (VOID
**) &Private
->NiiPtr
,
2147 This
->DriverBindingHandle
,
2149 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2152 if (EFI_ERROR (Status
)) {
2153 Status
= gBS
->OpenProtocol (
2155 &gEfiNetworkInterfaceIdentifierProtocolGuid
,
2156 (VOID
**) &Private
->NiiPtr
,
2157 This
->DriverBindingHandle
,
2159 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2162 if (EFI_ERROR (Status
)) {
2167 // Get the Snp interface
2169 Status
= gBS
->OpenProtocol (
2171 &gEfiSimpleNetworkProtocolGuid
,
2172 (VOID
**) &Private
->SimpleNetwork
,
2173 This
->DriverBindingHandle
,
2175 EFI_OPEN_PROTOCOL_BY_DRIVER
2178 if (EFI_ERROR (Status
)) {
2183 // Next, initialize the external 'public' data that
2184 // the application does see.
2186 Private
->EfiBc
.Revision
= EFI_PXE_BASE_CODE_INTERFACE_REVISION
;
2187 Private
->EfiBc
.Start
= BcStart
;
2188 Private
->EfiBc
.Stop
= BcStop
;
2189 Private
->EfiBc
.Dhcp
= BcDhcp
;
2190 Private
->EfiBc
.Discover
= BcDiscover
;
2191 Private
->EfiBc
.Mtftp
= BcMtftp
;
2192 Private
->EfiBc
.UdpWrite
= BcUdpWrite
;
2193 Private
->EfiBc
.UdpRead
= BcUdpRead
;
2194 Private
->EfiBc
.Arp
= BcArp
;
2195 Private
->EfiBc
.SetIpFilter
= BcIpFilter
;
2196 Private
->EfiBc
.SetParameters
= BcSetParameters
;
2197 Private
->EfiBc
.SetStationIp
= BcSetStationIP
;
2198 Private
->EfiBc
.SetPackets
= BcSetPackets
;
2201 // Initialize BaseCode Mode structure
2203 Private
->EfiBc
.Mode
->Started
= FALSE
;
2204 Private
->EfiBc
.Mode
->TTL
= DEFAULT_TTL
;
2205 Private
->EfiBc
.Mode
->ToS
= DEFAULT_ToS
;
2206 Private
->EfiBc
.Mode
->UsingIpv6
= FALSE
;
2207 Private
->EfiBc
.Mode
->AutoArp
= TRUE
;
2210 // Set to PXE_TRUE by the BC constructor if this BC
2211 // implementation supports IPv6.
2213 Private
->EfiBc
.Mode
->Ipv6Supported
= SUPPORT_IPV6
;
2214 Private
->EfiBc
.Mode
->Ipv6Available
= FALSE
;
2217 // Set to TRUE by the BC constructor if this BC
2218 // implementation supports BIS.
2220 Private
->EfiBc
.Mode
->BisSupported
= TRUE
;
2221 Private
->EfiBc
.Mode
->BisDetected
= PxebcBisDetect (Private
);
2224 // Initialize LoadFile structure.
2226 pLF
->Signature
= LOADFILE_DEVICE_SIGNATURE
;
2227 pLF
->LoadFile
.LoadFile
= LoadFile
;
2228 pLF
->Private
= Private
;
2231 // Install protocol interfaces.
2233 Status
= gBS
->InstallMultipleProtocolInterfaces (
2235 &gEfiPxeBaseCodeProtocolGuid
,
2237 &gEfiLoadFileProtocolGuid
,
2242 if (EFI_ERROR (Status
)) {
2243 gBS
->CloseProtocol (
2245 &gEfiSimpleNetworkProtocolGuid
,
2246 This
->DriverBindingHandle
,
2255 EfiReleaseLock (&pLF
->Lock
);
2256 EfiReleaseLock (&Private
->Lock
);
2260 FreePool (Private
->EfiBc
.Mode
);
2269 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2270 IN EFI_HANDLE Controller
,
2271 IN UINTN NumberOfChildren
,
2272 IN EFI_HANDLE
*ChildHandleBuffer
2276 Routine Description:
2277 Stop the Base code driver.
2280 This - Protocol instance pointer.
2281 Controller - Handle of device to test.
2282 NumberOfChildren - Not used
2283 ChildHandleBuffer - Not used
2286 EFI_SUCCESS - This driver supports this device.
2287 EFI_ALREADY_STARTED - This driver is already running on this device.
2288 other - This driver does not support this device.
2293 EFI_LOAD_FILE_PROTOCOL
*LfProtocol
;
2294 LOADFILE_DEVICE
*LoadDevice
;
2297 // Get our context back.
2299 Status
= gBS
->OpenProtocol (
2301 &gEfiLoadFileProtocolGuid
,
2302 (VOID
**) &LfProtocol
,
2303 This
->DriverBindingHandle
,
2305 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2308 if (EFI_ERROR (Status
)) {
2309 return EFI_UNSUPPORTED
;
2312 LoadDevice
= EFI_LOAD_FILE_DEV_FROM_THIS (LfProtocol
);
2314 Status
= gBS
->UninstallMultipleProtocolInterfaces (
2316 &gEfiLoadFileProtocolGuid
,
2317 &LoadDevice
->LoadFile
,
2318 &gEfiPxeBaseCodeProtocolGuid
,
2319 &LoadDevice
->Private
->EfiBc
,
2323 if (!EFI_ERROR (Status
)) {
2325 Status
= gBS
->CloseProtocol (
2327 &gEfiSimpleNetworkProtocolGuid
,
2328 This
->DriverBindingHandle
,
2332 FreePool (LoadDevice
->Private
->EfiBc
.Mode
);
2333 FreePool (LoadDevice
->Private
);
2334 FreePool (LoadDevice
);
2342 InitializeBCDriver (
2343 IN EFI_HANDLE ImageHandle
,
2344 IN EFI_SYSTEM_TABLE
*SystemTable
2348 Routine Description:
2349 Initialize the base code drivers and install the driver binding
2352 Standard EFI Image Entry
2355 EFI_SUCCESS - This driver was successfully bound
2360 OptionsStrucInit ();