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