]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/MnpDxe/MnpDriver.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / Network / MnpDxe / MnpDriver.c
1 /** @file
2 Implementation of driver entry point and driver binding protocol.
3
4 Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "MnpDriver.h"
10 #include "MnpImpl.h"
11 #include "MnpVlan.h"
12
13 EFI_DRIVER_BINDING_PROTOCOL gMnpDriverBinding = {
14 MnpDriverBindingSupported,
15 MnpDriverBindingStart,
16 MnpDriverBindingStop,
17 0xa,
18 NULL,
19 NULL
20 };
21
22 /**
23 Callback function which provided by user to remove one node in NetDestroyLinkList process.
24
25 @param[in] Entry The entry to be removed.
26 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
27
28 @retval EFI_SUCCESS The entry has been removed successfully.
29 @retval Others Fail to remove the entry.
30
31 **/
32 EFI_STATUS
33 EFIAPI
34 MnpDestroyServiceDataEntry (
35 IN LIST_ENTRY *Entry,
36 IN VOID *Context
37 )
38 {
39 MNP_SERVICE_DATA *MnpServiceData;
40
41 MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);
42 return MnpDestroyServiceData (MnpServiceData);
43 }
44
45 /**
46 Callback function which provided by user to remove one node in NetDestroyLinkList process.
47
48 @param[in] Entry The entry to be removed.
49 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
50
51 @retval EFI_SUCCESS The entry has been removed successfully.
52 @retval Others Fail to remove the entry.
53
54 **/
55 EFI_STATUS
56 EFIAPI
57 MnpDestroyServiceChildEntry (
58 IN LIST_ENTRY *Entry,
59 IN VOID *Context
60 )
61 {
62 MNP_SERVICE_DATA *MnpServiceData;
63
64 MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);
65 return MnpDestroyServiceChild (MnpServiceData);
66 }
67
68 /**
69 Test to see if this driver supports ControllerHandle. This service
70 is called by the EFI boot service ConnectController(). In
71 order to make drivers as small as possible, there are a few calling
72 restrictions for this service. ConnectController() must
73 follow these calling restrictions. If any other agent wishes to call
74 Supported() it must also follow these calling restrictions.
75
76 @param[in] This Protocol instance pointer.
77 @param[in] ControllerHandle Handle of device to test.
78 @param[in] RemainingDevicePath Optional parameter use to pick a specific
79 child device to start.
80
81 @retval EFI_SUCCESS This driver supports this device.
82 @retval EFI_ALREADY_STARTED This driver is already running on this device.
83 @retval Others This driver does not support this device.
84
85 **/
86 EFI_STATUS
87 EFIAPI
88 MnpDriverBindingSupported (
89 IN EFI_DRIVER_BINDING_PROTOCOL *This,
90 IN EFI_HANDLE ControllerHandle,
91 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
92 )
93 {
94 EFI_STATUS Status;
95 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
96
97 //
98 // Test to open the Simple Network protocol BY_DRIVER.
99 //
100 Status = gBS->OpenProtocol (
101 ControllerHandle,
102 &gEfiSimpleNetworkProtocolGuid,
103 (VOID **) &Snp,
104 This->DriverBindingHandle,
105 ControllerHandle,
106 EFI_OPEN_PROTOCOL_BY_DRIVER
107 );
108 if (EFI_ERROR (Status)) {
109 return Status;
110 }
111
112 //
113 // Close the openned SNP protocol.
114 //
115 gBS->CloseProtocol (
116 ControllerHandle,
117 &gEfiSimpleNetworkProtocolGuid,
118 This->DriverBindingHandle,
119 ControllerHandle
120 );
121
122 return EFI_SUCCESS;
123 }
124
125
126 /**
127 Start this driver on ControllerHandle. This service is called by the
128 EFI boot service ConnectController(). In order to make drivers as small
129 as possible, there are a few calling restrictions for this service.
130 ConnectController() must follow these calling restrictions. If any other
131 agent wishes to call Start() it must also follow these calling restrictions.
132
133 @param[in] This Protocol instance pointer.
134 @param[in] ControllerHandle Handle of device to bind driver to.
135 @param[in] RemainingDevicePath Optional parameter use to pick a specific
136 child device to start.
137
138 @retval EFI_SUCCESS This driver is added to ControllerHandle.
139 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
140 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for Mnp Service Data.
141 @retval Others This driver does not support this device.
142
143 **/
144 EFI_STATUS
145 EFIAPI
146 MnpDriverBindingStart (
147 IN EFI_DRIVER_BINDING_PROTOCOL *This,
148 IN EFI_HANDLE ControllerHandle,
149 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
150 )
151 {
152 EFI_STATUS Status;
153 MNP_SERVICE_DATA *MnpServiceData;
154 MNP_DEVICE_DATA *MnpDeviceData;
155 LIST_ENTRY *Entry;
156 VLAN_TCI *VlanVariable;
157 UINTN NumberOfVlan;
158 UINTN Index;
159
160 VlanVariable = NULL;
161
162 //
163 // Initialize the Mnp Device Data
164 //
165 MnpDeviceData = AllocateZeroPool (sizeof (MNP_DEVICE_DATA));
166 if (MnpDeviceData == NULL) {
167 DEBUG ((EFI_D_ERROR, "MnpDriverBindingStart(): Failed to allocate the Mnp Device Data.\n"));
168
169 return EFI_OUT_OF_RESOURCES;
170 }
171
172 Status = MnpInitializeDeviceData (MnpDeviceData, This->DriverBindingHandle, ControllerHandle);
173 if (EFI_ERROR (Status)) {
174 DEBUG ((EFI_D_ERROR, "MnpDriverBindingStart: MnpInitializeDeviceData failed, %r.\n", Status));
175
176 FreePool (MnpDeviceData);
177 return Status;
178 }
179
180 //
181 // Check whether NIC driver has already produced VlanConfig protocol
182 //
183 Status = gBS->OpenProtocol (
184 ControllerHandle,
185 &gEfiVlanConfigProtocolGuid,
186 NULL,
187 This->DriverBindingHandle,
188 ControllerHandle,
189 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
190 );
191 if (!EFI_ERROR (Status)) {
192 //
193 // NIC hardware already implement VLAN,
194 // no need to provide software VLAN implementation in MNP driver
195 //
196 MnpDeviceData->NumberOfVlan = 0;
197 ZeroMem (&MnpDeviceData->VlanConfig, sizeof (EFI_VLAN_CONFIG_PROTOCOL));
198 MnpServiceData = MnpCreateServiceData (MnpDeviceData, 0, 0);
199 Status = (MnpServiceData != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;
200 goto Exit;
201 }
202
203 //
204 // Install VLAN Config Protocol
205 //
206 Status = gBS->InstallMultipleProtocolInterfaces (
207 &ControllerHandle,
208 &gEfiVlanConfigProtocolGuid,
209 &MnpDeviceData->VlanConfig,
210 NULL
211 );
212 if (EFI_ERROR (Status)) {
213 goto Exit;
214 }
215
216 //
217 // Get current VLAN configuration from EFI Variable
218 //
219 NumberOfVlan = 0;
220 Status = MnpGetVlanVariable (MnpDeviceData, &NumberOfVlan, &VlanVariable);
221 if (EFI_ERROR (Status)) {
222 //
223 // No VLAN is set, create a default MNP service data for untagged frame
224 //
225 MnpDeviceData->NumberOfVlan = 0;
226 MnpServiceData = MnpCreateServiceData (MnpDeviceData, 0, 0);
227 Status = (MnpServiceData != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;
228 goto Exit;
229 }
230
231 //
232 // Create MNP service data for each VLAN
233 //
234 MnpDeviceData->NumberOfVlan = NumberOfVlan;
235 for (Index = 0; Index < NumberOfVlan; Index++) {
236 MnpServiceData = MnpCreateServiceData (
237 MnpDeviceData,
238 VlanVariable[Index].Bits.Vid,
239 (UINT8) VlanVariable[Index].Bits.Priority
240 );
241
242 if (MnpServiceData == NULL) {
243 Status = EFI_OUT_OF_RESOURCES;
244
245 goto Exit;
246 }
247 }
248
249 Exit:
250 if (VlanVariable != NULL) {
251 FreePool (VlanVariable);
252 }
253
254 if (EFI_ERROR (Status)) {
255 //
256 // Destroy all MNP service data
257 //
258 while (!IsListEmpty (&MnpDeviceData->ServiceList)) {
259 Entry = GetFirstNode (&MnpDeviceData->ServiceList);
260 MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);
261 MnpDestroyServiceData (MnpServiceData);
262 }
263
264 //
265 // Uninstall the VLAN Config Protocol if any
266 //
267 if (MnpDeviceData->VlanConfig.Set != NULL) {
268 gBS->UninstallMultipleProtocolInterfaces (
269 MnpDeviceData->ControllerHandle,
270 &gEfiVlanConfigProtocolGuid,
271 &MnpDeviceData->VlanConfig,
272 NULL
273 );
274 }
275
276 //
277 // Destroy Mnp Device Data
278 //
279 MnpDestroyDeviceData (MnpDeviceData, This->DriverBindingHandle);
280 FreePool (MnpDeviceData);
281 }
282
283 return Status;
284 }
285
286 /**
287 Stop this driver on ControllerHandle. This service is called by the
288 EFI boot service DisconnectController(). In order to make drivers as
289 small as possible, there are a few calling restrictions for this service.
290 DisconnectController() must follow these calling restrictions. If any other
291 agent wishes to call Stop() it must also follow these calling restrictions.
292
293 @param[in] This Protocol instance pointer.
294 @param[in] ControllerHandle Handle of device to stop driver on.
295 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If
296 number of children is zero stop the entire
297 bus driver.
298 @param[in] ChildHandleBuffer List of Child Handles to Stop.
299
300 @retval EFI_SUCCESS This driver is removed ControllerHandle.
301 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
302
303 **/
304 EFI_STATUS
305 EFIAPI
306 MnpDriverBindingStop (
307 IN EFI_DRIVER_BINDING_PROTOCOL *This,
308 IN EFI_HANDLE ControllerHandle,
309 IN UINTN NumberOfChildren,
310 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
311 )
312 {
313 EFI_STATUS Status;
314 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
315 EFI_VLAN_CONFIG_PROTOCOL *VlanConfig;
316 MNP_DEVICE_DATA *MnpDeviceData;
317 MNP_SERVICE_DATA *MnpServiceData;
318 LIST_ENTRY *List;
319 UINTN ListLength;
320
321 //
322 // Try to retrieve MNP service binding protocol from the ControllerHandle
323 //
324 Status = gBS->OpenProtocol (
325 ControllerHandle,
326 &gEfiManagedNetworkServiceBindingProtocolGuid,
327 (VOID **) &ServiceBinding,
328 This->DriverBindingHandle,
329 ControllerHandle,
330 EFI_OPEN_PROTOCOL_GET_PROTOCOL
331 );
332 if (EFI_ERROR (Status)) {
333 //
334 // Retrieve VLAN Config Protocol from the ControllerHandle
335 //
336 Status = gBS->OpenProtocol (
337 ControllerHandle,
338 &gEfiVlanConfigProtocolGuid,
339 (VOID **) &VlanConfig,
340 This->DriverBindingHandle,
341 ControllerHandle,
342 EFI_OPEN_PROTOCOL_GET_PROTOCOL
343 );
344 if (EFI_ERROR (Status)) {
345 DEBUG ((EFI_D_ERROR, "MnpDriverBindingStop: try to stop unknown Controller.\n"));
346 return EFI_DEVICE_ERROR;
347 }
348
349 MnpDeviceData = MNP_DEVICE_DATA_FROM_THIS (VlanConfig);
350 } else {
351 MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (ServiceBinding);
352 MnpDeviceData = MnpServiceData->MnpDeviceData;
353 }
354
355 if (NumberOfChildren == 0) {
356 //
357 // Destroy all MNP service data
358 //
359 List = &MnpDeviceData->ServiceList;
360 Status = NetDestroyLinkList (
361 List,
362 MnpDestroyServiceDataEntry,
363 NULL,
364 &ListLength
365 );
366 if (EFI_ERROR (Status) || ListLength !=0) {
367 return EFI_DEVICE_ERROR;
368 }
369
370 //
371 // Uninstall the VLAN Config Protocol if any
372 //
373 if (MnpDeviceData->VlanConfig.Set != NULL) {
374 gBS->UninstallMultipleProtocolInterfaces (
375 MnpDeviceData->ControllerHandle,
376 &gEfiVlanConfigProtocolGuid,
377 &MnpDeviceData->VlanConfig,
378 NULL
379 );
380 }
381
382 //
383 // Destroy Mnp Device Data
384 //
385 MnpDestroyDeviceData (MnpDeviceData, This->DriverBindingHandle);
386 FreePool (MnpDeviceData);
387
388 if (gMnpControllerNameTable != NULL) {
389 FreeUnicodeStringTable (gMnpControllerNameTable);
390 gMnpControllerNameTable = NULL;
391 }
392 return EFI_SUCCESS;
393 }
394
395 //
396 // Stop all MNP child
397 //
398 List = &MnpDeviceData->ServiceList;
399 Status = NetDestroyLinkList (
400 List,
401 MnpDestroyServiceChildEntry,
402 NULL,
403 &ListLength
404 );
405 if (EFI_ERROR (Status)) {
406 return EFI_DEVICE_ERROR;
407 }
408
409 return EFI_SUCCESS;
410 }
411
412
413 /**
414 Creates a child handle with a set of I/O services.
415
416 @param[in] This Protocol instance pointer.
417 @param[in, out] ChildHandle Pointer to the handle of the child to create. If
418 it is NULL, then a new handle is created. If
419 it is not NULL, then the I/O services are added
420 to the existing child handle.
421
422 @retval EFI_SUCCES The protocol was added to ChildHandle.
423 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
424 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
425 create the child.
426 @retval Others The child handle was not created.
427
428 **/
429 EFI_STATUS
430 EFIAPI
431 MnpServiceBindingCreateChild (
432 IN EFI_SERVICE_BINDING_PROTOCOL *This,
433 IN OUT EFI_HANDLE *ChildHandle
434 )
435 {
436 EFI_STATUS Status;
437 MNP_SERVICE_DATA *MnpServiceData;
438 MNP_INSTANCE_DATA *Instance;
439 VOID *MnpSb;
440 EFI_TPL OldTpl;
441
442 if ((This == NULL) || (ChildHandle == NULL)) {
443 return EFI_INVALID_PARAMETER;
444 }
445
446 MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (This);
447
448 //
449 // Allocate buffer for the new instance.
450 //
451 Instance = AllocateZeroPool (sizeof (MNP_INSTANCE_DATA));
452 if (Instance == NULL) {
453 DEBUG ((EFI_D_ERROR, "MnpServiceBindingCreateChild: Faild to allocate memory for the new instance.\n"));
454
455 return EFI_OUT_OF_RESOURCES;
456 }
457
458 //
459 // Init the instance data.
460 //
461 MnpInitializeInstanceData (MnpServiceData, Instance);
462
463 Status = gBS->InstallMultipleProtocolInterfaces (
464 ChildHandle,
465 &gEfiManagedNetworkProtocolGuid,
466 &Instance->ManagedNetwork,
467 NULL
468 );
469 if (EFI_ERROR (Status)) {
470 DEBUG (
471 (EFI_D_ERROR,
472 "MnpServiceBindingCreateChild: Failed to install the MNP protocol, %r.\n",
473 Status)
474 );
475
476 goto ErrorExit;
477 }
478
479 //
480 // Save the instance's childhandle.
481 //
482 Instance->Handle = *ChildHandle;
483
484 Status = gBS->OpenProtocol (
485 MnpServiceData->ServiceHandle,
486 &gEfiManagedNetworkServiceBindingProtocolGuid,
487 (VOID **) &MnpSb,
488 gMnpDriverBinding.DriverBindingHandle,
489 Instance->Handle,
490 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
491 );
492 if (EFI_ERROR (Status)) {
493 goto ErrorExit;
494 }
495
496 //
497 // Add the child instance into ChildrenList.
498 //
499 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
500
501 InsertTailList (&MnpServiceData->ChildrenList, &Instance->InstEntry);
502 MnpServiceData->ChildrenNumber++;
503
504 gBS->RestoreTPL (OldTpl);
505
506 ErrorExit:
507
508 if (EFI_ERROR (Status)) {
509
510 if (Instance->Handle != NULL) {
511
512 gBS->UninstallMultipleProtocolInterfaces (
513 Instance->Handle,
514 &gEfiManagedNetworkProtocolGuid,
515 &Instance->ManagedNetwork,
516 NULL
517 );
518 }
519
520 FreePool (Instance);
521 }
522
523 return Status;
524 }
525
526
527 /**
528 Destroys a child handle with a set of I/O services.
529
530 The DestroyChild() function does the opposite of CreateChild(). It removes a
531 protocol that was installed by CreateChild() from ChildHandle. If the removed
532 protocol is the last protocol on ChildHandle, then ChildHandle is destroyed.
533
534 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL
535 instance.
536 @param[in] ChildHandle Handle of the child to destroy.
537
538 @retval EFI_SUCCES The protocol was removed from ChildHandle.
539 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that
540 is being removed.
541 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
542 @retval EFI_ACCESS_DENIED The protocol could not be removed from the
543 ChildHandle because its services are being
544 used.
545 @retval Others The child handle was not destroyed.
546
547 **/
548 EFI_STATUS
549 EFIAPI
550 MnpServiceBindingDestroyChild (
551 IN EFI_SERVICE_BINDING_PROTOCOL *This,
552 IN EFI_HANDLE ChildHandle
553 )
554 {
555 EFI_STATUS Status;
556 MNP_SERVICE_DATA *MnpServiceData;
557 EFI_MANAGED_NETWORK_PROTOCOL *ManagedNetwork;
558 MNP_INSTANCE_DATA *Instance;
559 EFI_TPL OldTpl;
560
561 if ((This == NULL) || (ChildHandle == NULL)) {
562 return EFI_INVALID_PARAMETER;
563 }
564
565 MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (This);
566
567 //
568 // Try to retrieve ManagedNetwork Protocol from ChildHandle.
569 //
570 Status = gBS->OpenProtocol (
571 ChildHandle,
572 &gEfiManagedNetworkProtocolGuid,
573 (VOID **) &ManagedNetwork,
574 gMnpDriverBinding.DriverBindingHandle,
575 ChildHandle,
576 EFI_OPEN_PROTOCOL_GET_PROTOCOL
577 );
578 if (EFI_ERROR (Status)) {
579 return EFI_UNSUPPORTED;
580 }
581
582 Instance = MNP_INSTANCE_DATA_FROM_THIS (ManagedNetwork);
583
584 //
585 // MnpServiceBindingDestroyChild may be called twice: first called by
586 // MnpServiceBindingStop, second called by uninstalling the MNP protocol
587 // in this ChildHandle. Use destroyed to make sure the resource clean code
588 // will only excecute once.
589 //
590 if (Instance->Destroyed) {
591 return EFI_SUCCESS;
592 }
593
594 Instance->Destroyed = TRUE;
595
596 //
597 // Close the Simple Network protocol.
598 //
599 gBS->CloseProtocol (
600 MnpServiceData->ServiceHandle,
601 &gEfiManagedNetworkServiceBindingProtocolGuid,
602 MnpServiceData->MnpDeviceData->ImageHandle,
603 ChildHandle
604 );
605
606 //
607 // Uninstall the ManagedNetwork protocol.
608 //
609 Status = gBS->UninstallMultipleProtocolInterfaces (
610 ChildHandle,
611 &gEfiManagedNetworkProtocolGuid,
612 &Instance->ManagedNetwork,
613 NULL
614 );
615 if (EFI_ERROR (Status)) {
616 DEBUG (
617 (EFI_D_ERROR,
618 "MnpServiceBindingDestroyChild: Failed to uninstall the ManagedNetwork protocol, %r.\n",
619 Status)
620 );
621
622 Instance->Destroyed = FALSE;
623 return Status;
624 }
625
626 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
627
628 //
629 // Reset the configuration.
630 //
631 ManagedNetwork->Configure (ManagedNetwork, NULL);
632
633 //
634 // Try to flush the RcvdPacketQueue.
635 //
636 MnpFlushRcvdDataQueue (Instance);
637
638 //
639 // Clean the RxTokenMap.
640 //
641 NetMapClean (&Instance->RxTokenMap);
642
643 //
644 // Remove this instance from the ChildrenList.
645 //
646 RemoveEntryList (&Instance->InstEntry);
647 MnpServiceData->ChildrenNumber--;
648
649 gBS->RestoreTPL (OldTpl);
650
651 FreePool (Instance);
652
653 return Status;
654 }
655
656 /**
657 The entry point for Mnp driver which installs the driver binding and component
658 name protocol on its ImageHandle.
659
660 @param[in] ImageHandle The image handle of the driver.
661 @param[in] SystemTable The system table.
662
663 @retval EFI_SUCCES The driver binding and component name protocols are
664 successfully installed.
665 @retval Others Other errors as indicated.
666
667 **/
668 EFI_STATUS
669 EFIAPI
670 MnpDriverEntryPoint (
671 IN EFI_HANDLE ImageHandle,
672 IN EFI_SYSTEM_TABLE *SystemTable
673 )
674 {
675 return EfiLibInstallDriverBindingComponentName2 (
676 ImageHandle,
677 SystemTable,
678 &gMnpDriverBinding,
679 ImageHandle,
680 &gMnpComponentName,
681 &gMnpComponentName2
682 );
683 }