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