Пример #1
0
/**
  Release all the resource used the MTFTP service binding instance.

  @param  MtftpSb                The MTFTP service binding instance.

**/
VOID
Mtftp4CleanService (
  IN MTFTP4_SERVICE     *MtftpSb
  )
{
  UdpIoFreeIo (MtftpSb->ConnectUdp);
  gBS->CloseEvent (MtftpSb->TimerToGetMap);
  gBS->CloseEvent (MtftpSb->Timer);
}
Пример #2
0
/**
  Release all the resource used the DNS service binding instance.

  @param  DnsSb                The Dns service binding instance.

**/
VOID
DnsDestroyService (
  IN DNS_SERVICE     *DnsSb
  )
{
  UdpIoFreeIo (DnsSb->ConnectUdp);
  
  if (DnsSb->TimerToGetMap != NULL){
    gBS->CloseEvent (DnsSb->TimerToGetMap);
  }

  if (DnsSb->Timer != NULL){
    gBS->CloseEvent (DnsSb->Timer);
  }

  FreePool (DnsSb);
}
Пример #3
0
/**
  Destroy the DNS instance and recycle the resources.

  @param[in]  Instance        The pointer to the DNS instance.

**/
VOID
DnsDestroyInstance (
  IN DNS_INSTANCE         *Instance
  )
{
  ZeroMem (&Instance->Dns4CfgData, sizeof (EFI_DNS4_CONFIG_DATA));
  
  ZeroMem (&Instance->Dns6CfgData, sizeof (EFI_DNS6_CONFIG_DATA));
  
  if (!NetMapIsEmpty (&Instance->Dns4TxTokens)) {
    Dns4InstanceCancelToken (Instance, NULL);
  }

  if (!NetMapIsEmpty (&Instance->Dns6TxTokens)) {
    Dns6InstanceCancelToken (Instance, NULL);
  }
  
  if (Instance->UdpIo!= NULL) {
    UdpIoFreeIo (Instance->UdpIo);
  }
  
  FreePool (Instance);
}
Пример #4
0
/**
  Destroy one of the service binding's child.

  @param  This                   The service binding instance
  @param  ChildHandle            The child handle to destroy

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

**/
EFI_STATUS
EFIAPI
Mtftp4ServiceBindingDestroyChild (
  IN EFI_SERVICE_BINDING_PROTOCOL *This,
  IN EFI_HANDLE                   ChildHandle
  )
{
  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->InDestroy) {
    return EFI_SUCCESS;
  }

  Instance->InDestroy = TRUE;

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

  gBS->CloseProtocol (
         Instance->UnicastPort->UdpHandle,
         &gEfiUdp4ProtocolGuid,
         gMtftp4DriverBinding.DriverBindingHandle,
         ChildHandle
         );

  if (Instance->McastUdpPort != NULL) {
    gBS->CloseProtocol (
           Instance->McastUdpPort->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->InDestroy = FALSE;
    return Status;
  }

  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);

  Mtftp4CleanOperation (Instance, EFI_DEVICE_ERROR);
  UdpIoFreeIo (Instance->UnicastPort);

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

  gBS->RestoreTPL (OldTpl);

  FreePool (Instance);
  return EFI_SUCCESS;
}
Пример #5
0
/**
  Create a MTFTP child for the service binding instance, then
  install the MTFTP protocol to the ChildHandle.

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

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

**/
EFI_STATUS
EFIAPI
Mtftp4ServiceBindingCreateChild (
  IN EFI_SERVICE_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                *ChildHandle
  )
{
  MTFTP4_SERVICE            *MtftpSb;
  MTFTP4_PROTOCOL           *Instance;
  EFI_STATUS                Status;
  EFI_TPL                   OldTpl;
  VOID                      *Udp4;

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

  Instance = AllocatePool (sizeof (*Instance));

  if (Instance == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  MtftpSb = MTFTP4_SERVICE_FROM_THIS (This);

  Mtftp4InitProtocol (MtftpSb, Instance);

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

  if (Instance->UnicastPort == NULL) {
    FreePool (Instance);
    return EFI_OUT_OF_RESOURCES;
  }

  //
  // Install the MTFTP protocol onto ChildHandle
  //
  Status = gBS->InstallMultipleProtocolInterfaces (
                  ChildHandle,
                  &gEfiMtftp4ProtocolGuid,
                  &Instance->Mtftp4,
                  NULL
                  );

  if (EFI_ERROR (Status)) {
    UdpIoFreeIo (Instance->UnicastPort);
    FreePool (Instance);
    return Status;
  }

  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)) {
    goto ON_ERROR;
  }

  //
  // Open the Udp4 protocol by child.
  //
  Status = gBS->OpenProtocol (
                  Instance->UnicastPort->UdpHandle,
                  &gEfiUdp4ProtocolGuid,
                  (VOID **) &Udp4,
                  gMtftp4DriverBinding.DriverBindingHandle,
                  Instance->Handle,
                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
                  );
  if (EFI_ERROR (Status)) {
    //
    // Close the Udp4 protocol.
    //
    gBS->CloseProtocol (
           MtftpSb->ConnectUdp->UdpHandle,
           &gEfiUdp4ProtocolGuid,
           gMtftp4DriverBinding.DriverBindingHandle,
           ChildHandle
           );
    goto ON_ERROR;
  }

  //
  // Add it to the parent's child list.
  //
  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);

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

  gBS->RestoreTPL (OldTpl);

  return EFI_SUCCESS;

