Ejemplo n.º 1
0
/**
  Create the DNS instance and initialize it.

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

  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.
  @retval EFI_SUCCESS            The DNS instance is created.

**/
EFI_STATUS
DnsCreateInstance (
  IN  DNS_SERVICE         *Service,
  OUT DNS_INSTANCE        **Instance
  )
{
  DNS_INSTANCE            *DnsIns;

  *Instance = NULL;
  
  DnsIns = AllocateZeroPool (sizeof (DNS_INSTANCE));
  if (DnsIns == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  DnsIns->Signature = DNS_INSTANCE_SIGNATURE;
  InitializeListHead (&DnsIns->Link);
  DnsIns->State     = DNS_STATE_UNCONFIGED;
  DnsIns->InDestroy = FALSE;
  DnsIns->Service   = Service;
  
  if (Service->IpVersion == IP_VERSION_4) {
    CopyMem (&DnsIns->Dns4, &mDns4Protocol, sizeof (DnsIns->Dns4));
    NetMapInit (&DnsIns->Dns4TxTokens);
  } else {
    CopyMem (&DnsIns->Dns6, &mDns6Protocol, sizeof (DnsIns->Dns6));
    NetMapInit (&DnsIns->Dns6TxTokens);
  }

  DnsIns->UdpIo = UdpIoCreateIo (
                    Service->ControllerHandle, /// NicHandle
                    Service->ImageHandle,
                    DnsConfigNullUdp,
                    Service->IpVersion,
                    DnsIns
                    );
  if (DnsIns->UdpIo == NULL) {
    FreePool (DnsIns);
    return EFI_OUT_OF_RESOURCES;
  }
  
  *Instance = DnsIns;

  return EFI_SUCCESS;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
/**
  Create then initialize a MTFTP service binding instance.

  @param  Controller             The controller to install the MTFTP service
                                 binding on
  @param  Image                  The driver binding image of the MTFTP driver
  @param  Service                The variable to receive the created service
                                 binding instance.

  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resource to create the instance
  @retval EFI_DEVICE_ERROR       Failed to create a NULL UDP port to keep
                                 connection  with UDP.
  @retval EFI_SUCCESS            The service instance is created for the
                                 controller.

**/
EFI_STATUS
Mtftp4CreateService (
  IN     EFI_HANDLE            Controller,
  IN     EFI_HANDLE            Image,
     OUT MTFTP4_SERVICE        **Service
  )
{
  MTFTP4_SERVICE            *MtftpSb;
  EFI_STATUS                Status;

  *Service  = NULL;
  MtftpSb   = AllocatePool (sizeof (MTFTP4_SERVICE));

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

  MtftpSb->Signature      = MTFTP4_SERVICE_SIGNATURE;
  MtftpSb->ServiceBinding = gMtftp4ServiceBindingTemplete;
  MtftpSb->ChildrenNum    = 0;
  InitializeListHead (&MtftpSb->Children);

  MtftpSb->Timer          = NULL;
  MtftpSb->TimerToGetMap  = NULL;
  MtftpSb->Controller     = Controller;
  MtftpSb->Image          = Image;
  MtftpSb->ConnectUdp     = NULL;

  //
  // Create the timer and a udp to be notified when UDP is uninstalled
  //
  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL | EVT_TIMER,
                  TPL_CALLBACK,
                  Mtftp4OnTimerTick,
                  MtftpSb,
                  &MtftpSb->Timer
                  );

  if (EFI_ERROR (Status)) {
    FreePool (MtftpSb);
    return Status;
  }

  //
  // Create the timer used to time out the procedure which is used to
  // get the default IP address.
  //
  Status = gBS->CreateEvent (
                  EVT_TIMER,
                  TPL_CALLBACK,
                  NULL,
                  NULL,
                  &MtftpSb->TimerToGetMap
                  );
  if (EFI_ERROR (Status)) {
    gBS->CloseEvent (MtftpSb->Timer);
    FreePool (MtftpSb);
    return Status;
  }

  MtftpSb->ConnectUdp = UdpIoCreateIo (
                          Controller,
                          Image,
                          Mtftp4ConfigNullUdp,
                          UDP_IO_UDP4_VERSION,
                          NULL
                          );

  if (MtftpSb->ConnectUdp == NULL) {
    gBS->CloseEvent (MtftpSb->TimerToGetMap);
    gBS->CloseEvent (MtftpSb->Timer);
    FreePool (MtftpSb);
    return EFI_DEVICE_ERROR;
  }

  *Service = MtftpSb;
  return EFI_SUCCESS;
}
Ejemplo n.º 4
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));
}
Ejemplo n.º 5
0
/**
  Create then initialize a Dns service binding instance.

  @param  Controller             The controller to install the DNS service
                                 binding on
  @param  Image                  The driver binding image of the DNS driver
  @param  IpVersion              IpVersion for this service
  @param  Service                The variable to receive the created service
                                 binding instance.

  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resource to create the instance.
  @retval EFI_DEVICE_ERROR       Failed to create a NULL UDP port to keep
                                 connection  with UDP.
  @retval EFI_SUCCESS            The service instance is created for the
                                 controller.

**/
EFI_STATUS
DnsCreateService (
  IN     EFI_HANDLE            Controller,
  IN     EFI_HANDLE            Image,
  IN     UINT8                 IpVersion,
     OUT DNS_SERVICE           **Service
  )
{
  EFI_STATUS             Status;
  DNS_SERVICE            *DnsSb;
  
  Status    = EFI_SUCCESS;
  DnsSb     = NULL;

  *Service  = NULL;

  DnsSb = AllocateZeroPool (sizeof (DNS_SERVICE));
  if (DnsSb == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  DnsSb->Signature = DNS_SERVICE_SIGNATURE;

  if (IpVersion == IP_VERSION_4) {
    DnsSb->ServiceBinding = mDns4ServiceBinding;
  } else {
    DnsSb->ServiceBinding = mDns6ServiceBinding;
  }
  
  DnsSb->Dns4ChildrenNum = 0;
  InitializeListHead (&DnsSb->Dns4ChildrenList);

  DnsSb->Dns6ChildrenNum = 0;
  InitializeListHead (&DnsSb->Dns6ChildrenList);

  DnsSb->ControllerHandle = Controller;
  DnsSb->ImageHandle      = Image;

  DnsSb->TimerToGetMap    = NULL;
  
  DnsSb->Timer            = NULL;
 
  DnsSb->IpVersion        = IpVersion;

  //
  // Create the timer used to time out the procedure which is used to
  // get the default IP address.
  //
  if (DnsSb->IpVersion == IP_VERSION_4) {
    Status = gBS->CreateEvent (
                    EVT_TIMER,
                    TPL_CALLBACK,
                    NULL,
                    NULL,
                    &DnsSb->TimerToGetMap
                    );
    if (EFI_ERROR (Status)) {
      FreePool (DnsSb);
      return Status;
    }
  }
  
  //
  // Create the timer to retransmit packets.
  //
  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL | EVT_TIMER,
                  TPL_CALLBACK,
                  DnsOnTimerRetransmit,
                  DnsSb,
                  &DnsSb->Timer
                  );
  if (EFI_ERROR (Status)) {
    if (DnsSb->TimerToGetMap != NULL) {
      gBS->CloseEvent (DnsSb->TimerToGetMap);
    }
    FreePool (DnsSb);
    return Status;
  }
  
  DnsSb->ConnectUdp = NULL;
  DnsSb->ConnectUdp = UdpIoCreateIo (
                        Controller,
                        Image,
                        DnsConfigNullUdp,
                        DnsSb->IpVersion,
                        NULL
                        );
  if (DnsSb->ConnectUdp == NULL) {
    if (DnsSb->TimerToGetMap != NULL) {
      gBS->CloseEvent (DnsSb->TimerToGetMap);
    }
    gBS->CloseEvent (DnsSb->Timer);
    FreePool (DnsSb);
    return EFI_DEVICE_ERROR;
  }

  *Service = DnsSb;
  return Status;
}
Ejemplo n.º 6
0
/**
  Process the OACK packet for Rrq.

  @param[in]  Instance              The pointer to the Mtftp6 instance.
  @param[in]  Packet                The pointer to the received packet.
  @param[in]  Len                   The length of the packet.
  @param[out] UdpPacket             The net buf of received packet.
  @param[out] IsCompleted           If TRUE, the download has been completed.
                                    Otherwise, the download has not been completed.

  @retval EFI_DEVICE_ERROR      Failed to create/start a multicast Udp6 child.
  @retval EFI_TFTP_ERROR        An error happened during the process.
  @retval EFI_SUCCESS           The OACK packet successfully processed.

**/
EFI_STATUS
Mtftp6RrqHandleOack (
  IN  MTFTP6_INSTANCE       *Instance,
  IN  EFI_MTFTP6_PACKET     *Packet,
  IN  UINT32                Len,
  OUT NET_BUF               **UdpPacket,
  OUT BOOLEAN               *IsCompleted
  )
{
  EFI_MTFTP6_OPTION         *Options;
  UINT32                    Count;
  MTFTP6_EXT_OPTION_INFO    ExtInfo;
  EFI_STATUS                Status;
  INTN                      Expected;

  *IsCompleted = FALSE;

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

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

  ZeroMem (&ExtInfo, sizeof (MTFTP6_EXT_OPTION_INFO));

  //
  // Parse the options in the packet.
  //
  Status = Mtftp6ParseStart (Packet, Len, &Count, &Options);

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

  //
  // Parse the extensive options in the packet.
  //
  Status = Mtftp6ParseExtensionOption (Options, Count, FALSE, &ExtInfo);

  if (EFI_ERROR (Status) || !Mtftp6RrqOackValid (Instance, &ExtInfo, &Instance->ExtInfo)) {
    //
    // Don't send an ERROR packet if the error is EFI_OUT_OF_RESOURCES.
    //
    if (Status != EFI_OUT_OF_RESOURCES) {
      //
      // Free the received packet before send new packet in ReceiveNotify,
      // since the udpio might need to be reconfigured.
      //
      NetbufFree (*UdpPacket);
      *UdpPacket = NULL;
      //
      // Send the Mtftp6 error message if invalid packet.
      //
      Mtftp6SendError (
        Instance,
        EFI_MTFTP6_ERRORCODE_ILLEGAL_OPERATION,
        (UINT8 *) "Mal-formated OACK packet"
        );
    }

    return EFI_TFTP_ERROR;
  }

  if ((ExtInfo.BitMap & MTFTP6_OPT_MCAST_BIT) != 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->IsMaster = ExtInfo.IsMaster;

    if (NetIp6IsUnspecifiedAddr (&Instance->McastIp)) {
      if (NetIp6IsUnspecifiedAddr (&ExtInfo.McastIp) || ExtInfo.McastPort == 0) {
        //
        // Free the received packet before send new packet in ReceiveNotify,
        // since the udpio might need to be reconfigured.
        //
        NetbufFree (*UdpPacket);
        *UdpPacket = NULL;
        //
        // Send the Mtftp6 error message if invalid multi-cast setting.
        //
        Mtftp6SendError (
          Instance,
          EFI_MTFTP6_ERRORCODE_ILLEGAL_OPERATION,
          (UINT8 *) "Illegal multicast setting"
          );

        return EFI_TFTP_ERROR;
      }

      //
      // Create a UDP child then start receive the multicast from it.
      //
      CopyMem (
        &Instance->McastIp,
        &ExtInfo.McastIp,
        sizeof (EFI_IP_ADDRESS)
        );

      Instance->McastPort  = ExtInfo.McastPort;
      Instance->McastUdpIo = UdpIoCreateIo (
                               Instance->Service->Controller,
                               Instance->Service->Image,
                               Mtftp6RrqConfigMcastUdpIo,
                               UDP_IO_UDP6_VERSION,
                               Instance
                               );

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

      Status = UdpIoRecvDatagram (
                 Instance->McastUdpIo,
                 Mtftp6RrqInput,
                 Instance,
                 0
                 );

      if (EFI_ERROR (Status)) {
        //
        // Free the received packet before send new packet in ReceiveNotify,
        // since the udpio might need to be reconfigured.
        //
        NetbufFree (*UdpPacket);
        *UdpPacket = NULL;
        //
        // Send the Mtftp6 error message if failed to create Udp6Io to receive.
        //
        Mtftp6SendError (
          Instance,
          EFI_MTFTP6_ERRORCODE_ACCESS_VIOLATION,
          (UINT8 *) "Failed to create socket to receive multicast packet"
          );

        return Status;
      }

      //
      // Update the parameters used.
      //
      if (ExtInfo.BlkSize != 0) {
        Instance->BlkSize = ExtInfo.BlkSize;
      }

      if (ExtInfo.Timeout != 0) {
        Instance->Timeout = ExtInfo.Timeout;
      }
    }

  } else {

    Instance->IsMaster = TRUE;

    if (ExtInfo.BlkSize != 0) {
      Instance->BlkSize = ExtInfo.BlkSize;
    }

    if (ExtInfo.Timeout != 0) {
      Instance->Timeout = ExtInfo.Timeout;
    }
  }

  //
  // Free the received packet before send new packet in ReceiveNotify,
  // since the udpio might need to be reconfigured.
  //
  NetbufFree (*UdpPacket);
  *UdpPacket = NULL;
  //
  // Send an ACK to (Expected - 1) which is 0 for unicast download,
  // or tell the server we want to receive the Expected block.
  //
  return Mtftp6RrqSendAck (Instance, (UINT16) (Expected - 1));
}