dhcp4driver.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 699 行 · 第 1/2 页

C
699
字号

  return Status;

ON_ERROR:
  Dhcp4CloseService (DhcpSb);
  NetFreePool (DhcpSb);
  return Status;
}

EFI_STATUS
EFIAPI
Dhcp4DriverBindingStop (
  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;
  DHCP_SERVICE                  *DhcpSb;
  DHCP_PROTOCOL                 *Instance;
  EFI_HANDLE                    NicHandle;
  EFI_STATUS                    Status;
  EFI_TPL                       OldTpl;

  //
  // DHCP driver opens UDP child, So, the ControllerHandle is the
  // UDP child handle. locate the Nic handle first.
  //
  NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);
  
  if (NicHandle == NULL) {
    return EFI_SUCCESS;
  }
  
   Status = gBS->OpenProtocol (
                  NicHandle,
                  &gEfiDhcp4ServiceBindingProtocolGuid,
                  (VOID **) &ServiceBinding,
                  This->DriverBindingHandle,
                  NicHandle,
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
                  );

  if (EFI_ERROR (Status)) {
    return EFI_DEVICE_ERROR;
  }

  DhcpSb = DHCP_SERVICE_FROM_THIS (ServiceBinding);

  if (DhcpSb->InDestory) {
    return EFI_SUCCESS;
  }

  OldTpl            = NET_RAISE_TPL (NET_TPL_LOCK);
  DhcpSb->InDestory = TRUE;

  //
  // Don't use NET_LIST_FOR_EACH_SAFE here, Dhcp4ServiceBindingDestoryChild
  // may cause other child to be deleted.
  //
  while (!NetListIsEmpty (&DhcpSb->Children)) {
    Instance = NET_LIST_HEAD (&DhcpSb->Children, DHCP_PROTOCOL, Link);
    Dhcp4ServiceBindingDestroyChild (ServiceBinding, Instance->Handle);
  }

  if (DhcpSb->NumChildren != 0) {
    Status = EFI_DEVICE_ERROR;
    goto ON_ERROR;
  }

  DhcpSb->ServiceState  = DHCP_DESTORY;

  Status = gBS->UninstallProtocolInterface (
                  NicHandle,
                  &gEfiDhcp4ServiceBindingProtocolGuid,
                  ServiceBinding
                  );

  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Dhcp4CloseService (DhcpSb);
  NET_RESTORE_TPL (OldTpl);

  NetFreePool (DhcpSb);
  return EFI_SUCCESS;

ON_ERROR:
  DhcpSb->InDestory = FALSE;
  NET_RESTORE_TPL (OldTpl);
  return Status;
}

VOID
DhcpInitProtocol (
  IN DHCP_SERVICE           *DhcpSb,
  IN DHCP_PROTOCOL          *Instance
  )
/*++

Routine Description:

  Initialize a new DHCP child

Arguments:

  DhcpSb    - The dhcp service instance
  Instance  - The dhcp instance to initialize

Returns:

  None

--*/
{
  Instance->Signature         = DHCP_PROTOCOL_SIGNATURE;
  Instance->Dhcp4Protocol     = mDhcp4ProtocolTemplate;
  NetListInit (&Instance->Link);
  Instance->Handle            = NULL;
  Instance->Service           = DhcpSb;
  Instance->InDestory         = FALSE;
  Instance->CompletionEvent   = NULL;
  Instance->RenewRebindEvent  = NULL;
  Instance->Token             = NULL;
}

EFI_STATUS
EFIAPI
Dhcp4ServiceBindingCreateChild (
  IN EFI_SERVICE_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                    *ChildHandle
  )
