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.
32 Convert number to ASCII value
35 Number - Numeric value to convert to decimal ASCII value.
36 Buffer - Buffer to place ASCII version of the Number
37 Length - Length of Buffer.
47 Remainder
= Number
% 10;
49 Buffer
[Length
] = (UINT8
) ('0' + Remainder
);
61 Convert number to decimal ASCII value at Buffer location
64 Number - Numeric value to convert to decimal ASCII value.
65 Buffer - Buffer to place ASCII version of the Number
76 CvtNum (Number
, BuffArray
, 30);
78 for (Index
= 0; Index
< 30; ++Index
) {
79 if (BuffArray
[Index
] != '0') {
84 CopyMem (Buffer
, BuffArray
+ Index
, 31 - Index
);
94 Convert ASCII numeric string to a UINTN value
97 Number - Numeric value to convert to decimal ASCII value.
98 Buffer - Buffer to place ASCII version of the Number
101 Value - UINTN value of the ASCII string.
109 Character
= *Buffer
++;
111 Value
= Value
* 10 + Character
- '0';
112 Character
= *Buffer
++;
125 Convert ASCII numeric string to a UINTN value
128 Number - Numeric value to convert to decimal ASCII value.
129 Buffer - Buffer to place ASCII version of the Number
132 Value - UINTN value of the ASCII string.
140 while ((Character
= *Buffer
++) != '\0') {
141 Value
= MultU64x32 (Value
, 10) + (Character
- '0');
147 // random number generator
149 #define RANDOM_MULTIPLIER 2053
150 #define RANDOM_ADD_IN_VALUE 19
154 IN PXE_BASECODE_DEVICE
*Private
,
155 IN UINT16 InitialSeed
160 Initialize the Seed for the random number generator
169 if (Private
!= NULL
) {
170 Private
->RandomSeed
= InitialSeed
;
176 IN PXE_BASECODE_DEVICE
*Private
181 Generate and return a pseudo-random number
186 Number - UINT16 random number
192 if (Private
!= NULL
) {
193 Number
= -(INTN
) Private
->RandomSeed
* RANDOM_MULTIPLIER
+ RANDOM_ADD_IN_VALUE
;
195 return Private
->RandomSeed
= (UINT16
) Number
;
201 // calculate the internet checksum (RFC 1071)
202 // return 16 bit ones complement of ones complement sum of 16 bit words
212 Calculate the internet checksum (see RFC 1071)
215 Packet - Buffer which contains the data to be checksummed
216 Length - Length to be checksummed
219 Checksum - Returns the 16 bit ones complement of
220 ones complement sum of 16 bit words
228 Odd
= (UINT8
) (Length
& 1);
235 Sum
+= *(UINT8
*) Packet
;
238 Sum
= (Sum
& 0xffff) + (Sum
>> 16);
240 // in case above carried
244 return (UINT16
) (~ (UINT16
) Sum
);
257 Calculate the internet checksum (see RFC 1071)
258 on a non contiguous header and data
261 Header - Buffer which contains the data to be checksummed
262 HeaderLen - Length to be checksummed
263 Message - Buffer which contains the data to be checksummed
264 MessageLen - Length to be checksummed
267 Checksum - Returns the 16 bit ones complement of
268 ones complement sum of 16 bit words
274 Sum
= (UINT16
)~IpChecksum (Header
, HeaderLen
);
275 Sum
= Sum
+ (UINT16
)~IpChecksum (Message
, MessageLen
);
277 // in case above carried
281 return (UINT16
) (~ (UINT16
) Sum
);
293 Adjust the internet checksum (see RFC 1071) on a single word update.
296 OldChkSum - Checksum previously calculated
301 Checksum - Returns the 16 bit ones complement of
302 ones complement sum of 16 bit words
308 sum
= ~OldChksum
+ NewWord
- OldWord
;
310 // in case above carried
313 return (UINT16
) (~ (UINT16
) sum
);
319 IN PXE_BASECODE_DEVICE
*Private
324 See if a callback is in play
327 Private - Pointer to Pxe BaseCode Protocol
330 0 - Callbacks are active on the handle
331 1 - Callbacks are not active on the handle
335 Private
->EfiBc
.Mode
->MakeCallbacks
= (BOOLEAN
) (gBS
->HandleProtocol (
337 &gEfiPxeBaseCodeCallbackProtocolGuid
,
338 (VOID
*) &Private
->CallbackProtocolPtr
343 "\nMode->MakeCallbacks == %d ",
344 Private
->EfiBc
.Mode
->MakeCallbacks
)
349 "\nPrivate->CallbackProtocolPtr == %xh ",
350 Private
->CallbackProtocolPtr
)
353 if (Private
->CallbackProtocolPtr
!= NULL
) {
356 "\nCallbackProtocolPtr->Revision = %xh ",
357 Private
->CallbackProtocolPtr
->Revision
)
362 "\nCallbackProtocolPtr->Callback = %xh ",
363 Private
->CallbackProtocolPtr
->Callback
)
367 return Private
->EfiBc
.Mode
->MakeCallbacks
;
370 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
373 IN PXE_BASECODE_DEVICE
*Private
,
374 IN EFI_PXE_BASE_CODE_FUNCTION Function
,
375 IN EFI_EVENT TimeoutEvent
,
376 IN OUT UINTN
*HeaderSizePtr
,
377 IN OUT UINTN
*BufferSizePtr
,
378 IN OUT UINT16
*ProtocolPtr
383 Routine which does an SNP->Receive over a timeout period and doing callbacks
386 Private - Pointer to Pxe BaseCode Protocol
387 Function - What PXE function to callback
388 TimeoutEvent - Timer event that will trigger when we have waited too
389 long for an incoming packet
390 HeaderSizePtr - Pointer to the size of the Header size
391 BufferSizePtr - Pointer to the size of the Buffer size
392 ProtocolPtr - The protocol to sniff for (namely, UDP/etc)
395 0 - Something was returned
396 !0 - Like there was nothing to receive (EFI_TIMEOUT/NOT_READY)
400 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
401 EFI_PXE_CALLBACK CallbackPtr
;
403 EFI_EVENT CallbackEvent
;
406 // Initialize pointer to SNP interface
408 SnpPtr
= Private
->SimpleNetwork
;
411 // Initialize pointer to PxeBc callback routine - if any
413 CallbackPtr
= (Private
->EfiBc
.Mode
->MakeCallbacks
) ? Private
->CallbackProtocolPtr
->Callback
: NULL
;
416 // Create callback event and set timer
418 StatCode
= gBS
->CreateEvent (
426 if (EFI_ERROR (StatCode
)) {
427 return EFI_DEVICE_ERROR
;
431 // every 100 milliseconds
433 StatCode
= gBS
->SetTimer (
439 if (EFI_ERROR (StatCode
)) {
440 gBS
->CloseEvent (CallbackEvent
);
441 return EFI_DEVICE_ERROR
;
444 // Loop until a packet is received or a receive error is detected or
445 // a callback abort is detected or a timeout event occurs.
451 // Check for received packet event.
453 if (!EFI_ERROR (gBS
->CheckEvent (SnpPtr
->WaitForPacket
))) {
455 // Packet should be available. Attempt to read it.
457 *BufferSizePtr
= BUFFER_ALLOCATE_SIZE
;
459 StatCode
= SnpPtr
->Receive (
463 Private
->ReceiveBufferPtr
,
469 if (EFI_ERROR (StatCode
)) {
473 // Packet was received. Make received callback then return.
475 if (CallbackPtr
!= NULL
) {
476 StatCode
= CallbackPtr (
477 Private
->CallbackProtocolPtr
,
480 (UINT32
) *BufferSizePtr
,
481 (EFI_PXE_BASE_CODE_PACKET
*) Private
->ReceiveBufferPtr
484 if (StatCode
!= EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
) {
485 StatCode
= EFI_ABORTED
;
487 StatCode
= EFI_SUCCESS
;
496 // Poll for received packet.
498 *BufferSizePtr
= BUFFER_ALLOCATE_SIZE
;
500 StatCode
= SnpPtr
->Receive (
504 Private
->ReceiveBufferPtr
,
510 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
;
533 if (StatCode
!= EFI_NOT_READY
) {
538 // Check for callback event.
540 if (!EFI_ERROR (gBS
->CheckEvent (CallbackEvent
))) {
542 // Make periodic callback if callback pointer is initialized.
544 if (CallbackPtr
!= NULL
) {
545 StatCode
= CallbackPtr (
546 Private
->CallbackProtocolPtr
,
554 // Abort if directed to by callback routine.
556 if (StatCode
!= EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
) {
557 StatCode
= EFI_ABORTED
;
563 // Check for timeout event.
565 if (TimeoutEvent
== 0) {
566 StatCode
= EFI_TIMEOUT
;
570 if (!EFI_ERROR (gBS
->CheckEvent (TimeoutEvent
))) {
571 StatCode
= EFI_TIMEOUT
;
575 // Check IGMP timer events.
577 IgmpCheckTimers (Private
);
580 gBS
->CloseEvent (CallbackEvent
);
587 PXE_BASECODE_DEVICE
*Private
,
592 UINT16 MediaProtocol
,
593 IN EFI_PXE_BASE_CODE_FUNCTION Function
598 Routine which does an SNP->Transmit of a buffer
601 Private - Pointer to Pxe BaseCode Protocol
602 HeaderPtr - Pointer to the buffer
603 PacketPtr - Pointer to the packet to send
604 PacketLen - The length of the entire packet to send
605 HardwareAddr - Pointer to the MAC address of the destination
606 MediaProtocol - What type of frame to create (RFC 1700) - IE. Ethernet
607 Function - What PXE function to callback
610 0 - Something was sent
611 !0 - An error was encountered during sending of a packet
615 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
616 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
617 EFI_PXE_CALLBACK CallbackPtr
;
619 EFI_EVENT TimeoutEvent
;
626 CallbackPtr
= Private
->EfiBc
.Mode
->MakeCallbacks
? Private
->CallbackProtocolPtr
->Callback
: 0;
628 SnpPtr
= Private
->SimpleNetwork
;
629 SnpModePtr
= SnpPtr
->Mode
;
632 // clear prior interrupt status
634 StatCode
= SnpPtr
->GetStatus (SnpPtr
, &IntStatus
, 0);
636 if (EFI_ERROR (StatCode
)) {
639 "\nSendPacket() Exit #1 %xh (%r)",
646 Private
->DidTransmit
= FALSE
;
648 if (CallbackPtr
!= NULL
) {
650 Private
->CallbackProtocolPtr
,
655 ) != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE
) {
658 "\nSendPacket() Exit #2 %xh (%r)",
666 // put packet in transmit queue
667 // headersize should be zero if not filled in
669 StatCode
= gBS
->CreateEvent (
677 if (EFI_ERROR (StatCode
)) {
680 "Could not create transmit timeout event. %r\n",
683 return EFI_DEVICE_ERROR
;
689 StatCode
= gBS
->SetTimer (
695 if (EFI_ERROR (StatCode
)) {
698 "Could not set transmit timeout event timer. %r\n",
701 gBS
->CloseEvent (TimeoutEvent
);
702 return EFI_DEVICE_ERROR
;
706 StatCode
= SnpPtr
->Transmit (
708 (UINTN
) SnpPtr
->Mode
->MediaHeaderSize
,
709 (UINTN
) (PacketLen
+ SnpPtr
->Mode
->MediaHeaderSize
),
711 &SnpModePtr
->CurrentAddress
,
712 (EFI_MAC_ADDRESS
*) HardwareAddr
,
716 if (StatCode
!= EFI_NOT_READY
) {
720 if (!EFI_ERROR (gBS
->CheckEvent (TimeoutEvent
))) {
721 StatCode
= EFI_TIMEOUT
;
726 gBS
->CloseEvent (TimeoutEvent
);
728 if (EFI_ERROR (StatCode
)) {
731 "\nSendPacket() Exit #3 %xh (%r)",
738 // remove transmit buffer from snp's unused queue
739 // done this way in case someday things are buffered and we don't get it back
742 StatCode
= gBS
->CreateEvent (
750 if (EFI_ERROR (StatCode
)) {
753 "Could not create transmit status timeout event. %r\n",
756 return EFI_DEVICE_ERROR
;
762 StatCode
= gBS
->SetTimer (
768 if (EFI_ERROR (StatCode
)) {
771 "Could not set transmit status timeout event timer. %r\n",
774 gBS
->CloseEvent (TimeoutEvent
);
775 return EFI_DEVICE_ERROR
;
779 StatCode
= SnpPtr
->GetStatus (SnpPtr
, &IntStatus
, &TxBuf
);
781 if (EFI_ERROR (StatCode
)) {
784 "\nSendPacket() Exit #4 %xh (%r)",
791 if (IntStatus
& EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT
) {
792 Private
->DidTransmit
= TRUE
;
799 if (!EFI_ERROR (gBS
->CheckEvent (TimeoutEvent
))) {
800 StatCode
= EFI_TIMEOUT
;
805 gBS
->CloseEvent (TimeoutEvent
);
814 IN PXE_BASECODE_DEVICE
*Private
,
815 OUT BIS_APPLICATION_HANDLE
*BisAppHandle
,
816 OUT OPTIONAL EFI_BIS_DATA
**BisDataSigInfo
820 Locate BIS interface and if found, try to start it.
823 Private := Pointer to PxeBc protocol
824 BisAppHandle := Pointer to BIS application handle storage
825 BisDataSigInfo := Pointer to BIS signature information storage
829 EFI_STATUS EfiStatus
;
830 EFI_HANDLE BisHandleBuffer
;
831 UINTN BisHandleCount
;
832 EFI_BIS_PROTOCOL
*BisPtr
;
833 EFI_BIS_VERSION BisInterfaceVersion
;
834 BOOLEAN BisCheckFlag
;
836 BisHandleCount
= sizeof (EFI_HANDLE
);
837 BisCheckFlag
= FALSE
;
840 // Locate BIS protocol handle (if present).
841 // If BIS protocol handle is not found, return NULL.
843 DEBUG ((EFI_D_INFO
, "\ngBS->LocateHandle() "));
845 EfiStatus
= gBS
->LocateHandle (
847 &gEfiBisProtocolGuid
,
853 if (EFI_ERROR (EfiStatus
)) {
855 // Any error means that there is no BIS.
856 // Note - It could mean that there are more than
857 // one BIS protocols installed, but that scenario
858 // is not yet supported.
862 "\nPxebcBisStart()""\n gBS->LocateHandle() %r (%xh)\n",
870 if (BisHandleCount
!= sizeof BisHandleBuffer
) {
872 // This really should never happen, but I am paranoid.
876 "\nPxebcBisStart() BisHandleCount != %d\n",
877 sizeof BisHandleBuffer
)
883 DEBUG ((EFI_D_INFO
, "BIS handle found."));
886 // Locate BIS protocol interface.
887 // If the BIS protocol interface cannot be found, return NULL.
889 DEBUG ((EFI_D_INFO
, "\ngBS->HandleProtocol() "));
891 EfiStatus
= gBS
->HandleProtocol (
893 &gEfiBisProtocolGuid
,
897 if (EFI_ERROR (EfiStatus
)) {
900 "\nPxebcBisStart()""\n gBS->HandleProtocol() %r (%xh)\n",
908 if (BisPtr
== NULL
) {
910 // This really should never happen.
914 "\nPxebcBisStart()""\n gBS->HandleProtocoL() ""BIS protocol interface pointer is NULL!\n")
920 DEBUG ((EFI_D_INFO
, "BIS protocol interface found."));
923 // Check that all of the BIS API function pointers are not NULL.
925 if (BisPtr
->Initialize
== NULL
||
926 BisPtr
->Shutdown
== NULL
||
927 BisPtr
->Free
== NULL
||
928 BisPtr
->GetBootObjectAuthorizationCertificate
== NULL
||
929 BisPtr
->GetBootObjectAuthorizationCheckFlag
== NULL
||
930 BisPtr
->GetBootObjectAuthorizationUpdateToken
== NULL
||
931 BisPtr
->GetSignatureInfo
== NULL
||
932 BisPtr
->UpdateBootObjectAuthorization
== NULL
||
933 BisPtr
->VerifyBootObject
== NULL
||
934 BisPtr
->VerifyObjectWithCredential
== NULL
939 "\nPxebcBisStart()""\n BIS protocol interface is invalid."
940 "\n At least one BIS protocol function pointer is NULL.\n"
948 // If BIS does not initialize, return NULL.
950 DEBUG ((EFI_D_INFO
, "\nBisPtr->Initialize() "));
952 BisInterfaceVersion
.Major
= BIS_VERSION_1
;
954 EfiStatus
= BisPtr
->Initialize (
957 &BisInterfaceVersion
,
961 if (EFI_ERROR (EfiStatus
)) {
964 "\nPxebcBisStart()""\n BisPtr->Initialize() %r (%xh)\n",
974 " BIS version: %d.%d",
975 BisInterfaceVersion
.Major
,
976 BisInterfaceVersion
.Minor
)
980 // If the requested BIS API version is not supported,
981 // shutdown BIS and return NULL.
983 if (BisInterfaceVersion
.Major
!= BIS_VERSION_1
) {
986 "\nPxebcBisStart()""\n BIS version %d.%d not supported by PXE BaseCode.\n",
987 BisInterfaceVersion
.Major
,
988 BisInterfaceVersion
.Minor
)
991 BisPtr
->Shutdown (*BisAppHandle
);
995 // Get BIS check flag.
996 // If the BIS check flag cannot be read, shutdown BIS and return NULL.
998 DEBUG ((EFI_D_INFO
, "\nBisPtr->GetBootObjectAuthorizationCheckFlag() "));
1000 EfiStatus
= BisPtr
->GetBootObjectAuthorizationCheckFlag (*BisAppHandle
, &BisCheckFlag
);
1002 if (EFI_ERROR (EfiStatus
)) {
1005 "\nPxebcBisStart()""\n BisPtr->GetBootObjectAuthorizationCheckFlag() %r (%xh)\n",
1010 BisPtr
->Shutdown (*BisAppHandle
);
1014 // If the BIS check flag is FALSE, shutdown BIS and return NULL.
1016 if (!BisCheckFlag
) {
1017 DEBUG ((EFI_D_INFO
, "\nBIS check flag is FALSE.\n"));
1018 BisPtr
->Shutdown (*BisAppHandle
);
1021 DEBUG ((EFI_D_INFO
, "\nBIS check flag is TRUE."));
1024 // Early out if caller does not want signature information.
1026 if (BisDataSigInfo
== NULL
) {
1030 // Get BIS signature information.
1031 // If the signature information cannot be read or is invalid,
1032 // shutdown BIS and return NULL.
1034 DEBUG ((EFI_D_INFO
, "\nBisPtr->GetSignatureInfo() "));
1036 EfiStatus
= BisPtr
->GetSignatureInfo (*BisAppHandle
, BisDataSigInfo
);
1038 if (EFI_ERROR (EfiStatus
)) {
1041 "\nPxebcBisStart()""\n BisPtr_GetSignatureInfo() %r (%xh)\n",
1046 BisPtr
->Shutdown (*BisAppHandle
);
1050 if (*BisDataSigInfo
== NULL
) {
1052 // This should never happen.
1056 "\nPxebcBisStart()""\n BisPtr->GetSignatureInfo() Data pointer is NULL!\n")
1059 BisPtr
->Shutdown (*BisAppHandle
);
1063 if ((*BisDataSigInfo
)->Length
< sizeof (EFI_BIS_SIGNATURE_INFO
) ||
1064 (*BisDataSigInfo
)->Length
% sizeof (EFI_BIS_SIGNATURE_INFO
) ||
1065 (*BisDataSigInfo
)->Length
> sizeof (EFI_BIS_SIGNATURE_INFO
) * 63
1068 // This should never happen.
1072 "\nPxebcBisStart()""\n BisPtr->GetSignatureInfo() Invalid BIS siginfo length.\n")
1075 BisPtr
->Free (*BisAppHandle
, *BisDataSigInfo
);
1076 BisPtr
->Shutdown (*BisAppHandle
);
1085 EFI_BIS_PROTOCOL
*BisPtr
,
1086 BIS_APPLICATION_HANDLE BisAppHandle
,
1087 EFI_BIS_DATA
*BisDataSigInfo
1090 Routine description:
1091 Stop the BIS interface and release allocations.
1094 BisPtr := Pointer to BIS interface
1095 BisAppHandle := BIS application handle
1096 BisDataSigInfo := Pointer to BIS signature information data
1102 if (BisPtr
== NULL
) {
1106 // Free BIS allocated resources and shutdown BIS.
1107 // Return TRUE - BIS support is officially detected.
1109 if (BisDataSigInfo
!= NULL
) {
1110 BisPtr
->Free (BisAppHandle
, BisDataSigInfo
);
1113 BisPtr
->Shutdown (BisAppHandle
);
1118 PXE_BASECODE_DEVICE
*Private
,
1121 VOID
*CredentialBuffer
,
1122 UINTN CredentialLength
1125 Routine description:
1126 Verify image and credential file.
1129 Private := Pointer to PxeBc interface
1130 FileBuffer := Pointer to image buffer
1131 FileLength := Image length in bytes
1132 CredentialBuffer := Pointer to credential buffer
1133 CredentialLength := Credential length in bytes
1137 FALSE := not verified
1140 EFI_BIS_PROTOCOL
*BisPtr
;
1141 BIS_APPLICATION_HANDLE BisAppHandle
;
1142 EFI_BIS_DATA FileData
;
1143 EFI_BIS_DATA CredentialData
;
1144 EFI_STATUS EfiStatus
;
1147 if (Private
== NULL
|| FileBuffer
== NULL
|| FileLength
== 0 || CredentialBuffer
== NULL
|| CredentialLength
== 0) {
1151 BisPtr
= PxebcBisStart (Private
, &BisAppHandle
, NULL
);
1153 if (BisPtr
== NULL
) {
1157 FileData
.Length
= (UINT32
) FileLength
;
1158 FileData
.Data
= FileBuffer
;
1159 CredentialData
.Length
= (UINT32
) CredentialLength
;
1160 CredentialData
.Data
= CredentialBuffer
;
1162 EfiStatus
= BisPtr
->VerifyBootObject (
1169 PxebcBisStop (BisPtr
, BisAppHandle
, NULL
);
1171 return (BOOLEAN
) ((EFI_ERROR (EfiStatus
)) ? FALSE
: (IsVerified
? TRUE
: FALSE
));
1176 PXE_BASECODE_DEVICE
*Private
1179 Routine description:
1180 Check for BIS interface presence.
1183 Private := Pointer to PxeBc interface
1187 FALSE := BIS not present
1190 EFI_BIS_PROTOCOL
*BisPtr
;
1191 BIS_APPLICATION_HANDLE BisAppHandle
;
1192 EFI_BIS_DATA
*BisDataSigInfo
;
1194 BisPtr
= PxebcBisStart (Private
, &BisAppHandle
, &BisDataSigInfo
);
1196 if (BisPtr
== NULL
) {
1200 PxebcBisStop (BisPtr
, BisAppHandle
, BisDataSigInfo
);
1210 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1215 Routine Description:
1216 Start and initialize the BaseCode protocol, Simple Network protocol and UNDI.
1219 Private - Pointer to Pxe BaseCode Protocol
1220 UseIPv6 - Do we want to support IPv6?
1224 EFI_INVALID_PARAMETER
1227 EFI_OUT_OF_RESOURCES
1228 Status is also returned from SNP.Start() and SNP.Initialize().
1232 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
1233 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
1235 EFI_STATUS StatCode
;
1236 PXE_BASECODE_DEVICE
*Private
;
1239 // Lock the instance data
1241 StatCode
= EFI_SUCCESS
;
1244 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1245 return EFI_INVALID_PARAMETER
;
1248 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1250 if (Private
== NULL
) {
1251 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE pointer == NULL"));
1252 return EFI_INVALID_PARAMETER
;
1255 EfiAcquireLock (&Private
->Lock
);
1258 // Make sure BaseCode is not already started.
1260 if (This
->Mode
->Started
) {
1261 DEBUG ((EFI_D_WARN
, "\nBcStart() BC is already started.\n"));
1262 EfiReleaseLock (&Private
->Lock
);
1263 return EFI_ALREADY_STARTED
;
1268 // Fail if IPv6 is requested and not supported.
1271 DEBUG ((EFI_D_WARN
, "\nBcStart() IPv6 is not supported.\n"));
1272 EfiReleaseLock (&Private
->Lock
);
1273 return EFI_UNSUPPORTED
;
1277 // Setup shortcuts to SNP protocol and data structure.
1279 SnpPtr
= Private
->SimpleNetwork
;
1280 SnpModePtr
= SnpPtr
->Mode
;
1283 // Start and initialize SNP.
1285 if (SnpModePtr
->State
== EfiSimpleNetworkStopped
) {
1286 StatCode
= (*SnpPtr
->Start
) (SnpPtr
);
1288 if (SnpModePtr
->State
!= EfiSimpleNetworkStarted
) {
1289 DEBUG ((EFI_D_WARN
, "\nBcStart() Could not start SNP.\n"));
1290 EfiReleaseLock (&Private
->Lock
);
1295 // acquire memory for mode and transmit/receive buffers
1297 if (SnpModePtr
->State
== EfiSimpleNetworkStarted
) {
1298 StatCode
= (*SnpPtr
->Initialize
) (SnpPtr
, 0, 0);
1300 if (SnpModePtr
->State
!= EfiSimpleNetworkInitialized
) {
1301 DEBUG ((EFI_D_WARN
, "\nBcStart() Could not initialize SNP."));
1302 EfiReleaseLock (&Private
->Lock
);
1309 DEBUG ((EFI_D_INFO
, "\nBC Start()"));
1312 "\nSnpModePtr->State %Xh",
1317 "\nSnpModePtr->HwAddressSize %Xh",
1318 SnpModePtr
->HwAddressSize
)
1322 "\nSnpModePtr->MediaHeaderSize %Xh",
1323 SnpModePtr
->MediaHeaderSize
)
1327 "\nSnpModePtr->MaxPacketSize %Xh",
1328 SnpModePtr
->MaxPacketSize
)
1332 "\nSnpModePtr->MacAddressChangeable %Xh",
1333 SnpModePtr
->MacAddressChangeable
)
1337 "\nSnpModePtr->MultipleTxSupported %Xh",
1338 SnpModePtr
->MultipleTxSupported
)
1342 "\nSnpModePtr->CurrentAddress %Xh",
1343 *((UINTN
*)&SnpModePtr
->CurrentAddress
))
1347 "\nSnpModePtr->BroadcastAddress %Xh",
1348 *((UINTN
*)&SnpModePtr
->BroadcastAddress
))
1352 "\nSnpModePtr->PermanentAddress %Xh",
1353 *((UINTN
*)&SnpModePtr
->PermanentAddress
))
1357 "\nSnpModePtr->NvRamSize %Xh",
1358 SnpModePtr
->NvRamSize
)
1362 "\nSnpModePtr->NvRamAccessSize %Xh",
1363 SnpModePtr
->NvRamAccessSize
)
1367 "\nSnpModePtr->ReceiveFilterMask %Xh",
1368 SnpModePtr
->ReceiveFilterMask
)
1372 "\nSnpModePtr->ReceiveFilterSetting %Xh",
1373 SnpModePtr
->ReceiveFilterSetting
)
1377 "\nSnpModePtr->MCastFilterCount %Xh",
1378 SnpModePtr
->MCastFilterCount
)
1382 "\nSnpModePtr->MCastFilter %Xh",
1383 SnpModePtr
->MCastFilter
)
1387 "\nSnpModePtr->IfType %Xh",
1392 "\nSnpModePtr->MediaPresentSupported %Xh",
1393 SnpModePtr
->MediaPresentSupported
)
1397 "\nSnpModePtr->MediaPresent %Xh",
1398 SnpModePtr
->MediaPresent
)
1402 // If media check is supported and there is no media,
1403 // return error to caller.
1405 if (SnpModePtr
->MediaPresentSupported
&& !SnpModePtr
->MediaPresent
) {
1406 DEBUG ((EFI_D_WARN
, "\nBcStart() Media not present.\n"));
1407 EfiReleaseLock (&Private
->Lock
);
1408 return EFI_NO_MEDIA
;
1411 // Allocate Tx/Rx buffers
1413 Status
= gBS
->AllocatePool (
1414 EfiBootServicesData
,
1415 BUFFER_ALLOCATE_SIZE
,
1416 (VOID
**) &Private
->TransmitBufferPtr
1419 if (!EFI_ERROR (Status
)) {
1420 ZeroMem (Private
->TransmitBufferPtr
, BUFFER_ALLOCATE_SIZE
);
1422 DEBUG ((EFI_D_NET
, "\nBcStart() Could not alloc TxBuf.\n"));
1423 EfiReleaseLock (&Private
->Lock
);
1424 return EFI_OUT_OF_RESOURCES
;
1427 Status
= gBS
->AllocatePool (
1428 EfiBootServicesData
,
1429 BUFFER_ALLOCATE_SIZE
,
1430 (VOID
**) &Private
->ReceiveBufferPtr
1433 if (!EFI_ERROR (Status
)) {
1434 ZeroMem (Private
->ReceiveBufferPtr
, BUFFER_ALLOCATE_SIZE
);
1436 DEBUG ((EFI_D_NET
, "\nBcStart() Could not alloc RxBuf.\n"));
1437 gBS
->FreePool (Private
->TransmitBufferPtr
);
1438 EfiReleaseLock (&Private
->Lock
);
1439 return EFI_OUT_OF_RESOURCES
;
1442 Status
= gBS
->AllocatePool (
1443 EfiBootServicesData
,
1445 (VOID
**) &Private
->TftpErrorBuffer
1448 if (EFI_ERROR (Status
)) {
1449 gBS
->FreePool (Private
->ReceiveBufferPtr
);
1450 gBS
->FreePool (Private
->TransmitBufferPtr
);
1451 EfiReleaseLock (&Private
->Lock
);
1452 return EFI_OUT_OF_RESOURCES
;
1455 Status
= gBS
->AllocatePool (EfiBootServicesData
, 256, (VOID
**) &Private
->TftpAckBuffer
);
1457 if (EFI_ERROR (Status
)) {
1458 gBS
->FreePool (Private
->TftpErrorBuffer
);
1459 gBS
->FreePool (Private
->ReceiveBufferPtr
);
1460 gBS
->FreePool (Private
->TransmitBufferPtr
);
1461 EfiReleaseLock (&Private
->Lock
);
1462 return EFI_OUT_OF_RESOURCES
;
1465 // Initialize private BaseCode instance data
1468 Private
->RandomPort
= (UINT16
) (Private
->RandomPort
+ PXE_RND_PORT_LOW
+ Random (Private
));
1469 } while (Private
->RandomPort
< PXE_RND_PORT_LOW
);
1471 Private
->Igmpv1TimeoutEvent
= NULL
;
1472 Private
->UseIgmpv1Reporting
= TRUE
;
1473 Private
->IpLength
= IP_ADDRESS_LENGTH (Private
->EfiBc
.Mode
);
1476 // Initialize Mode structure
1479 // check for callback protocol and set boolean
1481 SetMakeCallback (Private
);
1482 Private
->EfiBc
.Mode
->Started
= TRUE
;
1483 Private
->EfiBc
.Mode
->TTL
= DEFAULT_TTL
;
1484 Private
->EfiBc
.Mode
->ToS
= DEFAULT_ToS
;
1485 Private
->EfiBc
.Mode
->UsingIpv6
= UseIPv6
;
1486 Private
->EfiBc
.Mode
->DhcpDiscoverValid
= FALSE
;
1487 Private
->EfiBc
.Mode
->DhcpAckReceived
= FALSE
;
1488 Private
->EfiBc
.Mode
->ProxyOfferReceived
= FALSE
;
1489 Private
->EfiBc
.Mode
->PxeDiscoverValid
= FALSE
;
1490 Private
->EfiBc
.Mode
->PxeReplyReceived
= FALSE
;
1491 Private
->EfiBc
.Mode
->PxeBisReplyReceived
= FALSE
;
1492 Private
->EfiBc
.Mode
->IcmpErrorReceived
= FALSE
;
1493 Private
->EfiBc
.Mode
->TftpErrorReceived
= FALSE
;
1494 ZeroMem (&Private
->EfiBc
.Mode
->StationIp
, sizeof (EFI_IP_ADDRESS
));
1495 ZeroMem (&Private
->EfiBc
.Mode
->SubnetMask
, sizeof (EFI_IP_ADDRESS
));
1496 Private
->EfiBc
.Mode
->IpFilter
.Filters
= 0;
1497 Private
->EfiBc
.Mode
->IpFilter
.IpCnt
= 0;
1498 Private
->EfiBc
.Mode
->ArpCacheEntries
= 0;
1499 Private
->EfiBc
.Mode
->RouteTableEntries
= 0;
1500 ZeroMem (&Private
->EfiBc
.Mode
->IcmpError
, sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR
));
1501 ZeroMem (&Private
->EfiBc
.Mode
->TftpError
, sizeof (EFI_PXE_BASE_CODE_TFTP_ERROR
));
1504 // Set to PXE_TRUE by the BC constructor if this BC implementation
1507 Private
->EfiBc
.Mode
->Ipv6Supported
= SUPPORT_IPV6
;
1510 Private
->EfiBc
.Mode
->Ipv6Available
= Private
->NiiPtr
->Ipv6Supported
;
1512 Private
->EfiBc
.Mode
->Ipv6Available
= FALSE
;
1515 // Set to TRUE by the BC constructor if this BC implementation
1518 Private
->EfiBc
.Mode
->BisSupported
= TRUE
;
1519 Private
->EfiBc
.Mode
->BisDetected
= PxebcBisDetect (Private
);
1522 // This field is set to PXE_TRUE by the BC Start() function. When this
1523 // field is PXE_TRUE, ARP packets are sent as needed to get IP and MAC
1524 // addresses. This can cause unexpected delays in the DHCP(), Discover()
1525 // and MTFTP() functions. Setting this to PXE_FALSE will cause these
1526 // functions to fail if the required IP/MAC information is not in the
1527 // ARP cache. The value of this field can be changed by an application
1530 Private
->EfiBc
.Mode
->AutoArp
= TRUE
;
1533 // Unlock the instance data
1535 EfiReleaseLock (&Private
->Lock
);
1542 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
1546 Routine Description:
1547 Stop the BaseCode protocol, Simple Network protocol and UNDI.
1550 Private - Pointer to Pxe BaseCode Protocol
1554 0 - Successfully stopped
1559 // Lock the instance data
1561 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
1562 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
1563 EFI_STATUS StatCode
;
1564 PXE_BASECODE_DEVICE
*Private
;
1566 StatCode
= EFI_SUCCESS
;
1569 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1570 return EFI_INVALID_PARAMETER
;
1573 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1575 if (Private
== NULL
) {
1576 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1577 return EFI_INVALID_PARAMETER
;
1580 EfiAcquireLock (&Private
->Lock
);
1582 SnpPtr
= Private
->SimpleNetwork
;
1583 SnpModePtr
= SnpPtr
->Mode
;
1588 StatCode
= EFI_NOT_STARTED
;
1590 if (SnpModePtr
->State
== EfiSimpleNetworkInitialized
) {
1591 StatCode
= (*SnpPtr
->Shutdown
) (SnpPtr
);
1594 if (SnpModePtr
->State
== EfiSimpleNetworkStarted
) {
1595 StatCode
= (*SnpPtr
->Stop
) (SnpPtr
);
1598 if (Private
->TransmitBufferPtr
!= NULL
) {
1599 gBS
->FreePool (Private
->TransmitBufferPtr
);
1600 Private
->TransmitBufferPtr
= NULL
;
1603 if (Private
->ReceiveBufferPtr
!= NULL
) {
1604 gBS
->FreePool (Private
->ReceiveBufferPtr
);
1605 Private
->ReceiveBufferPtr
= NULL
;
1608 if (Private
->ArpBuffer
!= NULL
) {
1609 gBS
->FreePool (Private
->ArpBuffer
);
1610 Private
->ArpBuffer
= NULL
;
1613 if (Private
->TftpErrorBuffer
!= NULL
) {
1614 gBS
->FreePool (Private
->TftpErrorBuffer
);
1615 Private
->TftpErrorBuffer
= NULL
;
1618 if (Private
->TftpAckBuffer
!= NULL
) {
1619 gBS
->FreePool (Private
->TftpAckBuffer
);
1620 Private
->TftpAckBuffer
= NULL
;
1623 if (Private
->Igmpv1TimeoutEvent
!= NULL
) {
1624 gBS
->CloseEvent (Private
->Igmpv1TimeoutEvent
);
1625 Private
->Igmpv1TimeoutEvent
= NULL
;
1628 Private
->FileSize
= 0;
1629 Private
->EfiBc
.Mode
->Started
= FALSE
;
1632 // Unlock the instance data
1634 EfiReleaseLock (&Private
->Lock
);
1638 const IPV4_ADDR AllSystemsGroup
= { { 224, 0, 0, 1 } };
1642 IN PXE_BASECODE_DEVICE
*Private
,
1643 IN EFI_PXE_BASE_CODE_IP_FILTER
*Filter
1647 Routine Description:
1648 Set up the IP filter
1651 Private - Pointer to Pxe BaseCode Protocol
1652 Filter - Pointer to the filter
1656 0 - Successfully set the filter
1660 EFI_STATUS StatCode
;
1661 EFI_MAC_ADDRESS MACadds
[PXE_IP_FILTER_SIZE
];
1662 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1663 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
1664 EFI_SIMPLE_NETWORK_MODE
*SnpModePtr
;
1670 PxebcMode
= Private
->EfiBc
.Mode
;
1671 SnpPtr
= Private
->SimpleNetwork
;
1672 SnpModePtr
= SnpPtr
->Mode
;
1675 // validate input parameters
1676 // must have a filter
1677 // must not have any extra filter bits set
1679 if (Filter
== NULL
||
1680 (Filter
->Filters
&~FILTER_BITS
)
1682 // must not have a count which is too large or with no IP list
1685 (Filter
->IpCnt
&& (!Filter
->IpList
|| Filter
->IpCnt
> PXE_IP_FILTER_SIZE
))
1687 // must not have incompatible filters - promiscuous incompatible with anything else
1691 (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) &&
1692 ((Filter
->Filters
&~EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) || Filter
->IpCnt
)
1695 DEBUG ((EFI_D_INFO
, "\nIpFilter() Exit #1"));
1696 return EFI_INVALID_PARAMETER
;
1699 // promiscuous multicast incompatible with multicast in IP list
1701 if (Filter
->IpCnt
&& (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
)) {
1702 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1703 if (IS_MULTICAST (&Filter
->IpList
[Index
])) {
1704 DEBUG ((EFI_D_INFO
, "\nIpFilter() Exit #2"));
1705 return EFI_INVALID_PARAMETER
;
1710 // leave groups for all those multicast which are no longer enabled
1712 for (Index
= 0; Index
< PxebcMode
->IpFilter
.IpCnt
; ++Index
) {
1713 if (!IS_MULTICAST (&PxebcMode
->IpFilter
.IpList
[Index
])) {
1717 for (Index2
= 0; Index2
< Filter
->IpCnt
; ++Index2
) {
1718 if (!CompareMem (&PxebcMode
->IpFilter
.IpList
[Index
], &Filter
->IpList
[Index2
], IP_ADDRESS_LENGTH (PxebcMode
))) {
1726 // if we didn't find it, remove from group
1728 if (Index2
== Filter
->IpCnt
) {
1729 IgmpLeaveGroup (Private
, &PxebcMode
->IpFilter
.IpList
[Index
]);
1733 // set enable bits, convert multicast ip adds, join groups
1734 // allways leave receive broadcast enabled at hardware layer
1738 if (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS
) {
1739 Enable
= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
1741 if (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST
) {
1742 Enable
= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
1744 Enable
= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
1746 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1747 CopyMem (&(PxebcMode
->IpFilter
.IpList
[Index
]), &(Filter
->IpList
[Index
]), sizeof (EFI_IP_ADDRESS
));
1749 if (IS_MULTICAST (&Filter
->IpList
[Index
])) {
1750 EFI_IP_ADDRESS
*TmpIp
;
1752 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
1755 // if this is the first group, add the all systems group to mcast list
1760 if (PxebcMode
->UsingIpv6
) {
1766 TmpIp
= (EFI_IP_ADDRESS
*) &AllSystemsGroup
;
1769 TmpIp
= (EFI_IP_ADDRESS
*) &Filter
->IpList
[Index
];
1772 // get MAC address of IP
1774 StatCode
= (*SnpPtr
->MCastIpToMac
) (SnpPtr
, PxebcMode
->UsingIpv6
, TmpIp
, &MACadds
[Index2
++]);
1776 if (EFI_ERROR (StatCode
)) {
1779 "\nIpFilter() Exit #2 %Xh (%r)",
1786 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
1791 if (Filter
->Filters
& EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
) {
1792 Enable
|= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
1796 // if nothing changed, just return
1800 "\nsnp->ReceiveFilterSetting == %Xh Filter->IpCnt == %Xh",
1801 SnpModePtr
->ReceiveFilterSetting
,
1805 if (SnpModePtr
->ReceiveFilterSetting
== Enable
&& !Filter
->IpCnt
) {
1806 DEBUG ((EFI_D_INFO
, "\nIpFilter() Exit #4"));
1810 // disable those currently set but not set in new filter
1812 Disable
= SnpModePtr
->ReceiveFilterSetting
&~Enable
;
1814 StatCode
= SnpPtr
->ReceiveFilters (SnpPtr
, Enable
, Disable
, FALSE
, Index2
, MACadds
);
1816 PxebcMode
->IpFilter
.IpCnt
= Filter
->IpCnt
;
1819 // join groups for all multicast in list
1821 for (Index
= 0; Index
< Filter
->IpCnt
; ++Index
) {
1822 if (IS_MULTICAST (&Filter
->IpList
[Index
])) {
1823 IgmpJoinGroup (Private
, &Filter
->IpList
[Index
]);
1827 DEBUG ((EFI_D_INFO
, "\nIpFilter() Exit #5 %Xh (%r)", StatCode
, StatCode
));
1835 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1836 IN EFI_PXE_BASE_CODE_IP_FILTER
*Filter
1840 Routine Description:
1844 Private - Pointer to Pxe BaseCode Protocol
1845 Filter - Pointer to the filter
1849 0 - Successfully set the filter
1853 EFI_STATUS StatCode
;
1854 PXE_BASECODE_DEVICE
*Private
;
1857 // Lock the instance data and make sure started
1859 StatCode
= EFI_SUCCESS
;
1862 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1863 return EFI_INVALID_PARAMETER
;
1866 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1868 if (Private
== NULL
) {
1869 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1870 return EFI_INVALID_PARAMETER
;
1873 EfiAcquireLock (&Private
->Lock
);
1875 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
1876 DEBUG ((EFI_D_ERROR
, "BC was not started."));
1877 EfiReleaseLock (&Private
->Lock
);
1878 return EFI_NOT_STARTED
;
1881 if (Filter
== NULL
) {
1882 return EFI_INVALID_PARAMETER
;
1887 StatCode
= IpFilter (Private
, Filter
);
1890 // Unlock the instance data
1892 EfiReleaseLock (&Private
->Lock
);
1899 EFI_PXE_BASE_CODE_PROTOCOL
*This
,
1900 BOOLEAN
*AutoArpPtr
,
1901 BOOLEAN
*SendGuidPtr
,
1902 UINT8
*TimeToLivePtr
,
1903 UINT8
*TypeOfServicePtr
,
1904 BOOLEAN
*MakeCallbackPtr
1908 Routine Description:
1909 Set the Base Code behavior parameters
1912 This - Pointer to Pxe BaseCode Protocol
1913 AutoArpPtr - Boolean to do ARP stuff
1914 SendGuidPtr - Boolean whether or not to send GUID info
1915 TimeToLivePtr - Value for Total time to live
1916 TypeOfServicePtr - Value for Type of Service
1917 MakeCallbackPtr - Boolean to determine if we make callbacks
1921 0 - Successfully set the parameters
1925 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1927 CHAR8
*SerialNumberPtr
;
1928 EFI_STATUS StatCode
;
1929 PXE_BASECODE_DEVICE
*Private
;
1932 // Lock the instance data and make sure started
1934 StatCode
= EFI_SUCCESS
;
1937 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
1938 return EFI_INVALID_PARAMETER
;
1941 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
1943 if (Private
== NULL
) {
1944 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
1945 return EFI_INVALID_PARAMETER
;
1948 EfiAcquireLock (&Private
->Lock
);
1950 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
1951 DEBUG ((EFI_D_ERROR
, "BC was not started."));
1952 EfiReleaseLock (&Private
->Lock
);
1953 return EFI_NOT_STARTED
;
1956 DEBUG ((EFI_D_INFO
, "\nSetParameters() Entry. "));
1958 PxebcMode
= Private
->EfiBc
.Mode
;
1959 StatCode
= EFI_SUCCESS
;
1961 if (SendGuidPtr
!= NULL
) {
1963 if (PxeBcLibGetSmbiosSystemGuidAndSerialNumber (&TmpGuid
, &SerialNumberPtr
) != EFI_SUCCESS
) {
1964 return EFI_INVALID_PARAMETER
;
1969 if (MakeCallbackPtr
!= NULL
) {
1970 if (*MakeCallbackPtr
) {
1971 if (!SetMakeCallback (Private
)) {
1972 return EFI_INVALID_PARAMETER
;
1976 PxebcMode
->MakeCallbacks
= *MakeCallbackPtr
;
1979 if (AutoArpPtr
!= NULL
) {
1980 PxebcMode
->AutoArp
= *AutoArpPtr
;
1983 if (SendGuidPtr
!= NULL
) {
1984 PxebcMode
->SendGUID
= *SendGuidPtr
;
1987 if (TimeToLivePtr
!= NULL
) {
1988 PxebcMode
->TTL
= *TimeToLivePtr
;
1991 if (TypeOfServicePtr
!= NULL
) {
1992 PxebcMode
->ToS
= *TypeOfServicePtr
;
1995 // Unlock the instance data
1997 DEBUG ((EFI_D_INFO
, "\nSetparameters() Exit = %xh ", StatCode
));
1999 EfiReleaseLock (&Private
->Lock
);
2003 // //////////////////////////////////////////////////////////
2005 // BC Set Station IP Routine
2010 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
2011 IN EFI_IP_ADDRESS
*StationIpPtr
,
2012 IN EFI_IP_ADDRESS
*SubnetMaskPtr
2016 Routine Description:
2017 Set the station IP address
2020 This - Pointer to Pxe BaseCode Protocol
2021 StationIpPtr - Pointer to the requested IP address to set in base code
2022 SubnetMaskPtr - Pointer to the requested subnet mask for the base code
2026 EFI_SUCCESS - Successfully set the parameters
2027 EFI_NOT_STARTED - BC has not started
2030 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
2031 PXE_BASECODE_DEVICE
*Private
;
2034 // Lock the instance data and make sure started
2038 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
2039 return EFI_INVALID_PARAMETER
;
2042 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
2044 if (Private
== NULL
) {
2045 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
2046 return EFI_INVALID_PARAMETER
;
2049 EfiAcquireLock (&Private
->Lock
);
2051 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
2052 DEBUG ((EFI_D_ERROR
, "BC was not started."));
2053 EfiReleaseLock (&Private
->Lock
);
2054 return EFI_NOT_STARTED
;
2057 PxebcMode
= Private
->EfiBc
.Mode
;
2059 if (StationIpPtr
!= NULL
) {
2060 CopyMem (&PxebcMode
->StationIp
, StationIpPtr
, sizeof (EFI_IP_ADDRESS
));
2061 Private
->GoodStationIp
= TRUE
;
2064 if (SubnetMaskPtr
!= NULL
) {
2065 CopyMem (&PxebcMode
->SubnetMask
, SubnetMaskPtr
, sizeof (EFI_IP_ADDRESS
));
2068 // Unlock the instance data
2070 EfiReleaseLock (&Private
->Lock
);
2075 EFI_DRIVER_BINDING_PROTOCOL gPxeBcDriverBinding
= {
2076 PxeBcDriverSupported
,
2086 PxeBcDriverSupported (
2087 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2088 IN EFI_HANDLE Controller
,
2089 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
2093 Routine Description:
2094 Test to see if this driver supports Controller. Any Controller
2095 than contains a Snp protocol can be supported.
2098 This - Protocol instance pointer.
2099 Controller - Handle of device to test.
2100 RemainingDevicePath - Not used.
2103 EFI_SUCCESS - This driver supports this device.
2104 EFI_ALREADY_STARTED - This driver is already running on this device.
2105 other - This driver does not support this device.
2110 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpPtr
;
2112 Status
= gBS
->OpenProtocol (
2114 &gEfiDevicePathProtocolGuid
,
2116 This
->DriverBindingHandle
,
2118 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
2121 if (EFI_ERROR (Status
)) {
2125 Status
= gBS
->OpenProtocol (
2127 &gEfiSimpleNetworkProtocolGuid
,
2129 This
->DriverBindingHandle
,
2131 EFI_OPEN_PROTOCOL_BY_DRIVER
2133 if (EFI_ERROR (Status
)) {
2137 gBS
->CloseProtocol (
2139 &gEfiSimpleNetworkProtocolGuid
,
2140 This
->DriverBindingHandle
,
2150 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2151 IN EFI_HANDLE Controller
,
2152 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
2156 Routine Description:
2157 Start the Base code driver.
2160 This - Protocol instance pointer.
2161 Controller - Handle of device to test.
2162 RemainingDevicePath - Not used.
2165 EFI_SUCCESS - This driver supports this device.
2166 EFI_ALREADY_STARTED - This driver is already running on this device.
2167 other - This driver does not support this device.
2172 PXE_BASECODE_DEVICE
*Private
;
2173 LOADFILE_DEVICE
*pLF
;
2176 // Allocate structures needed by BaseCode and LoadFile protocols.
2178 Status
= gBS
->AllocatePool (
2179 EfiBootServicesData
,
2180 sizeof (PXE_BASECODE_DEVICE
),
2184 if (!EFI_ERROR (Status
)) {
2185 ZeroMem (Private
, sizeof (PXE_BASECODE_DEVICE
));
2187 DEBUG ((EFI_D_NET
, "\nBcNotifySnp() Could not alloc PXE_BASECODE_DEVICE structure.\n"));
2191 Status
= gBS
->AllocatePool (
2192 EfiBootServicesData
,
2193 sizeof (LOADFILE_DEVICE
),
2197 if (!EFI_ERROR (Status
)) {
2198 ZeroMem (pLF
, sizeof (LOADFILE_DEVICE
));
2200 DEBUG ((EFI_D_NET
, "\nBcNotifySnp() Could not alloc LOADFILE_DEVICE structure.\n"));
2201 gBS
->FreePool (Private
);
2205 Status
= gBS
->AllocatePool (
2206 EfiBootServicesData
,
2207 sizeof (EFI_PXE_BASE_CODE_MODE
),
2208 (VOID
**) &Private
->EfiBc
.Mode
2211 if (!EFI_ERROR (Status
)) {
2212 ZeroMem (Private
->EfiBc
.Mode
, sizeof (EFI_PXE_BASE_CODE_MODE
));
2214 DEBUG ((EFI_D_NET
, "\nBcNotifySnp() Could not alloc Mode structure.\n"));
2215 gBS
->FreePool (Private
);
2216 gBS
->FreePool (pLF
);
2220 // Lock access, just in case
2222 EfiInitializeLock (&Private
->Lock
, EFI_TPL_CALLBACK
);
2223 EfiAcquireLock (&Private
->Lock
);
2225 EfiInitializeLock (&pLF
->Lock
, EFI_TPL_CALLBACK
);
2226 EfiAcquireLock (&pLF
->Lock
);
2229 // Initialize PXE structure
2232 // First initialize the internal 'private' data that the application
2235 Private
->Signature
= PXE_BASECODE_DEVICE_SIGNATURE
;
2236 Private
->Handle
= Controller
;
2239 // Get the NII interface
2241 Status
= gBS
->OpenProtocol (
2243 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
2244 (VOID
**) &Private
->NiiPtr
,
2245 This
->DriverBindingHandle
,
2247 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2250 if (EFI_ERROR (Status
)) {
2251 Status
= gBS
->OpenProtocol (
2253 &gEfiNetworkInterfaceIdentifierProtocolGuid
,
2254 (VOID
**) &Private
->NiiPtr
,
2255 This
->DriverBindingHandle
,
2257 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2260 if (EFI_ERROR (Status
)) {
2265 // Get the Snp interface
2267 Status
= gBS
->OpenProtocol (
2269 &gEfiSimpleNetworkProtocolGuid
,
2270 (VOID
**) &Private
->SimpleNetwork
,
2271 This
->DriverBindingHandle
,
2273 EFI_OPEN_PROTOCOL_BY_DRIVER
2276 if (EFI_ERROR (Status
)) {
2281 // Next, initialize the external 'public' data that
2282 // the application does see.
2284 Private
->EfiBc
.Revision
= EFI_PXE_BASE_CODE_INTERFACE_REVISION
;
2285 Private
->EfiBc
.Start
= BcStart
;
2286 Private
->EfiBc
.Stop
= BcStop
;
2287 Private
->EfiBc
.Dhcp
= BcDhcp
;
2288 Private
->EfiBc
.Discover
= BcDiscover
;
2289 Private
->EfiBc
.Mtftp
= BcMtftp
;
2290 Private
->EfiBc
.UdpWrite
= BcUdpWrite
;
2291 Private
->EfiBc
.UdpRead
= BcUdpRead
;
2292 Private
->EfiBc
.Arp
= BcArp
;
2293 Private
->EfiBc
.SetIpFilter
= BcIpFilter
;
2294 Private
->EfiBc
.SetParameters
= BcSetParameters
;
2295 Private
->EfiBc
.SetStationIp
= BcSetStationIP
;
2296 Private
->EfiBc
.SetPackets
= BcSetPackets
;
2299 // Initialize BaseCode Mode structure
2301 Private
->EfiBc
.Mode
->Started
= FALSE
;
2302 Private
->EfiBc
.Mode
->TTL
= DEFAULT_TTL
;
2303 Private
->EfiBc
.Mode
->ToS
= DEFAULT_ToS
;
2304 Private
->EfiBc
.Mode
->UsingIpv6
= FALSE
;
2305 Private
->EfiBc
.Mode
->AutoArp
= TRUE
;
2308 // Set to PXE_TRUE by the BC constructor if this BC
2309 // implementation supports IPv6.
2311 Private
->EfiBc
.Mode
->Ipv6Supported
= SUPPORT_IPV6
;
2314 Private
->EfiBc
.Mode
->Ipv6Available
= Private
->NiiPtr
->Ipv6Supported
;
2316 Private
->EfiBc
.Mode
->Ipv6Available
= FALSE
;
2319 // Set to TRUE by the BC constructor if this BC
2320 // implementation supports BIS.
2322 Private
->EfiBc
.Mode
->BisSupported
= TRUE
;
2323 Private
->EfiBc
.Mode
->BisDetected
= PxebcBisDetect (Private
);
2326 // Initialize LoadFile structure.
2328 pLF
->Signature
= LOADFILE_DEVICE_SIGNATURE
;
2329 pLF
->LoadFile
.LoadFile
= LoadFile
;
2330 pLF
->Private
= Private
;
2333 // Install protocol interfaces.
2335 Status
= gBS
->InstallMultipleProtocolInterfaces (
2337 &gEfiPxeBaseCodeProtocolGuid
,
2339 &gEfiLoadFileProtocolGuid
,
2344 if (EFI_ERROR (Status
)) {
2345 gBS
->CloseProtocol (
2347 &gEfiSimpleNetworkProtocolGuid
,
2348 This
->DriverBindingHandle
,
2357 EfiReleaseLock (&pLF
->Lock
);
2358 EfiReleaseLock (&Private
->Lock
);
2362 gBS
->FreePool (Private
->EfiBc
.Mode
);
2363 gBS
->FreePool (Private
);
2364 gBS
->FreePool (pLF
);
2371 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
2372 IN EFI_HANDLE Controller
,
2373 IN UINTN NumberOfChildren
,
2374 IN EFI_HANDLE
*ChildHandleBuffer
2378 Routine Description:
2379 Stop the Base code driver.
2382 This - Protocol instance pointer.
2383 Controller - Handle of device to test.
2384 NumberOfChildren - Not used
2385 ChildHandleBuffer - Not used
2388 EFI_SUCCESS - This driver supports this device.
2389 EFI_ALREADY_STARTED - This driver is already running on this device.
2390 other - This driver does not support this device.
2395 EFI_LOAD_FILE_PROTOCOL
*LfProtocol
;
2396 LOADFILE_DEVICE
*LoadDevice
;
2399 // Get our context back.
2401 Status
= gBS
->OpenProtocol (
2403 &gEfiLoadFileProtocolGuid
,
2404 (VOID
**) &LfProtocol
,
2405 This
->DriverBindingHandle
,
2407 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2410 if (EFI_ERROR (Status
)) {
2411 return EFI_UNSUPPORTED
;
2414 LoadDevice
= EFI_LOAD_FILE_DEV_FROM_THIS (LfProtocol
);
2416 Status
= gBS
->UninstallMultipleProtocolInterfaces (
2418 &gEfiLoadFileProtocolGuid
,
2419 &LoadDevice
->LoadFile
,
2420 &gEfiPxeBaseCodeProtocolGuid
,
2421 &LoadDevice
->Private
->EfiBc
,
2425 if (!EFI_ERROR (Status
)) {
2427 Status
= gBS
->CloseProtocol (
2429 &gEfiSimpleNetworkProtocolGuid
,
2430 This
->DriverBindingHandle
,
2434 gBS
->FreePool (LoadDevice
->Private
->EfiBc
.Mode
);
2435 gBS
->FreePool (LoadDevice
->Private
);
2436 gBS
->FreePool (LoadDevice
);
2444 InitializeBCDriver (
2445 IN EFI_HANDLE ImageHandle
,
2446 IN EFI_SYSTEM_TABLE
*SystemTable
2450 Routine Description:
2451 Initialize the base code drivers and install the driver binding
2454 Standard EFI Image Entry
2457 EFI_SUCCESS - This driver was successfully bound
2462 OptionsStrucInit ();