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