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