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