]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/PxeBcDxe/Bc.c
1. Add EFI LOADED IMAGE DEVICE PATH Protocol in LoadImage() service, per UEFI 2.1b.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / PxeBcDxe / Bc.c
1 /** @file
2
3 Copyright (c) 2004 - 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
8
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.
11
12 Module Name:
13
14 bc.c
15
16 Abstract:
17
18
19 **/
20
21 #include "Bc.h"
22
23 //
24 //
25 //
26 EFI_STATUS
27 EFIAPI
28 PxeBcDriverSupported (
29 IN EFI_DRIVER_BINDING_PROTOCOL *This,
30 IN EFI_HANDLE Controller,
31 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
32 );
33
34 EFI_STATUS
35 EFIAPI
36 PxeBcDriverStart (
37 IN EFI_DRIVER_BINDING_PROTOCOL *This,
38 IN EFI_HANDLE Controller,
39 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
40 );
41
42 EFI_STATUS
43 EFIAPI
44 PxeBcDriverStop (
45 IN EFI_DRIVER_BINDING_PROTOCOL *This,
46 IN EFI_HANDLE Controller,
47 IN UINTN NumberOfChildren,
48 IN EFI_HANDLE *ChildHandleBuffer
49 );
50
51 extern
52 VOID
53 InitArpHeader (
54 VOID
55 );
56 extern
57 VOID
58 OptionsStrucInit (
59 VOID
60 );
61
62 //
63 // helper routines
64 //
65
66 /**
67 Convert number to ASCII value
68
69 @param Number Numeric value to convert to decimal ASCII value.
70 @param Buffer Buffer to place ASCII version of the Number
71 @param Length Length of Buffer.
72
73 @retval none none
74
75 **/
76 VOID
77 CvtNum (
78 IN UINTN Number,
79 IN UINT8 *Buffer,
80 IN INTN Length
81 )
82 {
83 UINTN Remainder;
84
85 while (Length--) {
86 Remainder = Number % 10;
87 Number /= 10;
88 Buffer[Length] = (UINT8) ('0' + Remainder);
89 }
90 }
91
92
93 /**
94 Convert number to decimal ASCII value at Buffer location
95
96 @param Number Numeric value to convert to decimal ASCII value.
97 @param Buffer Buffer to place ASCII version of the Number
98
99 @retval none none
100
101 **/
102 VOID
103 UtoA10 (
104 IN UINTN Number,
105 IN UINT8 *Buffer
106 )
107 {
108 INTN Index;
109 UINT8 BuffArray[31];
110
111 BuffArray[30] = 0;
112 CvtNum (Number, BuffArray, 30);
113
114 for (Index = 0; Index < 30; ++Index) {
115 if (BuffArray[Index] != '0') {
116 break;
117 }
118 }
119
120 CopyMem (Buffer, BuffArray + Index, 31 - Index);
121 }
122
123
124 /**
125 Convert ASCII numeric string to a UINTN value
126
127 @param Number Numeric value to convert to decimal ASCII value.
128 @param Buffer Buffer to place ASCII version of the Number
129
130 @retval Value UINTN value of the ASCII string.
131
132 **/
133 UINTN
134 AtoU (
135 IN UINT8 *Buffer
136 )
137 {
138 UINTN Value;
139 INT8 Character;
140
141 Value = 0;
142 Character = *Buffer++;
143 do {
144 Value = Value * 10 + Character - '0';
145 Character = *Buffer++;
146 } while (Character);
147
148 return Value;
149 }
150
151
152 /**
153 Convert ASCII numeric string to a UINTN value
154
155 @param Number Numeric value to convert to decimal ASCII value.
156 @param Buffer Buffer to place ASCII version of the Number
157
158 @retval Value UINTN value of the ASCII string.
159
160 **/
161 UINT64
162 AtoU64 (
163 IN UINT8 *Buffer
164 )
165 {
166 UINT64 Value;
167 UINT8 Character;
168
169 Value = 0;
170 while ((Character = *Buffer++) != '\0') {
171 Value = MultU64x32 (Value, 10) + (Character - '0');
172 }
173
174 return Value;
175 }
176 //
177 // random number generator
178 //
179 #define RANDOM_MULTIPLIER 2053
180 #define RANDOM_ADD_IN_VALUE 19
181
182 VOID
183 SeedRandom (
184 IN PXE_BASECODE_DEVICE *Private,
185 IN UINT16 InitialSeed
186 )
187 /*++
188
189 Routine Description:
190 Initialize the Seed for the random number generator
191
192 Arguments:
193
194 Returns:
195 none -
196
197 --*/
198 {
199 if (Private != NULL) {
200 Private->RandomSeed = InitialSeed;
201 }
202 }
203
204
205 /**
206 Generate and return a pseudo-random number
207
208
209 @retval Number UINT16 random number
210
211 **/
212 UINT16
213 Random (
214 IN PXE_BASECODE_DEVICE *Private
215 )
216 {
217 UINTN Number;
218
219 if (Private != NULL) {
220 Number = -(INTN) Private->RandomSeed * RANDOM_MULTIPLIER + RANDOM_ADD_IN_VALUE;
221
222 return Private->RandomSeed = (UINT16) Number;
223 } else {
224 return 0;
225 }
226 }
227 //
228 // calculate the internet checksum (RFC 1071)
229 // return 16 bit ones complement of ones complement sum of 16 bit words
230 //
231
232 /**
233 Calculate the internet checksum (see RFC 1071)
234
235 @param Packet Buffer which contains the data to be checksummed
236 @param Length Length to be checksummed
237
238 @retval Checksum Returns the 16 bit ones complement of ones
239 complement sum of 16 bit words
240
241 **/
242 UINT16
243 IpChecksum (
244 IN UINT16 *Packet,
245 IN UINTN Length
246 )
247 {
248 UINT32 Sum;
249 UINT8 Odd;
250
251 Sum = 0;
252 Odd = (UINT8) (Length & 1);
253 Length >>= 1;
254 while (Length--) {
255 Sum += *Packet++;
256 }
257
258 if (Odd) {
259 Sum += *(UINT8 *) Packet;
260 }
261
262 Sum = (Sum & 0xffff) + (Sum >> 16);
263 //
264 // in case above carried
265 //
266 Sum += Sum >> 16;
267
268 return (UINT16) (~ (UINT16) Sum);
269 }
270
271
272 /**
273 Calculate the internet checksum (see RFC 1071)
274 on a non contiguous header and data
275
276 @param Header Buffer which contains the data to be checksummed
277 @param HeaderLen Length to be checksummed
278 @param Message Buffer which contains the data to be checksummed
279 @param MessageLen Length to be checksummed
280
281 @retval Checksum Returns the 16 bit ones complement of ones
282 complement sum of 16 bit words
283
284 **/
285 UINT16
286 IpChecksum2 (
287 IN UINT16 *Header,
288 IN UINTN HeaderLen,
289 IN UINT16 *Message,
290 IN UINTN MessageLen
291 )
292 {
293 UINT32 Sum;
294 UINT16 HeaderChecksum;
295 UINT16 MessageChecksum;
296
297 HeaderChecksum = (UINT16)~IpChecksum (Header, HeaderLen);
298 MessageChecksum = (UINT16)~IpChecksum (Message, MessageLen);
299 Sum = HeaderChecksum + MessageChecksum;
300
301 //
302 // in case above carried
303 //
304 Sum += Sum >> 16;
305
306 return (UINT16) (~ (UINT16) Sum);
307 }
308
309
310 /**
311 Adjust the internet checksum (see RFC 1071) on a single word update.
312
313 @param OldChkSum Checksum previously calculated
314 @param OldWord Value
315 @param NewWord New Value
316
317 @retval Checksum Returns the 16 bit ones complement of ones
318 complement sum of 16 bit words
319
320 **/
321 UINT16
322 UpdateChecksum (
323 IN UINT16 OldChksum,
324 IN UINT16 OldWord,
325 IN UINT16 NewWord
326 )
327 {
328 UINT32 sum;
329
330 sum = ~OldChksum + NewWord - OldWord;
331 //
332 // in case above carried
333 //
334 sum += sum >> 16;
335 return (UINT16) (~ (UINT16) sum);
336 }
337
338
339 /**
340 See if a callback is in play
341
342 @param Private Pointer to Pxe BaseCode Protocol
343
344 @retval 0 Callbacks are active on the handle
345 @retval 1 Callbacks are not active on the handle
346
347 **/
348 STATIC
349 BOOLEAN
350 SetMakeCallback (
351 IN PXE_BASECODE_DEVICE *Private
352 )
353 {
354 Private->EfiBc.Mode->MakeCallbacks = (BOOLEAN) (gBS->HandleProtocol (
355 Private->Handle,
356 &gEfiPxeBaseCodeCallbackProtocolGuid,
357 (VOID *) &Private->CallbackProtocolPtr
358 ) == EFI_SUCCESS);
359
360 DEBUG (
361 (DEBUG_INFO,
362 "\nMode->MakeCallbacks == %d ",
363 Private->EfiBc.Mode->MakeCallbacks)
364 );
365
366 DEBUG (
367 (DEBUG_INFO,
368 "\nPrivate->CallbackProtocolPtr == %xh ",
369 Private->CallbackProtocolPtr)
370 );
371
372 if (Private->CallbackProtocolPtr != NULL) {
373 DEBUG (
374 (DEBUG_INFO,
375 "\nCallbackProtocolPtr->Revision = %xh ",
376 Private->CallbackProtocolPtr->Revision)
377 );
378
379 DEBUG (
380 (DEBUG_INFO,
381 "\nCallbackProtocolPtr->Callback = %xh ",
382 Private->CallbackProtocolPtr->Callback)
383 );
384 }
385
386 return Private->EfiBc.Mode->MakeCallbacks;
387 }
388
389 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
390
391 /**
392 Routine which does an SNP->Receive over a timeout period and doing callbacks
393
394 @param Private Pointer to Pxe BaseCode Protocol
395 @param Function What PXE function to callback
396 @param TimeoutEvent Timer event that will trigger when we have waited
397 too long for an incoming packet
398 @param HeaderSizePtr Pointer to the size of the Header size
399 @param BufferSizePtr Pointer to the size of the Buffer size
400 @param ProtocolPtr The protocol to sniff for (namely, UDP/TCP/etc)
401
402 @retval 0 Something was returned
403 @retval !0 Like there was nothing to receive
404 (EFI_TIMEOUT/NOT_READY)
405
406 **/
407 EFI_STATUS
408 WaitForReceive (
409 IN PXE_BASECODE_DEVICE *Private,
410 IN EFI_PXE_BASE_CODE_FUNCTION Function,
411 IN EFI_EVENT TimeoutEvent,
412 IN OUT UINTN *HeaderSizePtr,
413 IN OUT UINTN *BufferSizePtr,
414 IN OUT UINT16 *ProtocolPtr
415 )
416 {
417 EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;
418 EFI_PXE_CALLBACK CallbackPtr;
419 EFI_STATUS StatCode;
420 EFI_EVENT CallbackEvent;
421
422 //
423 // Initialize pointer to SNP interface
424 //
425 SnpPtr = Private->SimpleNetwork;
426
427 //
428 // Initialize pointer to PxeBc callback routine - if any
429 //
430 CallbackPtr = (Private->EfiBc.Mode->MakeCallbacks) ? Private->CallbackProtocolPtr->Callback : NULL;
431
432 //
433 // Create callback event and set timer
434 //
435 StatCode = gBS->CreateEvent (
436 EVT_TIMER,
437 TPL_CALLBACK,
438 NULL,
439 NULL,
440 &CallbackEvent
441 );
442
443 if (EFI_ERROR (StatCode)) {
444 return EFI_DEVICE_ERROR;
445 }
446
447 //
448 // every 100 milliseconds
449 //
450 StatCode = gBS->SetTimer (
451 CallbackEvent,
452 TimerPeriodic,
453 1000000
454 );
455
456 if (EFI_ERROR (StatCode)) {
457 gBS->CloseEvent (CallbackEvent);
458 return EFI_DEVICE_ERROR;
459 }
460 //
461 // Loop until a packet is received or a receive error is detected or
462 // a callback abort is detected or a timeout event occurs.
463 //
464 for (;;)
465 {
466 //
467 // Poll for received packet.
468 //
469 *BufferSizePtr = BUFFER_ALLOCATE_SIZE;
470
471 StatCode = SnpPtr->Receive (
472 SnpPtr,
473 HeaderSizePtr,
474 BufferSizePtr,
475 Private->ReceiveBufferPtr,
476 0,
477 0,
478 ProtocolPtr
479 );
480
481 if (!EFI_ERROR (StatCode)) {
482 //
483 // Packet was received. Make received callback then return.
484 //
485 if (CallbackPtr != NULL) {
486 StatCode = CallbackPtr (
487 Private->CallbackProtocolPtr,
488 Function,
489 TRUE,
490 (UINT32) *BufferSizePtr,
491 (EFI_PXE_BASE_CODE_PACKET *) Private->ReceiveBufferPtr
492 );
493
494 if (StatCode != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) {
495 StatCode = EFI_ABORTED;
496 } else {
497 StatCode = EFI_SUCCESS;
498 }
499 }
500
501 break;
502 }
503
504 if (StatCode != EFI_NOT_READY) {
505 break;
506 }
507 //
508 // Check for callback event.
509 //
510 if (!EFI_ERROR (gBS->CheckEvent (CallbackEvent))) {
511 //
512 // Make periodic callback if callback pointer is initialized.
513 //
514 if (CallbackPtr != NULL) {
515 StatCode = CallbackPtr (
516 Private->CallbackProtocolPtr,
517 Function,
518 FALSE,
519 0,
520 NULL
521 );
522
523 //
524 // Abort if directed to by callback routine.
525 //
526 if (StatCode != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) {
527 StatCode = EFI_ABORTED;
528 break;
529 }
530 }
531 }
532 //
533 // Check for timeout event.
534 //
535 if (TimeoutEvent == 0) {
536 StatCode = EFI_TIMEOUT;
537 break;
538 }
539
540 if (!EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {
541 StatCode = EFI_TIMEOUT;
542 break;
543 }
544 //
545 // Check IGMP timer events.
546 //
547 IgmpCheckTimers (Private);
548 }
549
550 gBS->CloseEvent (CallbackEvent);
551
552 return StatCode;
553 }
554
555
556 /**
557 Routine which does an SNP->Transmit of a buffer
558
559 @param Private Pointer to Pxe BaseCode Protocol
560 @param HeaderPtr Pointer to the buffer
561 @param PacketPtr Pointer to the packet to send
562 @param PacketLen The length of the entire packet to send
563 @param HardwareAddr Pointer to the MAC address of the destination
564 @param MediaProtocol What type of frame to create (RFC 1700) - IE.
565 Ethernet
566 @param Function What PXE function to callback
567
568 @retval 0 Something was sent
569 @retval !0 An error was encountered during sending of a packet
570
571 **/
572 EFI_STATUS
573 SendPacket (
574 PXE_BASECODE_DEVICE *Private,
575 VOID *HeaderPtr,
576 VOID *PacketPtr,
577 INTN PacketLen,
578 VOID *HardwareAddr,
579 UINT16 MediaProtocol,
580 IN EFI_PXE_BASE_CODE_FUNCTION Function
581 )
582 {
583 EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;
584 EFI_SIMPLE_NETWORK_MODE *SnpModePtr;
585 EFI_PXE_CALLBACK CallbackPtr;
586 EFI_STATUS StatCode;
587 EFI_EVENT TimeoutEvent;
588 UINT32 IntStatus;
589 VOID *TxBuf;
590
591 //
592 //
593 //
594 CallbackPtr = Private->EfiBc.Mode->MakeCallbacks ? Private->CallbackProtocolPtr->Callback : 0;
595
596 SnpPtr = Private->SimpleNetwork;
597 SnpModePtr = SnpPtr->Mode;
598
599 //
600 // clear prior interrupt status
601 //
602 StatCode = SnpPtr->GetStatus (SnpPtr, &IntStatus, 0);
603
604 if (EFI_ERROR (StatCode)) {
605 DEBUG (
606 (DEBUG_WARN,
607 "\nSendPacket() Exit #1 %xh (%r)",
608 StatCode,
609 StatCode)
610 );
611 return StatCode;
612 }
613
614 Private->DidTransmit = FALSE;
615
616 if (CallbackPtr != NULL) {
617 if (CallbackPtr (
618 Private->CallbackProtocolPtr,
619 Function,
620 FALSE,
621 (UINT32) PacketLen,
622 PacketPtr
623 ) != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) {
624 DEBUG (
625 (DEBUG_WARN,
626 "\nSendPacket() Exit #2 %xh (%r)",
627 EFI_ABORTED,
628 EFI_ABORTED)
629 );
630 return EFI_ABORTED;
631 }
632 }
633 //
634 // put packet in transmit queue
635 // headersize should be zero if not filled in
636 //
637 StatCode = gBS->CreateEvent (
638 EVT_TIMER,
639 TPL_CALLBACK,
640 NULL,
641 NULL,
642 &TimeoutEvent
643 );
644
645 if (EFI_ERROR (StatCode)) {
646 DEBUG (
647 (DEBUG_ERROR,
648 "Could not create transmit timeout event. %r\n",
649 StatCode)
650 );
651 return EFI_DEVICE_ERROR;
652 }
653
654 //
655 // 5 milliseconds
656 //
657 StatCode = gBS->SetTimer (
658 TimeoutEvent,
659 TimerRelative,
660 50000
661 );
662
663 if (EFI_ERROR (StatCode)) {
664 DEBUG (
665 (DEBUG_ERROR,
666 "Could not set transmit timeout event timer. %r\n",
667 StatCode)
668 );
669 gBS->CloseEvent (TimeoutEvent);
670 return EFI_DEVICE_ERROR;
671 }
672
673 for (;;) {
674 StatCode = SnpPtr->Transmit (
675 SnpPtr,
676 (UINTN) SnpPtr->Mode->MediaHeaderSize,
677 (UINTN) (PacketLen + SnpPtr->Mode->MediaHeaderSize),
678 HeaderPtr,
679 &SnpModePtr->CurrentAddress,
680 (EFI_MAC_ADDRESS *) HardwareAddr,
681 &MediaProtocol
682 );
683
684 if (StatCode != EFI_NOT_READY) {
685 break;
686 }
687
688 if (!EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {
689 StatCode = EFI_TIMEOUT;
690 break;
691 }
692 }
693
694 gBS->CloseEvent (TimeoutEvent);
695
696 if (EFI_ERROR (StatCode)) {
697 DEBUG (
698 (DEBUG_WARN,
699 "\nSendPacket() Exit #3 %xh (%r)",
700 StatCode,
701 StatCode)
702 );
703 return StatCode;
704 }
705 //
706 // remove transmit buffer from snp's unused queue
707 // done this way in case someday things are buffered and we don't get it back
708 // immediately
709 //
710 StatCode = gBS->CreateEvent (
711 EVT_TIMER,
712 TPL_CALLBACK,
713 NULL,
714 NULL,
715 &TimeoutEvent
716 );
717
718 if (EFI_ERROR (StatCode)) {
719 DEBUG (
720 (DEBUG_ERROR,
721 "Could not create transmit status timeout event. %r\n",
722 StatCode)
723 );
724 return EFI_DEVICE_ERROR;
725 }
726
727 //
728 // 5 milliseconds
729 //
730 StatCode = gBS->SetTimer (
731 TimeoutEvent,
732 TimerRelative,
733 50000
734 );
735
736 if (EFI_ERROR (StatCode)) {
737 DEBUG (
738 (DEBUG_ERROR,
739 "Could not set transmit status timeout event timer. %r\n",
740 StatCode)
741 );
742 gBS->CloseEvent (TimeoutEvent);
743 return EFI_DEVICE_ERROR;
744 }
745
746 for (;;) {
747 StatCode = SnpPtr->GetStatus (SnpPtr, &IntStatus, &TxBuf);
748
749 if (EFI_ERROR (StatCode)) {
750 DEBUG (
751 (DEBUG_WARN,
752 "\nSendPacket() Exit #4 %xh (%r)",
753 StatCode,
754 StatCode)
755 );
756 break;
757 }
758
759 if (IntStatus & EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT) {
760 Private->DidTransmit = TRUE;
761 }
762
763 if (TxBuf != NULL) {
764 break;
765 }
766
767 if (!EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {
768 StatCode = EFI_TIMEOUT;
769 break;
770 }
771 }
772
773 gBS->CloseEvent (TimeoutEvent);
774
775 return StatCode;
776 }
777 //
778 //
779 //
780
781 /**
782
783
784 **/
785 EFI_BIS_PROTOCOL *
786 PxebcBisStart (
787 IN PXE_BASECODE_DEVICE *Private,
788 OUT BIS_APPLICATION_HANDLE *BisAppHandle,
789 OUT OPTIONAL EFI_BIS_DATA **BisDataSigInfo
790 )
791 {
792 EFI_STATUS EfiStatus;
793 EFI_HANDLE BisHandleBuffer;
794 UINTN BisHandleCount;
795 EFI_BIS_PROTOCOL *BisPtr;
796 EFI_BIS_VERSION BisInterfaceVersion;
797 BOOLEAN BisCheckFlag;
798
799 BisHandleCount = sizeof (EFI_HANDLE);
800 BisCheckFlag = FALSE;
801
802 //
803 // Locate BIS protocol handle (if present).
804 // If BIS protocol handle is not found, return NULL.
805 //
806 DEBUG ((DEBUG_INFO, "\ngBS->LocateHandle() "));
807
808 EfiStatus = gBS->LocateHandle (
809 ByProtocol,
810 &gEfiBisProtocolGuid,
811 NULL,
812 &BisHandleCount,
813 &BisHandleBuffer
814 );
815
816 if (EFI_ERROR (EfiStatus)) {
817 //
818 // Any error means that there is no BIS.
819 // Note - It could mean that there are more than
820 // one BIS protocols installed, but that scenario
821 // is not yet supported.
822 //
823 DEBUG (
824 (DEBUG_WARN,
825 "\nPxebcBisStart()""\n gBS->LocateHandle() %r (%xh)\n",
826 EfiStatus,
827 EfiStatus)
828 );
829
830 return NULL;
831 }
832
833 if (BisHandleCount != sizeof BisHandleBuffer) {
834 //
835 // This really should never happen, but I am paranoid.
836 //
837 DEBUG (
838 (DEBUG_NET,
839 "\nPxebcBisStart() BisHandleCount != %d\n",
840 sizeof BisHandleBuffer)
841 );
842
843 return NULL;
844 }
845
846 DEBUG ((DEBUG_INFO, "BIS handle found."));
847
848 //
849 // Locate BIS protocol interface.
850 // If the BIS protocol interface cannot be found, return NULL.
851 //
852 DEBUG ((DEBUG_INFO, "\ngBS->HandleProtocol() "));
853
854 EfiStatus = gBS->HandleProtocol (
855 BisHandleBuffer,
856 &gEfiBisProtocolGuid,
857 (VOID **) &BisPtr
858 );
859
860 if (EFI_ERROR (EfiStatus)) {
861 DEBUG (
862 (DEBUG_WARN,
863 "\nPxebcBisStart()""\n gBS->HandleProtocol() %r (%xh)\n",
864 EfiStatus,
865 EfiStatus)
866 );
867
868 return NULL;
869 }
870
871 if (BisPtr == NULL) {
872 //
873 // This really should never happen.
874 //
875 DEBUG (
876 (DEBUG_NET,
877 "\nPxebcBisStart()""\n gBS->HandleProtocoL() ""BIS protocol interface pointer is NULL!\n")
878 );
879
880 return NULL;
881 }
882
883 DEBUG ((DEBUG_INFO, "BIS protocol interface found."));
884
885 //
886 // Check that all of the BIS API function pointers are not NULL.
887 //
888 if (BisPtr->Initialize == NULL ||
889 BisPtr->Shutdown == NULL ||
890 BisPtr->Free == NULL ||
891 BisPtr->GetBootObjectAuthorizationCertificate == NULL ||
892 BisPtr->GetBootObjectAuthorizationCheckFlag == NULL ||
893 BisPtr->GetBootObjectAuthorizationUpdateToken == NULL ||
894 BisPtr->GetSignatureInfo == NULL ||
895 BisPtr->UpdateBootObjectAuthorization == NULL ||
896 BisPtr->VerifyBootObject == NULL ||
897 BisPtr->VerifyObjectWithCredential == NULL
898 ) {
899 DEBUG (
900 (
901 DEBUG_NET,
902 "\nPxebcBisStart()""\n BIS protocol interface is invalid."
903 "\n At least one BIS protocol function pointer is NULL.\n"
904 )
905 );
906
907 return NULL;
908 }
909 //
910 // Initialize BIS.
911 // If BIS does not initialize, return NULL.
912 //
913 DEBUG ((DEBUG_INFO, "\nBisPtr->Initialize() "));
914
915 BisInterfaceVersion.Major = BIS_VERSION_1;
916
917 EfiStatus = BisPtr->Initialize (
918 BisPtr,
919 BisAppHandle,
920 &BisInterfaceVersion,
921 NULL
922 );
923
924 if (EFI_ERROR (EfiStatus)) {
925 DEBUG (
926 (DEBUG_WARN,
927 "\nPxebcBisStart()""\n BisPtr->Initialize() %r (%xh)\n",
928 EfiStatus,
929 EfiStatus)
930 );
931
932 return NULL;
933 }
934
935 DEBUG (
936 (DEBUG_INFO,
937 " BIS version: %d.%d",
938 BisInterfaceVersion.Major,
939 BisInterfaceVersion.Minor)
940 );
941
942 //
943 // If the requested BIS API version is not supported,
944 // shutdown BIS and return NULL.
945 //
946 if (BisInterfaceVersion.Major != BIS_VERSION_1) {
947 DEBUG (
948 (DEBUG_WARN,
949 "\nPxebcBisStart()""\n BIS version %d.%d not supported by PXE BaseCode.\n",
950 BisInterfaceVersion.Major,
951 BisInterfaceVersion.Minor)
952 );
953
954 BisPtr->Shutdown (*BisAppHandle);
955 return NULL;
956 }
957 //
958 // Get BIS check flag.
959 // If the BIS check flag cannot be read, shutdown BIS and return NULL.
960 //
961 DEBUG ((DEBUG_INFO, "\nBisPtr->GetBootObjectAuthorizationCheckFlag() "));
962
963 EfiStatus = BisPtr->GetBootObjectAuthorizationCheckFlag (*BisAppHandle, &BisCheckFlag);
964
965 if (EFI_ERROR (EfiStatus)) {
966 DEBUG (
967 (DEBUG_WARN,
968 "\nPxebcBisStart()""\n BisPtr->GetBootObjectAuthorizationCheckFlag() %r (%xh)\n",
969 EfiStatus,
970 EfiStatus)
971 );
972
973 BisPtr->Shutdown (*BisAppHandle);
974 return NULL;
975 }
976 //
977 // If the BIS check flag is FALSE, shutdown BIS and return NULL.
978 //
979 if (!BisCheckFlag) {
980 DEBUG ((DEBUG_INFO, "\nBIS check flag is FALSE.\n"));
981 BisPtr->Shutdown (*BisAppHandle);
982 return NULL;
983 } else {
984 DEBUG ((DEBUG_INFO, "\nBIS check flag is TRUE."));
985 }
986 //
987 // Early out if caller does not want signature information.
988 //
989 if (BisDataSigInfo == NULL) {
990 return BisPtr;
991 }
992 //
993 // Get BIS signature information.
994 // If the signature information cannot be read or is invalid,
995 // shutdown BIS and return NULL.
996 //
997 DEBUG ((DEBUG_INFO, "\nBisPtr->GetSignatureInfo() "));
998
999 EfiStatus = BisPtr->GetSignatureInfo (*BisAppHandle, BisDataSigInfo);
1000
1001 if (EFI_ERROR (EfiStatus)) {
1002 DEBUG (
1003 (DEBUG_WARN,
1004 "\nPxebcBisStart()""\n BisPtr_GetSignatureInfo() %r (%xh)\n",
1005 EfiStatus,
1006 EfiStatus)
1007 );
1008
1009 BisPtr->Shutdown (*BisAppHandle);
1010 return NULL;
1011 }
1012
1013 if (*BisDataSigInfo == NULL) {
1014 //
1015 // This should never happen.
1016 //
1017 DEBUG (
1018 (DEBUG_NET,
1019 "\nPxebcBisStart()""\n BisPtr->GetSignatureInfo() Data pointer is NULL!\n")
1020 );
1021
1022 BisPtr->Shutdown (*BisAppHandle);
1023 return NULL;
1024 }
1025
1026 if ((*BisDataSigInfo)->Length < sizeof (EFI_BIS_SIGNATURE_INFO) ||
1027 (*BisDataSigInfo)->Length % sizeof (EFI_BIS_SIGNATURE_INFO) ||
1028 (*BisDataSigInfo)->Length > sizeof (EFI_BIS_SIGNATURE_INFO) * 63
1029 ) {
1030 //
1031 // This should never happen.
1032 //
1033 DEBUG (
1034 (DEBUG_NET,
1035 "\nPxebcBisStart()""\n BisPtr->GetSignatureInfo() Invalid BIS siginfo length.\n")
1036 );
1037
1038 BisPtr->Free (*BisAppHandle, *BisDataSigInfo);
1039 BisPtr->Shutdown (*BisAppHandle);
1040 return NULL;
1041 }
1042
1043 return BisPtr;
1044 }
1045
1046
1047 /**
1048
1049
1050 **/
1051 VOID
1052 PxebcBisStop (
1053 EFI_BIS_PROTOCOL *BisPtr,
1054 BIS_APPLICATION_HANDLE BisAppHandle,
1055 EFI_BIS_DATA *BisDataSigInfo
1056 )
1057 {
1058 if (BisPtr == NULL) {
1059 return ;
1060 }
1061 //
1062 // Free BIS allocated resources and shutdown BIS.
1063 // Return TRUE - BIS support is officially detected.
1064 //
1065 if (BisDataSigInfo != NULL) {
1066 BisPtr->Free (BisAppHandle, BisDataSigInfo);
1067 }
1068
1069 BisPtr->Shutdown (BisAppHandle);
1070 }
1071
1072
1073 /**
1074
1075 @return TRUE := verified
1076 @return FALSE := not verified
1077
1078 **/
1079 BOOLEAN
1080 PxebcBisVerify (
1081 PXE_BASECODE_DEVICE *Private,
1082 VOID *FileBuffer,
1083 UINTN FileLength,
1084 VOID *CredentialBuffer,
1085 UINTN CredentialLength
1086 )
1087 {
1088 EFI_BIS_PROTOCOL *BisPtr;
1089 BIS_APPLICATION_HANDLE BisAppHandle;
1090 EFI_BIS_DATA FileData;
1091 EFI_BIS_DATA CredentialData;
1092 EFI_STATUS EfiStatus;
1093 BOOLEAN IsVerified;
1094
1095 if (Private == NULL || FileBuffer == NULL || FileLength == 0 || CredentialBuffer == NULL || CredentialLength == 0) {
1096 return FALSE;
1097 }
1098
1099 BisPtr = PxebcBisStart (Private, &BisAppHandle, NULL);
1100
1101 if (BisPtr == NULL) {
1102 return FALSE;
1103 }
1104
1105 FileData.Length = (UINT32) FileLength;
1106 FileData.Data = FileBuffer;
1107 CredentialData.Length = (UINT32) CredentialLength;
1108 CredentialData.Data = CredentialBuffer;
1109
1110 EfiStatus = BisPtr->VerifyBootObject (
1111 BisAppHandle,
1112 &CredentialData,
1113 &FileData,
1114 &IsVerified
1115 );
1116
1117 PxebcBisStop (BisPtr, BisAppHandle, NULL);
1118
1119 return (BOOLEAN) ((EFI_ERROR (EfiStatus)) ? FALSE : (IsVerified ? TRUE : FALSE));
1120 }
1121
1122
1123 /**
1124
1125 @return TRUE := BIS present
1126 @return FALSE := BIS not present
1127
1128 **/
1129 BOOLEAN
1130 PxebcBisDetect (
1131 PXE_BASECODE_DEVICE *Private
1132 )
1133 {
1134 EFI_BIS_PROTOCOL *BisPtr;
1135 BIS_APPLICATION_HANDLE BisAppHandle;
1136 EFI_BIS_DATA *BisDataSigInfo;
1137
1138 BisPtr = PxebcBisStart (Private, &BisAppHandle, &BisDataSigInfo);
1139
1140 if (BisPtr == NULL) {
1141 return FALSE;
1142 }
1143
1144 PxebcBisStop (BisPtr, BisAppHandle, BisDataSigInfo);
1145
1146 return TRUE;
1147 }
1148
1149 /**
1150 Start and initialize the BaseCode protocol, Simple Network protocol and UNDI.
1151
1152 @param Private Pointer to Pxe BaseCode Protocol
1153 @param UseIPv6 Do we want to support IPv6?
1154
1155 @return EFI_SUCCESS
1156 @return EFI_INVALID_PARAMETER
1157 @return EFI_UNSUPPORTED
1158 @return EFI_ALREADY_STARTED
1159 @return EFI_OUT_OF_RESOURCES
1160 @return Status is also returned from SNP.Start() and SNP.Initialize().
1161
1162 **/
1163 EFI_STATUS
1164 EFIAPI
1165 BcStart (
1166 IN EFI_PXE_BASE_CODE_PROTOCOL *This,
1167 IN BOOLEAN UseIPv6
1168 )
1169 {
1170 EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;
1171 EFI_SIMPLE_NETWORK_MODE *SnpModePtr;
1172 EFI_STATUS Status;
1173 EFI_STATUS StatCode;
1174 PXE_BASECODE_DEVICE *Private;
1175
1176 //
1177 // Lock the instance data
1178 //
1179 StatCode = EFI_SUCCESS;
1180
1181 if (This == NULL) {
1182 DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));
1183 return EFI_INVALID_PARAMETER;
1184 }
1185
1186 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);
1187
1188 if (Private == NULL) {
1189 DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE pointer == NULL"));
1190 return EFI_INVALID_PARAMETER;
1191 }
1192
1193 EfiAcquireLock (&Private->Lock);
1194
1195 //
1196 // Make sure BaseCode is not already started.
1197 //
1198 if (This->Mode->Started) {
1199 DEBUG ((DEBUG_WARN, "\nBcStart() BC is already started.\n"));
1200 EfiReleaseLock (&Private->Lock);
1201 return EFI_ALREADY_STARTED;
1202 }
1203
1204 //
1205 // Fail if IPv6 is requested and not supported.
1206 //
1207 if (UseIPv6) {
1208 DEBUG ((DEBUG_WARN, "\nBcStart() IPv6 is not supported.\n"));
1209 EfiReleaseLock (&Private->Lock);
1210 return EFI_UNSUPPORTED;
1211 }
1212 //
1213 // Setup shortcuts to SNP protocol and data structure.
1214 //
1215 SnpPtr = Private->SimpleNetwork;
1216 SnpModePtr = SnpPtr->Mode;
1217
1218 //
1219 // Start and initialize SNP.
1220 //
1221 if (SnpModePtr->State == EfiSimpleNetworkStopped) {
1222 StatCode = (*SnpPtr->Start) (SnpPtr);
1223
1224 if (SnpModePtr->State != EfiSimpleNetworkStarted) {
1225 DEBUG ((DEBUG_WARN, "\nBcStart() Could not start SNP.\n"));
1226 EfiReleaseLock (&Private->Lock);
1227 return StatCode;
1228 }
1229 }
1230 //
1231 // acquire memory for mode and transmit/receive buffers
1232 //
1233 if (SnpModePtr->State == EfiSimpleNetworkStarted) {
1234 StatCode = (*SnpPtr->Initialize) (SnpPtr, 0, 0);
1235
1236 if (SnpModePtr->State != EfiSimpleNetworkInitialized) {
1237 DEBUG ((DEBUG_WARN, "\nBcStart() Could not initialize SNP."));
1238 EfiReleaseLock (&Private->Lock);
1239 return StatCode;
1240 }
1241 }
1242 //
1243 // Dump debug info.
1244 //
1245 DEBUG ((DEBUG_INFO, "\nBC Start()"));
1246 DEBUG (
1247 (DEBUG_INFO,
1248 "\nSnpModePtr->State %Xh",
1249 SnpModePtr->State)
1250 );
1251 DEBUG (
1252 (DEBUG_INFO,
1253 "\nSnpModePtr->HwAddressSize %Xh",
1254 SnpModePtr->HwAddressSize)
1255 );
1256 DEBUG (
1257 (DEBUG_INFO,
1258 "\nSnpModePtr->MediaHeaderSize %Xh",
1259 SnpModePtr->MediaHeaderSize)
1260 );
1261 DEBUG (
1262 (DEBUG_INFO,
1263 "\nSnpModePtr->MaxPacketSize %Xh",
1264 SnpModePtr->MaxPacketSize)
1265 );
1266 DEBUG (
1267 (DEBUG_INFO,
1268 "\nSnpModePtr->MacAddressChangeable %Xh",
1269 SnpModePtr->MacAddressChangeable)
1270 );
1271 DEBUG (
1272 (DEBUG_INFO,
1273 "\nSnpModePtr->MultipleTxSupported %Xh",
1274 SnpModePtr->MultipleTxSupported)
1275 );
1276 DEBUG (
1277 (DEBUG_INFO,
1278 "\nSnpModePtr->CurrentAddress %Xh",
1279 *((UINTN *)&SnpModePtr->CurrentAddress))
1280 );
1281 DEBUG (
1282 (DEBUG_INFO,
1283 "\nSnpModePtr->BroadcastAddress %Xh",
1284 *((UINTN *)&SnpModePtr->BroadcastAddress))
1285 );
1286 DEBUG (
1287 (DEBUG_INFO,
1288 "\nSnpModePtr->PermanentAddress %Xh",
1289 *((UINTN *)&SnpModePtr->PermanentAddress))
1290 );
1291 DEBUG (
1292 (DEBUG_INFO,
1293 "\nSnpModePtr->NvRamSize %Xh",
1294 SnpModePtr->NvRamSize)
1295 );
1296 DEBUG (
1297 (DEBUG_INFO,
1298 "\nSnpModePtr->NvRamAccessSize %Xh",
1299 SnpModePtr->NvRamAccessSize)
1300 );
1301 DEBUG (
1302 (DEBUG_INFO,
1303 "\nSnpModePtr->ReceiveFilterMask %Xh",
1304 SnpModePtr->ReceiveFilterMask)
1305 );
1306 DEBUG (
1307 (DEBUG_INFO,
1308 "\nSnpModePtr->ReceiveFilterSetting %Xh",
1309 SnpModePtr->ReceiveFilterSetting)
1310 );
1311 DEBUG (
1312 (DEBUG_INFO,
1313 "\nSnpModePtr->MCastFilterCount %Xh",
1314 SnpModePtr->MCastFilterCount)
1315 );
1316 DEBUG (
1317 (DEBUG_INFO,
1318 "\nSnpModePtr->MCastFilter %Xh",
1319 SnpModePtr->MCastFilter)
1320 );
1321 DEBUG (
1322 (DEBUG_INFO,
1323 "\nSnpModePtr->IfType %Xh",
1324 SnpModePtr->IfType)
1325 );
1326 DEBUG (
1327 (DEBUG_INFO,
1328 "\nSnpModePtr->MediaPresentSupported %Xh",
1329 SnpModePtr->MediaPresentSupported)
1330 );
1331 DEBUG (
1332 (DEBUG_INFO,
1333 "\nSnpModePtr->MediaPresent %Xh",
1334 SnpModePtr->MediaPresent)
1335 );
1336
1337 //
1338 // If media check is supported and there is no media,
1339 // return error to caller.
1340 //
1341 if (SnpModePtr->MediaPresentSupported && !SnpModePtr->MediaPresent) {
1342 DEBUG ((DEBUG_WARN, "\nBcStart() Media not present.\n"));
1343 EfiReleaseLock (&Private->Lock);
1344 return EFI_NO_MEDIA;
1345 }
1346 //
1347 // Allocate Tx/Rx buffers
1348 //
1349 Status = gBS->AllocatePool (
1350 EfiBootServicesData,
1351 BUFFER_ALLOCATE_SIZE,
1352 (VOID **) &Private->TransmitBufferPtr
1353 );
1354
1355 if (!EFI_ERROR (Status)) {
1356 ZeroMem (Private->TransmitBufferPtr, BUFFER_ALLOCATE_SIZE);
1357 } else {
1358 DEBUG ((DEBUG_NET, "\nBcStart() Could not alloc TxBuf.\n"));
1359 EfiReleaseLock (&Private->Lock);
1360 return EFI_OUT_OF_RESOURCES;
1361 }
1362
1363 Status = gBS->AllocatePool (
1364 EfiBootServicesData,
1365 BUFFER_ALLOCATE_SIZE,
1366 (VOID **) &Private->ReceiveBufferPtr
1367 );
1368
1369 if (!EFI_ERROR (Status)) {
1370 ZeroMem (Private->ReceiveBufferPtr, BUFFER_ALLOCATE_SIZE);
1371 } else {
1372 DEBUG ((DEBUG_NET, "\nBcStart() Could not alloc RxBuf.\n"));
1373 gBS->FreePool (Private->TransmitBufferPtr);
1374 EfiReleaseLock (&Private->Lock);
1375 return EFI_OUT_OF_RESOURCES;
1376 }
1377
1378 Status = gBS->AllocatePool (
1379 EfiBootServicesData,
1380 256,
1381 (VOID **) &Private->TftpErrorBuffer
1382 );
1383
1384 if (EFI_ERROR (Status)) {
1385 gBS->FreePool (Private->ReceiveBufferPtr);
1386 gBS->FreePool (Private->TransmitBufferPtr);
1387 EfiReleaseLock (&Private->Lock);
1388 return EFI_OUT_OF_RESOURCES;
1389 }
1390
1391 Status = gBS->AllocatePool (EfiBootServicesData, 256, (VOID **) &Private->TftpAckBuffer);
1392
1393 if (EFI_ERROR (Status)) {
1394 gBS->FreePool (Private->TftpErrorBuffer);
1395 gBS->FreePool (Private->ReceiveBufferPtr);
1396 gBS->FreePool (Private->TransmitBufferPtr);
1397 EfiReleaseLock (&Private->Lock);
1398 return EFI_OUT_OF_RESOURCES;
1399 }
1400 //
1401 // Initialize private BaseCode instance data
1402 //
1403 do {
1404 Private->RandomPort = (UINT16) (Private->RandomPort + PXE_RND_PORT_LOW + Random (Private));
1405 } while (Private->RandomPort < PXE_RND_PORT_LOW);
1406
1407 Private->Igmpv1TimeoutEvent = NULL;
1408 Private->UseIgmpv1Reporting = TRUE;
1409 Private->IpLength = IP_ADDRESS_LENGTH (Private->EfiBc.Mode);
1410
1411 //
1412 // Initialize Mode structure
1413 //
1414 ZeroMem (Private->EfiBc.Mode, sizeof (EFI_PXE_BASE_CODE_MODE));
1415 //
1416 // check for callback protocol and set boolean
1417 //
1418 SetMakeCallback (Private);
1419 Private->EfiBc.Mode->Started = TRUE;
1420 Private->EfiBc.Mode->TTL = DEFAULT_TTL;
1421 Private->EfiBc.Mode->ToS = DEFAULT_ToS;
1422 Private->EfiBc.Mode->UsingIpv6 = UseIPv6;
1423
1424 //
1425 // Set to PXE_TRUE by the BC constructor if this BC implementation
1426 // supports IPv6.
1427 //
1428 Private->EfiBc.Mode->Ipv6Supported = SUPPORT_IPV6;
1429
1430 Private->EfiBc.Mode->Ipv6Available = FALSE;
1431 //
1432 // Set to TRUE by the BC constructor if this BC implementation
1433 // supports BIS.
1434 //
1435 Private->EfiBc.Mode->BisSupported = TRUE;
1436 Private->EfiBc.Mode->BisDetected = PxebcBisDetect (Private);
1437
1438 //
1439 // This field is set to PXE_TRUE by the BC Start() function. When this
1440 // field is PXE_TRUE, ARP packets are sent as needed to get IP and MAC
1441 // addresses. This can cause unexpected delays in the DHCP(), Discover()
1442 // and MTFTP() functions. Setting this to PXE_FALSE will cause these
1443 // functions to fail if the required IP/MAC information is not in the
1444 // ARP cache. The value of this field can be changed by an application
1445 // at any time.
1446 //
1447 Private->EfiBc.Mode->AutoArp = TRUE;
1448
1449 //
1450 // Unlock the instance data
1451 //
1452 EfiReleaseLock (&Private->Lock);
1453 return EFI_SUCCESS;
1454 }
1455
1456
1457 /**
1458 Stop the BaseCode protocol, Simple Network protocol and UNDI.
1459
1460 @param Private Pointer to Pxe BaseCode Protocol
1461
1462 @retval 0 Successfully stopped
1463 @retval !0 Failed
1464
1465 **/
1466 EFI_STATUS
1467 EFIAPI
1468 BcStop (
1469 IN EFI_PXE_BASE_CODE_PROTOCOL *This
1470 )
1471 {
1472 //
1473 // Lock the instance data
1474 //
1475 EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;
1476 EFI_SIMPLE_NETWORK_MODE *SnpModePtr;
1477 EFI_STATUS StatCode;
1478 PXE_BASECODE_DEVICE *Private;
1479
1480 StatCode = EFI_SUCCESS;
1481
1482 if (This == NULL) {
1483 DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));
1484 return EFI_INVALID_PARAMETER;
1485 }
1486
1487 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);
1488
1489 if (Private == NULL) {
1490 DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));
1491 return EFI_INVALID_PARAMETER;
1492 }
1493
1494 EfiAcquireLock (&Private->Lock);
1495
1496 SnpPtr = Private->SimpleNetwork;
1497 SnpModePtr = SnpPtr->Mode;
1498
1499 //
1500 // Issue BC command
1501 //
1502 StatCode = EFI_NOT_STARTED;
1503
1504 if (SnpModePtr->State == EfiSimpleNetworkInitialized) {
1505 StatCode = (*SnpPtr->Shutdown) (SnpPtr);
1506 }
1507
1508 if (SnpModePtr->State == EfiSimpleNetworkStarted) {
1509 StatCode = (*SnpPtr->Stop) (SnpPtr);
1510 }
1511
1512 if (Private->TransmitBufferPtr != NULL) {
1513 gBS->FreePool (Private->TransmitBufferPtr);
1514 Private->TransmitBufferPtr = NULL;
1515 }
1516
1517 if (Private->ReceiveBufferPtr != NULL) {
1518 gBS->FreePool (Private->ReceiveBufferPtr);
1519 Private->ReceiveBufferPtr = NULL;
1520 }
1521
1522 if (Private->ArpBuffer != NULL) {
1523 gBS->FreePool (Private->ArpBuffer);
1524 Private->ArpBuffer = NULL;
1525 }
1526
1527 if (Private->TftpErrorBuffer != NULL) {
1528 gBS->FreePool (Private->TftpErrorBuffer);
1529 Private->TftpErrorBuffer = NULL;
1530 }
1531
1532 if (Private->TftpAckBuffer != NULL) {
1533 gBS->FreePool (Private->TftpAckBuffer);
1534 Private->TftpAckBuffer = NULL;
1535 }
1536
1537 if (Private->Igmpv1TimeoutEvent != NULL) {
1538 gBS->CloseEvent (Private->Igmpv1TimeoutEvent);
1539 Private->Igmpv1TimeoutEvent = NULL;
1540 }
1541
1542 Private->FileSize = 0;
1543
1544 if (!Private->EfiBc.Mode->Started) {
1545 StatCode = EFI_NOT_STARTED;
1546 } else {
1547 Private->EfiBc.Mode->Started = FALSE;
1548 }
1549
1550 //
1551 // Unlock the instance data
1552 //
1553 EfiReleaseLock (&Private->Lock);
1554 return StatCode;
1555 }
1556
1557 const IPV4_ADDR AllSystemsGroup = {{224, 0, 0, 1}};
1558
1559
1560 /**
1561 Set up the IP filter
1562
1563 @param Private Pointer to Pxe BaseCode Protocol
1564 @param Filter Pointer to the filter
1565
1566 @retval 0 Successfully set the filter
1567 @retval !0 Failed
1568
1569 **/
1570 EFI_STATUS
1571 IpFilter (
1572 IN PXE_BASECODE_DEVICE *Private,
1573 IN EFI_PXE_BASE_CODE_IP_FILTER *Filter
1574 )
1575 {
1576 EFI_STATUS StatCode;
1577 EFI_MAC_ADDRESS MACadds[PXE_IP_FILTER_SIZE];
1578 EFI_PXE_BASE_CODE_MODE *PxebcMode;
1579 EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;
1580 EFI_SIMPLE_NETWORK_MODE *SnpModePtr;
1581 UINT32 Enable;
1582 UINT32 Disable;
1583 UINTN Index;
1584 UINTN Index2;
1585
1586 PxebcMode = Private->EfiBc.Mode;
1587 SnpPtr = Private->SimpleNetwork;
1588 SnpModePtr = SnpPtr->Mode;
1589
1590 //
1591 // validate input parameters
1592 // must have a filter
1593 // must not have any extra filter bits set
1594 //
1595 if (Filter == NULL ||
1596 (Filter->Filters &~FILTER_BITS)
1597 //
1598 // must not have a count which is too large or with no IP list
1599 //
1600 ||
1601 (Filter->IpCnt && (!Filter->IpList || Filter->IpCnt > PXE_IP_FILTER_SIZE))
1602 //
1603 // must not have incompatible filters - promiscuous incompatible with anything else
1604 //
1605 ||
1606 (
1607 (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) &&
1608 ((Filter->Filters &~EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) || Filter->IpCnt)
1609 )
1610 ) {
1611 DEBUG ((DEBUG_INFO, "\nIpFilter() Exit #1"));
1612 return EFI_INVALID_PARAMETER;
1613 }
1614 //
1615 // promiscuous multicast incompatible with multicast in IP list
1616 //
1617 if (Filter->IpCnt && (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST)) {
1618 for (Index = 0; Index < Filter->IpCnt; ++Index) {
1619 if (IS_MULTICAST (&Filter->IpList[Index])) {
1620 DEBUG ((DEBUG_INFO, "\nIpFilter() Exit #2"));
1621 return EFI_INVALID_PARAMETER;
1622 }
1623 }
1624 }
1625 //
1626 // leave groups for all those multicast which are no longer enabled
1627 //
1628 for (Index = 0; Index < PxebcMode->IpFilter.IpCnt; ++Index) {
1629 if (!IS_MULTICAST (&PxebcMode->IpFilter.IpList[Index])) {
1630 continue;
1631 }
1632
1633 for (Index2 = 0; Index2 < Filter->IpCnt; ++Index2) {
1634 if (!CompareMem (&PxebcMode->IpFilter.IpList[Index], &Filter->IpList[Index2], IP_ADDRESS_LENGTH (PxebcMode))) {
1635 //
1636 // still enabled
1637 //
1638 break;
1639 }
1640 }
1641 //
1642 // if we didn't find it, remove from group
1643 //
1644 if (Index2 == Filter->IpCnt) {
1645 IgmpLeaveGroup (Private, &PxebcMode->IpFilter.IpList[Index]);
1646 }
1647 }
1648 //
1649 // set enable bits, convert multicast ip adds, join groups
1650 // allways leave receive broadcast enabled at hardware layer
1651 //
1652 Index2 = 0;
1653
1654 if (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) {
1655 Enable = EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
1656 } else {
1657 if (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST) {
1658 Enable = EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
1659 } else {
1660 Enable = EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
1661
1662 for (Index = 0; Index < Filter->IpCnt; ++Index) {
1663 CopyMem (&PxebcMode->IpFilter.IpList[Index], &Filter->IpList[Index], sizeof (EFI_IP_ADDRESS));
1664
1665 if (IS_MULTICAST (&Filter->IpList[Index])) {
1666 EFI_IP_ADDRESS *TmpIp;
1667
1668 Enable |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;
1669
1670 //
1671 // if this is the first group, add the all systems group to mcast list
1672 //
1673 if (!Index2)
1674 {
1675 TmpIp = (EFI_IP_ADDRESS *) &AllSystemsGroup;
1676 --Index;
1677 } else {
1678 TmpIp = (EFI_IP_ADDRESS *) &Filter->IpList[Index];
1679 }
1680 //
1681 // get MAC address of IP
1682 //
1683 StatCode = (*SnpPtr->MCastIpToMac) (SnpPtr, PxebcMode->UsingIpv6, TmpIp, &MACadds[Index2++]);
1684
1685 if (EFI_ERROR (StatCode)) {
1686 DEBUG (
1687 (DEBUG_INFO,
1688 "\nIpFilter() Exit #2 %Xh (%r)",
1689 StatCode,
1690 StatCode)
1691 );
1692 return StatCode;
1693 }
1694 } else {
1695 Enable |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
1696 }
1697 }
1698 }
1699
1700 if (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) {
1701 Enable |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
1702 }
1703 }
1704 //
1705 // if nothing changed, just return
1706 //
1707 DEBUG (
1708 (DEBUG_INFO,
1709 "\nsnp->ReceiveFilterSetting == %Xh Filter->IpCnt == %Xh",
1710 SnpModePtr->ReceiveFilterSetting,
1711 Filter->IpCnt)
1712 );
1713
1714 if (SnpModePtr->ReceiveFilterSetting == Enable && !Filter->IpCnt) {
1715 DEBUG ((DEBUG_INFO, "\nIpFilter() Exit #4"));
1716 return EFI_SUCCESS;
1717 }
1718 //
1719 // disable those currently set but not set in new filter
1720 //
1721 Disable = SnpModePtr->ReceiveFilterSetting &~Enable;
1722
1723 StatCode = SnpPtr->ReceiveFilters (SnpPtr, Enable, Disable, FALSE, Index2, MACadds);
1724
1725 PxebcMode->IpFilter.IpCnt = Filter->IpCnt;
1726
1727 //
1728 // join groups for all multicast in list
1729 //
1730 for (Index = 0; Index < Filter->IpCnt; ++Index) {
1731 if (IS_MULTICAST (&Filter->IpList[Index])) {
1732 IgmpJoinGroup (Private, &Filter->IpList[Index]);
1733 }
1734 }
1735
1736 DEBUG ((DEBUG_INFO, "\nIpFilter() Exit #5 %Xh (%r)", StatCode, StatCode));
1737
1738 return StatCode;
1739 }
1740
1741
1742 /**
1743 Call the IP filter
1744
1745 @param Private Pointer to Pxe BaseCode Protocol
1746 @param Filter Pointer to the filter
1747
1748 @retval 0 Successfully set the filter
1749 @retval !0 Failed
1750
1751 **/
1752 EFI_STATUS
1753 EFIAPI
1754 BcIpFilter (
1755 IN EFI_PXE_BASE_CODE_PROTOCOL *This,
1756 IN EFI_PXE_BASE_CODE_IP_FILTER *Filter
1757 )
1758 {
1759 EFI_STATUS StatCode;
1760 PXE_BASECODE_DEVICE *Private;
1761 UINTN Index;
1762 //
1763 // Lock the instance data and make sure started
1764 //
1765 StatCode = EFI_SUCCESS;
1766
1767 if (This == NULL) {
1768 DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));
1769 return EFI_INVALID_PARAMETER;
1770 }
1771
1772 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);
1773
1774 if (Private == NULL) {
1775 DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));
1776 return EFI_INVALID_PARAMETER;
1777 }
1778
1779 for (Index = 0; Index < Filter->IpCnt; ++Index) {
1780 if ((Filter->IpList[Index].Addr[0]) == BROADCAST_IPv4) {
1781 //
1782 // The IP is a broadcast address.
1783 //
1784 return EFI_INVALID_PARAMETER;
1785 }
1786 }
1787
1788 EfiAcquireLock (&Private->Lock);
1789
1790 if (This->Mode == NULL || !This->Mode->Started) {
1791 DEBUG ((DEBUG_ERROR, "BC was not started."));
1792 EfiReleaseLock (&Private->Lock);
1793 return EFI_NOT_STARTED;
1794 }
1795
1796 if (Filter == NULL) {
1797 return EFI_INVALID_PARAMETER;
1798 }
1799 //
1800 // Issue BC command
1801 //
1802 StatCode = IpFilter (Private, Filter);
1803
1804 //
1805 // Unlock the instance data
1806 //
1807 EfiReleaseLock (&Private->Lock);
1808 return StatCode;
1809 }
1810
1811
1812 /**
1813 Set the Base Code behavior parameters
1814
1815 @param This Pointer to Pxe BaseCode Protocol
1816 @param AutoArpPtr Boolean to do ARP stuff
1817 @param SendGuidPtr Boolean whether or not to send GUID info
1818 @param TimeToLivePtr Value for Total time to live
1819 @param TypeOfServicePtr Value for Type of Service
1820 @param MakeCallbackPtr Boolean to determine if we make callbacks
1821
1822 @retval 0 Successfully set the parameters
1823 @retval !0 Failed
1824
1825 **/
1826 EFI_STATUS
1827 EFIAPI
1828 BcSetParameters (
1829 EFI_PXE_BASE_CODE_PROTOCOL *This,
1830 BOOLEAN *AutoArpPtr,
1831 BOOLEAN *SendGuidPtr,
1832 UINT8 *TimeToLivePtr,
1833 UINT8 *TypeOfServicePtr,
1834 BOOLEAN *MakeCallbackPtr
1835 )
1836 {
1837 EFI_PXE_BASE_CODE_MODE *PxebcMode;
1838 EFI_GUID TmpGuid;
1839 UINT8 *SerialNumberPtr;
1840 EFI_STATUS StatCode;
1841 PXE_BASECODE_DEVICE *Private;
1842
1843 //
1844 // Lock the instance data and make sure started
1845 //
1846 StatCode = EFI_SUCCESS;
1847
1848 if (This == NULL) {
1849 DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));
1850 return EFI_INVALID_PARAMETER;
1851 }
1852
1853 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);
1854
1855 if (Private == NULL) {
1856 DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));
1857 return EFI_INVALID_PARAMETER;
1858 }
1859
1860 EfiAcquireLock (&Private->Lock);
1861
1862 if (This->Mode == NULL || !This->Mode->Started) {
1863 DEBUG ((DEBUG_ERROR, "BC was not started."));
1864 EfiReleaseLock (&Private->Lock);
1865 return EFI_NOT_STARTED;
1866 }
1867
1868 DEBUG ((DEBUG_INFO, "\nSetParameters() Entry. "));
1869
1870 PxebcMode = Private->EfiBc.Mode;
1871 StatCode = EFI_SUCCESS;
1872
1873 if (SendGuidPtr != NULL) {
1874 if (*SendGuidPtr) {
1875 if (PxeBcLibGetSmbiosSystemGuidAndSerialNumber (&TmpGuid, (CHAR8 **) &SerialNumberPtr) != EFI_SUCCESS) {
1876 return EFI_INVALID_PARAMETER;
1877 }
1878 }
1879 }
1880
1881 if (MakeCallbackPtr != NULL) {
1882 if (*MakeCallbackPtr) {
1883 if (!SetMakeCallback (Private)) {
1884 return EFI_INVALID_PARAMETER;
1885 }
1886 }
1887
1888 PxebcMode->MakeCallbacks = *MakeCallbackPtr;
1889 }
1890
1891 if (AutoArpPtr != NULL) {
1892 PxebcMode->AutoArp = *AutoArpPtr;
1893 }
1894
1895 if (SendGuidPtr != NULL) {
1896 PxebcMode->SendGUID = *SendGuidPtr;
1897 }
1898
1899 if (TimeToLivePtr != NULL) {
1900 PxebcMode->TTL = *TimeToLivePtr;
1901 }
1902
1903 if (TypeOfServicePtr != NULL) {
1904 PxebcMode->ToS = *TypeOfServicePtr;
1905 }
1906 //
1907 // Unlock the instance data
1908 //
1909 DEBUG ((DEBUG_INFO, "\nSetparameters() Exit = %xh ", StatCode));
1910
1911 EfiReleaseLock (&Private->Lock);
1912 return StatCode;
1913 }
1914 //
1915 // //////////////////////////////////////////////////////////
1916 //
1917 // BC Set Station IP Routine
1918 //
1919
1920 /**
1921 Set the station IP address
1922
1923 @param This Pointer to Pxe BaseCode Protocol
1924 @param StationIpPtr Pointer to the requested IP address to set in base
1925 code
1926 @param SubnetMaskPtr Pointer to the requested subnet mask for the base
1927 code
1928
1929 @retval EFI_SUCCESS Successfully set the parameters
1930 @retval EFI_NOT_STARTED BC has not started
1931
1932 **/
1933 EFI_STATUS
1934 EFIAPI
1935 BcSetStationIP (
1936 IN EFI_PXE_BASE_CODE_PROTOCOL *This,
1937 IN EFI_IP_ADDRESS *StationIpPtr,
1938 IN EFI_IP_ADDRESS *SubnetMaskPtr
1939 )
1940 {
1941 EFI_PXE_BASE_CODE_MODE *PxebcMode;
1942 EFI_STATUS StatCode;
1943 PXE_BASECODE_DEVICE *Private;
1944 UINT32 SubnetMask;
1945
1946 //
1947 // Lock the instance data and make sure started
1948 //
1949 StatCode = EFI_SUCCESS;
1950
1951 if (This == NULL) {
1952 DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));
1953 return EFI_INVALID_PARAMETER;
1954 }
1955
1956 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);
1957
1958 if (Private == NULL) {
1959 DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));
1960 return EFI_INVALID_PARAMETER;
1961 }
1962
1963 EfiAcquireLock (&Private->Lock);
1964
1965 if (This->Mode == NULL || !This->Mode->Started) {
1966 DEBUG ((DEBUG_ERROR, "BC was not started."));
1967 StatCode = EFI_NOT_STARTED;
1968 goto RELEASE_LOCK;
1969 }
1970
1971 PxebcMode = Private->EfiBc.Mode;
1972
1973 if (!Private->GoodStationIp && ((StationIpPtr == NULL) || (SubnetMaskPtr == NULL))) {
1974 //
1975 // It's not allowed to only set one of the two addresses while there isn't a previous
1976 // GOOD address configuration.
1977 //
1978 StatCode = EFI_INVALID_PARAMETER;
1979 goto RELEASE_LOCK;
1980 }
1981
1982 if (SubnetMaskPtr != NULL) {
1983 SubnetMask = SubnetMaskPtr->Addr[0];
1984
1985 if (SubnetMask & (SubnetMask + 1)) {
1986 //
1987 // the subnet mask is valid if it's with leading continuous 1 bits.
1988 //
1989 StatCode = EFI_INVALID_PARAMETER;
1990 goto RELEASE_LOCK;
1991 }
1992 } else {
1993 SubnetMaskPtr = &PxebcMode->SubnetMask;
1994 SubnetMask = SubnetMaskPtr->Addr[0];
1995 }
1996
1997 if (StationIpPtr == NULL) {
1998 StationIpPtr = &PxebcMode->StationIp;
1999 }
2000
2001 if (!IS_INADDR_UNICAST (StationIpPtr) ||
2002 ((StationIpPtr->Addr[0] | SubnetMask) == BROADCAST_IPv4)) {
2003 //
2004 // The station IP is not a unicast address.
2005 //
2006 StatCode = EFI_INVALID_PARAMETER;
2007 goto RELEASE_LOCK;
2008 }
2009
2010 CopyMem (&PxebcMode->StationIp, StationIpPtr, sizeof (EFI_IP_ADDRESS));
2011 CopyMem (&PxebcMode->SubnetMask, SubnetMaskPtr, sizeof (EFI_IP_ADDRESS));
2012 Private->GoodStationIp = TRUE;
2013
2014 RELEASE_LOCK:
2015 //
2016 // Unlock the instance data
2017 //
2018 EfiReleaseLock (&Private->Lock);
2019
2020 return StatCode;
2021 }
2022
2023 EFI_DRIVER_BINDING_PROTOCOL mPxeBcDriverBinding = {
2024 PxeBcDriverSupported,
2025 PxeBcDriverStart,
2026 PxeBcDriverStop,
2027 0xa,
2028 NULL,
2029 NULL
2030 };
2031
2032
2033 /**
2034 Test to see if this driver supports Controller. Any Controller
2035 than contains a Snp protocol can be supported.
2036
2037 @param This Protocol instance pointer.
2038 @param Controller Handle of device to test.
2039 @param RemainingDevicePath Not used.
2040
2041 @retval EFI_SUCCESS This driver supports this device.
2042 @retval EFI_ALREADY_STARTED This driver is already running on this device.
2043 @retval other This driver does not support this device.
2044
2045 **/
2046 EFI_STATUS
2047 EFIAPI
2048 PxeBcDriverSupported (
2049 IN EFI_DRIVER_BINDING_PROTOCOL *This,
2050 IN EFI_HANDLE Controller,
2051 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
2052 )
2053 {
2054 EFI_STATUS Status;
2055 EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;
2056
2057 Status = gBS->OpenProtocol (
2058 Controller,
2059 &gEfiDevicePathProtocolGuid,
2060 NULL,
2061 This->DriverBindingHandle,
2062 Controller,
2063 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
2064 );
2065
2066 if (EFI_ERROR (Status)) {
2067 return Status;
2068 }
2069
2070 Status = gBS->OpenProtocol (
2071 Controller,
2072 &gEfiSimpleNetworkProtocolGuid,
2073 (VOID **) &SnpPtr,
2074 This->DriverBindingHandle,
2075 Controller,
2076 EFI_OPEN_PROTOCOL_BY_DRIVER
2077 );
2078 if (EFI_ERROR (Status)) {
2079 return Status;
2080 }
2081
2082 gBS->CloseProtocol (
2083 Controller,
2084 &gEfiSimpleNetworkProtocolGuid,
2085 This->DriverBindingHandle,
2086 Controller
2087 );
2088
2089 return Status;
2090 }
2091
2092
2093 /**
2094 Start the Base code driver.
2095
2096 @param This Protocol instance pointer.
2097 @param Controller Handle of device to test.
2098 @param RemainingDevicePath Not used.
2099
2100 @retval EFI_SUCCESS This driver supports this device.
2101 @retval EFI_ALREADY_STARTED This driver is already running on this device.
2102 @retval other This driver does not support this device.
2103
2104 **/
2105 EFI_STATUS
2106 EFIAPI
2107 PxeBcDriverStart (
2108 IN EFI_DRIVER_BINDING_PROTOCOL *This,
2109 IN EFI_HANDLE Controller,
2110 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
2111 )
2112 {
2113 EFI_STATUS Status;
2114 PXE_BASECODE_DEVICE *Private;
2115 LOADFILE_DEVICE *pLF;
2116
2117 //
2118 // Allocate structures needed by BaseCode and LoadFile protocols.
2119 //
2120 Private = AllocateZeroPool (sizeof (PXE_BASECODE_DEVICE));
2121
2122 if (Private == NULL ) {
2123 DEBUG ((EFI_D_NET, "\nBcNotifySnp() Could not alloc PXE_BASECODE_DEVICE structure.\n"));
2124 return EFI_OUT_OF_RESOURCES;
2125 }
2126
2127 pLF = AllocateZeroPool (sizeof (LOADFILE_DEVICE));
2128 if (pLF == NULL) {
2129 DEBUG ((EFI_D_NET, "\nBcNotifySnp() Could not alloc LOADFILE_DEVICE structure.\n"));
2130 FreePool (Private);
2131 return EFI_OUT_OF_RESOURCES;
2132 }
2133
2134 Private->EfiBc.Mode = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_MODE));
2135 if (Private->EfiBc.Mode == NULL) {
2136 DEBUG ((EFI_D_NET, "\nBcNotifySnp() Could not alloc Mode structure.\n"));
2137 FreePool (Private);
2138 FreePool (pLF);
2139 return EFI_OUT_OF_RESOURCES;
2140 }
2141 //
2142 // Lock access, just in case
2143 //
2144 EfiInitializeLock (&Private->Lock, TPL_CALLBACK);
2145 EfiAcquireLock (&Private->Lock);
2146
2147 EfiInitializeLock (&pLF->Lock, TPL_CALLBACK);
2148 EfiAcquireLock (&pLF->Lock);
2149
2150 //
2151 // Initialize PXE structure
2152 //
2153 //
2154 // First initialize the internal 'private' data that the application
2155 // does not see.
2156 //
2157 Private->Signature = PXE_BASECODE_DEVICE_SIGNATURE;
2158 Private->Handle = Controller;
2159
2160 //
2161 // Get the NII interface
2162 //
2163 Status = gBS->OpenProtocol (
2164 Controller,
2165 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
2166 (VOID **) &Private->NiiPtr,
2167 This->DriverBindingHandle,
2168 Controller,
2169 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2170 );
2171
2172 if (EFI_ERROR (Status)) {
2173 goto PxeBcError;
2174 }
2175
2176 //
2177 // Get the Snp interface
2178 //
2179 Status = gBS->OpenProtocol (
2180 Controller,
2181 &gEfiSimpleNetworkProtocolGuid,
2182 (VOID **) &Private->SimpleNetwork,
2183 This->DriverBindingHandle,
2184 Controller,
2185 EFI_OPEN_PROTOCOL_BY_DRIVER
2186 );
2187
2188 if (EFI_ERROR (Status)) {
2189 goto PxeBcError;
2190 }
2191
2192 //
2193 // Next, initialize the external 'public' data that
2194 // the application does see.
2195 //
2196 Private->EfiBc.Revision = EFI_PXE_BASE_CODE_PROTOCOL_REVISION;
2197 Private->EfiBc.Start = BcStart;
2198 Private->EfiBc.Stop = BcStop;
2199 Private->EfiBc.Dhcp = BcDhcp;
2200 Private->EfiBc.Discover = BcDiscover;
2201 Private->EfiBc.Mtftp = BcMtftp;
2202 Private->EfiBc.UdpWrite = BcUdpWrite;
2203 Private->EfiBc.UdpRead = BcUdpRead;
2204 Private->EfiBc.Arp = BcArp;
2205 Private->EfiBc.SetIpFilter = BcIpFilter;
2206 Private->EfiBc.SetParameters = BcSetParameters;
2207 Private->EfiBc.SetStationIp = BcSetStationIP;
2208 Private->EfiBc.SetPackets = BcSetPackets;
2209
2210 //
2211 // Initialize BaseCode Mode structure
2212 //
2213 Private->EfiBc.Mode->Started = FALSE;
2214 Private->EfiBc.Mode->TTL = DEFAULT_TTL;
2215 Private->EfiBc.Mode->ToS = DEFAULT_ToS;
2216 Private->EfiBc.Mode->UsingIpv6 = FALSE;
2217 Private->EfiBc.Mode->AutoArp = TRUE;
2218
2219 //
2220 // Set to PXE_TRUE by the BC constructor if this BC
2221 // implementation supports IPv6.
2222 //
2223 Private->EfiBc.Mode->Ipv6Supported = SUPPORT_IPV6;
2224 Private->EfiBc.Mode->Ipv6Available = FALSE;
2225
2226 //
2227 // Set to TRUE by the BC constructor if this BC
2228 // implementation supports BIS.
2229 //
2230 Private->EfiBc.Mode->BisSupported = TRUE;
2231 Private->EfiBc.Mode->BisDetected = PxebcBisDetect (Private);
2232
2233 //
2234 // Initialize LoadFile structure.
2235 //
2236 pLF->Signature = LOADFILE_DEVICE_SIGNATURE;
2237 pLF->LoadFile.LoadFile = LoadFile;
2238 pLF->Private = Private;
2239
2240 //
2241 // Install protocol interfaces.
2242 //
2243 Status = gBS->InstallMultipleProtocolInterfaces (
2244 &Controller,
2245 &gEfiPxeBaseCodeProtocolGuid,
2246 &Private->EfiBc,
2247 &gEfiLoadFileProtocolGuid,
2248 &pLF->LoadFile,
2249 NULL
2250 );
2251
2252 if (EFI_ERROR (Status)) {
2253 gBS->CloseProtocol (
2254 Controller,
2255 &gEfiSimpleNetworkProtocolGuid,
2256 This->DriverBindingHandle,
2257 Controller
2258 );
2259
2260 goto PxeBcError;
2261 }
2262 //
2263 // Release locks.
2264 //
2265 EfiReleaseLock (&pLF->Lock);
2266 EfiReleaseLock (&Private->Lock);
2267 return Status;
2268
2269 PxeBcError: ;
2270 gBS->FreePool (Private->EfiBc.Mode);
2271 gBS->FreePool (Private);
2272 gBS->FreePool (pLF);
2273 return Status;
2274 }
2275
2276
2277 /**
2278 Stop the Base code driver.
2279
2280 @param This Protocol instance pointer.
2281 @param Controller Handle of device to test.
2282 @param NumberOfChildren Not used
2283 @param ChildHandleBuffer Not used
2284
2285 @retval EFI_SUCCESS This driver supports this device.
2286 @retval EFI_ALREADY_STARTED This driver is already running on this device.
2287 @retval other This driver does not support this device.
2288
2289 **/
2290 EFI_STATUS
2291 EFIAPI
2292 PxeBcDriverStop (
2293 IN EFI_DRIVER_BINDING_PROTOCOL *This,
2294 IN EFI_HANDLE Controller,
2295 IN UINTN NumberOfChildren,
2296 IN EFI_HANDLE *ChildHandleBuffer
2297 )
2298 {
2299 EFI_STATUS Status;
2300 EFI_LOAD_FILE_PROTOCOL *LfProtocol;
2301 LOADFILE_DEVICE *LoadDevice;
2302
2303 //
2304 // Get our context back.
2305 //
2306 Status = gBS->OpenProtocol (
2307 Controller,
2308 &gEfiLoadFileProtocolGuid,
2309 (VOID **) &LfProtocol,
2310 This->DriverBindingHandle,
2311 Controller,
2312 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2313 );
2314
2315 if (EFI_ERROR (Status)) {
2316 return EFI_UNSUPPORTED;
2317 }
2318
2319 LoadDevice = EFI_LOAD_FILE_DEV_FROM_THIS (LfProtocol);
2320
2321 Status = gBS->UninstallMultipleProtocolInterfaces (
2322 Controller,
2323 &gEfiLoadFileProtocolGuid,
2324 &LoadDevice->LoadFile,
2325 &gEfiPxeBaseCodeProtocolGuid,
2326 &LoadDevice->Private->EfiBc,
2327 NULL
2328 );
2329
2330 if (!EFI_ERROR (Status)) {
2331
2332 Status = gBS->CloseProtocol (
2333 Controller,
2334 &gEfiSimpleNetworkProtocolGuid,
2335 This->DriverBindingHandle,
2336 Controller
2337 );
2338
2339 gBS->FreePool (LoadDevice->Private->EfiBc.Mode);
2340 gBS->FreePool (LoadDevice->Private);
2341 gBS->FreePool (LoadDevice);
2342 }
2343
2344 return Status;
2345 }
2346
2347
2348 /**
2349 Initialize the base code drivers and install the driver binding
2350
2351 Standard EFI Image Entry
2352
2353 @retval EFI_SUCCESS This driver was successfully bound
2354
2355 **/
2356 EFI_STATUS
2357 EFIAPI
2358 InitializeBCDriver (
2359 IN EFI_HANDLE ImageHandle,
2360 IN EFI_SYSTEM_TABLE *SystemTable
2361 )
2362 {
2363 EFI_STATUS Status;
2364
2365 //
2366 // Initialize EFI library
2367 //
2368 Status = EfiLibInstallDriverBindingComponentName2 (
2369 ImageHandle,
2370 SystemTable,
2371 &mPxeBcDriverBinding,
2372 NULL,
2373 &gPxeBcComponentName,
2374 &gPxeBcComponentName2
2375 );
2376
2377 InitArpHeader ();
2378 OptionsStrucInit ();
2379
2380 return Status;
2381 }
2382
2383 /* eof - bc.c */