]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/ArpDxe/ArpDriver.c
Use Mde library and definition instead of some native definitions in NetLib, to simpl...
[mirror_edk2.git] / MdeModulePkg / Universal / Network / ArpDxe / ArpDriver.c
1 /** @file
2
3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 ArpDriver.c
15
16 Abstract:
17
18
19 **/
20
21
22 #include "ArpDriver.h"
23 #include "ArpImpl.h"
24
25 EFI_DRIVER_BINDING_PROTOCOL gArpDriverBinding = {
26 ArpDriverBindingSupported,
27 ArpDriverBindingStart,
28 ArpDriverBindingStop,
29 0xa,
30 NULL,
31 NULL
32 };
33
34
35 /**
36 Create and initialize the arp service context data.
37
38 @param ImageHandle The image handle representing the loaded driver
39 image.
40 @param ControllerHandle The controller handle the driver binds to.
41 @param ArpService Pointer to the buffer containing the arp service
42 context data.
43
44 @retval EFI_SUCCESS The arp service context is initialized.
45 @retval other Failed to initialize the arp service context.
46
47 **/
48 STATIC
49 EFI_STATUS
50 ArpCreateService (
51 IN EFI_HANDLE ImageHandle,
52 IN EFI_HANDLE ControllerHandle,
53 IN ARP_SERVICE_DATA *ArpService
54 )
55 {
56 EFI_STATUS Status;
57
58 ASSERT (ArpService != NULL);
59
60 ArpService->Signature = ARP_SERVICE_DATA_SIGNATURE;
61
62 //
63 // Init the servicebinding protocol members.
64 //
65 ArpService->ServiceBinding.CreateChild = ArpServiceBindingCreateChild;
66 ArpService->ServiceBinding.DestroyChild = ArpServiceBindingDestroyChild;
67
68 //
69 // Save the handles.
70 //
71 ArpService->ImageHandle = ImageHandle;
72 ArpService->ControllerHandle = ControllerHandle;
73
74 //
75 // Create a MNP child instance.
76 //
77 Status = NetLibCreateServiceChild (
78 ControllerHandle,
79 ImageHandle,
80 &gEfiManagedNetworkServiceBindingProtocolGuid,
81 &ArpService->MnpChildHandle
82 );
83 if (EFI_ERROR (Status)) {
84 return Status;
85 }
86
87 //
88 // Open the MNP protocol.
89 //
90 Status = gBS->OpenProtocol (
91 ArpService->MnpChildHandle,
92 &gEfiManagedNetworkProtocolGuid,
93 (VOID **)&ArpService->Mnp,
94 ImageHandle,
95 ControllerHandle,
96 EFI_OPEN_PROTOCOL_BY_DRIVER
97 );
98 if (EFI_ERROR (Status)) {
99 goto ERROR_EXIT;
100 }
101
102 //
103 // Get the underlayer Snp mode data.
104 //
105 Status = ArpService->Mnp->GetModeData (ArpService->Mnp, NULL, &ArpService->SnpMode);
106 if ((Status != EFI_NOT_STARTED) && EFI_ERROR (Status)) {
107 goto ERROR_EXIT;
108 }
109
110 if (ArpService->SnpMode.IfType != NET_IFTYPE_ETHERNET) {
111 //
112 // Only support the ethernet.
113 //
114 Status = EFI_UNSUPPORTED;
115 goto ERROR_EXIT;
116 }
117
118 //
119 // Set the Mnp config parameters.
120 //
121 ArpService->MnpConfigData.ReceivedQueueTimeoutValue = 0;
122 ArpService->MnpConfigData.TransmitQueueTimeoutValue = 0;
123 ArpService->MnpConfigData.ProtocolTypeFilter = ARP_ETHER_PROTO_TYPE;
124 ArpService->MnpConfigData.EnableUnicastReceive = TRUE;
125 ArpService->MnpConfigData.EnableMulticastReceive = FALSE;
126 ArpService->MnpConfigData.EnableBroadcastReceive = TRUE;
127 ArpService->MnpConfigData.EnablePromiscuousReceive = FALSE;
128 ArpService->MnpConfigData.FlushQueuesOnReset = TRUE;
129 ArpService->MnpConfigData.EnableReceiveTimestamps = FALSE;
130 ArpService->MnpConfigData.DisableBackgroundPolling = FALSE;
131
132 //
133 // Configure the Mnp child.
134 //
135 Status = ArpService->Mnp->Configure (ArpService->Mnp, &ArpService->MnpConfigData);
136 if (EFI_ERROR (Status)) {
137 goto ERROR_EXIT;
138 }
139
140 //
141 // Create the event used in the RxToken.
142 //
143 Status = gBS->CreateEvent (
144 EVT_NOTIFY_SIGNAL,
145 TPL_NOTIFY,
146 ArpOnFrameRcvd,
147 ArpService,
148 &ArpService->RxToken.Event
149 );
150 if (EFI_ERROR (Status)) {
151 goto ERROR_EXIT;
152 }
153
154 //
155 // Create the Arp heartbeat timer.
156 //
157 Status = gBS->CreateEvent (
158 EVT_NOTIFY_SIGNAL | EVT_TIMER,
159 TPL_CALLBACK,
160 ArpTimerHandler,
161 ArpService,
162 &ArpService->PeriodicTimer
163 );
164 if (EFI_ERROR (Status)) {
165 goto ERROR_EXIT;
166 }
167
168 //
169 // Start the heartbeat timer.
170 //
171 Status = gBS->SetTimer (
172 ArpService->PeriodicTimer,
173 TimerPeriodic,
174 ARP_PERIODIC_TIMER_INTERVAL
175 );
176 if (EFI_ERROR (Status)) {
177 goto ERROR_EXIT;
178 }
179
180 //
181 // Init the lists.
182 //
183 InitializeListHead (&ArpService->ChildrenList);
184 InitializeListHead (&ArpService->PendingRequestTable);
185 InitializeListHead (&ArpService->DeniedCacheTable);
186 InitializeListHead (&ArpService->ResolvedCacheTable);
187
188 ERROR_EXIT:
189
190 return Status;
191 }
192
193
194 /**
195 Clean the arp service context data.
196
197 @param ArpService Pointer to the buffer containing the arp service
198 context data.
199
200 @return None.
201
202 **/
203 STATIC
204 VOID
205 ArpCleanService (
206 IN ARP_SERVICE_DATA *ArpService
207 )
208 {
209 NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);
210
211 if (ArpService->PeriodicTimer != NULL) {
212 //
213 // Cancle and close the PeriodicTimer.
214 //
215 gBS->SetTimer (ArpService->PeriodicTimer, TimerCancel, 0);
216 gBS->CloseEvent (ArpService->PeriodicTimer);
217 }
218
219 if (ArpService->RxToken.Event != NULL) {
220 //
221 // Cancle the RxToken and close the event in the RxToken.
222 //
223 ArpService->Mnp->Cancel (ArpService->Mnp, NULL);
224 gBS->CloseEvent (ArpService->RxToken.Event);
225 }
226
227 if (ArpService->Mnp != NULL) {
228 //
229 // Reset the Mnp child and close the Mnp protocol.
230 //
231 ArpService->Mnp->Configure (ArpService->Mnp, NULL);
232 gBS->CloseProtocol (
233 ArpService->MnpChildHandle,
234 &gEfiManagedNetworkProtocolGuid,
235 ArpService->ImageHandle,
236 ArpService->ControllerHandle
237 );
238 }
239
240 if (ArpService->MnpChildHandle != NULL) {
241 //
242 // Destroy the mnp child.
243 //
244 NetLibDestroyServiceChild(
245 ArpService->ControllerHandle,
246 ArpService->ImageHandle,
247 &gEfiManagedNetworkServiceBindingProtocolGuid,
248 ArpService->MnpChildHandle
249 );
250 }
251 }
252
253
254 /**
255 Test to see if this driver supports ControllerHandle.
256
257 @param This Protocol instance pointer.
258 @param ControllerHandle Handle of device to test.
259 @param RemainingDevicePath Optional parameter use to pick a specific child
260 device to start.
261
262 @retval EFI_SUCCES This driver supports this device
263 @retval EFI_ALREADY_STARTED This driver is already running on this device.
264 @retval other This driver does not support this device.
265
266 **/
267 EFI_STATUS
268 EFIAPI
269 ArpDriverBindingSupported (
270 IN EFI_DRIVER_BINDING_PROTOCOL *This,
271 IN EFI_HANDLE ControllerHandle,
272 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
273 )
274 {
275 EFI_STATUS Status;
276
277 //
278 // Test to see if Arp SB is already installed.
279 //
280 Status = gBS->OpenProtocol (
281 ControllerHandle,
282 &gEfiArpServiceBindingProtocolGuid,
283 NULL,
284 This->DriverBindingHandle,
285 ControllerHandle,
286 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
287 );
288 if (Status == EFI_SUCCESS) {
289 return EFI_ALREADY_STARTED;
290 }
291
292 //
293 // Test to see if MNP SB is installed.
294 //
295 Status = gBS->OpenProtocol (
296 ControllerHandle,
297 &gEfiManagedNetworkServiceBindingProtocolGuid,
298 NULL,
299 This->DriverBindingHandle,
300 ControllerHandle,
301 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
302 );
303
304 return Status;
305 }
306
307
308 /**
309 Start this driver on ControllerHandle.
310
311 @param This Protocol instance pointer.
312 @param ControllerHandle Handle of device to bind driver to
313 @param RemainingDevicePath Optional parameter use to pick a specific child
314 device to start.
315
316 @retval EFI_SUCCES This driver is added to ControllerHandle
317 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
318 @retval other This driver does not support this device
319
320 **/
321 EFI_STATUS
322 EFIAPI
323 ArpDriverBindingStart (
324 IN EFI_DRIVER_BINDING_PROTOCOL *This,
325 IN EFI_HANDLE ControllerHandle,
326 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
327 )
328 {
329 EFI_STATUS Status;
330 ARP_SERVICE_DATA *ArpService;
331
332 //
333 // Allocate a zero pool for ArpService.
334 //
335 ArpService = AllocateZeroPool (sizeof(ARP_SERVICE_DATA));
336 if (ArpService == NULL) {
337 return EFI_OUT_OF_RESOURCES;
338 }
339
340 //
341 // Initialize the arp service context data.
342 //
343 Status = ArpCreateService (This->DriverBindingHandle, ControllerHandle, ArpService);
344 if (EFI_ERROR (Status)) {
345 goto ERROR;
346 }
347
348 //
349 // Install the ARP service binding protocol.
350 //
351 Status = gBS->InstallMultipleProtocolInterfaces (
352 &ControllerHandle,
353 &gEfiArpServiceBindingProtocolGuid,
354 &ArpService->ServiceBinding,
355 NULL
356 );
357 if (EFI_ERROR (Status)) {
358 goto ERROR;
359 }
360
361 //
362 // OK, start to receive arp packets from Mnp.
363 //
364 Status = ArpService->Mnp->Receive (ArpService->Mnp, &ArpService->RxToken);
365 if (EFI_ERROR (Status)) {
366 goto ERROR;
367 }
368
369 return Status;
370
371 ERROR:
372
373 //
374 // On error, clean the arp service context data, and free the memory allocated.
375 //
376 ArpCleanService (ArpService);
377 gBS->FreePool (ArpService);
378
379 return Status;
380 }
381
382
383 /**
384 Stop this driver on ControllerHandle.
385
386 @param This Protocol instance pointer.
387 @param ControllerHandle Handle of device to stop driver on
388 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number
389 of children is zero stop the entire bus driver.
390 @param ChildHandleBuffer List of Child Handles to Stop.
391
392 @retval EFI_SUCCES This driver is removed ControllerHandle
393 @retval other This driver was not removed from this device
394
395 **/
396 EFI_STATUS
397 EFIAPI
398 ArpDriverBindingStop (
399 IN EFI_DRIVER_BINDING_PROTOCOL *This,
400 IN EFI_HANDLE ControllerHandle,
401 IN UINTN NumberOfChildren,
402 IN EFI_HANDLE *ChildHandleBuffer
403 )
404 {
405 EFI_STATUS Status;
406 EFI_HANDLE NicHandle;
407 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
408 ARP_SERVICE_DATA *ArpService;
409 ARP_INSTANCE_DATA *Instance;
410
411 //
412 // Get the NicHandle which the arp servicebinding is installed on.
413 //
414 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);
415 if (NicHandle == NULL) {
416 return EFI_DEVICE_ERROR;
417 }
418
419 //
420 // Try to get the arp servicebinding protocol on the NicHandle.
421 //
422 Status = gBS->OpenProtocol (
423 NicHandle,
424 &gEfiArpServiceBindingProtocolGuid,
425 (VOID **)&ServiceBinding,
426 This->DriverBindingHandle,
427 ControllerHandle,
428 EFI_OPEN_PROTOCOL_GET_PROTOCOL
429 );
430 if (EFI_ERROR (Status)) {
431 DEBUG ((EFI_D_ERROR, "ArpDriverBindingStop: Open ArpSb failed, %r.\n", Status));
432 return EFI_DEVICE_ERROR;
433 }
434
435 ArpService = ARP_SERVICE_DATA_FROM_THIS (ServiceBinding);
436
437 if (NumberOfChildren == 0) {
438 //
439 // Uninstall the ARP ServiceBinding protocol.
440 //
441 gBS->UninstallMultipleProtocolInterfaces (
442 NicHandle,
443 &gEfiArpServiceBindingProtocolGuid,
444 &ArpService->ServiceBinding,
445 NULL
446 );
447
448 //
449 // Clean the arp servicebinding context data and free the memory allocated.
450 //
451 ArpCleanService (ArpService);
452
453 gBS->FreePool (ArpService);
454 } else {
455
456 while (!IsListEmpty (&ArpService->ChildrenList)) {
457 Instance = NET_LIST_HEAD (&ArpService->ChildrenList, ARP_INSTANCE_DATA, List);
458
459 ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
460 }
461
462 ASSERT (IsListEmpty (&ArpService->PendingRequestTable));
463 ASSERT (IsListEmpty (&ArpService->DeniedCacheTable));
464 ASSERT (IsListEmpty (&ArpService->ResolvedCacheTable));
465 }
466
467 return EFI_SUCCESS;
468 }
469
470 /**
471 Creates a child handle with a set of I/O services.
472
473 @param This Protocol instance pointer.
474 @param ChildHandle Pointer to the handle of the child to create. If
475 it is NULL, then a new handle is created. If it is
476 not NULL, then the I/O services are added to the
477 existing child handle.
478
479 @retval EFI_SUCCES The child handle was created with the I/O
480 services.
481 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
482 the child.
483 @retval other The child handle was not created.
484
485 **/
486 EFI_STATUS
487 EFIAPI
488 ArpServiceBindingCreateChild (
489 IN EFI_SERVICE_BINDING_PROTOCOL *This,
490 IN EFI_HANDLE *ChildHandle
491 )
492 {
493 EFI_STATUS Status;
494 ARP_SERVICE_DATA *ArpService;
495 ARP_INSTANCE_DATA *Instance;
496 VOID *Mnp;
497 EFI_TPL OldTpl;
498
499 if ((This == NULL) || (ChildHandle == NULL)) {
500 return EFI_INVALID_PARAMETER;
501 }
502
503 ArpService = ARP_SERVICE_DATA_FROM_THIS (This);
504
505 //
506 // Allocate memory for the instance context data.
507 //
508 Instance = AllocateZeroPool (sizeof(ARP_INSTANCE_DATA));
509 if (Instance == NULL) {
510 DEBUG ((EFI_D_ERROR, "ArpSBCreateChild: Failed to allocate memory for Instance.\n"));
511
512 return EFI_OUT_OF_RESOURCES;
513 }
514
515 //
516 // Init the instance context data.
517 //
518 ArpInitInstance (ArpService, Instance);
519
520 //
521 // Install the ARP protocol onto the ChildHandle.
522 //
523 Status = gBS->InstallMultipleProtocolInterfaces (
524 ChildHandle,
525 &gEfiArpProtocolGuid,
526 (VOID *)&Instance->ArpProto,
527 NULL
528 );
529 if (EFI_ERROR (Status)) {
530 DEBUG ((EFI_D_ERROR, "ArpSBCreateChild: faild to install ARP protocol, %r.\n", Status));
531
532 gBS->FreePool (Instance);
533 return Status;
534 }
535
536 //
537 // Save the ChildHandle.
538 //
539 Instance->Handle = *ChildHandle;
540
541 //
542 // Open the Managed Network protocol BY_CHILD.
543 //
544 Status = gBS->OpenProtocol (
545 ArpService->MnpChildHandle,
546 &gEfiManagedNetworkProtocolGuid,
547 (VOID **) &Mnp,
548 gArpDriverBinding.DriverBindingHandle,
549 Instance->Handle,
550 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
551 );
552 if (EFI_ERROR (Status)) {
553 goto ERROR;
554 }
555
556 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
557
558 //
559 // Insert the instance into children list managed by the arp service context data.
560 //
561 InsertTailList (&ArpService->ChildrenList, &Instance->List);
562 ArpService->ChildrenNumber++;
563
564 gBS->RestoreTPL (OldTpl);
565
566 ERROR:
567
568 if (EFI_ERROR (Status)) {
569
570 gBS->CloseProtocol (
571 ArpService->MnpChildHandle,
572 &gEfiManagedNetworkProtocolGuid,
573 gArpDriverBinding.DriverBindingHandle,
574 Instance->Handle
575 );
576
577 gBS->UninstallMultipleProtocolInterfaces (
578 Instance->Handle,
579 &gEfiArpProtocolGuid,
580 &Instance->ArpProto,
581 NULL
582 );
583
584 //
585 // Free the allocated memory.
586 //
587 gBS->FreePool (Instance);
588 }
589
590 return Status;
591 }
592
593
594 /**
595 Destroys a child handle with a set of I/O services.
596
597 @param This Protocol instance pointer.
598 @param ChildHandle Handle of the child to destroy.
599
600 @retval EFI_SUCCES The I/O services were removed from the child
601 handle.
602 @retval EFI_UNSUPPORTED The child handle does not support the I/O services
603 that are being removed.
604 @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
605 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because
606 its I/O services are being used.
607 @retval other The child handle was not destroyed.
608
609 **/
610 EFI_STATUS
611 EFIAPI
612 ArpServiceBindingDestroyChild (
613 IN EFI_SERVICE_BINDING_PROTOCOL *This,
614 IN EFI_HANDLE ChildHandle
615 )
616 {
617 EFI_STATUS Status;
618 ARP_SERVICE_DATA *ArpService;
619 ARP_INSTANCE_DATA *Instance;
620 EFI_ARP_PROTOCOL *Arp;
621 EFI_TPL OldTpl;
622
623 if ((This == NULL) || (ChildHandle == NULL)) {
624 return EFI_INVALID_PARAMETER;
625 }
626
627 ArpService = ARP_SERVICE_DATA_FROM_THIS (This);
628
629 //
630 // Get the arp protocol.
631 //
632 Status = gBS->OpenProtocol (
633 ChildHandle,
634 &gEfiArpProtocolGuid,
635 (VOID **)&Arp,
636 ArpService->ImageHandle,
637 ChildHandle,
638 EFI_OPEN_PROTOCOL_GET_PROTOCOL
639 );
640 if (EFI_ERROR (Status)) {
641 return EFI_UNSUPPORTED;
642 }
643
644 Instance = ARP_INSTANCE_DATA_FROM_THIS (Arp);
645
646 if (Instance->Destroyed) {
647 return EFI_SUCCESS;
648 }
649
650 //
651 // Use the Destroyed as a flag to avoid re-entrance.
652 //
653 Instance->Destroyed = TRUE;
654
655 //
656 // Close the Managed Network protocol.
657 //
658 gBS->CloseProtocol (
659 ArpService->MnpChildHandle,
660 &gEfiManagedNetworkProtocolGuid,
661 gArpDriverBinding.DriverBindingHandle,
662 ChildHandle
663 );
664
665 //
666 // Uninstall the ARP protocol.
667 //
668 Status = gBS->UninstallMultipleProtocolInterfaces (
669 ChildHandle,
670 &gEfiArpProtocolGuid,
671 &Instance->ArpProto,
672 NULL
673 );
674 if (EFI_ERROR (Status)) {
675 DEBUG ((EFI_D_ERROR, "ArpSBDestroyChild: Failed to uninstall the arp protocol, %r.\n",
676 Status));
677
678 Instance->Destroyed = FALSE;
679 return Status;
680 }
681
682 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
683
684 if (Instance->Configured) {
685 //
686 // Delete the related cache entry.
687 //
688 ArpDeleteCacheEntry (Instance, FALSE, NULL, TRUE);
689
690 //
691 // Reset the instance configuration.
692 //
693 ArpConfigureInstance (Instance, NULL);
694 }
695
696 //
697 // Remove this instance from the ChildrenList.
698 //
699 RemoveEntryList (&Instance->List);
700 ArpService->ChildrenNumber--;
701
702 gBS->RestoreTPL (OldTpl);
703
704 gBS->FreePool (Instance);
705
706 return Status;
707 }
708
709
710 EFI_STATUS
711 EFIAPI
712 ArpDriverEntryPoint (
713 IN EFI_HANDLE ImageHandle,
714 IN EFI_SYSTEM_TABLE *SystemTable
715 )
716 /*++
717
718 Routine Description:
719
720 The entry point for Arp driver which installs the driver binding and component name
721 protocol on its ImageHandle.
722
723 Arguments:
724
725 ImageHandle - The image handle of the driver.
726 SystemTable - The system table.
727
728 Returns:
729
730 EFI_SUCCESS - if the driver binding and component name protocols are successfully
731 installed, otherwise if failed.
732
733 --*/
734 {
735 return EfiLibInstallDriverBindingComponentName2 (
736 ImageHandle,
737 SystemTable,
738 &gArpDriverBinding,
739 ImageHandle,
740 &gArpComponentName,
741 &gArpComponentName2
742 );
743 }
744