ON_ERROR:
  if (Instance->Handle != NULL) {
    gBS->UninstallMultipleProtocolInterfaces (
           Instance->Handle,
           &gEfiMtftp4ProtocolGuid,
           &Instance->Mtftp4,
           NULL
           );
  }

  UdpIoFreeIo (Instance->UnicastPort);
  FreePool (Instance);

  return Status;
}
Пример #6
0
/**
  Function to process the OACK. 
  
  It will first validate the OACK packet, then update the various negotiated parameters.

  @param  Instance              The download MTFTP session
  @param  Packet                The packet received
  @param  Len                   The packet length
  @param  Multicast             Whether this packet is received as a multicast
  @param  Completed             Returns whether the download has completed. NOT
                                used  by this function.

  @retval EFI_DEVICE_ERROR      Failed to create/start a multicast UDP child
  @retval EFI_TFTP_ERROR        Some error happened during the process
  @retval EFI_SUCCESS           The OACK is successfully processed.

**/
EFI_STATUS
Mtftp4RrqHandleOack (
  IN OUT MTFTP4_PROTOCOL       *Instance,
  IN     EFI_MTFTP4_PACKET     *Packet,
  IN     UINT32                Len,
  IN     BOOLEAN               Multicast,
     OUT BOOLEAN               *Completed
  )
{
  MTFTP4_OPTION             Reply;
  EFI_STATUS                Status;
  INTN                      Expected;
  EFI_UDP4_PROTOCOL         *Udp4;

  *Completed = FALSE;

  //
  // If already started the master download, don't change the
  // setting. Master download always succeeds.
  //
  Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);
  ASSERT (Expected != -1);

  if (Instance->Master && (Expected != 1)) {
    return EFI_SUCCESS;
  }

  //
  // Parse and validate the options from server
  //
  ZeroMem (&Reply, sizeof (MTFTP4_OPTION));

  Status = Mtftp4ParseOptionOack (Packet, Len, &Reply);

  if (EFI_ERROR (Status) ||
      !Mtftp4RrqOackValid (Instance, &Reply, &Instance->RequestOption)) {
    //
    // Don't send an ERROR packet if the error is EFI_OUT_OF_RESOURCES.
    //
    if (Status != EFI_OUT_OF_RESOURCES) {
      Mtftp4SendError (
        Instance,
        EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION,
        (UINT8 *) "Mal-formated OACK packet"
        );
    }

    return EFI_TFTP_ERROR;
  }

  if ((Reply.Exist & MTFTP4_MCAST_EXIST) != 0) {

    //
    // Save the multicast info. Always update the Master, only update the
    // multicast IP address, block size, timeoute at the first time. If IP
    // address is updated, create a UDP child to receive the multicast.
    //
    Instance->Master = Reply.Master;

    if (Instance->McastIp == 0) {
      if ((Reply.McastIp == 0) || (Reply.McastPort == 0)) {
        Mtftp4SendError (
          Instance,
          EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION,
          (UINT8 *) "Illegal multicast setting"
          );

        return EFI_TFTP_ERROR;
      }

      //
      // Create a UDP child then start receive the multicast from it.
      //
      Instance->McastIp      = Reply.McastIp;
      Instance->McastPort    = Reply.McastPort;
      if (Instance->McastUdpPort == NULL) {
        Instance->McastUdpPort = UdpIoCreateIo (
                                   Instance->Service->Controller,
                                   Instance->Service->Image,
                                   Mtftp4RrqConfigMcastPort,
                                   UDP_IO_UDP4_VERSION,
                                   Instance
                                   );
        if (Instance->McastUdpPort != NULL) {
          Status = gBS->OpenProtocol (
                          Instance->McastUdpPort->UdpHandle,
                          &gEfiUdp4ProtocolGuid,
                          (VOID **) &Udp4,
                          Instance->Service->Image,
                          Instance->Handle,
                          EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
                          );
          if (EFI_ERROR (Status)) {
            UdpIoFreeIo (Instance->McastUdpPort);
            Instance->McastUdpPort = NULL;
            return EFI_DEVICE_ERROR;
          }
        }
      }


      if (Instance->McastUdpPort == NULL) {
        return EFI_DEVICE_ERROR;
      }

      Status = UdpIoRecvDatagram (Instance->McastUdpPort, Mtftp4RrqInput, Instance, 0);

      if (EFI_ERROR (Status)) {
        Mtftp4SendError (
          Instance,
          EFI_MTFTP4_ERRORCODE_ACCESS_VIOLATION,
          (UINT8 *) "Failed to create socket to receive multicast packet"
          );

        return Status;
      }
    
      //
      // Update the parameters used.
      //
      if (Reply.BlkSize != 0) {
        Instance->BlkSize = Reply.BlkSize;
      }
      
      if (Reply.Timeout != 0) {
        Instance->Timeout = Reply.Timeout;
      }  
    }    
    
  } else {
    Instance->Master = TRUE;
    
    if (Reply.BlkSize != 0) {
      Instance->BlkSize = Reply.BlkSize;
    }

    if (Reply.Timeout != 0) {
      Instance->Timeout = Reply.Timeout;
    }
  }
  
  //
  // Send an ACK to (Expected - 1) which is 0 for unicast download,
  // or tell the server we want to receive the Expected block.
  //
  return Mtftp4RrqSendAck (Instance, (UINT16) (Expected - 1));
}