/*++

  Routine Description:
    Creates a child handle with a set of DHCP4 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 DHCP4 services are added to the existing 
                   child handle.

  Returns:
    EFI_SUCCES           - The child handle was created with the DHCP4 services
    EFI_OUT_OF_RESOURCES - There are not enough resources to create the child
    other                - The child handle was not created

--*/
{
  DHCP_SERVICE              *DhcpSb;
  DHCP_PROTOCOL             *Instance;
  EFI_STATUS                Status;
  EFI_TPL                   OldTpl;
  VOID                      *Udp4;

  if ((This == NULL) || (ChildHandle == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  Instance = NetAllocatePool (sizeof (*Instance));
  
  if (Instance == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  DhcpSb = DHCP_SERVICE_FROM_THIS (This);
  DhcpInitProtocol (DhcpSb, Instance);

  //
  // Install DHCP4 onto ChildHandle
  //
  Status = gBS->InstallMultipleProtocolInterfaces (
                  ChildHandle,
                  &gEfiDhcp4ProtocolGuid,
                  &Instance->Dhcp4Protocol,
                  NULL
                  );

  if (EFI_ERROR (Status)) {
    NetFreePool (Instance);
    return Status;
  }

  Instance->Handle  = *ChildHandle;

  //
  // Open the Udp4 protocol BY_CHILD.
  //
  Status = gBS->OpenProtocol (
                  DhcpSb->UdpIo->UdpHandle,
                  &gEfiUdp4ProtocolGuid,
                  (VOID **) &Udp4,
                  gDhcp4DriverBinding.DriverBindingHandle,
                  Instance->Handle,
                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
                  );
  if (EFI_ERROR (Status)) {
    gBS->UninstallMultipleProtocolInterfaces (
           Instance->Handle,
           &gEfiDhcp4ProtocolGuid,
           &Instance->Dhcp4Protocol,
           NULL
           );

    NetFreePool (Instance);
    return Status;
  }

  OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
  
  NetListInsertTail (&DhcpSb->Children, &Instance->Link);
  DhcpSb->NumChildren++;

  NET_RESTORE_TPL (OldTpl);

  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
Dhcp4ServiceBindingDestroyChild (
  IN EFI_SERVICE_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                    ChildHandle
  )
/*++

  Routine Description:
    Destroys a child handle with a set of DHCP4 services.

  Arguments:
    This         - Protocol instance pointer.
    ChildHandle  - Handle of the child to destroy

  Returns:
    EFI_SUCCES            - The DHCP4 service is removed from the child handle
    EFI_UNSUPPORTED       - The child handle does not support the DHCP4 service
    EFI_INVALID_PARAMETER - Child handle is not a valid EFI Handle.
    EFI_ACCESS_DENIED     - The child handle could not be destroyed because its 
                            DHCP4 services are being used.
    other                 - The child handle was not destroyed

--*/
{
  DHCP_SERVICE              *DhcpSb;
  DHCP_PROTOCOL             *Instance;
  EFI_DHCP4_PROTOCOL        *Dhcp;
  EFI_TPL                   OldTpl;
  EFI_STATUS                Status;

  if ((This == NULL) || (ChildHandle == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // Retrieve the private context data structures
  //
  Status = gBS->OpenProtocol (
                  ChildHandle,
                  &gEfiDhcp4ProtocolGuid,
                  (VOID **) &Dhcp,
                  gDhcp4DriverBinding.DriverBindingHandle,
                  ChildHandle,
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
                  );

  if (EFI_ERROR (Status)) {
    return EFI_UNSUPPORTED;
  }

  Instance  = DHCP_INSTANCE_FROM_THIS (Dhcp);
  DhcpSb    = DHCP_SERVICE_FROM_THIS (This);

  if (Instance->Service != DhcpSb) {
    return EFI_INVALID_PARAMETER;
  }
  
  //
  // A child can be destoried more than once. For example,
  // Dhcp4DriverBindingStop will destory all of its children.
  // when caller driver is being stopped, it will destory the
  // dhcp child it opens.
  //
  if (Instance->InDestory) {
    return EFI_SUCCESS;
  }

  OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
  Instance->InDestory = TRUE;

  //
  // Close the Udp4 protocol.
  //
  gBS->CloseProtocol (
         DhcpSb->UdpIo->UdpHandle,
         &gEfiUdp4ProtocolGuid,
         gDhcp4DriverBinding.DriverBindingHandle,
         ChildHandle
         );

  //
  // Uninstall the DHCP4 protocol first to enable a top down destruction.
  //
  Status = gBS->UninstallProtocolInterface (
                  ChildHandle,
                  &gEfiDhcp4ProtocolGuid,
                  Dhcp
                  );

  if (EFI_ERROR (Status)) {
    Instance->InDestory = FALSE;
    
    NET_RESTORE_TPL (OldTpl);
    return Status;
  }

  if (DhcpSb->ActiveChild == Instance) {
    DhcpYieldControl (DhcpSb);
  }

  NetListRemoveEntry (&Instance->Link);
  DhcpSb->NumChildren--;

  NET_RESTORE_TPL (OldTpl);

  NetFreePool (Instance);
  return EFI_SUCCESS;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?