]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Universal/Network/PxeBc/Dxe/bc.c
Add some definitions for efi event in Uefi/UefiSpec.h to follow spec.
[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
93b0fbc8 420 EVT_TIMER,\r
421 TPL_CALLBACK,\r
878ddf1f 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
93b0fbc8 625 EVT_TIMER,\r
626 TPL_CALLBACK,\r
878ddf1f 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
93b0fbc8 698 EVT_TIMER,\r
699 TPL_CALLBACK,\r
878ddf1f 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
56056c7c 1953 EFI_STATUS StatCode;\r
878ddf1f 1954 PXE_BASECODE_DEVICE *Private;\r
56056c7c 1955 UINT32 SubnetMask;\r
878ddf1f 1956\r
1957 //\r
1958 // Lock the instance data and make sure started\r
1959 //\r
56056c7c 1960 StatCode = EFI_SUCCESS;\r
878ddf1f 1961\r
1962 if (This == NULL) {\r
1963 DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL"));\r
1964 return EFI_INVALID_PARAMETER;\r
1965 }\r
1966\r
1967 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
1968\r
1969 if (Private == NULL) {\r
1970 DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));\r
1971 return EFI_INVALID_PARAMETER;\r
1972 }\r
1973\r
1974 EfiAcquireLock (&Private->Lock);\r
1975\r
1976 if (This->Mode == NULL || !This->Mode->Started) {\r
1977 DEBUG ((EFI_D_ERROR, "BC was not started."));\r
56056c7c 1978 StatCode = EFI_NOT_STARTED;\r
1979 goto RELEASE_LOCK;\r
878ddf1f 1980 }\r
1981\r
1982 PxebcMode = Private->EfiBc.Mode;\r
1983\r
56056c7c 1984 if (!Private->GoodStationIp && ((StationIpPtr == NULL) || (SubnetMaskPtr == NULL))) {\r
1985 //\r
1986 // It's not allowed to only set one of the two addresses while there isn't a previous\r
1987 // GOOD address configuration.\r
1988 //\r
1989 StatCode = EFI_INVALID_PARAMETER;\r
1990 goto RELEASE_LOCK;\r
878ddf1f 1991 }\r
1992\r
1993 if (SubnetMaskPtr != NULL) {\r
56056c7c 1994 SubnetMask = SubnetMaskPtr->Addr[0];\r
1995\r
1996 if (SubnetMask & (SubnetMask + 1)) {\r
1997 //\r
1998 // the subnet mask is valid if it's with leading continuous 1 bits.\r
1999 //\r
2000 StatCode = EFI_INVALID_PARAMETER;\r
2001 goto RELEASE_LOCK;\r
2002 }\r
2003 } else {\r
2004 SubnetMaskPtr = &PxebcMode->SubnetMask;\r
2005 SubnetMask = SubnetMaskPtr->Addr[0];\r
878ddf1f 2006 }\r
56056c7c 2007\r
2008 if (StationIpPtr == NULL) {\r
2009 StationIpPtr = &PxebcMode->StationIp;\r
2010 }\r
2011\r
93b0fbc8 2012 if (!IS_INADDR_UNICAST (StationIpPtr) ||\r
56056c7c 2013 ((StationIpPtr->Addr[0] | SubnetMask) == BROADCAST_IPv4)) {\r
2014 //\r
2015 // The station IP is not a unicast address.\r
2016 //\r
2017 StatCode = EFI_INVALID_PARAMETER;\r
2018 goto RELEASE_LOCK;\r
2019 }\r
2020\r
2021 CopyMem (&PxebcMode->StationIp, StationIpPtr, sizeof (EFI_IP_ADDRESS));\r
2022 CopyMem (&PxebcMode->SubnetMask, SubnetMaskPtr, sizeof (EFI_IP_ADDRESS));\r
2023\r
2024 Private->GoodStationIp = TRUE;\r
2025\r
2026RELEASE_LOCK:\r
878ddf1f 2027 //\r
2028 // Unlock the instance data\r
2029 //\r
2030 EfiReleaseLock (&Private->Lock);\r
2031\r
56056c7c 2032 return StatCode;\r
878ddf1f 2033}\r
2034\r
2035EFI_DRIVER_BINDING_PROTOCOL gPxeBcDriverBinding = {\r
2036 PxeBcDriverSupported,\r
2037 PxeBcDriverStart,\r
2038 PxeBcDriverStop,\r
61fb1657 2039 0xa,\r
878ddf1f 2040 NULL,\r
2041 NULL\r
2042};\r
2043\r
2044EFI_STATUS\r
2045EFIAPI\r
2046PxeBcDriverSupported (\r
2047 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
2048 IN EFI_HANDLE Controller,\r
2049 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
2050 )\r
2051/*++\r
2052\r
2053 Routine Description:\r
2054 Test to see if this driver supports Controller. Any Controller\r
2055 than contains a Snp protocol can be supported.\r
2056\r
2057 Arguments:\r
2058 This - Protocol instance pointer.\r
2059 Controller - Handle of device to test.\r
2060 RemainingDevicePath - Not used.\r
2061\r
2062 Returns:\r
2063 EFI_SUCCESS - This driver supports this device.\r
2064 EFI_ALREADY_STARTED - This driver is already running on this device.\r
2065 other - This driver does not support this device.\r
2066\r
2067--*/\r
2068{\r
2069 EFI_STATUS Status;\r
2070 EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr;\r
2071\r
2072 Status = gBS->OpenProtocol (\r
2073 Controller,\r
2074 &gEfiDevicePathProtocolGuid,\r
2075 NULL,\r
2076 This->DriverBindingHandle,\r
2077 Controller,\r
2078 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
2079 );\r
2080\r
2081 if (EFI_ERROR (Status)) {\r
2082 return Status;\r
2083 }\r
2084\r
2085 Status = gBS->OpenProtocol (\r
2086 Controller,\r
2087 &gEfiSimpleNetworkProtocolGuid,\r
2088 (VOID **) &SnpPtr,\r
2089 This->DriverBindingHandle,\r
2090 Controller,\r
2091 EFI_OPEN_PROTOCOL_BY_DRIVER\r
2092 );\r
2093 if (EFI_ERROR (Status)) {\r
2094 return Status;\r
2095 }\r
2096\r
2097 gBS->CloseProtocol (\r
2098 Controller,\r
2099 &gEfiSimpleNetworkProtocolGuid,\r
2100 This->DriverBindingHandle,\r
2101 Controller\r
2102 );\r
2103\r
2104 return Status;\r
2105}\r
2106\r
2107EFI_STATUS\r
2108EFIAPI\r
2109PxeBcDriverStart (\r
2110 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
2111 IN EFI_HANDLE Controller,\r
2112 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
2113 )\r
2114/*++\r
2115\r
2116 Routine Description:\r
2117 Start the Base code driver.\r
2118\r
2119 Arguments:\r
2120 This - Protocol instance pointer.\r
2121 Controller - Handle of device to test.\r
2122 RemainingDevicePath - Not used.\r
2123\r
2124 Returns:\r
2125 EFI_SUCCESS - This driver supports this device.\r
2126 EFI_ALREADY_STARTED - This driver is already running on this device.\r
2127 other - This driver does not support this device.\r
2128\r
2129--*/\r
2130{\r
2131 EFI_STATUS Status;\r
2132 PXE_BASECODE_DEVICE *Private;\r
2133 LOADFILE_DEVICE *pLF;\r
2134\r
2135 //\r
2136 // Allocate structures needed by BaseCode and LoadFile protocols.\r
2137 //\r
26aa0c2f 2138 Private = AllocateZeroPool (sizeof (PXE_BASECODE_DEVICE));\r
878ddf1f 2139\r
26aa0c2f 2140 if (Private == NULL ) {\r
878ddf1f 2141 DEBUG ((EFI_D_NET, "\nBcNotifySnp() Could not alloc PXE_BASECODE_DEVICE structure.\n"));\r
26aa0c2f 2142 return EFI_OUT_OF_RESOURCES;\r
878ddf1f 2143 }\r
2144\r
26aa0c2f
LG
2145 pLF = AllocateZeroPool (sizeof (LOADFILE_DEVICE));\r
2146 if (pLF == NULL) {\r
878ddf1f 2147 DEBUG ((EFI_D_NET, "\nBcNotifySnp() Could not alloc LOADFILE_DEVICE structure.\n"));\r
26aa0c2f
LG
2148 FreePool (Private);\r
2149 return EFI_OUT_OF_RESOURCES;\r
878ddf1f 2150 }\r
2151\r
26aa0c2f
LG
2152 Private->EfiBc.Mode = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_MODE));\r
2153 if (Private->EfiBc.Mode == NULL) {\r
878ddf1f 2154 DEBUG ((EFI_D_NET, "\nBcNotifySnp() Could not alloc Mode structure.\n"));\r
26aa0c2f
LG
2155 FreePool (Private);\r
2156 FreePool (pLF);\r
2157 return EFI_OUT_OF_RESOURCES;\r
878ddf1f 2158 }\r
2159 //\r
2160 // Lock access, just in case\r
2161 //\r
93b0fbc8 2162 EfiInitializeLock (&Private->Lock, TPL_CALLBACK);\r
878ddf1f 2163 EfiAcquireLock (&Private->Lock);\r
2164\r
93b0fbc8 2165 EfiInitializeLock (&pLF->Lock, TPL_CALLBACK);\r
878ddf1f 2166 EfiAcquireLock (&pLF->Lock);\r
2167\r
2168 //\r
2169 // Initialize PXE structure\r
2170 //\r
2171 //\r
2172 // First initialize the internal 'private' data that the application\r
2173 // does not see.\r
2174 //\r
2175 Private->Signature = PXE_BASECODE_DEVICE_SIGNATURE;\r
2176 Private->Handle = Controller;\r
2177\r
2178 //\r
2179 // Get the NII interface\r
2180 //\r
2181 Status = gBS->OpenProtocol (\r
2182 Controller,\r
2183 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
2184 (VOID **) &Private->NiiPtr,\r
2185 This->DriverBindingHandle,\r
2186 Controller,\r
2187 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2188 );\r
2189\r
2190 if (EFI_ERROR (Status)) {\r
2191 Status = gBS->OpenProtocol (\r
2192 Controller,\r
2193 &gEfiNetworkInterfaceIdentifierProtocolGuid,\r
2194 (VOID **) &Private->NiiPtr,\r
2195 This->DriverBindingHandle,\r
2196 Controller,\r
2197 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2198 );\r
2199\r
2200 if (EFI_ERROR (Status)) {\r
2201 goto PxeBcError;\r
2202 }\r
2203 }\r
2204 //\r
2205 // Get the Snp interface\r
2206 //\r
2207 Status = gBS->OpenProtocol (\r
2208 Controller,\r
2209 &gEfiSimpleNetworkProtocolGuid,\r
2210 (VOID **) &Private->SimpleNetwork,\r
2211 This->DriverBindingHandle,\r
2212 Controller,\r
2213 EFI_OPEN_PROTOCOL_BY_DRIVER\r
2214 );\r
2215\r
2216 if (EFI_ERROR (Status)) {\r
2217 goto PxeBcError;\r
2218 }\r
2219\r
2220 //\r
2221 // Next, initialize the external 'public' data that\r
2222 // the application does see.\r
2223 //\r
2224 Private->EfiBc.Revision = EFI_PXE_BASE_CODE_INTERFACE_REVISION;\r
2225 Private->EfiBc.Start = BcStart;\r
2226 Private->EfiBc.Stop = BcStop;\r
2227 Private->EfiBc.Dhcp = BcDhcp;\r
2228 Private->EfiBc.Discover = BcDiscover;\r
2229 Private->EfiBc.Mtftp = BcMtftp;\r
2230 Private->EfiBc.UdpWrite = BcUdpWrite;\r
2231 Private->EfiBc.UdpRead = BcUdpRead;\r
2232 Private->EfiBc.Arp = BcArp;\r
2233 Private->EfiBc.SetIpFilter = BcIpFilter;\r
2234 Private->EfiBc.SetParameters = BcSetParameters;\r
2235 Private->EfiBc.SetStationIp = BcSetStationIP;\r
2236 Private->EfiBc.SetPackets = BcSetPackets;\r
2237\r
2238 //\r
2239 // Initialize BaseCode Mode structure\r
2240 //\r
2241 Private->EfiBc.Mode->Started = FALSE;\r
2242 Private->EfiBc.Mode->TTL = DEFAULT_TTL;\r
2243 Private->EfiBc.Mode->ToS = DEFAULT_ToS;\r
2244 Private->EfiBc.Mode->UsingIpv6 = FALSE;\r
2245 Private->EfiBc.Mode->AutoArp = TRUE;\r
2246\r
2247 //\r
2248 // Set to PXE_TRUE by the BC constructor if this BC\r
2249 // implementation supports IPv6.\r
2250 //\r
2251 Private->EfiBc.Mode->Ipv6Supported = SUPPORT_IPV6;\r
878ddf1f 2252 Private->EfiBc.Mode->Ipv6Available = FALSE;\r
e5f461a8 2253\r
878ddf1f 2254 //\r
2255 // Set to TRUE by the BC constructor if this BC\r
2256 // implementation supports BIS.\r
2257 //\r
2258 Private->EfiBc.Mode->BisSupported = TRUE;\r
2259 Private->EfiBc.Mode->BisDetected = PxebcBisDetect (Private);\r
2260\r
2261 //\r
2262 // Initialize LoadFile structure.\r
2263 //\r
2264 pLF->Signature = LOADFILE_DEVICE_SIGNATURE;\r
2265 pLF->LoadFile.LoadFile = LoadFile;\r
2266 pLF->Private = Private;\r
2267\r
2268 //\r
2269 // Install protocol interfaces.\r
2270 //\r
2271 Status = gBS->InstallMultipleProtocolInterfaces (\r
2272 &Controller,\r
2273 &gEfiPxeBaseCodeProtocolGuid,\r
2274 &Private->EfiBc,\r
2275 &gEfiLoadFileProtocolGuid,\r
2276 &pLF->LoadFile,\r
2277 NULL\r
2278 );\r
2279\r
2280 if (EFI_ERROR (Status)) {\r
2281 gBS->CloseProtocol (\r
2282 Controller,\r
2283 &gEfiSimpleNetworkProtocolGuid,\r
2284 This->DriverBindingHandle,\r
2285 Controller\r
2286 );\r
2287\r
2288 goto PxeBcError;\r
2289 }\r
2290 //\r
2291 // Release locks.\r
2292 //\r
2293 EfiReleaseLock (&pLF->Lock);\r
2294 EfiReleaseLock (&Private->Lock);\r
2295 return Status;\r
2296\r
2297PxeBcError: ;\r
26aa0c2f
LG
2298 FreePool (Private->EfiBc.Mode);\r
2299 FreePool (Private);\r
2300 FreePool (pLF);\r
878ddf1f 2301 return Status;\r
2302}\r
2303\r
2304EFI_STATUS\r
2305EFIAPI\r
2306PxeBcDriverStop (\r
2307 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
2308 IN EFI_HANDLE Controller,\r
2309 IN UINTN NumberOfChildren,\r
2310 IN EFI_HANDLE *ChildHandleBuffer\r
2311 )\r
2312/*++\r
2313\r
2314 Routine Description:\r
2315 Stop the Base code driver.\r
2316\r
2317 Arguments:\r
2318 This - Protocol instance pointer.\r
2319 Controller - Handle of device to test.\r
2320 NumberOfChildren - Not used\r
2321 ChildHandleBuffer - Not used\r
2322\r
2323 Returns:\r
2324 EFI_SUCCESS - This driver supports this device.\r
2325 EFI_ALREADY_STARTED - This driver is already running on this device.\r
2326 other - This driver does not support this device.\r
2327\r
2328--*/\r
2329{\r
2330 EFI_STATUS Status;\r
2331 EFI_LOAD_FILE_PROTOCOL *LfProtocol;\r
2332 LOADFILE_DEVICE *LoadDevice;\r
2333\r
2334 //\r
2335 // Get our context back.\r
2336 //\r
2337 Status = gBS->OpenProtocol (\r
2338 Controller,\r
2339 &gEfiLoadFileProtocolGuid,\r
2340 (VOID **) &LfProtocol,\r
2341 This->DriverBindingHandle,\r
2342 Controller,\r
2343 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2344 );\r
2345\r
2346 if (EFI_ERROR (Status)) {\r
2347 return EFI_UNSUPPORTED;\r
2348 }\r
2349\r
2350 LoadDevice = EFI_LOAD_FILE_DEV_FROM_THIS (LfProtocol);\r
2351\r
2352 Status = gBS->UninstallMultipleProtocolInterfaces (\r
2353 Controller,\r
2354 &gEfiLoadFileProtocolGuid,\r
2355 &LoadDevice->LoadFile,\r
2356 &gEfiPxeBaseCodeProtocolGuid,\r
2357 &LoadDevice->Private->EfiBc,\r
2358 NULL\r
2359 );\r
2360\r
2361 if (!EFI_ERROR (Status)) {\r
2362\r
2363 Status = gBS->CloseProtocol (\r
2364 Controller,\r
2365 &gEfiSimpleNetworkProtocolGuid,\r
2366 This->DriverBindingHandle,\r
2367 Controller\r
2368 );\r
2369\r
26aa0c2f
LG
2370 FreePool (LoadDevice->Private->EfiBc.Mode);\r
2371 FreePool (LoadDevice->Private);\r
2372 FreePool (LoadDevice);\r
878ddf1f 2373 }\r
2374\r
2375 return Status;\r
2376}\r
2377\r
2378EFI_STATUS\r
2379EFIAPI\r
2380InitializeBCDriver (\r
2381 IN EFI_HANDLE ImageHandle,\r
2382 IN EFI_SYSTEM_TABLE *SystemTable\r
2383 )\r
2384/*++\r
2385\r
2386 Routine Description:\r
2387 Initialize the base code drivers and install the driver binding\r
2388\r
2389 Arguments:\r
2390 Standard EFI Image Entry\r
2391\r
2392 Returns:\r
2393 EFI_SUCCESS - This driver was successfully bound\r
2394\r
2395--*/\r
2396{\r
2397 InitArpHeader ();\r
2398 OptionsStrucInit ();\r
2399\r
2400 return EFI_SUCCESS;\r
2401}\r
2402\r
2403/* eof - bc.c */\r