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