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