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
;
1190 EFI_STATUS StatCode
;
1191 PXE_BASECODE_DEVICE
*Private
;
1194 // Lock the instance data
1196 StatCode
= EFI_SUCCESS
;
1199 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1200 return EFI_INVALID_PARAMETER
;
1203 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1205 if (Private
== NULL
) {
1206 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE pointer == NULL"));
1207 return EFI_INVALID_PARAMETER
;
1210 EfiAcquireLock (&Private
->Lock
);
1213 // Make sure BaseCode is not already started.
1215 if (This
->Mode
->Started
) {
1216 DEBUG ((EFI_D_WARN
, "\nBcStart() BC is already started.\n"));
1217 EfiReleaseLock (&Private
->Lock
);
1218 return EFI_ALREADY_STARTED
;
1222 // Fail if IPv6 is requested and not supported.
1225 DEBUG ((EFI_D_WARN
, "\nBcStart() IPv6 is not supported.\n"));
1226 EfiReleaseLock (&Private
->Lock
);
1227 return EFI_UNSUPPORTED
;
1231 // Setup shortcuts to SNP protocol and data structure.
1233 SnpPtr
= Private
->SimpleNetwork
;
1234 SnpModePtr
= SnpPtr
->Mode
;
1237 // Start and initialize SNP.
1239 if (SnpModePtr
->State
== EfiSimpleNetworkStopped
) {
1240 StatCode
= (*SnpPtr
->Start
) (SnpPtr
);
1242 if (SnpModePtr
->State
!= EfiSimpleNetworkStarted
) {
1243 DEBUG ((EFI_D_WARN
, "\nBcStart() Could not start SNP.\n"));
1244 EfiReleaseLock (&Private
->Lock
);
1249 // acquire memory for mode and transmit/receive buffers
1251 if (SnpModePtr
->State
== EfiSimpleNetworkStarted
) {
1252 StatCode
= (*SnpPtr
->Initialize
) (SnpPtr
, 0, 0);
1254 if (SnpModePtr
->State
!= EfiSimpleNetworkInitialized
) {
1255 DEBUG ((EFI_D_WARN
, "\nBcStart() Could not initialize SNP."));
1256 EfiReleaseLock (&Private
->Lock
);
1263 DEBUG ((EFI_D_INFO
, "\nBC Start()"));
1266 "\nSnpModePtr->State %Xh",
1271 "\nSnpModePtr->HwAddressSize %Xh",
1272 SnpModePtr
->HwAddressSize
)
1276 "\nSnpModePtr->MediaHeaderSize %Xh",
1277 SnpModePtr
->MediaHeaderSize
)
1281 "\nSnpModePtr->MaxPacketSize %Xh",
1282 SnpModePtr
->MaxPacketSize
)
1286 "\nSnpModePtr->MacAddressChangeable %Xh",
1287 SnpModePtr
->MacAddressChangeable
)
1291 "\nSnpModePtr->MultipleTxSupported %Xh",
1292 SnpModePtr
->MultipleTxSupported
)
1296 "\nSnpModePtr->CurrentAddress %Xh",
1297 *((UINTN
*)&SnpModePtr
->CurrentAddress
))
1301 "\nSnpModePtr->BroadcastAddress %Xh",
1302 *((UINTN
*)&SnpModePtr
->BroadcastAddress
))
1306 "\nSnpModePtr->PermanentAddress %Xh",
1307 *((UINTN
*)&SnpModePtr
->PermanentAddress
))
1311 "\nSnpModePtr->NvRamSize %Xh",
1312 SnpModePtr
->NvRamSize
)
1316 "\nSnpModePtr->NvRamAccessSize %Xh",
1317 SnpModePtr
->NvRamAccessSize
)
1321 "\nSnpModePtr->ReceiveFilterMask %Xh",
1322 SnpModePtr
->ReceiveFilterMask
)
1326 "\nSnpModePtr->ReceiveFilterSetting %Xh",
1327 SnpModePtr
->ReceiveFilterSetting
)
1331 "\nSnpModePtr->MCastFilterCount %Xh",
1332 SnpModePtr
->MCastFilterCount
)
1336 "\nSnpModePtr->MCastFilter %Xh",
1337 SnpModePtr
->MCastFilter
)
1341 "\nSnpModePtr->IfType %Xh",
1346 "\nSnpModePtr->MediaPresentSupported %Xh",
1347 SnpModePtr
->MediaPresentSupported
)
1351 "\nSnpModePtr->MediaPresent %Xh",
1352 SnpModePtr
->MediaPresent
)
1356 // If media check is supported and there is no media,
1357 // return error to caller.
1359 if (SnpModePtr
->MediaPresentSupported
&& !SnpModePtr
->MediaPresent
) {
1360 DEBUG ((EFI_D_WARN
, "\nBcStart() Media not present.\n"));
1361 EfiReleaseLock (&Private
->Lock
);
1362 return EFI_NO_MEDIA
;
1365 // Allocate Tx/Rx buffers
1367 Status
= gBS
->AllocatePool (
1368 EfiBootServicesData
,
1369 BUFFER_ALLOCATE_SIZE
,
1370 (VOID
**) &Private
->TransmitBufferPtr
1373 if (!EFI_ERROR (Status
)) {
1374 ZeroMem (Private
->TransmitBufferPtr
, BUFFER_ALLOCATE_SIZE
);
1376 DEBUG ((EFI_D_NET
, "\nBcStart() Could not alloc TxBuf.\n"));
1377 EfiReleaseLock (&Private
->Lock
);
1378 return EFI_OUT_OF_RESOURCES
;
1381 Status
= gBS
->AllocatePool (
1382 EfiBootServicesData
,
1383 BUFFER_ALLOCATE_SIZE
,
1384 (VOID
**) &Private
->ReceiveBufferPtr
1387 if (!EFI_ERROR (Status
)) {
1388 ZeroMem (Private
->ReceiveBufferPtr
, BUFFER_ALLOCATE_SIZE
);
1390 DEBUG ((EFI_D_NET
, "\nBcStart() Could not alloc RxBuf.\n"));
1391 gBS
->FreePool (Private
->TransmitBufferPtr
);
1392 EfiReleaseLock (&Private
->Lock
);
1393 return EFI_OUT_OF_RESOURCES
;
1396 Status
= gBS
->AllocatePool (
1397 EfiBootServicesData
,
1399 (VOID
**) &Private
->TftpErrorBuffer
1402 if (EFI_ERROR (Status
)) {
1403 gBS
->FreePool (Private
->ReceiveBufferPtr
);
1404 gBS
->FreePool (Private
->TransmitBufferPtr
);
1405 EfiReleaseLock (&Private
->Lock
);
1406 return EFI_OUT_OF_RESOURCES
;
1409 Status
= gBS
->AllocatePool (EfiBootServicesData
, 256, (VOID
**) &Private
->TftpAckBuffer
);
1411 if (EFI_ERROR (Status
)) {
1412 gBS
->FreePool (Private
->TftpErrorBuffer
);
1413 gBS
->FreePool (Private
->ReceiveBufferPtr
);
1414 gBS
->FreePool (Private
->TransmitBufferPtr
);
1415 EfiReleaseLock (&Private
->Lock
);
1416 return EFI_OUT_OF_RESOURCES
;
1419 // Initialize private BaseCode instance data
1422 Private
->RandomPort
= (UINT16
) (Private
->RandomPort
+ PXE_RND_PORT_LOW
+ Random (Private
));
1423 } while (Private
->RandomPort
< PXE_RND_PORT_LOW
);
1425 Private
->Igmpv1TimeoutEvent
= NULL
;
1426 Private
->UseIgmpv1Reporting
= TRUE
;
1427 Private
->IpLength
= IP_ADDRESS_LENGTH (Private
->EfiBc
.Mode
);
1430 // Initialize Mode structure
1433 // check for callback protocol and set boolean
1435 SetMakeCallback (Private
);
1436 Private
->EfiBc
.Mode
->Started
= TRUE
;
1437 Private
->EfiBc
.Mode
->TTL
= DEFAULT_TTL
;
1438 Private
->EfiBc
.Mode
->ToS
= DEFAULT_ToS
;
1439 Private
->EfiBc
.Mode
->UsingIpv6
= UseIPv6
;
1440 Private
->EfiBc
.Mode
->DhcpDiscoverValid
= FALSE
;
1441 Private
->EfiBc
.Mode
->DhcpAckReceived
= FALSE
;
1442 Private
->EfiBc
.Mode
->ProxyOfferReceived
= FALSE
;
1443 Private
->EfiBc
.Mode
->PxeDiscoverValid
= FALSE
;
1444 Private
->EfiBc
.Mode
->PxeReplyReceived
= FALSE
;
1445 Private
->EfiBc
.Mode
->PxeBisReplyReceived
= FALSE
;
1446 Private
->EfiBc
.Mode
->IcmpErrorReceived
= FALSE
;
1447 Private
->EfiBc
.Mode
->TftpErrorReceived
= FALSE
;
1448 ZeroMem (&Private
->EfiBc
.Mode
->StationIp
, sizeof (EFI_IP_ADDRESS
));
1449 ZeroMem (&Private
->EfiBc
.Mode
->SubnetMask
, sizeof (EFI_IP_ADDRESS
));
1450 Private
->EfiBc
.Mode
->IpFilter
.Filters
= 0;
1451 Private
->EfiBc
.Mode
->IpFilter
.IpCnt
= 0;
1452 Private
->EfiBc
.Mode
->ArpCacheEntries
= 0;
1453 Private
->EfiBc
.Mode
->RouteTableEntries
= 0;
1454 ZeroMem (&Private
->EfiBc
.Mode
->IcmpError
, sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR
));
1455 ZeroMem (&Private
->EfiBc
.Mode
->TftpError
, sizeof (EFI_PXE_BASE_CODE_TFTP_ERROR
));
1458 // Set to PXE_TRUE by the BC constructor if this BC implementation
1461 Private
->EfiBc
.Mode
->Ipv6Supported
= SUPPORT_IPV6
;
1462 Private
->EfiBc
.Mode
->Ipv6Available
= FALSE
;
1465 // Set to TRUE by the BC constructor if this BC implementation
1468 Private
->EfiBc
.Mode
->BisSupported
= TRUE
;
1469 Private
->EfiBc
.Mode
->BisDetected
= PxebcBisDetect (Private
);
1472 // This field is set to PXE_TRUE by the BC Start() function. When this
1473 // field is PXE_TRUE, ARP packets are sent as needed to get IP and MAC
1474 // addresses. This can cause unexpected delays in the DHCP(), Discover()
1475 // and MTFTP() functions. Setting this to PXE_FALSE will cause these
1476 // functions to fail if the required IP/MAC information is not in the
1477 // ARP cache. The value of this field can be changed by an application
1480 Private
->EfiBc
.Mode
->AutoArp
= TRUE
;
1483 // Unlock the instance data
1485 EfiReleaseLock (&Private
->Lock
);
1492 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
1496 Routine Description:
1497 Stop the BaseCode protocol, Simple Network protocol and UNDI.
1500 Private - Pointer to Pxe BaseCode Protocol
1504 0 - Successfully stopped
1509 // Lock the instance data
1511 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
1512 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
1513 EFI_STATUS StatCode
;
1514 PXE_BASECODE_DEVICE
*Private
;
1516 StatCode
= EFI_SUCCESS
;
1519 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1520 return EFI_INVALID_PARAMETER
;
1523 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1525 if (Private
== NULL
) {
1526 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1527 return EFI_INVALID_PARAMETER
;
1530 EfiAcquireLock (&Private
->Lock
);
1532 SnpPtr
= Private
->SimpleNetwork
;
1533 SnpModePtr
= SnpPtr
->Mode
;
1538 StatCode
= EFI_NOT_STARTED
;
1540 if (SnpModePtr
->State
== EfiSimpleNetworkInitialized
) {
1541 StatCode
= (*SnpPtr
->Shutdown
) (SnpPtr
);
1544 if (SnpModePtr
->State
== EfiSimpleNetworkStarted
) {
1545 StatCode
= (*SnpPtr
->Stop
) (SnpPtr
);
1548 if (Private
->TransmitBufferPtr
!= NULL
) {
1549 gBS
->FreePool (Private
->TransmitBufferPtr
);
1550 Private
->TransmitBufferPtr
= NULL
;
1553 if (Private
->ReceiveBufferPtr
!= NULL
) {
1554 gBS
->FreePool (Private
->ReceiveBufferPtr
);
1555 Private
->ReceiveBufferPtr
= NULL
;
1558 if (Private
->ArpBuffer
!= NULL
) {
1559 gBS
->FreePool (Private
->ArpBuffer
);
1560 Private
->ArpBuffer
= NULL
;
1563 if (Private
->TftpErrorBuffer
!= NULL
) {
1564 gBS
->FreePool (Private
->TftpErrorBuffer
);
1565 Private
->TftpErrorBuffer
= NULL
;
1568 if (Private
->TftpAckBuffer
!= NULL
) {
1569 gBS
->FreePool (Private
->TftpAckBuffer
);
1570 Private
->TftpAckBuffer
= NULL
;
1573 if (Private
->Igmpv1TimeoutEvent
!= NULL
) {
1574 gBS
->CloseEvent (Private
->Igmpv1TimeoutEvent
);
1575 Private
->Igmpv1TimeoutEvent
= NULL
;
1578 Private
->FileSize
= 0;
1579 Private
->EfiBc
.Mode
->Started
= FALSE
;
1582 // Unlock the instance data
1584 EfiReleaseLock (&Private
->Lock
);
1588 const IPV4_ADDR AllSystemsGroup
= { { 224, 0, 0, 1 } };
1592 IN PXE_BASECODE_DEVICE
*Private
,
1593 IN EFI_PXE_BASE_CODE_IP_FILTER
*Filter
1597 Routine Description:
1598 Set up the IP filter
1601 Private - Pointer to Pxe BaseCode Protocol
1602 Filter - Pointer to the filter
1606 0 - Successfully set the filter
1610 EFI_STATUS StatCode
;
1611 EFI_MAC_ADDRESS MACadds
[PXE_IP_FILTER_SIZE
];
1612 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1613 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
1614 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
1620 PxebcMode
= Private
->EfiBc
.Mode
;
1621 SnpPtr
= Private
->SimpleNetwork
;
1622 SnpModePtr
= SnpPtr
->Mode
;
1625 // validate input parameters
1626 // must have a filter
1627 // must not have any extra filter bits set
1629 if (Filter
== NULL
||
1630 (Filter
->Filters
&~FILTER_BITS
)
1632 // must not have a count which is too large or with no IP list
1635 (Filter
->IpCnt
&& (!Filter
->IpList
|| Filter
->IpCnt
> PXE_IP_FILTER_SIZE
))
1637 // must not have incompatible filters - promiscuous incompatible with anything else
1641 (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) &&
1642 ((Filter
->Filters
&~EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) || Filter
->IpCnt
)
1645 DEBUG ((EFI_D_INFO
, "\nIpFilter() Exit #1"));
1646 return EFI_INVALID_PARAMETER
;
1649 // promiscuous multicast incompatible with multicast in IP list
1651 if (Filter
->IpCnt
&& (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
)) {
1652 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1653 if (IS_MULTICAST (&Filter
->IpList
[Index
])) {
1654 DEBUG ((EFI_D_INFO
, "\nIpFilter() Exit #2"));
1655 return EFI_INVALID_PARAMETER
;
1660 // leave groups for all those multicast which are no longer enabled
1662 for (Index
= 0; Index
< PxebcMode
->IpFilter
.IpCnt
; ++Index
) {
1663 if (!IS_MULTICAST (&PxebcMode
->IpFilter
.IpList
[Index
])) {
1667 for (Index2
= 0; Index2
< Filter
->IpCnt
; ++Index2
) {
1668 if (!CompareMem (&PxebcMode
->IpFilter
.IpList
[Index
], &Filter
->IpList
[Index2
], IP_ADDRESS_LENGTH (PxebcMode
))) {
1676 // if we didn't find it, remove from group
1678 if (Index2
== Filter
->IpCnt
) {
1679 IgmpLeaveGroup (Private
, &PxebcMode
->IpFilter
.IpList
[Index
]);
1683 // set enable bits, convert multicast ip adds, join groups
1684 // allways leave receive broadcast enabled at hardware layer
1688 if (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) {
1689 Enable
= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
1691 if (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
) {
1692 Enable
= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
1694 Enable
= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
1696 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1697 CopyMem (&(PxebcMode
->IpFilter
.IpList
[Index
]), &(Filter
->IpList
[Index
]), sizeof (EFI_IP_ADDRESS
));
1699 if (IS_MULTICAST (&Filter
->IpList
[Index
])) {
1700 EFI_IP_ADDRESS
*TmpIp
;
1702 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
1705 // if this is the first group, add the all systems group to mcast list
1709 TmpIp
= (EFI_IP_ADDRESS
*) &AllSystemsGroup
;
1712 TmpIp
= (EFI_IP_ADDRESS
*) &Filter
->IpList
[Index
];
1715 // get MAC address of IP
1717 StatCode
= (*SnpPtr
->MCastIpToMac
) (SnpPtr
, PxebcMode
->UsingIpv6
, TmpIp
, &MACadds
[Index2
++]);
1719 if (EFI_ERROR (StatCode
)) {
1722 "\nIpFilter() Exit #2 %Xh (%r)",
1729 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
1734 if (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
) {
1735 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
1739 // if nothing changed, just return
1743 "\nsnp->ReceiveFilterSetting == %Xh Filter->IpCnt == %Xh",
1744 SnpModePtr
->ReceiveFilterSetting
,
1748 if (SnpModePtr
->ReceiveFilterSetting
== Enable
&& !Filter
->IpCnt
) {
1749 DEBUG ((EFI_D_INFO
, "\nIpFilter() Exit #4"));
1753 // disable those currently set but not set in new filter
1755 Disable
= SnpModePtr
->ReceiveFilterSetting
&~Enable
;
1757 StatCode
= SnpPtr
->ReceiveFilters (SnpPtr
, Enable
, Disable
, FALSE
, Index2
, MACadds
);
1759 PxebcMode
->IpFilter
.IpCnt
= Filter
->IpCnt
;
1762 // join groups for all multicast in list
1764 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1765 if (IS_MULTICAST (&Filter
->IpList
[Index
])) {
1766 IgmpJoinGroup (Private
, &Filter
->IpList
[Index
]);
1770 DEBUG ((EFI_D_INFO
, "\nIpFilter() Exit #5 %Xh (%r)", StatCode
, StatCode
));
1778 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1779 IN EFI_PXE_BASE_CODE_IP_FILTER
*Filter
1783 Routine Description:
1787 Private - Pointer to Pxe BaseCode Protocol
1788 Filter - Pointer to the filter
1792 0 - Successfully set the filter
1796 EFI_STATUS StatCode
;
1797 PXE_BASECODE_DEVICE
*Private
;
1800 // Lock the instance data and make sure started
1802 StatCode
= EFI_SUCCESS
;
1805 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1806 return EFI_INVALID_PARAMETER
;
1809 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1811 if (Private
== NULL
) {
1812 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1813 return EFI_INVALID_PARAMETER
;
1816 EfiAcquireLock (&Private
->Lock
);
1818 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
1819 DEBUG ((EFI_D_ERROR
, "BC was not started."));
1820 EfiReleaseLock (&Private
->Lock
);
1821 return EFI_NOT_STARTED
;
1824 if (Filter
== NULL
) {
1825 return EFI_INVALID_PARAMETER
;
1830 StatCode
= IpFilter (Private
, Filter
);
1833 // Unlock the instance data
1835 EfiReleaseLock (&Private
->Lock
);
1842 EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1843 BOOLEAN
*AutoArpPtr
,
1844 BOOLEAN
*SendGuidPtr
,
1845 UINT8
*TimeToLivePtr
,
1846 UINT8
*TypeOfServicePtr
,
1847 BOOLEAN
*MakeCallbackPtr
1851 Routine Description:
1852 Set the Base Code behavior parameters
1855 This - Pointer to Pxe BaseCode Protocol
1856 AutoArpPtr - Boolean to do ARP stuff
1857 SendGuidPtr - Boolean whether or not to send GUID info
1858 TimeToLivePtr - Value for Total time to live
1859 TypeOfServicePtr - Value for Type of Service
1860 MakeCallbackPtr - Boolean to determine if we make callbacks
1864 0 - Successfully set the parameters
1868 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1870 CHAR8
*SerialNumberPtr
;
1871 EFI_STATUS StatCode
;
1872 PXE_BASECODE_DEVICE
*Private
;
1875 // Lock the instance data and make sure started
1877 StatCode
= EFI_SUCCESS
;
1880 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1881 return EFI_INVALID_PARAMETER
;
1884 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1886 if (Private
== NULL
) {
1887 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1888 return EFI_INVALID_PARAMETER
;
1891 EfiAcquireLock (&Private
->Lock
);
1893 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
1894 DEBUG ((EFI_D_ERROR
, "BC was not started."));
1895 EfiReleaseLock (&Private
->Lock
);
1896 return EFI_NOT_STARTED
;
1899 DEBUG ((EFI_D_INFO
, "\nSetParameters() Entry. "));
1901 PxebcMode
= Private
->EfiBc
.Mode
;
1902 StatCode
= EFI_SUCCESS
;
1904 if (SendGuidPtr
!= NULL
) {
1906 if (PxeBcLibGetSmbiosSystemGuidAndSerialNumber (&TmpGuid
, &SerialNumberPtr
) != EFI_SUCCESS
) {
1907 return EFI_INVALID_PARAMETER
;
1912 if (MakeCallbackPtr
!= NULL
) {
1913 if (*MakeCallbackPtr
) {
1914 if (!SetMakeCallback (Private
)) {
1915 return EFI_INVALID_PARAMETER
;
1919 PxebcMode
->MakeCallbacks
= *MakeCallbackPtr
;
1922 if (AutoArpPtr
!= NULL
) {
1923 PxebcMode
->AutoArp
= *AutoArpPtr
;
1926 if (SendGuidPtr
!= NULL
) {
1927 PxebcMode
->SendGUID
= *SendGuidPtr
;
1930 if (TimeToLivePtr
!= NULL
) {
1931 PxebcMode
->TTL
= *TimeToLivePtr
;
1934 if (TypeOfServicePtr
!= NULL
) {
1935 PxebcMode
->ToS
= *TypeOfServicePtr
;
1938 // Unlock the instance data
1940 DEBUG ((EFI_D_INFO
, "\nSetparameters() Exit = %xh ", StatCode
));
1942 EfiReleaseLock (&Private
->Lock
);
1946 // //////////////////////////////////////////////////////////
1948 // BC Set Station IP Routine
1953 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1954 IN EFI_IP_ADDRESS
*StationIpPtr
,
1955 IN EFI_IP_ADDRESS
*SubnetMaskPtr
1959 Routine Description:
1960 Set the station IP address
1963 This - Pointer to Pxe BaseCode Protocol
1964 StationIpPtr - Pointer to the requested IP address to set in base code
1965 SubnetMaskPtr - Pointer to the requested subnet mask for the base code
1969 EFI_SUCCESS - Successfully set the parameters
1970 EFI_NOT_STARTED - BC has not started
1973 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1974 PXE_BASECODE_DEVICE
*Private
;
1977 // Lock the instance data and make sure started
1981 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1982 return EFI_INVALID_PARAMETER
;
1985 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1987 if (Private
== NULL
) {
1988 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1989 return EFI_INVALID_PARAMETER
;
1992 EfiAcquireLock (&Private
->Lock
);
1994 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
1995 DEBUG ((EFI_D_ERROR
, "BC was not started."));
1996 EfiReleaseLock (&Private
->Lock
);
1997 return EFI_NOT_STARTED
;
2000 PxebcMode
= Private
->EfiBc
.Mode
;
2002 if (StationIpPtr
!= NULL
) {
2003 CopyMem (&PxebcMode
->StationIp
, StationIpPtr
, sizeof (EFI_IP_ADDRESS
));
2004 Private
->GoodStationIp
= TRUE
;
2007 if (SubnetMaskPtr
!= NULL
) {
2008 CopyMem (&PxebcMode
->SubnetMask
, SubnetMaskPtr
, sizeof (EFI_IP_ADDRESS
));
2011 // Unlock the instance data
2013 EfiReleaseLock (&Private
->Lock
);
2018 EFI_DRIVER_BINDING_PROTOCOL gPxeBcDriverBinding
= {
2019 PxeBcDriverSupported
,
2029 PxeBcDriverSupported (
2030 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2031 IN EFI_HANDLE Controller
,
2032 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
2036 Routine Description:
2037 Test to see if this driver supports Controller. Any Controller
2038 than contains a Snp protocol can be supported.
2041 This - Protocol instance pointer.
2042 Controller - Handle of device to test.
2043 RemainingDevicePath - Not used.
2046 EFI_SUCCESS - This driver supports this device.
2047 EFI_ALREADY_STARTED - This driver is already running on this device.
2048 other - This driver does not support this device.
2053 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
2055 Status
= gBS
->OpenProtocol (
2057 &gEfiDevicePathProtocolGuid
,
2059 This
->DriverBindingHandle
,
2061 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
2064 if (EFI_ERROR (Status
)) {
2068 Status
= gBS
->OpenProtocol (
2070 &gEfiSimpleNetworkProtocolGuid
,
2072 This
->DriverBindingHandle
,
2074 EFI_OPEN_PROTOCOL_BY_DRIVER
2076 if (EFI_ERROR (Status
)) {
2080 gBS
->CloseProtocol (
2082 &gEfiSimpleNetworkProtocolGuid
,
2083 This
->DriverBindingHandle
,
2093 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2094 IN EFI_HANDLE Controller
,
2095 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
2099 Routine Description:
2100 Start the Base code driver.
2103 This - Protocol instance pointer.
2104 Controller - Handle of device to test.
2105 RemainingDevicePath - Not used.
2108 EFI_SUCCESS - This driver supports this device.
2109 EFI_ALREADY_STARTED - This driver is already running on this device.
2110 other - This driver does not support this device.
2115 PXE_BASECODE_DEVICE
*Private
;
2116 LOADFILE_DEVICE
*pLF
;
2119 // Allocate structures needed by BaseCode and LoadFile protocols.
2121 Status
= gBS
->AllocatePool (
2122 EfiBootServicesData
,
2123 sizeof (PXE_BASECODE_DEVICE
),
2127 if (!EFI_ERROR (Status
)) {
2128 ZeroMem (Private
, sizeof (PXE_BASECODE_DEVICE
));
2130 DEBUG ((EFI_D_NET
, "\nBcNotifySnp() Could not alloc PXE_BASECODE_DEVICE structure.\n"));
2134 Status
= gBS
->AllocatePool (
2135 EfiBootServicesData
,
2136 sizeof (LOADFILE_DEVICE
),
2140 if (!EFI_ERROR (Status
)) {
2141 ZeroMem (pLF
, sizeof (LOADFILE_DEVICE
));
2143 DEBUG ((EFI_D_NET
, "\nBcNotifySnp() Could not alloc LOADFILE_DEVICE structure.\n"));
2144 gBS
->FreePool (Private
);
2148 Status
= gBS
->AllocatePool (
2149 EfiBootServicesData
,
2150 sizeof (EFI_PXE_BASE_CODE_MODE
),
2151 (VOID
**) &Private
->EfiBc
.Mode
2154 if (!EFI_ERROR (Status
)) {
2155 ZeroMem (Private
->EfiBc
.Mode
, sizeof (EFI_PXE_BASE_CODE_MODE
));
2157 DEBUG ((EFI_D_NET
, "\nBcNotifySnp() Could not alloc Mode structure.\n"));
2158 gBS
->FreePool (Private
);
2159 gBS
->FreePool (pLF
);
2163 // Lock access, just in case
2165 EfiInitializeLock (&Private
->Lock
, EFI_TPL_CALLBACK
);
2166 EfiAcquireLock (&Private
->Lock
);
2168 EfiInitializeLock (&pLF
->Lock
, EFI_TPL_CALLBACK
);
2169 EfiAcquireLock (&pLF
->Lock
);
2172 // Initialize PXE structure
2175 // First initialize the internal 'private' data that the application
2178 Private
->Signature
= PXE_BASECODE_DEVICE_SIGNATURE
;
2179 Private
->Handle
= Controller
;
2182 // Get the NII interface
2184 Status
= gBS
->OpenProtocol (
2186 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
2187 (VOID
**) &Private
->NiiPtr
,
2188 This
->DriverBindingHandle
,
2190 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2193 if (EFI_ERROR (Status
)) {
2194 Status
= gBS
->OpenProtocol (
2196 &gEfiNetworkInterfaceIdentifierProtocolGuid
,
2197 (VOID
**) &Private
->NiiPtr
,
2198 This
->DriverBindingHandle
,
2200 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2203 if (EFI_ERROR (Status
)) {
2208 // Get the Snp interface
2210 Status
= gBS
->OpenProtocol (
2212 &gEfiSimpleNetworkProtocolGuid
,
2213 (VOID
**) &Private
->SimpleNetwork
,
2214 This
->DriverBindingHandle
,
2216 EFI_OPEN_PROTOCOL_BY_DRIVER
2219 if (EFI_ERROR (Status
)) {
2224 // Next, initialize the external 'public' data that
2225 // the application does see.
2227 Private
->EfiBc
.Revision
= EFI_PXE_BASE_CODE_INTERFACE_REVISION
;
2228 Private
->EfiBc
.Start
= BcStart
;
2229 Private
->EfiBc
.Stop
= BcStop
;
2230 Private
->EfiBc
.Dhcp
= BcDhcp
;
2231 Private
->EfiBc
.Discover
= BcDiscover
;
2232 Private
->EfiBc
.Mtftp
= BcMtftp
;
2233 Private
->EfiBc
.UdpWrite
= BcUdpWrite
;
2234 Private
->EfiBc
.UdpRead
= BcUdpRead
;
2235 Private
->EfiBc
.Arp
= BcArp
;
2236 Private
->EfiBc
.SetIpFilter
= BcIpFilter
;
2237 Private
->EfiBc
.SetParameters
= BcSetParameters
;
2238 Private
->EfiBc
.SetStationIp
= BcSetStationIP
;
2239 Private
->EfiBc
.SetPackets
= BcSetPackets
;
2242 // Initialize BaseCode Mode structure
2244 Private
->EfiBc
.Mode
->Started
= FALSE
;
2245 Private
->EfiBc
.Mode
->TTL
= DEFAULT_TTL
;
2246 Private
->EfiBc
.Mode
->ToS
= DEFAULT_ToS
;
2247 Private
->EfiBc
.Mode
->UsingIpv6
= FALSE
;
2248 Private
->EfiBc
.Mode
->AutoArp
= TRUE
;
2251 // Set to PXE_TRUE by the BC constructor if this BC
2252 // implementation supports IPv6.
2254 Private
->EfiBc
.Mode
->Ipv6Supported
= SUPPORT_IPV6
;
2255 Private
->EfiBc
.Mode
->Ipv6Available
= FALSE
;
2258 // Set to TRUE by the BC constructor if this BC
2259 // implementation supports BIS.
2261 Private
->EfiBc
.Mode
->BisSupported
= TRUE
;
2262 Private
->EfiBc
.Mode
->BisDetected
= PxebcBisDetect (Private
);
2265 // Initialize LoadFile structure.
2267 pLF
->Signature
= LOADFILE_DEVICE_SIGNATURE
;
2268 pLF
->LoadFile
.LoadFile
= LoadFile
;
2269 pLF
->Private
= Private
;
2272 // Install protocol interfaces.
2274 Status
= gBS
->InstallMultipleProtocolInterfaces (
2276 &gEfiPxeBaseCodeProtocolGuid
,
2278 &gEfiLoadFileProtocolGuid
,
2283 if (EFI_ERROR (Status
)) {
2284 gBS
->CloseProtocol (
2286 &gEfiSimpleNetworkProtocolGuid
,
2287 This
->DriverBindingHandle
,
2296 EfiReleaseLock (&pLF
->Lock
);
2297 EfiReleaseLock (&Private
->Lock
);
2301 gBS
->FreePool (Private
->EfiBc
.Mode
);
2302 gBS
->FreePool (Private
);
2303 gBS
->FreePool (pLF
);
2310 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2311 IN EFI_HANDLE Controller
,
2312 IN UINTN NumberOfChildren
,
2313 IN EFI_HANDLE
*ChildHandleBuffer
2317 Routine Description:
2318 Stop the Base code driver.
2321 This - Protocol instance pointer.
2322 Controller - Handle of device to test.
2323 NumberOfChildren - Not used
2324 ChildHandleBuffer - Not used
2327 EFI_SUCCESS - This driver supports this device.
2328 EFI_ALREADY_STARTED - This driver is already running on this device.
2329 other - This driver does not support this device.
2334 EFI_LOAD_FILE_PROTOCOL
*LfProtocol
;
2335 LOADFILE_DEVICE
*LoadDevice
;
2338 // Get our context back.
2340 Status
= gBS
->OpenProtocol (
2342 &gEfiLoadFileProtocolGuid
,
2343 (VOID
**) &LfProtocol
,
2344 This
->DriverBindingHandle
,
2346 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2349 if (EFI_ERROR (Status
)) {
2350 return EFI_UNSUPPORTED
;
2353 LoadDevice
= EFI_LOAD_FILE_DEV_FROM_THIS (LfProtocol
);
2355 Status
= gBS
->UninstallMultipleProtocolInterfaces (
2357 &gEfiLoadFileProtocolGuid
,
2358 &LoadDevice
->LoadFile
,
2359 &gEfiPxeBaseCodeProtocolGuid
,
2360 &LoadDevice
->Private
->EfiBc
,
2364 if (!EFI_ERROR (Status
)) {
2366 Status
= gBS
->CloseProtocol (
2368 &gEfiSimpleNetworkProtocolGuid
,
2369 This
->DriverBindingHandle
,
2373 gBS
->FreePool (LoadDevice
->Private
->EfiBc
.Mode
);
2374 gBS
->FreePool (LoadDevice
->Private
);
2375 gBS
->FreePool (LoadDevice
);
2383 InitializeBCDriver (
2384 IN EFI_HANDLE ImageHandle
,
2385 IN EFI_SYSTEM_TABLE
*SystemTable
2389 Routine Description:
2390 Initialize the base code drivers and install the driver binding
2393 Standard EFI Image Entry
2396 EFI_SUCCESS - This driver was successfully bound
2401 OptionsStrucInit ();