ip4driver.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 957 行 · 第 1/2 页
C
957 行
//
mIp4Id = (UINT16)NET_RANDOM (NetRandomInitSeed ());
Ip4SetVariableData (IpSb);
return Status;
UNINSTALL_PROTOCOL:
gBS->UninstallProtocolInterface (
ControllerHandle,
&gEfiIp4ServiceBindingProtocolGuid,
&IpSb->ServiceBinding
);
FREE_SERVICE:
Ip4CleanService (IpSb);
NetFreePool (IpSb);
return Status;
}
EFI_STATUS
EFIAPI
Ip4DriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
/*++
Routine Description:
Stop this driver on ControllerHandle.
Arguments:
This - Protocol instance pointer.
ControllerHandle - Handle of device to stop driver on
NumberOfChildren - Number of Handles in ChildHandleBuffer. If
number of children is zero stop the entire
bus driver.
ChildHandleBuffer - List of Child Handles to Stop.
Returns:
EFI_SUCCES - This driver is removed ControllerHandle
other - This driver was not removed from this device
--*/
{
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
IP4_SERVICE *IpSb;
IP4_PROTOCOL *IpInstance;
EFI_HANDLE NicHandle;
EFI_STATUS Status;
EFI_TPL OldTpl;
INTN State;
//
// IP4 driver opens the MNP child, ARP children or the IP4_CONFIG protocol
// by driver. So the ControllerHandle may be the MNP child handle, ARP child
// handle, or the NIC (UNDI) handle because IP4_CONFIG protocol is installed
// in the NIC handle.
//
//
// First, check whether it is the IP4_CONFIG protocol being uninstalled.
// IP4_CONFIG protocol is installed on the NIC handle. It isn't necessary
// to clean up the default configuration if IP4_CONFIG is being stopped.
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiIp4ConfigProtocolGuid,
NULL,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
if (Status == EFI_SUCCESS) {
//
// Retrieve the IP4 service binding protocol. If failed, it is
// likely that Ip4 ServiceBinding is uninstalled already. In this
// case, return immediately.
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiIp4ServiceBindingProtocolGuid,
(VOID **) &ServiceBinding,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return EFI_SUCCESS;
}
IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
if (IpSb->Ip4Config && (IpSb->State != IP4_SERVICE_DESTORY)) {
IpSb->Ip4Config->Stop (IpSb->Ip4Config);
Status = gBS->CloseProtocol (
ControllerHandle,
&gEfiIp4ConfigProtocolGuid,
IpSb->Image,
ControllerHandle
);
if (EFI_ERROR (Status)) {
NET_RESTORE_TPL (OldTpl);
return Status;
}
//
// If the auto configure hasn't complete, mark it as not started.
//
if (IpSb->State == IP4_SERVICE_STARTED) {
IpSb->State = IP4_SERVICE_UNSTARTED;
}
IpSb->Ip4Config = NULL;
gBS->CloseEvent (IpSb->DoneEvent);
gBS->CloseEvent (IpSb->ReconfigEvent);
}
NET_RESTORE_TPL (OldTpl);
return EFI_SUCCESS;
}
//
// Either MNP or ARP protocol is being uninstalled. The controller
// handle is either the MNP child or ARP child. But, the IP4's
// service binding is installed on the NIC handle. So, need to open
// the protocol info to find the NIC handle.
//
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);
if (NicHandle == NULL) {
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);
}
if (NicHandle == NULL) {
return EFI_SUCCESS;
}
//
// Retrieve the IP4 service binding protocol
//
Status = gBS->OpenProtocol (
NicHandle,
&gEfiIp4ServiceBindingProtocolGuid,
(VOID **) &ServiceBinding,
This->DriverBindingHandle,
NicHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
if (IpSb->InDestory) {
NET_RESTORE_TPL (OldTpl);
return EFI_SUCCESS;
}
IpSb->InDestory = TRUE;
State = IpSb->State;
IpSb->State = IP4_SERVICE_DESTORY;
//
// Destory all the children first. If not all children are destoried,
// the IP driver can operate correctly, so restore it state. Don't
// use NET_LIST_FOR_EACH_SAFE here, because it will cache the next
// pointer, which may point to the child that has already been destoried.
// For example, if there are two child in the list, the first is UDP
// listen child, the send is the MTFTP's child. When Udp child is
// destoried, it will destory the MTFTP's child. Then Next point to
// a invalid child.
//
while (!NetListIsEmpty (&IpSb->Children)) {
IpInstance = NET_LIST_HEAD (&IpSb->Children, IP4_PROTOCOL, Link);
Ip4ServiceBindingDestroyChild (ServiceBinding, IpInstance->Handle);
}
if (IpSb->NumChildren != 0) {
IpSb->State = State;
Status = EFI_DEVICE_ERROR;
goto ON_ERROR;
}
//
// Clear the variable data.
//
Ip4ClearVariableData (IpSb);
//
// OK, clean other resources then uninstall the service binding protocol.
//
Status = Ip4CleanService (IpSb);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = gBS->UninstallProtocolInterface (
NicHandle,
&gEfiIp4ServiceBindingProtocolGuid,
ServiceBinding
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
NET_RESTORE_TPL (OldTpl);
NetFreePool (IpSb);
return EFI_SUCCESS;
ON_ERROR:
IpSb->InDestory = FALSE;
NET_RESTORE_TPL (OldTpl);
return Status;
}
EFI_STATUS
EFIAPI
Ip4ServiceBindingCreateChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE *ChildHandle
)
/*++
Routine Description:
Creates a child handle with a set of I/O services.
Arguments:
This - Protocol instance pointer.
ChildHandle - Pointer to the handle of the child to create.
If it is NULL, then a new handle is created.
If it is not NULL, then the I/O services are
added to the existing child handle.
Returns:
EFI_SUCCES - The child handle was created with the I/O services
EFI_OUT_OF_RESOURCES - There are not enough resources availabe to create
the child
other - The child handle was not created
--*/
{
IP4_SERVICE *IpSb;
IP4_PROTOCOL *IpInstance;
EFI_TPL OldTpl;
EFI_STATUS Status;
VOID *Mnp;
if ((This == NULL) || (ChildHandle == NULL)) {
return EFI_INVALID_PARAMETER;
}
IpSb = IP4_SERVICE_FROM_PROTOCOL (This);
IpInstance = NetAllocatePool (sizeof (IP4_PROTOCOL));
if (IpInstance == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Ip4InitProtocol (IpSb, IpInstance);
//
// Install Ip4 onto ChildHandle
//
Status = gBS->InstallMultipleProtocolInterfaces (
ChildHandle,
&gEfiIp4ProtocolGuid,
&IpInstance->Ip4Proto,
NULL
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
IpInstance->Handle = *ChildHandle;
//
// Open the Managed Network protocol BY_CHILD.
//
Status = gBS->OpenProtocol (
IpSb->MnpChildHandle,
&gEfiManagedNetworkProtocolGuid,
(VOID **) &Mnp,
gIp4DriverBinding.DriverBindingHandle,
IpInstance->Handle,
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
if (EFI_ERROR (Status)) {
gBS->UninstallMultipleProtocolInterfaces (
ChildHandle,
&gEfiIp4ProtocolGuid,
&IpInstance->Ip4Proto,
NULL
);
goto ON_ERROR;
}
//
// Insert it into the service binding instance.
//
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
NetListInsertTail (&IpSb->Children, &IpInstance->Link);
IpSb->NumChildren++;
NET_RESTORE_TPL (OldTpl);
ON_ERROR:
if (EFI_ERROR (Status)) {
Ip4CleanProtocol (IpInstance);
NetFreePool (IpInstance);
}
return Status;
}
EFI_STATUS
EFIAPI
Ip4ServiceBindingDestroyChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE ChildHandle
)
/*++
Routine Description:
Destroys a child handle with a set of I/O services.
Arguments:
This - Protocol instance pointer.
ChildHandle - Handle of the child to destroy
Returns:
EFI_SUCCES - The I/O services were removed from the child handle
EFI_UNSUPPORTED - The child handle does not support the I/O services
that are being removed
EFI_INVALID_PARAMETER - Child handle is not a valid EFI Handle.
EFI_ACCESS_DENIED - The child handle could not be destroyed because its
I/O services are being used.
other - The child handle was not destroyed
--*/
{
EFI_STATUS Status;
IP4_SERVICE *IpSb;
IP4_PROTOCOL *IpInstance;
EFI_IP4_PROTOCOL *Ip4;
EFI_TPL OldTpl;
INTN State;
if ((This == NULL) || (ChildHandle == NULL)) {
return EFI_INVALID_PARAMETER;
}
//
// Retrieve the private context data structures
//
IpSb = IP4_SERVICE_FROM_PROTOCOL (This);
Status = gBS->OpenProtocol (
ChildHandle,
&gEfiIp4ProtocolGuid,
(VOID **) &Ip4,
gIp4DriverBinding.DriverBindingHandle,
ChildHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
IpInstance = IP4_INSTANCE_FROM_PROTOCOL (Ip4);
if (IpInstance->Service != IpSb) {
return EFI_INVALID_PARAMETER;
}
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
//
// A child can be destoried more than once. For example,
// Ip4DriverBindingStop will destory all of its children.
// when UDP driver is being stopped, it will destory all
// the IP child it opens.
//
if (IpInstance->State == IP4_STATE_DESTORY) {
NET_RESTORE_TPL (OldTpl);
return EFI_SUCCESS;
}
State = IpInstance->State;
IpInstance->State = IP4_STATE_DESTORY;
//
// Close the Managed Network protocol.
//
gBS->CloseProtocol (
IpSb->MnpChildHandle,
&gEfiManagedNetworkProtocolGuid,
gIp4DriverBinding.DriverBindingHandle,
ChildHandle
);
//
// Uninstall the IP4 protocol first. Many thing happens during
// this:
// 1. The consumer of the IP4 protocol will be stopped if it
// opens the protocol BY_DRIVER. For eaxmple, if MNP driver is
// stopped, IP driver's stop function will be called, and uninstall
// EFI_IP4_PROTOCOL will trigger the UDP's stop function. This
// makes it possible to create the network stack bottom up, and
// stop it top down.
// 2. the upper layer will recycle the received packet. The recycle
// event's TPL is higher than this function. The recycle events
// will be called back before preceeding. If any packets not recycled,
// that means there is a resource leak.
//
Status = gBS->UninstallProtocolInterface (
ChildHandle,
&gEfiIp4ProtocolGuid,
&IpInstance->Ip4Proto
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = Ip4CleanProtocol (IpInstance);
Ip4SetVariableData (IpSb);
if (EFI_ERROR (Status)) {
gBS->InstallMultipleProtocolInterfaces (
&ChildHandle,
&gEfiIp4ProtocolGuid,
Ip4,
NULL
);
goto ON_ERROR;
}
NetListRemoveEntry (&IpInstance->Link);
IpSb->NumChildren--;
NET_RESTORE_TPL (OldTpl);
NetFreePool (IpInstance);
return EFI_SUCCESS;
ON_ERROR:
IpInstance->State = State;
NET_RESTORE_TPL (OldTpl);
return Status;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?