]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/PxeBcDxe/Bc.c
Clean up Network Components to support GCC build.
[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 #if !SUPPORT_IPV6
1205 //
1206 // Fail if IPv6 is requested and not supported.
1207 //
1208 if (UseIPv6) {
1209 DEBUG ((DEBUG_WARN, "\nBcStart() IPv6 is not supported.\n"));
1210 EfiReleaseLock (&Private->Lock);
1211 return EFI_UNSUPPORTED;
1212 }
1213 #endif
1214 //
1215 // Setup shortcuts to SNP protocol and data structure.
1216 //
1217 SnpPtr = Private->SimpleNetwork;
1218 SnpModePtr = SnpPtr->Mode;
1219
1220 //
1221 // Start and initialize SNP.
1222 //
1223 if (SnpModePtr->State == EfiSimpleNetworkStopped) {
1224 StatCode = (*SnpPtr->Start) (SnpPtr);
1225
1226 if (SnpModePtr->State != EfiSimpleNetworkStarted) {
1227 DEBUG ((DEBUG_WARN, "\nBcStart() Could not start SNP.\n"));
1228 EfiReleaseLock (&Private->Lock);
1229 return StatCode;
1230 }
1231 }
1232 //
1233 // acquire memory for mode and transmit/receive buffers
1234 //
1235 if (SnpModePtr->State == EfiSimpleNetworkStarted) {
1236 StatCode = (*SnpPtr->Initialize) (SnpPtr, 0, 0);
1237
1238 if (SnpModePtr->State != EfiSimpleNetworkInitialized) {
1239 DEBUG ((DEBUG_WARN, "\nBcStart() Could not initialize SNP."));
1240 EfiReleaseLock (&Private->Lock);
1241 return StatCode;
1242 }
1243 }
1244 //
1245 // Dump debug info.
1246 //
1247 DEBUG ((DEBUG_INFO, "\nBC Start()"));
1248 DEBUG (
1249 (DEBUG_INFO,
1250 "\nSnpModePtr->State %Xh",
1251 SnpModePtr->State)
1252 );
1253 DEBUG (
1254 (DEBUG_INFO,
1255 "\nSnpModePtr->HwAddressSize %Xh",
1256 SnpModePtr->HwAddressSize)
1257 );
1258 DEBUG (
1259 (DEBUG_INFO,
1260 "\nSnpModePtr->MediaHeaderSize %Xh",
1261 SnpModePtr->MediaHeaderSize)
1262 );
1263 DEBUG (
1264 (DEBUG_INFO,
1265 "\nSnpModePtr->MaxPacketSize %Xh",
1266 SnpModePtr->MaxPacketSize)
1267 );
1268 DEBUG (
1269 (DEBUG_INFO,
1270 "\nSnpModePtr->MacAddressChangeable %Xh",
1271 SnpModePtr->MacAddressChangeable)
1272 );
1273 DEBUG (
1274 (DEBUG_INFO,
1275 "\nSnpModePtr->MultipleTxSupported %Xh",
1276 SnpModePtr->MultipleTxSupported)
1277 );
1278 DEBUG (
1279 (DEBUG_INFO,
1280 "\nSnpModePtr->CurrentAddress %Xh",
1281 *((UINTN *)&SnpModePtr->CurrentAddress))
1282 );
1283 DEBUG (
1284 (DEBUG_INFO,
1285 "\nSnpModePtr->BroadcastAddress %Xh",
1286 *((UINTN *)&SnpModePtr->BroadcastAddress))
1287 );
1288 DEBUG (
1289 (DEBUG_INFO,
1290 "\nSnpModePtr->PermanentAddress %Xh",
1291 *((UINTN *)&SnpModePtr->PermanentAddress))
1292 );
1293 DEBUG (
1294 (DEBUG_INFO,
1295 "\nSnpModePtr->NvRamSize %Xh",
1296 SnpModePtr->NvRamSize)
1297 );
1298 DEBUG (
1299 (DEBUG_INFO,
1300 "\nSnpModePtr->NvRamAccessSize %Xh",
1301 SnpModePtr->NvRamAccessSize)
1302 );
1303 DEBUG (
1304 (DEBUG_INFO,
1305 "\nSnpModePtr->ReceiveFilterMask %Xh",
1306 SnpModePtr->ReceiveFilterMask)
1307 );
1308 DEBUG (
1309 (DEBUG_INFO,
1310 "\nSnpModePtr->ReceiveFilterSetting %Xh",
1311 SnpModePtr->ReceiveFilterSetting)
1312 );
1313 DEBUG (
1314 (DEBUG_INFO,
1315 "\nSnpModePtr->MCastFilterCount %Xh",
1316 SnpModePtr->MCastFilterCount)
1317 );
1318 DEBUG (
1319 (DEBUG_INFO,
1320 "\nSnpModePtr->MCastFilter %Xh",
1321 SnpModePtr->MCastFilter)
1322 );
1323 DEBUG (
1324 (DEBUG_INFO,
1325 "\nSnpModePtr->IfType %Xh",
1326 SnpModePtr->IfType)
1327 );
1328 DEBUG (
1329 (DEBUG_INFO,
1330 "\nSnpModePtr->MediaPresentSupported %Xh",
1331 SnpModePtr->MediaPresentSupported)
1332 );
1333 DEBUG (
1334 (DEBUG_INFO,
1335 "\nSnpModePtr->MediaPresent %Xh",
1336 SnpModePtr->MediaPresent)
1337 );
1338
1339 //
1340 // If media check is supported and there is no media,
1341 // return error to caller.
1342 //
1343 if (SnpModePtr->MediaPresentSupported && !SnpModePtr->MediaPresent) {
1344 DEBUG ((DEBUG_WARN, "\nBcStart() Media not present.\n"));
1345 EfiReleaseLock (&Private->Lock);
1346 return EFI_NO_MEDIA;
1347 }
1348 //
1349 // Allocate Tx/Rx buffers
1350 //
1351 Status = gBS->AllocatePool (
1352 EfiBootServicesData,
1353 BUFFER_ALLOCATE_SIZE,
1354 (VOID **) &Private->TransmitBufferPtr
1355 );
1356
1357 if (!EFI_ERROR (Status)) {
1358 ZeroMem (Private->TransmitBufferPtr, BUFFER_ALLOCATE_SIZE);
1359 } else {
1360 DEBUG ((DEBUG_NET, "\nBcStart() Could not alloc TxBuf.\n"));
1361 EfiReleaseLock (&Private->Lock);
1362 return EFI_OUT_OF_RESOURCES;
1363 }
1364
1365 Status = gBS->AllocatePool (
1366 EfiBootServicesData,
1367 BUFFER_ALLOCATE_SIZE,
1368 (VOID **) &Private->ReceiveBufferPtr
1369 );
1370
1371 if (!EFI_ERROR (Status)) {
1372 ZeroMem (Private->ReceiveBufferPtr, BUFFER_ALLOCATE_SIZE);
1373 } else {
1374 DEBUG ((DEBUG_NET, "\nBcStart() Could not alloc RxBuf.\n"));
1375 gBS->FreePool (Private->TransmitBufferPtr);
1376 EfiReleaseLock (&Private->Lock);
1377 return EFI_OUT_OF_RESOURCES;
1378 }
1379
1380 Status = gBS->AllocatePool (
1381 EfiBootServicesData,
1382 256,
1383 (VOID **) &Private->TftpErrorBuffer
1384 );
1385
1386 if (EFI_ERROR (Status)) {
1387 gBS->FreePool (Private->ReceiveBufferPtr);
1388 gBS->FreePool (Private->TransmitBufferPtr);
1389 EfiReleaseLock (&Private->Lock);
1390 return EFI_OUT_OF_RESOURCES;
1391 }
1392
1393 Status = gBS->AllocatePool (EfiBootServicesData, 256, (VOID **) &Private->TftpAckBuffer);
1394
1395 if (EFI_ERROR (Status)) {
1396 gBS->FreePool (Private->TftpErrorBuffer);
1397 gBS->FreePool (Private->ReceiveBufferPtr);
1398 gBS->FreePool (Private->TransmitBufferPtr);
1399 EfiReleaseLock (&Private->Lock);
1400 return EFI_OUT_OF_RESOURCES;
1401 }
1402 //
1403 // Initialize private BaseCode instance data
1404 //
1405 do {
1406 Private->RandomPort = (UINT16) (Private->RandomPort + PXE_RND_PORT_LOW + Random (Private));
1407 } while (Private->RandomPort < PXE_RND_PORT_LOW);
1408
1409 Private->Igmpv1TimeoutEvent = NULL;
1410 Private->UseIgmpv1Reporting = TRUE;
1411 Private->IpLength = IP_ADDRESS_LENGTH (Private->EfiBc.Mode);
1412
1413 //
1414 // Initialize Mode structure
1415 //
1416 ZeroMem (Private->EfiBc.Mode, sizeof (EFI_PXE_BASE_CODE_MODE));
1417 //
1418 // check for callback protocol and set boolean
1419 //
1420 SetMakeCallback (Private);
1421 Private->EfiBc.Mode->Started = TRUE;
1422 Private->EfiBc.Mode->TTL = DEFAULT_TTL;
1423 Private->EfiBc.Mode->ToS = DEFAULT_ToS;
1424 Private->EfiBc.Mode->UsingIpv6 = UseIPv6;
1425
1426 //
1427 // Set to PXE_TRUE by the BC constructor if this BC implementation
1428 // supports IPv6.
1429 //
1430 Private->EfiBc.Mode->Ipv6Supported = SUPPORT_IPV6;
1431
1432 Private->EfiBc.Mode->Ipv6Available = FALSE;
1433 //
1434 // Set to TRUE by the BC constructor if this BC implementation
1435 // supports BIS.
1436 //
1437 Private->EfiBc.Mode->BisSupported = TRUE;
1438 Private->EfiBc.Mode->BisDetected = PxebcBisDetect (Private);
1439
1440 //
1441 // This field is set to PXE_TRUE by the BC Start() function. When this
1442 // field is PXE_TRUE, ARP packets are sent as needed to get IP and MAC
1443 // addresses. This can cause unexpected delays in the DHCP(), Discover()
1444 // and MTFTP() functions. Setting this to PXE_FALSE will cause these
1445 // functions to fail if the required IP/MAC information is not in the
1446 // ARP cache. The value of this field can be changed by an application
1447 // at any time.
1448 //
1449 Private->EfiBc.Mode->AutoArp = TRUE;
1450
1451 //
1452 // Unlock the instance data
1453 //
1454 EfiReleaseLock (&Private->Lock);
1455 return EFI_SUCCESS;
1456 }
1457
1458
1459 /**
1460 Stop the BaseCode protocol, Simple Network protocol and UNDI.
1461
1462 @param Private Pointer to Pxe BaseCode Protocol
1463
1464 @retval 0 Successfully stopped
1465 @retval !0 Failed
1466
1467 **/
1468 EFI_STATUS
1469 EFIAPI
1470 BcStop (
1471 IN EFI_PXE_BASE_CODE_PROTOCOL *This
1472 )
1473 {
1474 //
1475 // Lock the instance data
1476 //
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 SnpPtr = Private->SimpleNetwork;
1499 SnpModePtr = SnpPtr->Mode;
1500
1501 //
1502 // Issue BC command
1503 //
1504 StatCode = EFI_NOT_STARTED;
1505
1506 if (SnpModePtr->State == EfiSimpleNetworkInitialized) {
1507 StatCode = (*SnpPtr->Shutdown) (SnpPtr);
1508 }
1509
1510 if (SnpModePtr->State == EfiSimpleNetworkStarted) {
1511 StatCode = (*SnpPtr->Stop) (SnpPtr);
1512 }
1513
1514 if (Private->TransmitBufferPtr != NULL) {
1515 gBS->FreePool (Private->TransmitBufferPtr);
1516 Private->TransmitBufferPtr = NULL;
1517 }
1518
1519 if (Private->ReceiveBufferPtr != NULL) {
1520 gBS->FreePool (Private->ReceiveBufferPtr);
1521 Private->ReceiveBufferPtr = NULL;
1522 }
1523
1524 if (Private->ArpBuffer != NULL) {
1525 gBS->FreePool (Private->ArpBuffer);
1526 Private->ArpBuffer = NULL;
1527 }
1528
1529 if (Private->TftpErrorBuffer != NULL) {
1530 gBS->FreePool (Private->TftpErrorBuffer);
1531 Private->TftpErrorBuffer = NULL;
1532 }
1533
1534 if (Private->TftpAckBuffer != NULL) {
1535 gBS->FreePool (Private->TftpAckBuffer);
1536 Private->TftpAckBuffer = NULL;
1537 }
1538
1539 if (Private->Igmpv1TimeoutEvent != NULL) {
1540 gBS->CloseEvent (Private->Igmpv1TimeoutEvent);
1541 Private->Igmpv1TimeoutEvent = NULL;
1542 }
1543
1544 Private->FileSize = 0;
1545
1546 if (!Private->EfiBc.Mode->Started) {
1547 StatCode = EFI_NOT_STARTED;
1548 } else {
1549 Private->EfiBc.Mode->Started = FALSE;
1550 }
1551
1552 //
1553 // Unlock the instance data
1554 //
1555 EfiReleaseLock (&Private->Lock);
1556 return StatCode;
1557 }
1558
1559 const IPV4_ADDR AllSystemsGroup = {{224, 0, 0, 1}};
1560
1561
1562 /**
1563 Set up the IP filter
1564
1565 @param Private Pointer to Pxe BaseCode Protocol
1566 @param Filter Pointer to the filter
1567
1568 @retval 0 Successfully set the filter
1569 @retval !0 Failed
1570
1571 **/
1572 EFI_STATUS
1573 IpFilter (
1574 IN PXE_BASECODE_DEVICE *Private,
1575 IN EFI_PXE_BASE_CODE_IP_FILTER *Filter
1576 )
1577 {
1578 EFI_STATUS StatCode;
1579 EFI_MAC_ADDRESS MACadds[PXE_IP_FILTER_SIZE];
1580 EFI_PXE_BASE_CODE_MODE *PxebcMode;
1581 EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;
1582 EFI_SIMPLE_NETWORK_MODE *SnpModePtr;
1583 UINT32 Enable;
1584 UINT32 Disable;
1585 UINTN Index;
1586 UINTN Index2;
1587
1588 PxebcMode = Private->EfiBc.Mode;
1589 SnpPtr = Private->SimpleNetwork;
1590 SnpModePtr = SnpPtr->Mode;
1591
1592 //
1593 // validate input parameters
1594 // must have a filter
1595 // must not have any extra filter bits set
1596 //
1597 if (Filter == NULL ||
1598 (Filter->Filters &~FILTER_BITS)
1599 //
1600 // must not have a count which is too large or with no IP list
1601 //
1602 ||
1603 (Filter->IpCnt && (!Filter->IpList || Filter->IpCnt > PXE_IP_FILTER_SIZE))
1604 //
1605 // must not have incompatible filters - promiscuous incompatible with anything else
1606 //
1607 ||
1608 (
1609 (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) &&
1610 ((Filter->Filters &~EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) || Filter->IpCnt)
1611 )
1612 ) {
1613 DEBUG ((DEBUG_INFO, "\nIpFilter() Exit #1"));
1614 return EFI_INVALID_PARAMETER;
1615 }
1616 //
1617 // promiscuous multicast incompatible with multicast in IP list
1618 //
1619 if (Filter->IpCnt && (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST)) {
1620 for (Index = 0; Index < Filter->IpCnt; ++Index) {
1621 if (IS_MULTICAST (&Filter->IpList[Index])) {
1622 DEBUG ((DEBUG_INFO, "\nIpFilter() Exit #2"));
1623 return EFI_INVALID_PARAMETER;
1624 }
1625 }
1626 }
1627 //
1628 // leave groups for all those multicast which are no longer enabled
1629 //
1630 for (Index = 0; Index < PxebcMode->IpFilter.IpCnt; ++Index) {
1631 if (!IS_MULTICAST (&PxebcMode->IpFilter.IpList[Index])) {
1632 continue;
1633 }
1634
1635 for (Index2 = 0; Index2 < Filter->IpCnt; ++Index2) {
1636 if (!CompareMem (&PxebcMode->IpFilter.IpList[Index], &Filter->IpList[Index2], IP_ADDRESS_LENGTH (PxebcMode))) {
1637 //
1638 // still enabled
1639 //
1640 break;
1641 }
1642 }
1643 //
1644 // if we didn't find it, remove from group
1645 //
1646 if (Index2 == Filter->IpCnt) {
1647 IgmpLeaveGroup (Private, &PxebcMode->IpFilter.IpList[Index]);
1648 }
1649 }
1650 //
1651 // set enable bits, convert multicast ip adds, join groups
1652 // allways leave receive broadcast enabled at hardware layer
1653 //
1654 Index2 = 0;
1655
1656 if (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) {
1657 Enable = EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
1658 } else {
1659 if (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST) {
1660 Enable = EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
1661 } else {
1662 Enable = EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
1663
1664 for (Index = 0; Index < Filter->IpCnt; ++Index) {
1665 CopyMem (&PxebcMode->IpFilter.IpList[Index], &Filter->IpList[Index], sizeof (EFI_IP_ADDRESS));
1666
1667 if (IS_MULTICAST (&Filter->IpList[Index])) {
1668 EFI_IP_ADDRESS *TmpIp;
1669
1670 Enable |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;
1671
1672 //
1673 // if this is the first group, add the all systems group to mcast list
1674 //
1675 if (!Index2)
1676 {
1677 TmpIp = (EFI_IP_ADDRESS *) &AllSystemsGroup;
1678 --Index;
1679 } else {
1680 TmpIp = (EFI_IP_ADDRESS *) &Filter->IpList[Index];
1681 }
1682 //
1683 // get MAC address of IP
1684 //
1685 StatCode = (*SnpPtr->MCastIpToMac) (SnpPtr, PxebcMode->UsingIpv6, TmpIp, &MACadds[Index2++]);
1686
1687 if (EFI_ERROR (StatCode)) {
1688 DEBUG (
1689 (DEBUG_INFO,
1690 "\nIpFilter() Exit #2 %Xh (%r)",
1691 StatCode,
1692 StatCode)
1693 );
1694 return StatCode;
1695 }
1696 } else {
1697 Enable |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
1698 }
1699 }
1700 }
1701
1702 if (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) {
1703 Enable |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
1704 }
1705 }
1706 //
1707 // if nothing changed, just return
1708 //
1709 DEBUG (
1710 (DEBUG_INFO,
1711 "\nsnp->ReceiveFilterSetting == %Xh Filter->IpCnt == %Xh",
1712 SnpModePtr->ReceiveFilterSetting,
1713 Filter->IpCnt)
1714 );
1715
1716 if (SnpModePtr->ReceiveFilterSetting == Enable && !Filter->IpCnt) {
1717 DEBUG ((DEBUG_INFO, "\nIpFilter() Exit #4"));
1718 return EFI_SUCCESS;
1719 }
1720 //
1721 // disable those currently set but not set in new filter
1722 //
1723 Disable = SnpModePtr->ReceiveFilterSetting &~Enable;
1724
1725 StatCode = SnpPtr->ReceiveFilters (SnpPtr, Enable, Disable, FALSE, Index2, MACadds);
1726
1727 PxebcMode->IpFilter.IpCnt = Filter->IpCnt;
1728
1729 //
1730 // join groups for all multicast in list
1731 //
1732 for (Index = 0; Index < Filter->IpCnt; ++Index) {
1733 if (IS_MULTICAST (&Filter->IpList[Index])) {
1734 IgmpJoinGroup (Private, &Filter->IpList[Index]);
1735 }
1736 }
1737
1738 DEBUG ((DEBUG_INFO, "\nIpFilter() Exit #5 %Xh (%r)", StatCode, StatCode));
1739
1740 return StatCode;
1741 }
1742
1743
1744 /**
1745 Call the IP filter
1746
1747 @param Private Pointer to Pxe BaseCode Protocol
1748 @param Filter Pointer to the filter
1749
1750 @retval 0 Successfully set the filter
1751 @retval !0 Failed
1752
1753 **/
1754 EFI_STATUS
1755 EFIAPI
1756 BcIpFilter (
1757 IN EFI_PXE_BASE_CODE_PROTOCOL *This,
1758 IN EFI_PXE_BASE_CODE_IP_FILTER *Filter
1759 )
1760 {
1761 EFI_STATUS StatCode;
1762 PXE_BASECODE_DEVICE *Private;
1763 UINTN Index;
1764 //
1765 // Lock the instance data and make sure started
1766 //
1767 StatCode = EFI_SUCCESS;
1768
1769 if (This == NULL) {
1770 DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));
1771 return EFI_INVALID_PARAMETER;
1772 }
1773
1774 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);
1775
1776 if (Private == NULL) {
1777 DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));
1778 return EFI_INVALID_PARAMETER;
1779 }
1780
1781 for (Index = 0; Index < Filter->IpCnt; ++Index) {
1782 if ((Filter->IpList[Index].Addr[0]) == BROADCAST_IPv4) {
1783 //
1784 // The IP is a broadcast address.
1785 //
1786 return EFI_INVALID_PARAMETER;
1787 }
1788 }
1789
1790 EfiAcquireLock (&Private->Lock);
1791
1792 if (This->Mode == NULL || !This->Mode->Started) {
1793 DEBUG ((DEBUG_ERROR, "BC was not started."));
1794 EfiReleaseLock (&Private->Lock);
1795 return EFI_NOT_STARTED;
1796 }
1797
1798 if (Filter == NULL) {
1799 return EFI_INVALID_PARAMETER;
1800 }
1801 //
1802 // Issue BC command
1803 //
1804 StatCode = IpFilter (Private, Filter);
1805
1806 //
1807 // Unlock the instance data
1808 //
1809 EfiReleaseLock (&Private->Lock);
1810 return StatCode;
1811 }
1812
1813
1814 /**
1815 Set the Base Code behavior parameters
1816
1817 @param This Pointer to Pxe BaseCode Protocol
1818 @param AutoArpPtr Boolean to do ARP stuff
1819 @param SendGuidPtr Boolean whether or not to send GUID info
1820 @param TimeToLivePtr Value for Total time to live
1821 @param TypeOfServicePtr Value for Type of Service
1822 @param MakeCallbackPtr Boolean to determine if we make callbacks
1823
1824 @retval 0 Successfully set the parameters
1825 @retval !0 Failed
1826
1827 **/
1828 EFI_STATUS
1829 EFIAPI
1830 BcSetParameters (
1831 EFI_PXE_BASE_CODE_PROTOCOL *This,
1832 BOOLEAN *AutoArpPtr,
1833 BOOLEAN *SendGuidPtr,
1834 UINT8 *TimeToLivePtr,
1835 UINT8 *TypeOfServicePtr,
1836 BOOLEAN *MakeCallbackPtr
1837 )
1838 {
1839 EFI_PXE_BASE_CODE_MODE *PxebcMode;
1840 EFI_GUID TmpGuid;
1841 UINT8 *SerialNumberPtr;
1842 EFI_STATUS StatCode;
1843 PXE_BASECODE_DEVICE *Private;
1844
1845 //
1846 // Lock the instance data and make sure started
1847 //
1848 StatCode = EFI_SUCCESS;
1849
1850 if (This == NULL) {
1851 DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));
1852 return EFI_INVALID_PARAMETER;
1853 }
1854
1855 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);
1856
1857 if (Private == NULL) {
1858 DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));
1859 return EFI_INVALID_PARAMETER;
1860 }
1861
1862 EfiAcquireLock (&Private->Lock);
1863
1864 if (This->Mode == NULL || !This->Mode->Started) {
1865 DEBUG ((DEBUG_ERROR, "BC was not started."));
1866 EfiReleaseLock (&Private->Lock);
1867 return EFI_NOT_STARTED;
1868 }
1869
1870 DEBUG ((DEBUG_INFO, "\nSetParameters() Entry. "));
1871
1872 PxebcMode = Private->EfiBc.Mode;
1873 StatCode = EFI_SUCCESS;
1874
1875 if (SendGuidPtr != NULL) {
1876 if (*SendGuidPtr) {
1877 if (PxeBcLibGetSmbiosSystemGuidAndSerialNumber (&TmpGuid, (CHAR8 **) &SerialNumberPtr) != EFI_SUCCESS) {
1878 return EFI_INVALID_PARAMETER;
1879 }
1880 }
1881 }
1882
1883 if (MakeCallbackPtr != NULL) {
1884 if (*MakeCallbackPtr) {
1885 if (!SetMakeCallback (Private)) {
1886 return EFI_INVALID_PARAMETER;
1887 }
1888 }
1889
1890 PxebcMode->MakeCallbacks = *MakeCallbackPtr;
1891 }
1892
1893 if (AutoArpPtr != NULL) {
1894 PxebcMode->AutoArp = *AutoArpPtr;
1895 }
1896
1897 if (SendGuidPtr != NULL) {
1898 PxebcMode->SendGUID = *SendGuidPtr;
1899 }
1900
1901 if (TimeToLivePtr != NULL) {
1902 PxebcMode->TTL = *TimeToLivePtr;
1903 }
1904
1905 if (TypeOfServicePtr != NULL) {
1906 PxebcMode->ToS = *TypeOfServicePtr;
1907 }
1908 //
1909 // Unlock the instance data
1910 //
1911 DEBUG ((DEBUG_INFO, "\nSetparameters() Exit = %xh ", StatCode));
1912
1913 EfiReleaseLock (&Private->Lock);
1914 return StatCode;
1915 }
1916 //
1917 // //////////////////////////////////////////////////////////
1918 //
1919 // BC Set Station IP Routine
1920 //
1921
1922 /**
1923 Set the station IP address
1924
1925 @param This Pointer to Pxe BaseCode Protocol
1926 @param StationIpPtr Pointer to the requested IP address to set in base
1927 code
1928 @param SubnetMaskPtr Pointer to the requested subnet mask for the base
1929 code
1930
1931 @retval EFI_SUCCESS Successfully set the parameters
1932 @retval EFI_NOT_STARTED BC has not started
1933
1934 **/
1935 EFI_STATUS
1936 EFIAPI
1937 BcSetStationIP (
1938 IN EFI_PXE_BASE_CODE_PROTOCOL *This,
1939 IN EFI_IP_ADDRESS *StationIpPtr,
1940 IN EFI_IP_ADDRESS *SubnetMaskPtr
1941 )
1942 {
1943 EFI_PXE_BASE_CODE_MODE *PxebcMode;
1944 EFI_STATUS StatCode;
1945 PXE_BASECODE_DEVICE *Private;
1946 UINT32 SubnetMask;
1947
1948 //
1949 // Lock the instance data and make sure started
1950 //
1951 StatCode = EFI_SUCCESS;
1952
1953 if (This == NULL) {
1954 DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));
1955 return EFI_INVALID_PARAMETER;
1956 }
1957
1958 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);
1959
1960 if (Private == NULL) {
1961 DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));
1962 return EFI_INVALID_PARAMETER;
1963 }
1964
1965 EfiAcquireLock (&Private->Lock);
1966
1967 if (This->Mode == NULL || !This->Mode->Started) {
1968 DEBUG ((DEBUG_ERROR, "BC was not started."));
1969 StatCode = EFI_NOT_STARTED;
1970 goto RELEASE_LOCK;
1971 }
1972
1973 PxebcMode = Private->EfiBc.Mode;
1974
1975 if (!Private->GoodStationIp && ((StationIpPtr == NULL) || (SubnetMaskPtr == NULL))) {
1976 //
1977 // It's not allowed to only set one of the two addresses while there isn't a previous
1978 // GOOD address configuration.
1979 //
1980 StatCode = EFI_INVALID_PARAMETER;
1981 goto RELEASE_LOCK;
1982 }
1983
1984 if (SubnetMaskPtr != NULL) {
1985 SubnetMask = SubnetMaskPtr->Addr[0];
1986
1987 if (SubnetMask & (SubnetMask + 1)) {
1988 //
1989 // the subnet mask is valid if it's with leading continuous 1 bits.
1990 //
1991 StatCode = EFI_INVALID_PARAMETER;
1992 goto RELEASE_LOCK;
1993 }
1994 } else {
1995 SubnetMaskPtr = &PxebcMode->SubnetMask;
1996 SubnetMask = SubnetMaskPtr->Addr[0];
1997 }
1998
1999 if (StationIpPtr == NULL) {
2000 StationIpPtr = &PxebcMode->StationIp;
2001 }
2002
2003 if (!IS_INADDR_UNICAST (StationIpPtr) ||
2004 ((StationIpPtr->Addr[0] | SubnetMask) == BROADCAST_IPv4)) {
2005 //
2006 // The station IP is not a unicast address.
2007 //
2008 StatCode = EFI_INVALID_PARAMETER;
2009 goto RELEASE_LOCK;
2010 }
2011
2012 CopyMem (&PxebcMode->StationIp, StationIpPtr, sizeof (EFI_IP_ADDRESS));
2013 CopyMem (&PxebcMode->SubnetMask, SubnetMaskPtr, sizeof (EFI_IP_ADDRESS));
2014 Private->GoodStationIp = TRUE;
2015
2016 RELEASE_LOCK:
2017 //
2018 // Unlock the instance data
2019 //
2020 EfiReleaseLock (&Private->Lock);
2021
2022 return StatCode;
2023 }
2024
2025 EFI_DRIVER_BINDING_PROTOCOL mPxeBcDriverBinding = {
2026 PxeBcDriverSupported,
2027 PxeBcDriverStart,
2028 PxeBcDriverStop,
2029 0xa,
2030 NULL,
2031 NULL
2032 };
2033
2034
2035 /**
2036 Test to see if this driver supports Controller. Any Controller
2037 than contains a Snp protocol can be supported.
2038
2039 @param This Protocol instance pointer.
2040 @param Controller Handle of device to test.
2041 @param RemainingDevicePath Not used.
2042
2043 @retval EFI_SUCCESS This driver supports this device.
2044 @retval EFI_ALREADY_STARTED This driver is already running on this device.
2045 @retval other This driver does not support this device.
2046
2047 **/
2048 EFI_STATUS
2049 EFIAPI
2050 PxeBcDriverSupported (
2051 IN EFI_DRIVER_BINDING_PROTOCOL *This,
2052 IN EFI_HANDLE Controller,
2053 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
2054 )
2055 {
2056 EFI_STATUS Status;
2057 EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;
2058
2059 Status = gBS->OpenProtocol (
2060 Controller,
2061 &gEfiDevicePathProtocolGuid,
2062 NULL,
2063 This->DriverBindingHandle,
2064 Controller,
2065 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
2066 );
2067
2068 if (EFI_ERROR (Status)) {
2069 return Status;
2070 }
2071
2072 Status = gBS->OpenProtocol (
2073 Controller,
2074 &gEfiSimpleNetworkProtocolGuid,
2075 (VOID **) &SnpPtr,
2076 This->DriverBindingHandle,
2077 Controller,
2078 EFI_OPEN_PROTOCOL_BY_DRIVER
2079 );
2080 if (EFI_ERROR (Status)) {
2081 return Status;
2082 }
2083
2084 gBS->CloseProtocol (
2085 Controller,
2086 &gEfiSimpleNetworkProtocolGuid,
2087 This->DriverBindingHandle,
2088 Controller
2089 );
2090
2091 return Status;
2092 }
2093
2094
2095 /**
2096 Start the Base code driver.
2097
2098 @param This Protocol instance pointer.
2099 @param Controller Handle of device to test.
2100 @param RemainingDevicePath Not used.
2101
2102 @retval EFI_SUCCESS This driver supports this device.
2103 @retval EFI_ALREADY_STARTED This driver is already running on this device.
2104 @retval other This driver does not support this device.
2105
2106 **/
2107 EFI_STATUS
2108 EFIAPI
2109 PxeBcDriverStart (
2110 IN EFI_DRIVER_BINDING_PROTOCOL *This,
2111 IN EFI_HANDLE Controller,
2112 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
2113 )
2114 {
2115 EFI_STATUS Status;
2116 PXE_BASECODE_DEVICE *Private;
2117 LOADFILE_DEVICE *pLF;
2118
2119 //
2120 // Allocate structures needed by BaseCode and LoadFile protocols.
2121 //
2122 Private = AllocateZeroPool (sizeof (PXE_BASECODE_DEVICE));
2123
2124 if (Private == NULL ) {
2125 DEBUG ((EFI_D_NET, "\nBcNotifySnp() Could not alloc PXE_BASECODE_DEVICE structure.\n"));
2126 return EFI_OUT_OF_RESOURCES;
2127 }
2128
2129 pLF = AllocateZeroPool (sizeof (LOADFILE_DEVICE));
2130 if (pLF == NULL) {
2131 DEBUG ((EFI_D_NET, "\nBcNotifySnp() Could not alloc LOADFILE_DEVICE structure.\n"));
2132 FreePool (Private);
2133 return EFI_OUT_OF_RESOURCES;
2134 }
2135
2136 Private->EfiBc.Mode = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_MODE));
2137 if (Private->EfiBc.Mode == NULL) {
2138 DEBUG ((EFI_D_NET, "\nBcNotifySnp() Could not alloc Mode structure.\n"));
2139 FreePool (Private);
2140 FreePool (pLF);
2141 return EFI_OUT_OF_RESOURCES;
2142 }
2143 //
2144 // Lock access, just in case
2145 //
2146 EfiInitializeLock (&Private->Lock, TPL_CALLBACK);
2147 EfiAcquireLock (&Private->Lock);
2148
2149 EfiInitializeLock (&pLF->Lock, TPL_CALLBACK);
2150 EfiAcquireLock (&pLF->Lock);
2151
2152 //
2153 // Initialize PXE structure
2154 //
2155 //
2156 // First initialize the internal 'private' data that the application
2157 // does not see.
2158 //
2159 Private->Signature = PXE_BASECODE_DEVICE_SIGNATURE;
2160 Private->Handle = Controller;
2161
2162 //
2163 // Get the NII interface
2164 //
2165 Status = gBS->OpenProtocol (
2166 Controller,
2167 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
2168 (VOID **) &Private->NiiPtr,
2169 This->DriverBindingHandle,
2170 Controller,
2171 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2172 );
2173
2174 if (EFI_ERROR (Status)) {
2175 Status = gBS->OpenProtocol (
2176 Controller,
2177 &gEfiNetworkInterfaceIdentifierProtocolGuid,
2178 (VOID **) &Private->NiiPtr,
2179 This->DriverBindingHandle,
2180 Controller,
2181 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2182 );
2183
2184 if (EFI_ERROR (Status)) {
2185 goto PxeBcError;
2186 }
2187 }
2188 //
2189 // Get the Snp interface
2190 //
2191 Status = gBS->OpenProtocol (
2192 Controller,
2193 &gEfiSimpleNetworkProtocolGuid,
2194 (VOID **) &Private->SimpleNetwork,
2195 This->DriverBindingHandle,
2196 Controller,
2197 EFI_OPEN_PROTOCOL_BY_DRIVER
2198 );
2199
2200 if (EFI_ERROR (Status)) {
2201 goto PxeBcError;
2202 }
2203
2204 //
2205 // Next, initialize the external 'public' data that
2206 // the application does see.
2207 //
2208 Private->EfiBc.Revision = EFI_PXE_BASE_CODE_PROTOCOL_REVISION;
2209 Private->EfiBc.Start = BcStart;
2210 Private->EfiBc.Stop = BcStop;
2211 Private->EfiBc.Dhcp = BcDhcp;
2212 Private->EfiBc.Discover = BcDiscover;
2213 Private->EfiBc.Mtftp = BcMtftp;
2214 Private->EfiBc.UdpWrite = BcUdpWrite;
2215 Private->EfiBc.UdpRead = BcUdpRead;
2216 Private->EfiBc.Arp = BcArp;
2217 Private->EfiBc.SetIpFilter = BcIpFilter;
2218 Private->EfiBc.SetParameters = BcSetParameters;
2219 Private->EfiBc.SetStationIp = BcSetStationIP;
2220 Private->EfiBc.SetPackets = BcSetPackets;
2221
2222 //
2223 // Initialize BaseCode Mode structure
2224 //
2225 Private->EfiBc.Mode->Started = FALSE;
2226 Private->EfiBc.Mode->TTL = DEFAULT_TTL;
2227 Private->EfiBc.Mode->ToS = DEFAULT_ToS;
2228 Private->EfiBc.Mode->UsingIpv6 = FALSE;
2229 Private->EfiBc.Mode->AutoArp = TRUE;
2230
2231 //
2232 // Set to PXE_TRUE by the BC constructor if this BC
2233 // implementation supports IPv6.
2234 //
2235 Private->EfiBc.Mode->Ipv6Supported = SUPPORT_IPV6;
2236
2237 #if SUPPORT_IPV6
2238 Private->EfiBc.Mode->Ipv6Available = Private->NiiPtr->Ipv6Supported;
2239 #else
2240 Private->EfiBc.Mode->Ipv6Available = FALSE;
2241 #endif
2242 //
2243 // Set to TRUE by the BC constructor if this BC
2244 // implementation supports BIS.
2245 //
2246 Private->EfiBc.Mode->BisSupported = TRUE;
2247 Private->EfiBc.Mode->BisDetected = PxebcBisDetect (Private);
2248
2249 //
2250 // Initialize LoadFile structure.
2251 //
2252 pLF->Signature = LOADFILE_DEVICE_SIGNATURE;
2253 pLF->LoadFile.LoadFile = LoadFile;
2254 pLF->Private = Private;
2255
2256 //
2257 // Install protocol interfaces.
2258 //
2259 Status = gBS->InstallMultipleProtocolInterfaces (
2260 &Controller,
2261 &gEfiPxeBaseCodeProtocolGuid,
2262 &Private->EfiBc,
2263 &gEfiLoadFileProtocolGuid,
2264 &pLF->LoadFile,
2265 NULL
2266 );
2267
2268 if (EFI_ERROR (Status)) {
2269 gBS->CloseProtocol (
2270 Controller,
2271 &gEfiSimpleNetworkProtocolGuid,
2272 This->DriverBindingHandle,
2273 Controller
2274 );
2275
2276 goto PxeBcError;
2277 }
2278 //
2279 // Release locks.
2280 //
2281 EfiReleaseLock (&pLF->Lock);
2282 EfiReleaseLock (&Private->Lock);
2283 return Status;
2284
2285 PxeBcError: ;
2286 gBS->FreePool (Private->EfiBc.Mode);
2287 gBS->FreePool (Private);
2288 gBS->FreePool (pLF);
2289 return Status;
2290 }
2291
2292
2293 /**
2294 Stop the Base code driver.
2295
2296 @param This Protocol instance pointer.
2297 @param Controller Handle of device to test.
2298 @param NumberOfChildren Not used
2299 @param ChildHandleBuffer Not used
2300
2301 @retval EFI_SUCCESS This driver supports this device.
2302 @retval EFI_ALREADY_STARTED This driver is already running on this device.
2303 @retval other This driver does not support this device.
2304
2305 **/
2306 EFI_STATUS
2307 EFIAPI
2308 PxeBcDriverStop (
2309 IN EFI_DRIVER_BINDING_PROTOCOL *This,
2310 IN EFI_HANDLE Controller,
2311 IN UINTN NumberOfChildren,
2312 IN EFI_HANDLE *ChildHandleBuffer
2313 )
2314 {
2315 EFI_STATUS Status;
2316 EFI_LOAD_FILE_PROTOCOL *LfProtocol;
2317 LOADFILE_DEVICE *LoadDevice;
2318
2319 //
2320 // Get our context back.
2321 //
2322 Status = gBS->OpenProtocol (
2323 Controller,
2324 &gEfiLoadFileProtocolGuid,
2325 (VOID **) &LfProtocol,
2326 This->DriverBindingHandle,
2327 Controller,
2328 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2329 );
2330
2331 if (EFI_ERROR (Status)) {
2332 return EFI_UNSUPPORTED;
2333 }
2334
2335 LoadDevice = EFI_LOAD_FILE_DEV_FROM_THIS (LfProtocol);
2336
2337 Status = gBS->UninstallMultipleProtocolInterfaces (
2338 Controller,
2339 &gEfiLoadFileProtocolGuid,
2340 &LoadDevice->LoadFile,
2341 &gEfiPxeBaseCodeProtocolGuid,
2342 &LoadDevice->Private->EfiBc,
2343 NULL
2344 );
2345
2346 if (!EFI_ERROR (Status)) {
2347
2348 Status = gBS->CloseProtocol (
2349 Controller,
2350 &gEfiSimpleNetworkProtocolGuid,
2351 This->DriverBindingHandle,
2352 Controller
2353 );
2354
2355 gBS->FreePool (LoadDevice->Private->EfiBc.Mode);
2356 gBS->FreePool (LoadDevice->Private);
2357 gBS->FreePool (LoadDevice);
2358 }
2359
2360 return Status;
2361 }
2362
2363
2364 /**
2365 Initialize the base code drivers and install the driver binding
2366
2367 Standard EFI Image Entry
2368
2369 @retval EFI_SUCCESS This driver was successfully bound
2370
2371 **/
2372 EFI_STATUS
2373 EFIAPI
2374 InitializeBCDriver (
2375 IN EFI_HANDLE ImageHandle,
2376 IN EFI_SYSTEM_TABLE *SystemTable
2377 )
2378 {
2379 EFI_STATUS Status;
2380
2381 //
2382 // Initialize EFI library
2383 //
2384 Status = EfiLibInstallDriverBindingComponentName2 (
2385 ImageHandle,
2386 SystemTable,
2387 &mPxeBcDriverBinding,
2388 NULL,
2389 &gPxeBcComponentName,
2390 &gPxeBcComponentName2
2391 );
2392
2393 InitArpHeader ();
2394 OptionsStrucInit ();
2395
2396 return Status;
2397 }
2398
2399 /* eof - bc.c */