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