mtftp4driver.c

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

C
674
字号

  This              - The MTFTP driver binding protocol
  Controller        - The controller to stop 
  NumberOfChildren  - The number of children
  ChildHandleBuffer - The array of the child handle.

Returns:

  EFI_SUCCESS      - The driver is stopped on the controller.
  EFI_DEVICE_ERROR - Failed to stop the driver on the controller.

--*/
{
  EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;
  MTFTP4_SERVICE                *MtftpSb;
  MTFTP4_PROTOCOL               *Instance;
  EFI_HANDLE                    NicHandle;
  EFI_STATUS                    Status;
  EFI_TPL                       OldTpl;

  //
  // MTFTP driver opens UDP child, So, Controller is a UDP 
  // child handle. Locate the Nic handle first. Then get the
  // MTFTP private data back.
  //
  NicHandle = NetLibGetNicHandle (Controller, &gEfiUdp4ProtocolGuid);
  
  if (NicHandle == NULL) {
    return EFI_SUCCESS;
  }
  
  Status = gBS->OpenProtocol (
                  NicHandle,
                  &gEfiMtftp4ServiceBindingProtocolGuid,
                  (VOID **) &ServiceBinding,
                  This->DriverBindingHandle,
                  NicHandle,
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
                  );

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

  MtftpSb = MTFTP4_SERVICE_FROM_THIS (ServiceBinding);

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

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

  while (!NetListIsEmpty (&MtftpSb->Children)) {
    Instance = NET_LIST_HEAD (&MtftpSb->Children, MTFTP4_PROTOCOL, Link);
    Mtftp4ServiceBindingDestroyChild (ServiceBinding, Instance->Handle);
  }

  if (MtftpSb->ChildrenNum != 0) {
    Status = EFI_DEVICE_ERROR;
    goto ON_ERROR;
  }

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

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

  Mtftp4CleanService (MtftpSb);
  NetFreePool (MtftpSb);

  NET_RESTORE_TPL (OldTpl);
  return EFI_SUCCESS;

ON_ERROR:
  MtftpSb->InDestory = FALSE;

  NET_RESTORE_TPL (OldTpl);
  return Status;
}

VOID
Mtftp4InitProtocol (
  IN MTFTP4_SERVICE         *MtftpSb,
  IN MTFTP4_PROTOCOL        *Instance
  )
/*++

Routine Description:

  Initialize a MTFTP protocol instance which is the child of MtftpSb.

Arguments:

  MtftpSb   - The MTFTP service binding protocol.
  Instance  - The MTFTP instance to initialize.

Returns:

  None

--*/
{
  NetZeroMem (Instance, sizeof (MTFTP4_PROTOCOL));

  Instance->Signature = MTFTP4_PROTOCOL_SIGNATURE;
  NetListInit (&Instance->Link);
  Instance->Mtftp4    = gMtftp4ProtocolTemplate;
  Instance->State     = MTFTP4_STATE_UNCONFIGED;
  Instance->Indestory = FALSE;
  Instance->Service   = MtftpSb;

  NetListInit (&Instance->Blocks);
}

EFI_STATUS
Mtftp4ServiceBindingCreateChild (
  IN EFI_SERVICE_BINDING_PROTOCOL  *This,
  IN OUT EFI_HANDLE                *ChildHandle
  )
