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