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