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