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