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