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