/*++

Routine Description:

  Create a MTFTP child for the service binding instance, then
  install the MTFTP protocol to the ChildHandle.

Arguments:

  This        - The MTFTP service binding instance.
  ChildHandle - The Child handle to install the MTFTP protocol.

Returns:

  EFI_INVALID_PARAMETER - The parameter is invalid.
  EFI_OUT_OF_RESOURCES  - Failed to allocate resource for the new child.
  EFI_SUCCESS           - The child is successfully create.

--*/
{
  MTFTP4_SERVICE            *MtftpSb;
  MTFTP4_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;
  }

  MtftpSb = MTFTP4_SERVICE_FROM_THIS (This);
  
  Mtftp4InitProtocol (MtftpSb, Instance);

  Instance->UnicastPort = UdpIoCreatePort (
                            MtftpSb->Controller,
                            MtftpSb->Image,
                            Mtftp4ConfigNullUdp,
                            Instance
                            );

  if (Instance->UnicastPort == NULL) {
    NetFreePool (Instance);
    return EFI_OUT_OF_RESOURCES;
  }
  
  //
  // Install the MTFTP protocol onto ChildHandle
  //
  Status = gBS->InstallMultipleProtocolInterfaces (
                  ChildHandle,
                  &gEfiMtftp4ProtocolGuid,
                  &Instance->Mtftp4,
                  NULL
                  );

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

  Instance->Handle  = *ChildHandle;

  //
  // Open the Udp4 protocol BY_CHILD.
  //
  Status = gBS->OpenProtocol (
                  MtftpSb->ConnectUdp->UdpHandle,
                  &gEfiUdp4ProtocolGuid,
                  (VOID **) &Udp4,
                  gMtftp4DriverBinding.DriverBindingHandle,
                  Instance->Handle,
                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
                  );
  if (EFI_ERROR (Status)) {
    gBS->UninstallMultipleProtocolInterfaces (
           Instance->Handle,
           &gEfiMtftp4ProtocolGuid,
           &Instance->Mtftp4,
           NULL
           );

    goto ON_ERROR;
  }

  //
  // Add it to the parent's child list.
  //
  OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);

  NetListInsertTail (&MtftpSb->Children, &Instance->Link);
  MtftpSb->ChildrenNum++;

  NET_RESTORE_TPL (OldTpl);

ON_ERROR:

  if (EFI_ERROR (Status)) {
    UdpIoFreePort (Instance->UnicastPort);
    NetFreePool (Instance);
  }

  return Status;
}

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

Routine Description:

  Destory one of the service binding's child.

Arguments:

  This        - The service binding instance
  ChildHandle - The child handle to destory

Returns:

  EFI_INVALID_PARAMETER - The parameter is invaid.
  EFI_UNSUPPORTED       - The child may have already been destoried.
  EFI_SUCCESS           - The child is destoried and removed from the 
                          parent's child list.

--*/
{
  MTFTP4_SERVICE            *MtftpSb;
  MTFTP4_PROTOCOL           *Instance;
  EFI_MTFTP4_PROTOCOL       *Mtftp4;
  EFI_STATUS                Status;
  EFI_TPL                   OldTpl;

  if ((This == NULL) || (ChildHandle == NULL)) {
    return EFI_INVALID_PARAMETER;
  }
  
  //
  // Retrieve the private context data structures
  //
  Status = gBS->OpenProtocol (
                  ChildHandle,
                  &gEfiMtftp4ProtocolGuid,
                  (VOID **) &Mtftp4,
                  gMtftp4DriverBinding.DriverBindingHandle,
                  ChildHandle,
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
                  );

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

  Instance  = MTFTP4_PROTOCOL_FROM_THIS (Mtftp4);
  MtftpSb   = MTFTP4_SERVICE_FROM_THIS (This);

  if (Instance->Service != MtftpSb) {
    return EFI_INVALID_PARAMETER;
  }

  if (Instance->Indestory) {
    return EFI_SUCCESS;
  }

  Instance->Indestory = TRUE;

  //
  // Close the Udp4 protocol.
  //
  gBS->CloseProtocol (
         MtftpSb->ConnectUdp->UdpHandle,
         &gEfiUdp4ProtocolGuid,
         gMtftp4DriverBinding.DriverBindingHandle,
         ChildHandle
         );

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

  if (EFI_ERROR (Status)) {
    Instance->Indestory = FALSE;
    return Status;
  }

  OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
  
  Mtftp4CleanOperation (Instance, EFI_DEVICE_ERROR);
  UdpIoFreePort (Instance->UnicastPort);

  NetListRemoveEntry (&Instance->Link);
  MtftpSb->ChildrenNum--;

  NET_RESTORE_TPL (OldTpl);

  NetFreePool (Instance);
  return EFI_SUCCESS;
}

⌨️ 快捷键说明

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