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