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