]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/PxeBcDxe/Bc.c
1. Enable Network stack to pass SCT, currently MNP, ARP, IP4, TCP4 and DHCP4 have...
[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
1149static VOID *BCNotifyReg;\r
1150\r
1151\r
1152/**\r
1153 Start and initialize the BaseCode protocol, Simple Network protocol and UNDI.\r
1154\r
1155 @param Private Pointer to Pxe BaseCode Protocol\r
1156 @param UseIPv6 Do we want to support IPv6?\r
1157\r
1158 @return EFI_SUCCESS\r
1159 @return EFI_INVALID_PARAMETER\r
1160 @return EFI_UNSUPPORTED\r
1161 @return EFI_ALREADY_STARTED\r
1162 @return EFI_OUT_OF_RESOURCES\r
1163 @return Status is also returned from SNP.Start() and SNP.Initialize().\r
1164\r
1165**/\r
1166EFI_STATUS\r
1167EFIAPI\r
1168BcStart (\r
1169 IN EFI_PXE_BASE_CODE_PROTOCOL *This,\r
1170 IN BOOLEAN UseIPv6\r
1171 )\r
1172{\r
1173 EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;\r
1174 EFI_SIMPLE_NETWORK_MODE *SnpModePtr;\r
1175 EFI_STATUS Status;\r
1176 EFI_STATUS StatCode;\r
1177 PXE_BASECODE_DEVICE *Private;\r
1178\r
1179 //\r
1180 // Lock the instance data\r
1181 //\r
1182 StatCode = EFI_SUCCESS;\r
1183\r
1184 if (This == NULL) {\r
1185 DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));\r
1186 return EFI_INVALID_PARAMETER;\r
1187 }\r
1188\r
1189 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
1190\r
1191 if (Private == NULL) {\r
1192 DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE pointer == NULL"));\r
1193 return EFI_INVALID_PARAMETER;\r
1194 }\r
1195\r
1196 EfiAcquireLock (&Private->Lock);\r
1197\r
1198 //\r
1199 // Make sure BaseCode is not already started.\r
1200 //\r
1201 if (This->Mode->Started) {\r
1202 DEBUG ((DEBUG_WARN, "\nBcStart() BC is already started.\n"));\r
1203 EfiReleaseLock (&Private->Lock);\r
1204 return EFI_ALREADY_STARTED;\r
1205 }\r
1206\r
1207#if !SUPPORT_IPV6\r
1208 //\r
1209 // Fail if IPv6 is requested and not supported.\r
1210 //\r
1211 if (UseIPv6) {\r
1212 DEBUG ((DEBUG_WARN, "\nBcStart() IPv6 is not supported.\n"));\r
1213 EfiReleaseLock (&Private->Lock);\r
1214 return EFI_UNSUPPORTED;\r
1215 }\r
1216#endif\r
1217 //\r
1218 // Setup shortcuts to SNP protocol and data structure.\r
1219 //\r
1220 SnpPtr = Private->SimpleNetwork;\r
1221 SnpModePtr = SnpPtr->Mode;\r
1222\r
1223 //\r
1224 // Start and initialize SNP.\r
1225 //\r
1226 if (SnpModePtr->State == EfiSimpleNetworkStopped) {\r
1227 StatCode = (*SnpPtr->Start) (SnpPtr);\r
1228\r
1229 if (SnpModePtr->State != EfiSimpleNetworkStarted) {\r
1230 DEBUG ((DEBUG_WARN, "\nBcStart() Could not start SNP.\n"));\r
1231 EfiReleaseLock (&Private->Lock);\r
1232 return StatCode;\r
1233 }\r
1234 }\r
1235 //\r
1236 // acquire memory for mode and transmit/receive buffers\r
1237 //\r
1238 if (SnpModePtr->State == EfiSimpleNetworkStarted) {\r
1239 StatCode = (*SnpPtr->Initialize) (SnpPtr, 0, 0);\r
1240\r
1241 if (SnpModePtr->State != EfiSimpleNetworkInitialized) {\r
1242 DEBUG ((DEBUG_WARN, "\nBcStart() Could not initialize SNP."));\r
1243 EfiReleaseLock (&Private->Lock);\r
1244 return StatCode;\r
1245 }\r
1246 }\r
1247 //\r
1248 // Dump debug info.\r
1249 //\r
1250 DEBUG ((DEBUG_INFO, "\nBC Start()"));\r
1251 DEBUG (\r
1252 (DEBUG_INFO,\r
1253 "\nSnpModePtr->State %Xh",\r
1254 SnpModePtr->State)\r
1255 );\r
1256 DEBUG (\r
1257 (DEBUG_INFO,\r
1258 "\nSnpModePtr->HwAddressSize %Xh",\r
1259 SnpModePtr->HwAddressSize)\r
1260 );\r
1261 DEBUG (\r
1262 (DEBUG_INFO,\r
1263 "\nSnpModePtr->MediaHeaderSize %Xh",\r
1264 SnpModePtr->MediaHeaderSize)\r
1265 );\r
1266 DEBUG (\r
1267 (DEBUG_INFO,\r
1268 "\nSnpModePtr->MaxPacketSize %Xh",\r
1269 SnpModePtr->MaxPacketSize)\r
1270 );\r
1271 DEBUG (\r
1272 (DEBUG_INFO,\r
1273 "\nSnpModePtr->MacAddressChangeable %Xh",\r
1274 SnpModePtr->MacAddressChangeable)\r
1275 );\r
1276 DEBUG (\r
1277 (DEBUG_INFO,\r
1278 "\nSnpModePtr->MultipleTxSupported %Xh",\r
1279 SnpModePtr->MultipleTxSupported)\r
1280 );\r
1281 DEBUG (\r
1282 (DEBUG_INFO,\r
1283 "\nSnpModePtr->CurrentAddress %Xh",\r
1284 *((UINTN *)&SnpModePtr->CurrentAddress))\r
1285 );\r
1286 DEBUG (\r
1287 (DEBUG_INFO,\r
1288 "\nSnpModePtr->BroadcastAddress %Xh",\r
1289 *((UINTN *)&SnpModePtr->BroadcastAddress))\r
1290 );\r
1291 DEBUG (\r
1292 (DEBUG_INFO,\r
1293 "\nSnpModePtr->PermanentAddress %Xh",\r
1294 *((UINTN *)&SnpModePtr->PermanentAddress))\r
1295 );\r
1296 DEBUG (\r
1297 (DEBUG_INFO,\r
1298 "\nSnpModePtr->NvRamSize %Xh",\r
1299 SnpModePtr->NvRamSize)\r
1300 );\r
1301 DEBUG (\r
1302 (DEBUG_INFO,\r
1303 "\nSnpModePtr->NvRamAccessSize %Xh",\r
1304 SnpModePtr->NvRamAccessSize)\r
1305 );\r
1306 DEBUG (\r
1307 (DEBUG_INFO,\r
1308 "\nSnpModePtr->ReceiveFilterMask %Xh",\r
1309 SnpModePtr->ReceiveFilterMask)\r
1310 );\r
1311 DEBUG (\r
1312 (DEBUG_INFO,\r
1313 "\nSnpModePtr->ReceiveFilterSetting %Xh",\r
1314 SnpModePtr->ReceiveFilterSetting)\r
1315 );\r
1316 DEBUG (\r
1317 (DEBUG_INFO,\r
1318 "\nSnpModePtr->MCastFilterCount %Xh",\r
1319 SnpModePtr->MCastFilterCount)\r
1320 );\r
1321 DEBUG (\r
1322 (DEBUG_INFO,\r
1323 "\nSnpModePtr->MCastFilter %Xh",\r
1324 SnpModePtr->MCastFilter)\r
1325 );\r
1326 DEBUG (\r
1327 (DEBUG_INFO,\r
1328 "\nSnpModePtr->IfType %Xh",\r
1329 SnpModePtr->IfType)\r
1330 );\r
1331 DEBUG (\r
1332 (DEBUG_INFO,\r
1333 "\nSnpModePtr->MediaPresentSupported %Xh",\r
1334 SnpModePtr->MediaPresentSupported)\r
1335 );\r
1336 DEBUG (\r
1337 (DEBUG_INFO,\r
1338 "\nSnpModePtr->MediaPresent %Xh",\r
1339 SnpModePtr->MediaPresent)\r
1340 );\r
1341\r
1342 //\r
1343 // If media check is supported and there is no media,\r
1344 // return error to caller.\r
1345 //\r
1346 if (SnpModePtr->MediaPresentSupported && !SnpModePtr->MediaPresent) {\r
1347 DEBUG ((DEBUG_WARN, "\nBcStart() Media not present.\n"));\r
1348 EfiReleaseLock (&Private->Lock);\r
1349 return EFI_NO_MEDIA;\r
1350 }\r
1351 //\r
1352 // Allocate Tx/Rx buffers\r
1353 //\r
1354 Status = gBS->AllocatePool (\r
1355 EfiBootServicesData,\r
1356 BUFFER_ALLOCATE_SIZE,\r
687a2e5f 1357 (VOID **) &Private->TransmitBufferPtr\r
772db4bb 1358 );\r
1359\r
1360 if (!EFI_ERROR (Status)) {\r
1361 ZeroMem (Private->TransmitBufferPtr, BUFFER_ALLOCATE_SIZE);\r
1362 } else {\r
1363 DEBUG ((DEBUG_NET, "\nBcStart() Could not alloc TxBuf.\n"));\r
1364 EfiReleaseLock (&Private->Lock);\r
1365 return EFI_OUT_OF_RESOURCES;\r
1366 }\r
1367\r
1368 Status = gBS->AllocatePool (\r
1369 EfiBootServicesData,\r
1370 BUFFER_ALLOCATE_SIZE,\r
687a2e5f 1371 (VOID **) &Private->ReceiveBufferPtr\r
772db4bb 1372 );\r
1373\r
1374 if (!EFI_ERROR (Status)) {\r
1375 ZeroMem (Private->ReceiveBufferPtr, BUFFER_ALLOCATE_SIZE);\r
1376 } else {\r
1377 DEBUG ((DEBUG_NET, "\nBcStart() Could not alloc RxBuf.\n"));\r
1378 gBS->FreePool (Private->TransmitBufferPtr);\r
1379 EfiReleaseLock (&Private->Lock);\r
1380 return EFI_OUT_OF_RESOURCES;\r
1381 }\r
1382\r
1383 Status = gBS->AllocatePool (\r
1384 EfiBootServicesData,\r
1385 256,\r
687a2e5f 1386 (VOID **) &Private->TftpErrorBuffer\r
772db4bb 1387 );\r
1388\r
1389 if (EFI_ERROR (Status)) {\r
1390 gBS->FreePool (Private->ReceiveBufferPtr);\r
1391 gBS->FreePool (Private->TransmitBufferPtr);\r
1392 EfiReleaseLock (&Private->Lock);\r
1393 return EFI_OUT_OF_RESOURCES;\r
1394 }\r
1395\r
687a2e5f 1396 Status = gBS->AllocatePool (EfiBootServicesData, 256, (VOID **) &Private->TftpAckBuffer);\r
772db4bb 1397\r
1398 if (EFI_ERROR (Status)) {\r
1399 gBS->FreePool (Private->TftpErrorBuffer);\r
1400 gBS->FreePool (Private->ReceiveBufferPtr);\r
1401 gBS->FreePool (Private->TransmitBufferPtr);\r
1402 EfiReleaseLock (&Private->Lock);\r
1403 return EFI_OUT_OF_RESOURCES;\r
1404 }\r
1405 //\r
1406 // Initialize private BaseCode instance data\r
1407 //\r
1408 do {\r
1409 Private->RandomPort = (UINT16) (Private->RandomPort + PXE_RND_PORT_LOW + Random (Private));\r
1410 } while (Private->RandomPort < PXE_RND_PORT_LOW);\r
1411\r
1412 Private->Igmpv1TimeoutEvent = NULL;\r
1413 Private->UseIgmpv1Reporting = TRUE;\r
1414 Private->IpLength = IP_ADDRESS_LENGTH (Private->EfiBc.Mode);\r
1415\r
1416 //\r
1417 // Initialize Mode structure\r
1418 //\r
1419 ZeroMem (Private->EfiBc.Mode, sizeof (EFI_PXE_BASE_CODE_MODE));\r
1420 //\r
1421 // check for callback protocol and set boolean\r
1422 //\r
1423 SetMakeCallback (Private);\r
1424 Private->EfiBc.Mode->Started = TRUE;\r
1425 Private->EfiBc.Mode->TTL = DEFAULT_TTL;\r
1426 Private->EfiBc.Mode->ToS = DEFAULT_ToS;\r
1427 Private->EfiBc.Mode->UsingIpv6 = UseIPv6;\r
1428\r
1429 //\r
1430 // Set to PXE_TRUE by the BC constructor if this BC implementation\r
1431 // supports IPv6.\r
1432 //\r
1433 Private->EfiBc.Mode->Ipv6Supported = SUPPORT_IPV6;\r
1434\r
1435 Private->EfiBc.Mode->Ipv6Available = FALSE;\r
1436 //\r
1437 // Set to TRUE by the BC constructor if this BC implementation\r
1438 // supports BIS.\r
1439 //\r
1440 Private->EfiBc.Mode->BisSupported = TRUE;\r
1441 Private->EfiBc.Mode->BisDetected = PxebcBisDetect (Private);\r
1442\r
1443 //\r
1444 // This field is set to PXE_TRUE by the BC Start() function. When this\r
1445 // field is PXE_TRUE, ARP packets are sent as needed to get IP and MAC\r
1446 // addresses. This can cause unexpected delays in the DHCP(), Discover()\r
1447 // and MTFTP() functions. Setting this to PXE_FALSE will cause these\r
1448 // functions to fail if the required IP/MAC information is not in the\r
1449 // ARP cache. The value of this field can be changed by an application\r
1450 // at any time.\r
1451 //\r
1452 Private->EfiBc.Mode->AutoArp = TRUE;\r
1453\r
1454 //\r
1455 // Unlock the instance data\r
1456 //\r
1457 EfiReleaseLock (&Private->Lock);\r
1458 return EFI_SUCCESS;\r
1459}\r
1460\r
1461\r
1462/**\r
1463 Stop the BaseCode protocol, Simple Network protocol and UNDI.\r
1464\r
1465 @param Private Pointer to Pxe BaseCode Protocol\r
1466\r
1467 @retval 0 Successfully stopped\r
1468 @retval !0 Failed\r
1469\r
1470**/\r
1471EFI_STATUS\r
1472EFIAPI\r
1473BcStop (\r
1474 IN EFI_PXE_BASE_CODE_PROTOCOL *This\r
1475 )\r
1476{\r
1477 //\r
1478 // Lock the instance data\r
1479 //\r
772db4bb 1480 EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;\r
1481 EFI_SIMPLE_NETWORK_MODE *SnpModePtr;\r
1482 EFI_STATUS StatCode;\r
1483 PXE_BASECODE_DEVICE *Private;\r
1484\r
1485 StatCode = EFI_SUCCESS;\r
1486\r
1487 if (This == NULL) {\r
1488 DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));\r
1489 return EFI_INVALID_PARAMETER;\r
1490 }\r
1491\r
1492 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
1493\r
1494 if (Private == NULL) {\r
1495 DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));\r
1496 return EFI_INVALID_PARAMETER;\r
1497 }\r
1498\r
1499 EfiAcquireLock (&Private->Lock);\r
1500\r
772db4bb 1501 SnpPtr = Private->SimpleNetwork;\r
1502 SnpModePtr = SnpPtr->Mode;\r
1503\r
1504 //\r
1505 // Issue BC command\r
1506 //\r
1507 StatCode = EFI_NOT_STARTED;\r
1508\r
1509 if (SnpModePtr->State == EfiSimpleNetworkInitialized) {\r
1510 StatCode = (*SnpPtr->Shutdown) (SnpPtr);\r
1511 }\r
1512\r
1513 if (SnpModePtr->State == EfiSimpleNetworkStarted) {\r
1514 StatCode = (*SnpPtr->Stop) (SnpPtr);\r
1515 }\r
1516\r
1517 if (Private->TransmitBufferPtr != NULL) {\r
1518 gBS->FreePool (Private->TransmitBufferPtr);\r
1519 Private->TransmitBufferPtr = NULL;\r
1520 }\r
1521\r
1522 if (Private->ReceiveBufferPtr != NULL) {\r
1523 gBS->FreePool (Private->ReceiveBufferPtr);\r
1524 Private->ReceiveBufferPtr = NULL;\r
1525 }\r
1526\r
1527 if (Private->ArpBuffer != NULL) {\r
1528 gBS->FreePool (Private->ArpBuffer);\r
1529 Private->ArpBuffer = NULL;\r
1530 }\r
1531\r
1532 if (Private->TftpErrorBuffer != NULL) {\r
1533 gBS->FreePool (Private->TftpErrorBuffer);\r
1534 Private->TftpErrorBuffer = NULL;\r
1535 }\r
1536\r
1537 if (Private->TftpAckBuffer != NULL) {\r
1538 gBS->FreePool (Private->TftpAckBuffer);\r
1539 Private->TftpAckBuffer = NULL;\r
1540 }\r
1541\r
1542 if (Private->Igmpv1TimeoutEvent != NULL) {\r
1543 gBS->CloseEvent (Private->Igmpv1TimeoutEvent);\r
1544 Private->Igmpv1TimeoutEvent = NULL;\r
1545 }\r
1546\r
1547 Private->FileSize = 0;\r
1548\r
1549 if (!Private->EfiBc.Mode->Started) {\r
1550 StatCode = EFI_NOT_STARTED;\r
1551 } else {\r
1552 Private->EfiBc.Mode->Started = FALSE;\r
1553 }\r
1554\r
1555 //\r
1556 // Unlock the instance data\r
1557 //\r
1558 EfiReleaseLock (&Private->Lock);\r
1559 return StatCode;\r
1560}\r
1561\r
1562const IPV4_ADDR AllSystemsGroup = { 224, 0, 0, 1 };\r
1563\r
1564\r
1565/**\r
1566 Set up the IP filter\r
1567\r
1568 @param Private Pointer to Pxe BaseCode Protocol\r
1569 @param Filter Pointer to the filter\r
1570\r
1571 @retval 0 Successfully set the filter\r
1572 @retval !0 Failed\r
1573\r
1574**/\r
1575EFI_STATUS\r
1576IpFilter (\r
1577 IN PXE_BASECODE_DEVICE *Private,\r
1578 IN EFI_PXE_BASE_CODE_IP_FILTER *Filter\r
1579 )\r
1580{\r
1581 EFI_STATUS StatCode;\r
1582 EFI_MAC_ADDRESS MACadds[PXE_IP_FILTER_SIZE];\r
1583 EFI_PXE_BASE_CODE_MODE *PxebcMode;\r
1584 EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;\r
1585 EFI_SIMPLE_NETWORK_MODE *SnpModePtr;\r
1586 UINT32 Enable;\r
1587 UINT32 Disable;\r
1588 UINTN Index;\r
1589 UINTN Index2;\r
1590\r
1591 PxebcMode = Private->EfiBc.Mode;\r
1592 SnpPtr = Private->SimpleNetwork;\r
1593 SnpModePtr = SnpPtr->Mode;\r
1594\r
1595 //\r
1596 // validate input parameters\r
1597 // must have a filter\r
1598 // must not have any extra filter bits set\r
1599 //\r
1600 if (Filter == NULL ||\r
1601 (Filter->Filters &~FILTER_BITS)\r
1602 //\r
1603 // must not have a count which is too large or with no IP list\r
1604 //\r
1605 ||\r
1606 (Filter->IpCnt && (!Filter->IpList || Filter->IpCnt > PXE_IP_FILTER_SIZE))\r
1607 //\r
1608 // must not have incompatible filters - promiscuous incompatible with anything else\r
1609 //\r
1610 ||\r
1611 (\r
1612 (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) &&\r
1613 ((Filter->Filters &~EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) || Filter->IpCnt)\r
1614 )\r
1615 ) {\r
1616 DEBUG ((DEBUG_INFO, "\nIpFilter() Exit #1"));\r
1617 return EFI_INVALID_PARAMETER;\r
1618 }\r
1619 //\r
1620 // promiscuous multicast incompatible with multicast in IP list\r
1621 //\r
1622 if (Filter->IpCnt && (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST)) {\r
1623 for (Index = 0; Index < Filter->IpCnt; ++Index) {\r
1624 if (IS_MULTICAST (&Filter->IpList[Index])) {\r
1625 DEBUG ((DEBUG_INFO, "\nIpFilter() Exit #2"));\r
1626 return EFI_INVALID_PARAMETER;\r
1627 }\r
1628 }\r
1629 }\r
1630 //\r
1631 // leave groups for all those multicast which are no longer enabled\r
1632 //\r
1633 for (Index = 0; Index < PxebcMode->IpFilter.IpCnt; ++Index) {\r
1634 if (!IS_MULTICAST (&PxebcMode->IpFilter.IpList[Index])) {\r
1635 continue;\r
1636 }\r
1637\r
1638 for (Index2 = 0; Index2 < Filter->IpCnt; ++Index2) {\r
1639 if (!CompareMem (&PxebcMode->IpFilter.IpList[Index], &Filter->IpList[Index2], IP_ADDRESS_LENGTH (PxebcMode))) {\r
1640 //\r
1641 // still enabled\r
1642 //\r
1643 break;\r
1644 }\r
1645 }\r
1646 //\r
1647 // if we didn't find it, remove from group\r
1648 //\r
1649 if (Index2 == Filter->IpCnt) {\r
1650 IgmpLeaveGroup (Private, &PxebcMode->IpFilter.IpList[Index]);\r
1651 }\r
1652 }\r
1653 //\r
1654 // set enable bits, convert multicast ip adds, join groups\r
1655 // allways leave receive broadcast enabled at hardware layer\r
1656 //\r
1657 Index2 = 0;\r
1658\r
1659 if (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) {\r
1660 Enable = EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
1661 } else {\r
1662 if (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST) {\r
1663 Enable = EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
1664 } else {\r
1665 Enable = EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;\r
1666\r
1667 for (Index = 0; Index < Filter->IpCnt; ++Index) {\r
1668 PxebcMode->IpFilter.IpList[Index] = Filter->IpList[Index];\r
1669\r
1670 if (IS_MULTICAST (&Filter->IpList[Index])) {\r
1671 EFI_IP_ADDRESS *TmpIp;\r
1672\r
1673 Enable |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;\r
1674\r
1675 //\r
1676 // if this is the first group, add the all systems group to mcast list\r
1677 //\r
1678 if (!Index2)\r
1679 {\r
1680 TmpIp = (EFI_IP_ADDRESS *) &AllSystemsGroup;\r
1681 --Index;\r
1682 } else {\r
1683 TmpIp = (EFI_IP_ADDRESS *) &Filter->IpList[Index];\r
1684 }\r
1685 //\r
1686 // get MAC address of IP\r
1687 //\r
1688 StatCode = (*SnpPtr->MCastIpToMac) (SnpPtr, PxebcMode->UsingIpv6, TmpIp, &MACadds[Index2++]);\r
1689\r
1690 if (EFI_ERROR (StatCode)) {\r
1691 DEBUG (\r
1692 (DEBUG_INFO,\r
1693 "\nIpFilter() Exit #2 %Xh (%r)",\r
1694 StatCode,\r
1695 StatCode)\r
1696 );\r
1697 return StatCode;\r
1698 }\r
1699 } else {\r
1700 Enable |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;\r
1701 }\r
1702 }\r
1703 }\r
1704\r
1705 if (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) {\r
1706 Enable |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;\r
1707 }\r
1708 }\r
1709 //\r
1710 // if nothing changed, just return\r
1711 //\r
1712 DEBUG (\r
1713 (DEBUG_INFO,\r
1714 "\nsnp->ReceiveFilterSetting == %Xh Filter->IpCnt == %Xh",\r
1715 SnpModePtr->ReceiveFilterSetting,\r
1716 Filter->IpCnt)\r
1717 );\r
1718\r
1719 if (SnpModePtr->ReceiveFilterSetting == Enable && !Filter->IpCnt) {\r
1720 DEBUG ((DEBUG_INFO, "\nIpFilter() Exit #4"));\r
1721 return EFI_SUCCESS;\r
1722 }\r
1723 //\r
1724 // disable those currently set but not set in new filter\r
1725 //\r
1726 Disable = SnpModePtr->ReceiveFilterSetting &~Enable;\r
1727\r
1728 StatCode = SnpPtr->ReceiveFilters (SnpPtr, Enable, Disable, FALSE, Index2, MACadds);\r
1729\r
1730 PxebcMode->IpFilter.IpCnt = Filter->IpCnt;\r
1731\r
1732 //\r
1733 // join groups for all multicast in list\r
1734 //\r
1735 for (Index = 0; Index < Filter->IpCnt; ++Index) {\r
1736 if (IS_MULTICAST (&Filter->IpList[Index])) {\r
1737 IgmpJoinGroup (Private, &Filter->IpList[Index]);\r
1738 }\r
1739 }\r
1740\r
1741 DEBUG ((DEBUG_INFO, "\nIpFilter() Exit #5 %Xh (%r)", StatCode, StatCode));\r
1742\r
1743 return StatCode;\r
1744}\r
1745\r
1746\r
1747/**\r
1748 Call the IP filter\r
1749\r
1750 @param Private Pointer to Pxe BaseCode Protocol\r
1751 @param Filter Pointer to the filter\r
1752\r
1753 @retval 0 Successfully set the filter\r
1754 @retval !0 Failed\r
1755\r
1756**/\r
1757EFI_STATUS\r
1758EFIAPI\r
1759BcIpFilter (\r
1760 IN EFI_PXE_BASE_CODE_PROTOCOL *This,\r
1761 IN EFI_PXE_BASE_CODE_IP_FILTER *Filter\r
1762 )\r
1763{\r
1764 EFI_STATUS StatCode;\r
1765 PXE_BASECODE_DEVICE *Private;\r
1766 UINTN Index;\r
1767 //\r
1768 // Lock the instance data and make sure started\r
1769 //\r
1770 StatCode = EFI_SUCCESS;\r
1771\r
1772 if (This == NULL) {\r
1773 DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));\r
1774 return EFI_INVALID_PARAMETER;\r
1775 }\r
1776\r
1777 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
1778\r
1779 if (Private == NULL) {\r
1780 DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));\r
1781 return EFI_INVALID_PARAMETER;\r
1782 }\r
1783\r
1784 for (Index = 0; Index < Filter->IpCnt; ++Index) {\r
1785 if ((Filter->IpList[Index].Addr[0]) == BROADCAST_IPv4) {\r
1786 //\r
1787 // The IP is a broadcast address.\r
1788 //\r
1789 return EFI_INVALID_PARAMETER;\r
1790 }\r
1791 }\r
1792\r
1793 EfiAcquireLock (&Private->Lock);\r
1794\r
1795 if (This->Mode == NULL || !This->Mode->Started) {\r
1796 DEBUG ((DEBUG_ERROR, "BC was not started."));\r
1797 EfiReleaseLock (&Private->Lock);\r
1798 return EFI_NOT_STARTED;\r
1799 }\r
1800\r
1801 if (Filter == NULL) {\r
1802 return EFI_INVALID_PARAMETER;\r
1803 }\r
1804 //\r
1805 // Issue BC command\r
1806 //\r
1807 StatCode = IpFilter (Private, Filter);\r
1808\r
1809 //\r
1810 // Unlock the instance data\r
1811 //\r
1812 EfiReleaseLock (&Private->Lock);\r
1813 return StatCode;\r
1814}\r
1815\r
1816\r
1817/**\r
1818 Set the Base Code behavior parameters\r
1819\r
1820 @param This Pointer to Pxe BaseCode Protocol\r
1821 @param AutoArpPtr Boolean to do ARP stuff\r
1822 @param SendGuidPtr Boolean whether or not to send GUID info\r
1823 @param TimeToLivePtr Value for Total time to live\r
1824 @param TypeOfServicePtr Value for Type of Service\r
1825 @param MakeCallbackPtr Boolean to determine if we make callbacks\r
1826\r
1827 @retval 0 Successfully set the parameters\r
1828 @retval !0 Failed\r
1829\r
1830**/\r
1831EFI_STATUS\r
1832EFIAPI\r
1833BcSetParameters (\r
1834 EFI_PXE_BASE_CODE_PROTOCOL *This,\r
1835 BOOLEAN *AutoArpPtr,\r
1836 BOOLEAN *SendGuidPtr,\r
1837 UINT8 *TimeToLivePtr,\r
1838 UINT8 *TypeOfServicePtr,\r
1839 BOOLEAN *MakeCallbackPtr\r
1840 )\r
1841{\r
1842 EFI_PXE_BASE_CODE_MODE *PxebcMode;\r
1843 EFI_GUID TmpGuid;\r
1844 UINT8 *SerialNumberPtr;\r
1845 EFI_STATUS StatCode;\r
1846 PXE_BASECODE_DEVICE *Private;\r
1847\r
1848 //\r
1849 // Lock the instance data and make sure started\r
1850 //\r
1851 StatCode = EFI_SUCCESS;\r
1852\r
1853 if (This == NULL) {\r
1854 DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));\r
1855 return EFI_INVALID_PARAMETER;\r
1856 }\r
1857\r
1858 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
1859\r
1860 if (Private == NULL) {\r
1861 DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));\r
1862 return EFI_INVALID_PARAMETER;\r
1863 }\r
1864\r
1865 EfiAcquireLock (&Private->Lock);\r
1866\r
1867 if (This->Mode == NULL || !This->Mode->Started) {\r
1868 DEBUG ((DEBUG_ERROR, "BC was not started."));\r
1869 EfiReleaseLock (&Private->Lock);\r
1870 return EFI_NOT_STARTED;\r
1871 }\r
1872\r
1873 DEBUG ((DEBUG_INFO, "\nSetParameters() Entry. "));\r
1874\r
1875 PxebcMode = Private->EfiBc.Mode;\r
1876 StatCode = EFI_SUCCESS;\r
1877\r
1878 if (SendGuidPtr != NULL) {\r
1879 if (*SendGuidPtr) {\r
687a2e5f 1880 if (PxeBcLibGetSmbiosSystemGuidAndSerialNumber (&TmpGuid, (CHAR8 **) &SerialNumberPtr) != EFI_SUCCESS) {\r
772db4bb 1881 return EFI_INVALID_PARAMETER;\r
1882 }\r
1883 }\r
1884 }\r
1885\r
1886 if (MakeCallbackPtr != NULL) {\r
1887 if (*MakeCallbackPtr) {\r
1888 if (!SetMakeCallback (Private)) {\r
1889 return EFI_INVALID_PARAMETER;\r
1890 }\r
1891 }\r
1892\r
1893 PxebcMode->MakeCallbacks = *MakeCallbackPtr;\r
1894 }\r
1895\r
1896 if (AutoArpPtr != NULL) {\r
1897 PxebcMode->AutoArp = *AutoArpPtr;\r
1898 }\r
1899\r
1900 if (SendGuidPtr != NULL) {\r
1901 PxebcMode->SendGUID = *SendGuidPtr;\r
1902 }\r
1903\r
1904 if (TimeToLivePtr != NULL) {\r
1905 PxebcMode->TTL = *TimeToLivePtr;\r
1906 }\r
1907\r
1908 if (TypeOfServicePtr != NULL) {\r
1909 PxebcMode->ToS = *TypeOfServicePtr;\r
1910 }\r
1911 //\r
1912 // Unlock the instance data\r
1913 //\r
1914 DEBUG ((DEBUG_INFO, "\nSetparameters() Exit = %xh ", StatCode));\r
1915\r
1916 EfiReleaseLock (&Private->Lock);\r
1917 return StatCode;\r
1918}\r
1919//\r
1920// //////////////////////////////////////////////////////////\r
1921//\r
1922// BC Set Station IP Routine\r
1923//\r
1924\r
1925/**\r
1926 Set the station IP address\r
1927\r
1928 @param This Pointer to Pxe BaseCode Protocol\r
1929 @param StationIpPtr Pointer to the requested IP address to set in base\r
1930 code\r
1931 @param SubnetMaskPtr Pointer to the requested subnet mask for the base\r
1932 code\r
1933\r
1934 @retval EFI_SUCCESS Successfully set the parameters\r
1935 @retval EFI_NOT_STARTED BC has not started\r
1936\r
1937**/\r
1938EFI_STATUS\r
1939EFIAPI\r
1940BcSetStationIP (\r
1941 IN EFI_PXE_BASE_CODE_PROTOCOL *This,\r
1942 IN EFI_IP_ADDRESS *StationIpPtr,\r
1943 IN EFI_IP_ADDRESS *SubnetMaskPtr\r
1944 )\r
1945{\r
1946 EFI_PXE_BASE_CODE_MODE *PxebcMode;\r
1947 EFI_STATUS StatCode;\r
1948 PXE_BASECODE_DEVICE *Private;\r
1949 UINT32 SubnetMask;\r
1950\r
1951 //\r
1952 // Lock the instance data and make sure started\r
1953 //\r
1954 StatCode = EFI_SUCCESS;\r
1955\r
1956 if (This == NULL) {\r
1957 DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));\r
1958 return EFI_INVALID_PARAMETER;\r
1959 }\r
1960\r
1961 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
1962\r
1963 if (Private == NULL) {\r
1964 DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));\r
1965 return EFI_INVALID_PARAMETER;\r
1966 }\r
1967\r
1968 EfiAcquireLock (&Private->Lock);\r
1969\r
1970 if (This->Mode == NULL || !This->Mode->Started) {\r
1971 DEBUG ((DEBUG_ERROR, "BC was not started."));\r
1972 StatCode = EFI_NOT_STARTED;\r
1973 goto RELEASE_LOCK;\r
1974 }\r
1975\r
1976 PxebcMode = Private->EfiBc.Mode;\r
1977\r
1978 if (!Private->GoodStationIp && ((StationIpPtr == NULL) || (SubnetMaskPtr == NULL))) {\r
1979 //\r
1980 // It's not allowed to only set one of the two addresses while there isn't a previous\r
1981 // GOOD address configuration.\r
1982 //\r
1983 StatCode = EFI_INVALID_PARAMETER;\r
1984 goto RELEASE_LOCK;\r
1985 }\r
1986\r
1987 if (SubnetMaskPtr != NULL) {\r
1988 SubnetMask = SubnetMaskPtr->Addr[0];\r
1989\r
1990 if (SubnetMask & (SubnetMask + 1)) {\r
1991 //\r
1992 // the subnet mask is valid if it's with leading continuous 1 bits.\r
1993 //\r
1994 StatCode = EFI_INVALID_PARAMETER;\r
1995 goto RELEASE_LOCK;\r
1996 }\r
1997 } else {\r
1998 SubnetMaskPtr = &PxebcMode->SubnetMask;\r
1999 SubnetMask = SubnetMaskPtr->Addr[0];\r
2000 }\r
2001\r
2002 if (StationIpPtr == NULL) {\r
2003 StationIpPtr = &PxebcMode->StationIp;\r
2004 }\r
2005\r
2006 if (!IS_INADDR_UNICAST (StationIpPtr) ||\r
2007 ((StationIpPtr->Addr[0] | SubnetMask) == BROADCAST_IPv4)) {\r
2008 //\r
2009 // The station IP is not a unicast address.\r
2010 //\r
2011 StatCode = EFI_INVALID_PARAMETER;\r
2012 goto RELEASE_LOCK;\r
2013 }\r
2014\r
2015 PxebcMode->StationIp = *StationIpPtr;\r
2016 PxebcMode->SubnetMask = *SubnetMaskPtr;\r
2017 Private->GoodStationIp = TRUE;\r
2018\r
2019RELEASE_LOCK:\r
2020 //\r
2021 // Unlock the instance data\r
2022 //\r
2023 EfiReleaseLock (&Private->Lock);\r
2024\r
2025 return StatCode;\r
2026}\r
2027\r
2028EFI_DRIVER_BINDING_PROTOCOL mPxeBcDriverBinding = {\r
2029 PxeBcDriverSupported,\r
2030 PxeBcDriverStart,\r
2031 PxeBcDriverStop,\r
2032 0xa,\r
2033 NULL,\r
2034 NULL\r
2035};\r
2036\r
2037\r
2038/**\r
2039 Test to see if this driver supports Controller. Any Controller\r
2040 than contains a Snp protocol can be supported.\r
2041\r
2042 @param This Protocol instance pointer.\r
2043 @param Controller Handle of device to test.\r
2044 @param RemainingDevicePath Not used.\r
2045\r
2046 @retval EFI_SUCCESS This driver supports this device.\r
2047 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
2048 @retval other This driver does not support this device.\r
2049\r
2050**/\r
2051EFI_STATUS\r
2052EFIAPI\r
2053PxeBcDriverSupported (\r
2054 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
2055 IN EFI_HANDLE Controller,\r
2056 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
2057 )\r
2058{\r
2059 EFI_STATUS Status;\r
2060 EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;\r
2061\r
2062 Status = gBS->OpenProtocol (\r
2063 Controller,\r
2064 &gEfiDevicePathProtocolGuid,\r
2065 NULL,\r
2066 This->DriverBindingHandle,\r
2067 Controller,\r
2068 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
2069 );\r
2070\r
2071 if (EFI_ERROR (Status)) {\r
2072 return Status;\r
2073 }\r
2074\r
2075 Status = gBS->OpenProtocol (\r
2076 Controller,\r
2077 &gEfiSimpleNetworkProtocolGuid,\r
2078 (VOID **) &SnpPtr,\r
2079 This->DriverBindingHandle,\r
2080 Controller,\r
2081 EFI_OPEN_PROTOCOL_BY_DRIVER\r
2082 );\r
2083 if (EFI_ERROR (Status)) {\r
2084 return Status;\r
2085 }\r
2086\r
2087 gBS->CloseProtocol (\r
2088 Controller,\r
2089 &gEfiSimpleNetworkProtocolGuid,\r
2090 This->DriverBindingHandle,\r
2091 Controller\r
2092 );\r
2093\r
2094 return Status;\r
2095}\r
2096\r
2097\r
2098/**\r
2099 Start the Base code driver.\r
2100\r
2101 @param This Protocol instance pointer.\r
2102 @param Controller Handle of device to test.\r
2103 @param RemainingDevicePath Not used.\r
2104\r
2105 @retval EFI_SUCCESS This driver supports this device.\r
2106 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
2107 @retval other This driver does not support this device.\r
2108\r
2109**/\r
2110EFI_STATUS\r
2111EFIAPI\r
2112PxeBcDriverStart (\r
2113 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
2114 IN EFI_HANDLE Controller,\r
2115 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
2116 )\r
2117{\r
2118 EFI_STATUS Status;\r
2119 PXE_BASECODE_DEVICE *Private;\r
2120 LOADFILE_DEVICE *pLF;\r
2121\r
2122 //\r
2123 // Allocate structures needed by BaseCode and LoadFile protocols.\r
2124 //\r
2125 Private = AllocateZeroPool (sizeof (PXE_BASECODE_DEVICE));\r
2126\r
2127 if (Private == NULL ) {\r
2128 DEBUG ((EFI_D_NET, "\nBcNotifySnp() Could not alloc PXE_BASECODE_DEVICE structure.\n"));\r
2129 return EFI_OUT_OF_RESOURCES;\r
2130 }\r
2131\r
2132 pLF = AllocateZeroPool (sizeof (LOADFILE_DEVICE));\r
2133 if (pLF == NULL) {\r
2134 DEBUG ((EFI_D_NET, "\nBcNotifySnp() Could not alloc LOADFILE_DEVICE structure.\n"));\r
2135 FreePool (Private);\r
2136 return EFI_OUT_OF_RESOURCES;\r
2137 }\r
2138\r
2139 Private->EfiBc.Mode = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_MODE));\r
2140 if (Private->EfiBc.Mode == NULL) {\r
2141 DEBUG ((EFI_D_NET, "\nBcNotifySnp() Could not alloc Mode structure.\n"));\r
2142 FreePool (Private);\r
2143 FreePool (pLF);\r
2144 return EFI_OUT_OF_RESOURCES;\r
2145 }\r
2146 //\r
2147 // Lock access, just in case\r
2148 //\r
2149 EfiInitializeLock (&Private->Lock, TPL_CALLBACK);\r
2150 EfiAcquireLock (&Private->Lock);\r
2151\r
2152 EfiInitializeLock (&pLF->Lock, TPL_CALLBACK);\r
2153 EfiAcquireLock (&pLF->Lock);\r
2154\r
2155 //\r
2156 // Initialize PXE structure\r
2157 //\r
2158 //\r
2159 // First initialize the internal 'private' data that the application\r
2160 // does not see.\r
2161 //\r
2162 Private->Signature = PXE_BASECODE_DEVICE_SIGNATURE;\r
2163 Private->Handle = Controller;\r
2164\r
2165 //\r
2166 // Get the NII interface\r
2167 //\r
2168 Status = gBS->OpenProtocol (\r
2169 Controller,\r
2170 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
2171 (VOID **) &Private->NiiPtr,\r
2172 This->DriverBindingHandle,\r
2173 Controller,\r
2174 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2175 );\r
2176\r
2177 if (EFI_ERROR (Status)) {\r
2178 Status = gBS->OpenProtocol (\r
2179 Controller,\r
2180 &gEfiNetworkInterfaceIdentifierProtocolGuid,\r
2181 (VOID **) &Private->NiiPtr,\r
2182 This->DriverBindingHandle,\r
2183 Controller,\r
2184 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2185 );\r
2186\r
2187 if (EFI_ERROR (Status)) {\r
2188 goto PxeBcError;\r
2189 }\r
2190 }\r
2191 //\r
2192 // Get the Snp interface\r
2193 //\r
2194 Status = gBS->OpenProtocol (\r
2195 Controller,\r
2196 &gEfiSimpleNetworkProtocolGuid,\r
2197 (VOID **) &Private->SimpleNetwork,\r
2198 This->DriverBindingHandle,\r
2199 Controller,\r
2200 EFI_OPEN_PROTOCOL_BY_DRIVER\r
2201 );\r
2202\r
2203 if (EFI_ERROR (Status)) {\r
2204 goto PxeBcError;\r
2205 }\r
2206\r
2207 //\r
2208 // Next, initialize the external 'public' data that\r
2209 // the application does see.\r
2210 //\r
2211 Private->EfiBc.Revision = EFI_PXE_BASE_CODE_PROTOCOL_REVISION;\r
2212 Private->EfiBc.Start = BcStart;\r
2213 Private->EfiBc.Stop = BcStop;\r
2214 Private->EfiBc.Dhcp = BcDhcp;\r
2215 Private->EfiBc.Discover = BcDiscover;\r
2216 Private->EfiBc.Mtftp = BcMtftp;\r
2217 Private->EfiBc.UdpWrite = BcUdpWrite;\r
2218 Private->EfiBc.UdpRead = BcUdpRead;\r
2219 Private->EfiBc.Arp = BcArp;\r
2220 Private->EfiBc.SetIpFilter = BcIpFilter;\r
2221 Private->EfiBc.SetParameters = BcSetParameters;\r
2222 Private->EfiBc.SetStationIp = BcSetStationIP;\r
2223 Private->EfiBc.SetPackets = BcSetPackets;\r
2224\r
2225 //\r
2226 // Initialize BaseCode Mode structure\r
2227 //\r
2228 Private->EfiBc.Mode->Started = FALSE;\r
2229 Private->EfiBc.Mode->TTL = DEFAULT_TTL;\r
2230 Private->EfiBc.Mode->ToS = DEFAULT_ToS;\r
2231 Private->EfiBc.Mode->UsingIpv6 = FALSE;\r
2232 Private->EfiBc.Mode->AutoArp = TRUE;\r
2233\r
2234 //\r
2235 // Set to PXE_TRUE by the BC constructor if this BC\r
2236 // implementation supports IPv6.\r
2237 //\r
2238 Private->EfiBc.Mode->Ipv6Supported = SUPPORT_IPV6;\r
2239\r
2240#if SUPPORT_IPV6\r
2241 Private->EfiBc.Mode->Ipv6Available = Private->NiiPtr->Ipv6Supported;\r
2242#else\r
2243 Private->EfiBc.Mode->Ipv6Available = FALSE;\r
2244#endif\r
2245 //\r
2246 // Set to TRUE by the BC constructor if this BC\r
2247 // implementation supports BIS.\r
2248 //\r
2249 Private->EfiBc.Mode->BisSupported = TRUE;\r
2250 Private->EfiBc.Mode->BisDetected = PxebcBisDetect (Private);\r
2251\r
2252 //\r
2253 // Initialize LoadFile structure.\r
2254 //\r
2255 pLF->Signature = LOADFILE_DEVICE_SIGNATURE;\r
2256 pLF->LoadFile.LoadFile = LoadFile;\r
2257 pLF->Private = Private;\r
2258\r
2259 //\r
2260 // Install protocol interfaces.\r
2261 //\r
2262 Status = gBS->InstallMultipleProtocolInterfaces (\r
2263 &Controller,\r
2264 &gEfiPxeBaseCodeProtocolGuid,\r
2265 &Private->EfiBc,\r
2266 &gEfiLoadFileProtocolGuid,\r
2267 &pLF->LoadFile,\r
2268 NULL\r
2269 );\r
2270\r
2271 if (EFI_ERROR (Status)) {\r
2272 gBS->CloseProtocol (\r
2273 Controller,\r
2274 &gEfiSimpleNetworkProtocolGuid,\r
2275 This->DriverBindingHandle,\r
2276 Controller\r
2277 );\r
2278\r
2279 goto PxeBcError;\r
2280 }\r
2281 //\r
2282 // Release locks.\r
2283 //\r
2284 EfiReleaseLock (&pLF->Lock);\r
2285 EfiReleaseLock (&Private->Lock);\r
2286 return Status;\r
2287\r
2288PxeBcError: ;\r
2289 gBS->FreePool (Private->EfiBc.Mode);\r
2290 gBS->FreePool (Private);\r
2291 gBS->FreePool (pLF);\r
2292 return Status;\r
2293}\r
2294\r
2295\r
2296/**\r
2297 Stop the Base code driver.\r
2298\r
2299 @param This Protocol instance pointer.\r
2300 @param Controller Handle of device to test.\r
2301 @param NumberOfChildren Not used\r
2302 @param ChildHandleBuffer Not used\r
2303\r
2304 @retval EFI_SUCCESS This driver supports this device.\r
2305 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
2306 @retval other This driver does not support this device.\r
2307\r
2308**/\r
2309EFI_STATUS\r
2310EFIAPI\r
2311PxeBcDriverStop (\r
2312 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
2313 IN EFI_HANDLE Controller,\r
2314 IN UINTN NumberOfChildren,\r
2315 IN EFI_HANDLE *ChildHandleBuffer\r
2316 )\r
2317{\r
2318 EFI_STATUS Status;\r
2319 EFI_LOAD_FILE_PROTOCOL *LfProtocol;\r
2320 LOADFILE_DEVICE *LoadDevice;\r
2321\r
2322 //\r
2323 // Get our context back.\r
2324 //\r
2325 Status = gBS->OpenProtocol (\r
2326 Controller,\r
2327 &gEfiLoadFileProtocolGuid,\r
2328 (VOID **) &LfProtocol,\r
2329 This->DriverBindingHandle,\r
2330 Controller,\r
2331 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2332 );\r
2333\r
2334 if (EFI_ERROR (Status)) {\r
2335 return EFI_UNSUPPORTED;\r
2336 }\r
2337\r
2338 LoadDevice = EFI_LOAD_FILE_DEV_FROM_THIS (LfProtocol);\r
2339\r
2340 Status = gBS->UninstallMultipleProtocolInterfaces (\r
2341 Controller,\r
2342 &gEfiLoadFileProtocolGuid,\r
2343 &LoadDevice->LoadFile,\r
2344 &gEfiPxeBaseCodeProtocolGuid,\r
2345 &LoadDevice->Private->EfiBc,\r
2346 NULL\r
2347 );\r
2348\r
2349 if (!EFI_ERROR (Status)) {\r
2350\r
2351 Status = gBS->CloseProtocol (\r
2352 Controller,\r
2353 &gEfiSimpleNetworkProtocolGuid,\r
2354 This->DriverBindingHandle,\r
2355 Controller\r
2356 );\r
2357\r
2358 gBS->FreePool (LoadDevice->Private->EfiBc.Mode);\r
2359 gBS->FreePool (LoadDevice->Private);\r
2360 gBS->FreePool (LoadDevice);\r
2361 }\r
2362\r
2363 return Status;\r
2364}\r
2365\r
2366\r
2367/**\r
2368 Initialize the base code drivers and install the driver binding\r
2369\r
2370 Standard EFI Image Entry\r
2371\r
2372 @retval EFI_SUCCESS This driver was successfully bound\r
2373\r
2374**/\r
2375EFI_STATUS\r
2376EFIAPI\r
2377InitializeBCDriver (\r
2378 IN EFI_HANDLE ImageHandle,\r
2379 IN EFI_SYSTEM_TABLE *SystemTable\r
2380 )\r
2381{\r
2382 EFI_STATUS Status;\r
2383\r
2384 //\r
2385 // Initialize EFI library\r
2386 //\r
2387 Status = EfiLibInstallAllDriverProtocols (\r
2388 ImageHandle,\r
2389 SystemTable,\r
2390 &mPxeBcDriverBinding,\r
2391 NULL,\r
2392 COMPONENT_NAME,\r
2393 NULL,\r
2394 NULL\r
2395 );\r
2396\r
2397 InitArpHeader ();\r
2398 OptionsStrucInit ();\r
2399\r
687a2e5f 2400 return Status;\r
772db4bb 2401}\r
2402\r
2403/* eof - bc.c */\r