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