Пример #1
0
/**
  Create a child for the service identified by its service binding protocol GUID
  and get from the child the interface of the protocol identified by its GUID.

  @param[in]   ControllerHandle            Controller handle.
  @param[in]   ServiceBindingProtocolGuid  Service binding protocol GUID of the
                                           service to be created.
  @param[in]   ProtocolGuid                GUID of the protocol to be open.
  @param[out]  ChildHandle                 Address where the handler of the
                                           created child is returned. NULL is
                                           returned in case of error.
  @param[out]  Interface                   Address where a pointer to the
                                           protocol interface is returned in
                                           case of success.

  @return  EFI_SUCCESS  The child was created and the protocol opened.
  @return  Others       Either the creation of the child or the opening
                        of the protocol failed.
**/
STATIC
EFI_STATUS
CreateServiceChildAndOpenProtocol (
  IN   EFI_HANDLE  ControllerHandle,
  IN   EFI_GUID    *ServiceBindingProtocolGuid,
  IN   EFI_GUID    *ProtocolGuid,
  OUT  EFI_HANDLE  *ChildHandle,
  OUT  VOID        **Interface
  )
{
  EFI_STATUS  Status;

  *ChildHandle = NULL;
  Status = NetLibCreateServiceChild (
             ControllerHandle,
             gImageHandle,
             ServiceBindingProtocolGuid,
             ChildHandle
             );
  if (!EFI_ERROR (Status)) {
    Status = gBS->OpenProtocol (
                    *ChildHandle,
                    ProtocolGuid,
                    Interface,
                    gImageHandle,
                    ControllerHandle,
                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
                    );
    if (EFI_ERROR (Status)) {
      NetLibDestroyServiceChild (
        ControllerHandle,
        gImageHandle,
        ServiceBindingProtocolGuid,
        *ChildHandle
        );
      *ChildHandle = NULL;
    }
  }

  return Status;
}
Пример #2
0
/**
  Create the opened instances based on IPv6.

  @param[in]  This              Pointer to EFI_DRIVER_BINDING_PROTOCOL.
  @param[in]  ControllerHandle  Handle of the child to destroy.
  @param[in]  Private Handle    Pointer to PXEBC_PRIVATE_DATA.

  @retval EFI_SUCCESS           The instances based on IPv6 were all created successfully.
  @retval Others                An unexpected error occurred.

**/
EFI_STATUS
PxeBcCreateIp6Children (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   ControllerHandle,
  IN PXEBC_PRIVATE_DATA           *Private
  )
{
  EFI_STATUS                      Status;
  IPv6_DEVICE_PATH                Ip6Node;
  EFI_UDP6_CONFIG_DATA            *Udp6CfgData;
  EFI_IP6_CONFIG_DATA             *Ip6CfgData;
  EFI_IP6_MODE_DATA               Ip6ModeData;
  PXEBC_PRIVATE_PROTOCOL          *Id;
  EFI_SIMPLE_NETWORK_PROTOCOL     *Snp;
  UINTN                           Index;

  if (Private->Ip6Nic != NULL) {
    //
    // Already created before.
    //
    return EFI_SUCCESS;
  }

  Private->Ip6Nic = AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC));

  if (Private->Ip6Nic == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  Private->Ip6Nic->Private   = Private;
  Private->Ip6Nic->Signature = PXEBC_VIRTUAL_NIC_SIGNATURE;

  //
  // Create Dhcp6 child and open Dhcp6 protocol for PxeBc->Dhcp.
  //
  Status = NetLibCreateServiceChild (
             ControllerHandle,
             This->DriverBindingHandle,
             &gEfiDhcp6ServiceBindingProtocolGuid,
             &Private->Dhcp6Child
             );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Status = gBS->OpenProtocol (
                  Private->Dhcp6Child,
                  &gEfiDhcp6ProtocolGuid,
                  (VOID **) &Private->Dhcp6,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  //
  // Generate a random IAID for the Dhcp6 assigned address.
  //
  Private->IaId = NET_RANDOM (NetRandomInitSeed ());
  if (Private->Snp != NULL) {
    for (Index = 0; Index < Private->Snp->Mode->HwAddressSize; Index++) {
      Private->IaId |= (Private->Snp->Mode->CurrentAddress.Addr[Index] << ((Index << 3) & 31));
    }  
  }

  //
  // Create Mtftp6 child and open Mtftp6 protocol for PxeBc->Mtftp.
  //
  Status = NetLibCreateServiceChild (
             ControllerHandle,
             This->DriverBindingHandle,
             &gEfiMtftp6ServiceBindingProtocolGuid,
             &Private->Mtftp6Child
             );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Status = gBS->OpenProtocol (
                  Private->Mtftp6Child,
                  &gEfiMtftp6ProtocolGuid,
                  (VOID **) &Private->Mtftp6,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  //
  // Create Udp6 child and open Udp6 protocol for PxeBc->UdpRead.
  //
  Status = NetLibCreateServiceChild (
             ControllerHandle,
             This->DriverBindingHandle,
             &gEfiUdp6ServiceBindingProtocolGuid,
             &Private->Udp6ReadChild
             );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Status = gBS->OpenProtocol (
                  Private->Udp6ReadChild,
                  &gEfiUdp6ProtocolGuid,
                  (VOID **) &Private->Udp6Read,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  //
  // Create Udp6 child and open Udp6 protocol for PxeBc->UdpWrite.
  //
  Status = NetLibCreateServiceChild (
             ControllerHandle,
             This->DriverBindingHandle,
             &gEfiUdp6ServiceBindingProtocolGuid,
             &Private->Udp6WriteChild
             );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Status = gBS->OpenProtocol (
                  Private->Udp6WriteChild,
                  &gEfiUdp6ProtocolGuid,
                  (VOID **) &Private->Udp6Write,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  //
  // Create Ip6 child and open Ip6 protocol for background ICMP6 packets.
  //
  Status = NetLibCreateServiceChild (
             ControllerHandle,
             This->DriverBindingHandle,
             &gEfiIp6ServiceBindingProtocolGuid,
             &Private->Ip6Child
             );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Status = gBS->OpenProtocol (
                  Private->Ip6Child,
                  &gEfiIp6ProtocolGuid,
                  (VOID **) &Private->Ip6,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  //
  // Get max packet size from Ip6 to calculate block size for Tftp later.
  //
  Status = Private->Ip6->GetModeData (Private->Ip6, &Ip6ModeData, NULL, NULL);
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Private->Ip6MaxPacketSize = Ip6ModeData.MaxPacketSize;

  //
  // Locate Ip6->Ip6Config and store it for set IPv6 address.
  //
  Status = gBS->HandleProtocol (
                  ControllerHandle,
                  &gEfiIp6ConfigProtocolGuid,
                  (VOID **) &Private->Ip6Cfg
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  //
  // Create a device path node for Ipv6 virtual nic, and append it.
  //
  ZeroMem (&Ip6Node, sizeof (IPv6_DEVICE_PATH));
  Ip6Node.Header.Type     = MESSAGING_DEVICE_PATH;
  Ip6Node.Header.SubType  = MSG_IPv6_DP;
  Ip6Node.PrefixLength    = IP6_PREFIX_LENGTH;

  SetDevicePathNodeLength (&Ip6Node.Header, sizeof (Ip6Node));

  Private->Ip6Nic->DevicePath = AppendDevicePathNode (Private->DevicePath, &Ip6Node.Header);

  if (Private->Ip6Nic->DevicePath == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_ERROR;
  }

  CopyMem (
    &Private->Ip6Nic->LoadFile,
    &gLoadFileProtocolTemplate,
    sizeof (EFI_LOAD_FILE_PROTOCOL)
    );

  //
  // Create a new handle for IPv6 virtual nic,
  // and install PxeBaseCode, LoadFile and DevicePath protocols.
  //
  Status = gBS->InstallMultipleProtocolInterfaces (
                  &Private->Ip6Nic->Controller,
                  &gEfiDevicePathProtocolGuid,
                  Private->Ip6Nic->DevicePath,
                  &gEfiLoadFileProtocolGuid,
                  &Private->Ip6Nic->LoadFile,
                  &gEfiPxeBaseCodeProtocolGuid,
                  &Private->PxeBc,
                  NULL
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }
  
  if (Private->Snp != NULL) {
    //
    // Install SNP protocol on purpose is for some OS loader backward
    // compatibility consideration.
    //
    Status = gBS->InstallProtocolInterface (
                    &Private->Ip6Nic->Controller,
                    &gEfiSimpleNetworkProtocolGuid,
                    EFI_NATIVE_INTERFACE,
                    Private->Snp
                    );
    if (EFI_ERROR (Status)) {
      goto ON_ERROR;
    }

    //
    // Open SNP on the child handle BY_DRIVER. It will prevent any additionally 
    // layering to perform the experiment.
    //
    Status = gBS->OpenProtocol (
                    Private->Ip6Nic->Controller,
                    &gEfiSimpleNetworkProtocolGuid,
                    (VOID **) &Snp,
                    This->DriverBindingHandle,
                    Private->Ip6Nic->Controller,
                    EFI_OPEN_PROTOCOL_BY_DRIVER
                    );
    if (EFI_ERROR (Status)) {
      goto ON_ERROR;
    }
  }

  //
  // Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between
  // real NIC handle and the virtual IPv6 NIC handle.
  //
  Status = gBS->OpenProtocol (
                  ControllerHandle,
                  &gEfiCallerIdGuid,
                  (VOID **) &Id,
                  This->DriverBindingHandle,
                  Private->Ip6Nic->Controller,
                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  //
  // Set IPv6 avaiable flag and set default configure data for
  // Udp6Read and Ip6 instance.
  //
  Private->Mode.Ipv6Available     = TRUE;
  Udp6CfgData                     = &Private->Udp6CfgData;
  Ip6CfgData                      = &Private->Ip6CfgData;

  Udp6CfgData->AcceptAnyPort      = TRUE;
  Udp6CfgData->AllowDuplicatePort = TRUE;
  Udp6CfgData->HopLimit           = PXEBC_DEFAULT_HOPLIMIT;
  Udp6CfgData->ReceiveTimeout     = PXEBC_DEFAULT_LIFETIME;
  Udp6CfgData->TransmitTimeout    = PXEBC_DEFAULT_LIFETIME;

  Ip6CfgData->AcceptIcmpErrors    = TRUE;
  Ip6CfgData->DefaultProtocol     = IP6_ICMP;
  Ip6CfgData->HopLimit            = PXEBC_DEFAULT_HOPLIMIT;
  Ip6CfgData->ReceiveTimeout      = PXEBC_DEFAULT_LIFETIME;
  Ip6CfgData->TransmitTimeout     = PXEBC_DEFAULT_LIFETIME;

  return EFI_SUCCESS;

ON_ERROR:
  PxeBcDestroyIp6Children (This, Private);
  return Status;
}
Пример #3
0
/**
  Create the opened instances based on IPv4.

  @param[in]  This              Pointer to EFI_DRIVER_BINDING_PROTOCOL.
  @param[in]  ControllerHandle  Handle of the child to destroy.
  @param[in]  Private Handle    Pointer to PXEBC_PRIVATE_DATA.

  @retval EFI_SUCCESS           The instances based on IPv4 were all created successfully.
  @retval Others                An unexpected error occurred.

**/
EFI_STATUS
PxeBcCreateIp4Children (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   ControllerHandle,
  IN PXEBC_PRIVATE_DATA           *Private
  )
{
  EFI_STATUS                      Status;
  IPv4_DEVICE_PATH                Ip4Node;
  EFI_PXE_BASE_CODE_MODE          *Mode;
  EFI_UDP4_CONFIG_DATA            *Udp4CfgData;
  EFI_IP4_CONFIG_DATA             *Ip4CfgData;
  EFI_IP4_MODE_DATA               Ip4ModeData;
  PXEBC_PRIVATE_PROTOCOL          *Id;
  EFI_SIMPLE_NETWORK_PROTOCOL     *Snp;

  if (Private->Ip4Nic != NULL) {
    //
    // Already created before.
    //
    return EFI_SUCCESS;
  }

  //
  // Create Dhcp4 child and open Dhcp4 protocol for PxeBc->Dhcp.
  //
  Status = NetLibCreateServiceChild (
             ControllerHandle,
             This->DriverBindingHandle,
             &gEfiDhcp4ServiceBindingProtocolGuid,
             &Private->Dhcp4Child
             );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Status = gBS->OpenProtocol (
                  Private->Dhcp4Child,
                  &gEfiDhcp4ProtocolGuid,
                  (VOID **) &Private->Dhcp4,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  //
  // Create Mtftp4 child and open Mtftp4 protocol for PxeBc->Mtftp.
  //
  Status = NetLibCreateServiceChild (
             ControllerHandle,
             This->DriverBindingHandle,
             &gEfiMtftp4ServiceBindingProtocolGuid,
             &Private->Mtftp4Child
             );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Status = gBS->OpenProtocol (
                  Private->Mtftp4Child,
                  &gEfiMtftp4ProtocolGuid,
                  (VOID **) &Private->Mtftp4,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  //
  // Create Udp4 child and open Udp4 protocol for PxeBc->UdpRead.
  //
  Status = NetLibCreateServiceChild (
             ControllerHandle,
             This->DriverBindingHandle,
             &gEfiUdp4ServiceBindingProtocolGuid,
             &Private->Udp4ReadChild
             );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Status = gBS->OpenProtocol (
                  Private->Udp4ReadChild,
                  &gEfiUdp4ProtocolGuid,
                  (VOID **) &Private->Udp4Read,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  //
  // Create Udp4 child and open Udp4 protocol for PxeBc->UdpWrite.
  //
  Status = NetLibCreateServiceChild (
             ControllerHandle,
             This->DriverBindingHandle,
             &gEfiUdp4ServiceBindingProtocolGuid,
             &Private->Udp4WriteChild
             );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Status = gBS->OpenProtocol (
                  Private->Udp4WriteChild,
                  &gEfiUdp4ProtocolGuid,
                  (VOID **) &Private->Udp4Write,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  //
  // Create Arp child and open Arp protocol for PxeBc->Arp.
  //
  Status = NetLibCreateServiceChild (
             ControllerHandle,
             This->DriverBindingHandle,
             &gEfiArpServiceBindingProtocolGuid,
             &Private->ArpChild
             );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Status = gBS->OpenProtocol (
                  Private->ArpChild,
                  &gEfiArpProtocolGuid,
                  (VOID **) &Private->Arp,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  //
  // Create Ip4 child and open Ip4 protocol for background ICMP packets.
  //
  Status = NetLibCreateServiceChild (
             ControllerHandle,
             This->DriverBindingHandle,
             &gEfiIp4ServiceBindingProtocolGuid,
             &Private->Ip4Child
             );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Status = gBS->OpenProtocol (
                  Private->Ip4Child,
                  &gEfiIp4ProtocolGuid,
                  (VOID **) &Private->Ip4,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  //
  // Get max packet size from Ip4 to calculate block size for Tftp later.
  //
  Status = Private->Ip4->GetModeData (Private->Ip4, &Ip4ModeData, NULL, NULL);
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Private->Ip4MaxPacketSize = Ip4ModeData.MaxPacketSize;

  Private->Ip4Nic = AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC));
  if (Private->Ip4Nic == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  Private->Ip4Nic->Private   = Private;
  Private->Ip4Nic->Signature = PXEBC_VIRTUAL_NIC_SIGNATURE;

  //
  // Create a device path node for Ipv4 virtual nic, and append it.
  //
  ZeroMem (&Ip4Node, sizeof (IPv4_DEVICE_PATH));
  Ip4Node.Header.Type     = MESSAGING_DEVICE_PATH;
  Ip4Node.Header.SubType  = MSG_IPv4_DP;
  Ip4Node.StaticIpAddress = FALSE;

  SetDevicePathNodeLength (&Ip4Node.Header, sizeof (Ip4Node));

  Private->Ip4Nic->DevicePath = AppendDevicePathNode (Private->DevicePath, &Ip4Node.Header);

  if (Private->Ip4Nic->DevicePath == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_ERROR;
  }

  CopyMem (
    &Private->Ip4Nic->LoadFile,
    &gLoadFileProtocolTemplate,
    sizeof (EFI_LOAD_FILE_PROTOCOL)
    );

  //
  // Create a new handle for IPv4 virtual nic,
  // and install PxeBaseCode, LoadFile and DevicePath protocols.
  //
  Status = gBS->InstallMultipleProtocolInterfaces (
                  &Private->Ip4Nic->Controller,
                  &gEfiDevicePathProtocolGuid,
                  Private->Ip4Nic->DevicePath,
                  &gEfiLoadFileProtocolGuid,
                  &Private->Ip4Nic->LoadFile,
                  &gEfiPxeBaseCodeProtocolGuid,
                  &Private->PxeBc,
                  NULL
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  if (Private->Snp != NULL) {
    //
    // Install SNP protocol on purpose is for some OS loader backward
    // compatibility consideration.
    //
    Status = gBS->InstallProtocolInterface (
                    &Private->Ip4Nic->Controller,
                    &gEfiSimpleNetworkProtocolGuid,
                    EFI_NATIVE_INTERFACE,
                    Private->Snp
                    );
    if (EFI_ERROR (Status)) {
      goto ON_ERROR;
    }

    //
    // Open SNP on the child handle BY_DRIVER. It will prevent any additionally 
    // layering to perform the experiment.
    //
    Status = gBS->OpenProtocol (
                    Private->Ip4Nic->Controller,
                    &gEfiSimpleNetworkProtocolGuid,
                    (VOID **) &Snp,
                    This->DriverBindingHandle,
                    Private->Ip4Nic->Controller,
                    EFI_OPEN_PROTOCOL_BY_DRIVER
                    );
    if (EFI_ERROR (Status)) {
      goto ON_ERROR;
    }
  }

  //
  // Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between
  // real NIC handle and the virtual IPv4 NIC handle.
  //
  Status = gBS->OpenProtocol (
                  ControllerHandle,
                  &gEfiCallerIdGuid,
                  (VOID **) &Id,
                  This->DriverBindingHandle,
                  Private->Ip4Nic->Controller,
                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  //
  // Set default configure data for Udp4Read and Ip4 instance.
  //
  Mode                            = Private->PxeBc.Mode;
  Udp4CfgData                     = &Private->Udp4CfgData;
  Ip4CfgData                      = &Private->Ip4CfgData;

  Udp4CfgData->AcceptBroadcast    = FALSE;
  Udp4CfgData->AcceptAnyPort      = TRUE;
  Udp4CfgData->AllowDuplicatePort = TRUE;
  Udp4CfgData->TypeOfService      = Mode->ToS;
  Udp4CfgData->TimeToLive         = Mode->TTL;
  Udp4CfgData->ReceiveTimeout     = PXEBC_DEFAULT_LIFETIME;
  Udp4CfgData->TransmitTimeout    = PXEBC_DEFAULT_LIFETIME;

  Ip4CfgData->AcceptIcmpErrors    = TRUE;
  Ip4CfgData->DefaultProtocol     = EFI_IP_PROTO_ICMP;
  Ip4CfgData->TypeOfService       = Mode->ToS;
  Ip4CfgData->TimeToLive          = Mode->TTL;
  Ip4CfgData->ReceiveTimeout      = PXEBC_DEFAULT_LIFETIME;
  Ip4CfgData->TransmitTimeout     = PXEBC_DEFAULT_LIFETIME;

  return EFI_SUCCESS;

ON_ERROR:
  PxeBcDestroyIp4Children (This, Private);
  return Status;
}
Пример #4
0
/**
  Intiialize the HTTP_PROTOCOL structure to the unconfigured state.

  @param[in]       HttpSb               The HTTP service private instance.
  @param[in, out]  HttpInstance         Pointer to HTTP_PROTOCOL structure.

  @retval EFI_SUCCESS       HTTP_PROTOCOL structure is initialized successfully.
  @retval Others            Other error as indicated.

**/
EFI_STATUS
HttpInitProtocol (
    IN     HTTP_SERVICE            *HttpSb,
    IN OUT HTTP_PROTOCOL           *HttpInstance
)
{
    EFI_STATUS                     Status;
    VOID                           *Interface;

    ASSERT ((HttpSb != NULL) && (HttpInstance != NULL));

    HttpInstance->Signature = HTTP_PROTOCOL_SIGNATURE;
    CopyMem (&HttpInstance->Http, &mEfiHttpTemplate, sizeof (HttpInstance->Http));
    HttpInstance->Service = HttpSb;

    //
    // Create TCP child.
    //
    Status = NetLibCreateServiceChild (
                 HttpInstance->Service->ControllerHandle,
                 HttpInstance->Service->ImageHandle,
                 &gEfiTcp4ServiceBindingProtocolGuid,
                 &HttpInstance->TcpChildHandle
             );

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

    Status = gBS->OpenProtocol (
                 HttpInstance->TcpChildHandle,
                 &gEfiTcp4ProtocolGuid,
                 (VOID **) &Interface,
                 HttpInstance->Service->ImageHandle,
                 HttpInstance->Service->ControllerHandle,
                 EFI_OPEN_PROTOCOL_BY_DRIVER
             );

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

    Status = gBS->OpenProtocol (
                 HttpInstance->TcpChildHandle,
                 &gEfiTcp4ProtocolGuid,
                 (VOID **) &HttpInstance->Tcp4,
                 HttpInstance->Service->ImageHandle,
                 HttpInstance->Handle,
                 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
             );
    if (EFI_ERROR(Status)) {
        goto ON_ERROR;
    }

    HttpInstance->Url = AllocateZeroPool (HTTP_URL_BUFFER_LEN);
    if (HttpInstance->Url == NULL) {
        Status = EFI_OUT_OF_RESOURCES;
        goto ON_ERROR;
    }

    NetMapInit (&HttpInstance->TxTokens);
    NetMapInit (&HttpInstance->RxTokens);

    return EFI_SUCCESS;

ON_ERROR:

    if (HttpInstance->TcpChildHandle != NULL) {
        gBS->CloseProtocol (
            HttpInstance->TcpChildHandle,
            &gEfiTcp4ProtocolGuid,
            HttpInstance->Service->ImageHandle,
            HttpInstance->Service->ControllerHandle
        );

        gBS->CloseProtocol (
            HttpInstance->TcpChildHandle,
            &gEfiTcp4ProtocolGuid,
            HttpInstance->Service->ImageHandle,
            HttpInstance->Handle
        );

        NetLibDestroyServiceChild (
            HttpInstance->Service->ControllerHandle,
            HttpInstance->Service->ImageHandle,
            &gEfiTcp4ServiceBindingProtocolGuid,
            HttpInstance->TcpChildHandle
        );
    }

    return Status;

}
Пример #5
0
/**
  Parse the DHCP ACK to get Dns6 server information.

  @param  Image            The handle of the driver image.
  @param  Controller       The handle of the controller.
  @param  DnsServerCount   Retrieved Dns6 server Ip count.
  @param  DnsServerList    Retrieved Dns6 server Ip list.

  @retval EFI_SUCCESS           The Dns6 information is got from the DHCP ACK.
  @retval EFI_OUT_OF_RESOURCES  Failed to allocate memory.
  @retval EFI_NO_MEDIA          There was a media error.
  @retval Others                Other errors as indicated.

**/
EFI_STATUS
GetDns6ServerFromDhcp6 (
  IN  EFI_HANDLE                 Image,
  IN  EFI_HANDLE                 Controller,
  OUT UINT32                     *DnsServerCount,
  OUT EFI_IPv6_ADDRESS           **DnsServerList
  )
{
  EFI_HANDLE                Dhcp6Handle;
  EFI_DHCP6_PROTOCOL        *Dhcp6;
  EFI_STATUS                Status;
  EFI_STATUS                TimerStatus;
  EFI_DHCP6_PACKET_OPTION   *Oro;
  EFI_DHCP6_RETRANSMISSION  InfoReqReXmit;
  EFI_EVENT                 Timer;
  EFI_STATUS                MediaStatus;
  DNS6_SERVER_INFOR         DnsServerInfor;

  Dhcp6Handle = NULL;
  Dhcp6       = NULL;
  Oro         = NULL;
  Timer       = NULL;

  ZeroMem (&DnsServerInfor, sizeof (DNS6_SERVER_INFOR));

  DnsServerInfor.ServerCount = DnsServerCount;

  //
  // Check media status before doing DHCP.
  //
  MediaStatus = EFI_SUCCESS;
  NetLibDetectMediaWaitTimeout (Controller, DNS_CHECK_MEDIA_GET_DHCP_WAITING_TIME, &MediaStatus);
  if (MediaStatus != EFI_SUCCESS) {
    return EFI_NO_MEDIA;
  }

  //
  // Create a DHCP6 child instance and get the protocol.
  //
  Status = NetLibCreateServiceChild (
             Controller,
             Image,
             &gEfiDhcp6ServiceBindingProtocolGuid,
             &Dhcp6Handle
             );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  Status = gBS->OpenProtocol (
                  Dhcp6Handle,
                  &gEfiDhcp6ProtocolGuid,
                  (VOID **) &Dhcp6,
                  Image,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto ON_EXIT;
  }

  Oro = AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + 1);
  if (Oro == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_EXIT;
  }

  //
  // Ask the server to reply with DNS options.
  // All members in EFI_DHCP6_PACKET_OPTION are in network order.
  //
  Oro->OpCode  = HTONS (DHCP6_TAG_DNS_REQUEST);
  Oro->OpLen   = HTONS (2);
  Oro->Data[1] = DHCP6_TAG_DNS_SERVER;

  InfoReqReXmit.Irt = 4;
  InfoReqReXmit.Mrc = 1;
  InfoReqReXmit.Mrt = 10;
  InfoReqReXmit.Mrd = 30;

  Status = Dhcp6->InfoRequest (
                    Dhcp6,
                    TRUE,
                    Oro,
                    0,
                    NULL,
                    &InfoReqReXmit,
                    NULL,
                    ParseDhcp6Ack,
                    &DnsServerInfor
                    );
  if (Status == EFI_NO_MAPPING) {
    Status = gBS->CreateEvent (EVT_TIMER, TPL_CALLBACK, NULL, NULL, &Timer);
    if (EFI_ERROR (Status)) {
      goto ON_EXIT;
    }

    Status = gBS->SetTimer (
                    Timer,
                    TimerRelative,
                    DNS_TIME_TO_GETMAP * TICKS_PER_SECOND
                    );

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

    do {
      TimerStatus = gBS->CheckEvent (Timer);
      if (!EFI_ERROR (TimerStatus)) {
        Status = Dhcp6->InfoRequest (
                          Dhcp6,
                          TRUE,
                          Oro,
                          0,
                          NULL,
                          &InfoReqReXmit,
                          NULL,
                          ParseDhcp6Ack,
                          &DnsServerInfor
                          );
      }
    } while (TimerStatus == EFI_NOT_READY);
  }

  *DnsServerList  = DnsServerInfor.ServerList;

ON_EXIT:

  if (Oro != NULL) {
    FreePool (Oro);
  }

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

  if (Dhcp6 != NULL) {
    gBS->CloseProtocol (
           Dhcp6Handle,
           &gEfiDhcp6ProtocolGuid,
           Image,
           Controller
           );
  }

  NetLibDestroyServiceChild (
    Controller,
    Image,
    &gEfiDhcp6ServiceBindingProtocolGuid,
    Dhcp6Handle
    );

  return Status;

}
Пример #6
0
/**
  Parse the DHCP ACK to get the address configuration and DNS information.

  @param[in]       Image         The handle of the driver image.
  @param[in]       Controller    The handle of the controller;
  @param[in, out]  ConfigData    The attempt configuration data.

  @retval EFI_SUCCESS            The DNS information is got from the DHCP ACK.
  @retval EFI_NO_MAPPING         DHCP failed to acquire address and other
                                 information.
  @retval EFI_INVALID_PARAMETER  The DHCP ACK's DNS option is malformatted.
  @retval EFI_DEVICE_ERROR       Some unexpected error occurred.
  @retval EFI_OUT_OF_RESOURCES   There is no sufficient resource to finish the
                                 operation.
  @retval EFI_NO_MEDIA           There was a media error.

**/
EFI_STATUS
IScsiDoDhcp6 (
  IN     EFI_HANDLE                  Image,
  IN     EFI_HANDLE                  Controller,
  IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA *ConfigData
  )
{
  EFI_HANDLE                Dhcp6Handle;
  EFI_DHCP6_PROTOCOL        *Dhcp6;
  EFI_STATUS                Status;
  EFI_STATUS                TimerStatus;
  EFI_DHCP6_PACKET_OPTION   *Oro;
  EFI_DHCP6_RETRANSMISSION  InfoReqReXmit;
  EFI_EVENT                 Timer;
  BOOLEAN                   MediaPresent;

  //
  // Check media status before doing DHCP.
  //
  MediaPresent = TRUE;
  NetLibDetectMedia (Controller, &MediaPresent);
  if (!MediaPresent) {
    return EFI_NO_MEDIA;
  }

  //
  // iSCSI will only request target info from DHCPv6 server.
  //
  if (!ConfigData->SessionConfigData.TargetInfoFromDhcp) {
    return EFI_SUCCESS;
  }

  Dhcp6Handle = NULL;
  Dhcp6       = NULL;
  Oro         = NULL;
  Timer       = NULL;

  //
  // Create a DHCP6 child instance and get the protocol.
  //
  Status = NetLibCreateServiceChild (
             Controller,
             Image,
             &gEfiDhcp6ServiceBindingProtocolGuid,
             &Dhcp6Handle
             );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  Status = gBS->OpenProtocol (
                  Dhcp6Handle,
                  &gEfiDhcp6ProtocolGuid,
                  (VOID **) &Dhcp6,
                  Image,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto ON_EXIT;
  }

  Oro = AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + 5);
  if (Oro == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_EXIT;
  }

  //
  // Ask the server to reply with DNS and Boot File URL options by info request.
  // All members in EFI_DHCP6_PACKET_OPTION are in network order.
  //
  Oro->OpCode  = HTONS (DHCP6_OPT_ORO);
  Oro->OpLen   = HTONS (2 * 3);
  Oro->Data[1] = DHCP6_OPT_DNS_SERVERS;
  Oro->Data[3] = DHCP6_OPT_BOOT_FILE_URL;
  Oro->Data[5] = DHCP6_OPT_BOOT_FILE_PARAM;

  InfoReqReXmit.Irt = 4;
  InfoReqReXmit.Mrc = 1;
  InfoReqReXmit.Mrt = 10;
  InfoReqReXmit.Mrd = 30;

  Status = Dhcp6->InfoRequest (
                    Dhcp6,
                    TRUE,
                    Oro,
                    0,
                    NULL,
                    &InfoReqReXmit,
                    NULL,
                    IScsiDhcp6ParseReply,
                    ConfigData
                    );
  if (Status == EFI_NO_MAPPING) {
    Status = gBS->CreateEvent (EVT_TIMER, TPL_CALLBACK, NULL, NULL, &Timer);
    if (EFI_ERROR (Status)) {
      goto ON_EXIT;
    }

    Status = gBS->SetTimer (
                    Timer,
                    TimerRelative,
                    ISCSI_GET_MAPPING_TIMEOUT
                    );

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

    do {

      TimerStatus = gBS->CheckEvent (Timer);

      if (!EFI_ERROR (TimerStatus)) {
        Status = Dhcp6->InfoRequest (
                          Dhcp6,
                          TRUE,
                          Oro,
                          0,
                          NULL,
                          &InfoReqReXmit,
                          NULL,
                          IScsiDhcp6ParseReply,
                          ConfigData
                          );
      }

    } while (TimerStatus == EFI_NOT_READY);

  }

ON_EXIT:

  if (Oro != NULL) {
    FreePool (Oro);
  }  

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

  if (Dhcp6 != NULL) {
    gBS->CloseProtocol (
           Dhcp6Handle,
           &gEfiDhcp6ProtocolGuid,
           Image,
           Controller
           );
  }

  NetLibDestroyServiceChild (
    Controller,
    Image,
    &gEfiDhcp6ServiceBindingProtocolGuid,
    Dhcp6Handle
    );

  return Status;
}
Пример #7
0
/**
  Parse the DHCP ACK to get Dns4 server information.

  @param  Instance         The DNS instance.
  @param  DnsServerCount   Retrieved Dns4 server Ip count.
  @param  DnsServerList    Retrieved Dns4 server Ip list.

  @retval EFI_SUCCESS           The Dns4 information is got from the DHCP ACK.
  @retval EFI_OUT_OF_RESOURCES  Failed to allocate memory.
  @retval EFI_NO_MEDIA          There was a media error.
  @retval Others                Other errors as indicated.

**/
EFI_STATUS
GetDns4ServerFromDhcp4 (
  IN  DNS_INSTANCE               *Instance,
  OUT UINT32                     *DnsServerCount,
  OUT EFI_IPv4_ADDRESS           **DnsServerList
  )
{
  EFI_STATUS                          Status;
  EFI_HANDLE                          Image;
  EFI_HANDLE                          Controller;
  EFI_STATUS                          MediaStatus;
  EFI_HANDLE                          MnpChildHandle;
  EFI_MANAGED_NETWORK_PROTOCOL        *Mnp;
  EFI_MANAGED_NETWORK_CONFIG_DATA     MnpConfigData;
  EFI_HANDLE                          Dhcp4Handle;
  EFI_DHCP4_PROTOCOL                  *Dhcp4;
  EFI_IP4_CONFIG2_PROTOCOL            *Ip4Config2;
  UINTN                               DataSize;
  VOID                                *Data;
  EFI_IP4_CONFIG2_INTERFACE_INFO      *InterfaceInfo;
  EFI_DHCP4_PACKET                    SeedPacket;
  EFI_DHCP4_PACKET_OPTION             *ParaList[2];
  DNS4_SERVER_INFOR                   DnsServerInfor;

  EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN    Token;
  BOOLEAN                             IsDone;
  UINTN                               Index;

  Image                      = Instance->Service->ImageHandle;
  Controller                 = Instance->Service->ControllerHandle;

  MnpChildHandle             = NULL;
  Mnp                        = NULL;

  Dhcp4Handle                = NULL;
  Dhcp4                      = NULL;

  Ip4Config2                 = NULL;
  DataSize                   = 0;
  Data                       = NULL;
  InterfaceInfo              = NULL;

  ZeroMem ((UINT8 *) ParaList, sizeof (ParaList));

  ZeroMem (&MnpConfigData, sizeof (EFI_MANAGED_NETWORK_CONFIG_DATA));

  ZeroMem (&DnsServerInfor, sizeof (DNS4_SERVER_INFOR));

  ZeroMem (&Token, sizeof (EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN));

  DnsServerInfor.ServerCount = DnsServerCount;

  IsDone = FALSE;

  //
  // Check media.
  //
  MediaStatus = EFI_SUCCESS;
  NetLibDetectMediaWaitTimeout (Controller, DNS_CHECK_MEDIA_GET_DHCP_WAITING_TIME, &MediaStatus);
  if (MediaStatus != EFI_SUCCESS) {
    return EFI_NO_MEDIA;
  }

  //
  // Create a Mnp child instance, get the protocol and config for it.
  //
  Status = NetLibCreateServiceChild (
             Controller,
             Image,
             &gEfiManagedNetworkServiceBindingProtocolGuid,
             &MnpChildHandle
             );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  Status = gBS->OpenProtocol (
                  MnpChildHandle,
                  &gEfiManagedNetworkProtocolGuid,
                  (VOID **) &Mnp,
                  Image,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto ON_EXIT;
  }

  MnpConfigData.ReceivedQueueTimeoutValue = 0;
  MnpConfigData.TransmitQueueTimeoutValue = 0;
  MnpConfigData.ProtocolTypeFilter        = IP4_ETHER_PROTO;
  MnpConfigData.EnableUnicastReceive      = TRUE;
  MnpConfigData.EnableMulticastReceive    = TRUE;
  MnpConfigData.EnableBroadcastReceive    = TRUE;
  MnpConfigData.EnablePromiscuousReceive  = FALSE;
  MnpConfigData.FlushQueuesOnReset        = TRUE;
  MnpConfigData.EnableReceiveTimestamps   = FALSE;
  MnpConfigData.DisableBackgroundPolling  = FALSE;

  Status = Mnp->Configure(Mnp, &MnpConfigData);
  if (EFI_ERROR (Status)) {
    goto ON_EXIT;
  }

  //
  // Create a DHCP4 child instance and get the protocol.
  //
  Status = NetLibCreateServiceChild (
             Controller,
             Image,
             &gEfiDhcp4ServiceBindingProtocolGuid,
             &Dhcp4Handle
             );
  if (EFI_ERROR (Status)) {
    goto ON_EXIT;
  }

  Status = gBS->OpenProtocol (
                  Dhcp4Handle,
                  &gEfiDhcp4ProtocolGuid,
                  (VOID **) &Dhcp4,
                  Image,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto ON_EXIT;
  }

  //
  // Get Ip4Config2 instance info.
  //
  Status = gBS->HandleProtocol (Controller, &gEfiIp4Config2ProtocolGuid, (VOID **) &Ip4Config2);
  if (EFI_ERROR (Status)) {
    goto ON_EXIT;
  }

  Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeInterfaceInfo, &DataSize, Data);
  if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
    goto ON_EXIT;
  }

  Data = AllocateZeroPool (DataSize);
  if (Data == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_EXIT;
  }

  Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeInterfaceInfo, &DataSize, Data);
  if (EFI_ERROR (Status)) {
    goto ON_EXIT;
  }

  InterfaceInfo = (EFI_IP4_CONFIG2_INTERFACE_INFO *)Data;

  //
  // Build required Token.
  //
  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  DhcpCommonNotify,
                  &IsDone,
                  &Token.CompletionEvent
                  );
  if (EFI_ERROR (Status)) {
    goto ON_EXIT;
  }

  SetMem (&Token.RemoteAddress, sizeof (EFI_IPv4_ADDRESS), 0xff);

  Token.RemotePort = 67;

  Token.ListenPointCount = 1;

  Token.ListenPoints = AllocateZeroPool (Token.ListenPointCount * sizeof (EFI_DHCP4_LISTEN_POINT));
  if (Token.ListenPoints == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_EXIT;
  }

  if (Instance->Dns4CfgData.UseDefaultSetting) {
    CopyMem (&(Token.ListenPoints[0].ListenAddress), &(InterfaceInfo->StationAddress), sizeof (EFI_IPv4_ADDRESS));
    CopyMem (&(Token.ListenPoints[0].SubnetMask), &(InterfaceInfo->SubnetMask), sizeof (EFI_IPv4_ADDRESS));
  } else {
    CopyMem (&(Token.ListenPoints[0].ListenAddress), &(Instance->Dns4CfgData.StationIp), sizeof (EFI_IPv4_ADDRESS));
    CopyMem (&(Token.ListenPoints[0].SubnetMask), &(Instance->Dns4CfgData.SubnetMask), sizeof (EFI_IPv4_ADDRESS));
  }

  Token.ListenPoints[0].ListenPort = 68;

  Token.TimeoutValue = DNS_TIME_TO_GETMAP;

  DnsInitSeedPacket (&SeedPacket, InterfaceInfo);

  ParaList[0] = AllocateZeroPool (sizeof (EFI_DHCP4_PACKET_OPTION));
  if (ParaList[0] == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_EXIT;
  }

  ParaList[0]->OpCode  = DHCP4_TAG_TYPE;
  ParaList[0]->Length  = 1;
  ParaList[0]->Data[0] = DHCP4_MSG_REQUEST;

  ParaList[1] = AllocateZeroPool (sizeof (EFI_DHCP4_PACKET_OPTION));
  if (ParaList[1] == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_EXIT;
  }

  ParaList[1]->OpCode  = DHCP4_TAG_PARA_LIST;
  ParaList[1]->Length  = 1;
  ParaList[1]->Data[0] = DHCP4_TAG_DNS_SERVER;

  Status = Dhcp4->Build (Dhcp4, &SeedPacket, 0, NULL, 2, ParaList, &Token.Packet);

  Token.Packet->Dhcp4.Header.Xid      = HTONL(NET_RANDOM (NetRandomInitSeed ()));

  Token.Packet->Dhcp4.Header.Reserved = HTONS ((UINT16)0x8000);

  if (Instance->Dns4CfgData.UseDefaultSetting) {
    CopyMem (&(Token.Packet->Dhcp4.Header.ClientAddr), &(InterfaceInfo->StationAddress), sizeof (EFI_IPv4_ADDRESS));
  } else {
    CopyMem (&(Token.Packet->Dhcp4.Header.ClientAddr), &(Instance->Dns4CfgData.StationIp), sizeof (EFI_IPv4_ADDRESS));
  }

  CopyMem (Token.Packet->Dhcp4.Header.ClientHwAddr, &(InterfaceInfo->HwAddress), InterfaceInfo->HwAddressSize);

  Token.Packet->Dhcp4.Header.HwAddrLen = (UINT8)(InterfaceInfo->HwAddressSize);

  //
  // TransmitReceive Token
  //
  Status = Dhcp4->TransmitReceive (Dhcp4, &Token);
  if (EFI_ERROR (Status)) {
    goto ON_EXIT;
  }

  //
  // Poll the packet
  //
  do {
    Status = Mnp->Poll (Mnp);
  } while (!IsDone);

  //
  // Parse the ACK to get required information if received done.
  //
  if (IsDone && !EFI_ERROR (Token.Status)) {
    for (Index = 0; Index < Token.ResponseCount; Index++) {
      Status = ParseDhcp4Ack (Dhcp4, &Token.ResponseList[Index], &DnsServerInfor);
      if (!EFI_ERROR (Status)) {
        break;
      }
    }

    *DnsServerList = DnsServerInfor.ServerList;
  } else {
    Status = Token.Status;
  }

ON_EXIT:

  if (Data != NULL) {
    FreePool (Data);
  }

  for (Index = 0; Index < 2; Index++) {
    if (ParaList[Index] != NULL) {
      FreePool (ParaList[Index]);
    }
  }

  if (Token.ListenPoints) {
    FreePool (Token.ListenPoints);
  }

  if (Token.Packet) {
    FreePool (Token.Packet);
  }

  if (Token.ResponseList != NULL) {
    FreePool (Token.ResponseList);
  }

  if (Token.CompletionEvent != NULL) {
    gBS->CloseEvent (Token.CompletionEvent);
  }

  if (Dhcp4 != NULL) {
    Dhcp4->Stop (Dhcp4);
    Dhcp4->Configure (Dhcp4, NULL);

    gBS->CloseProtocol (
           Dhcp4Handle,
           &gEfiDhcp4ProtocolGuid,
           Image,
           Controller
           );
  }

  if (Dhcp4Handle != NULL) {
    NetLibDestroyServiceChild (
      Controller,
      Image,
      &gEfiDhcp4ServiceBindingProtocolGuid,
      Dhcp4Handle
      );
  }

  if (Mnp != NULL) {
    Mnp->Configure (Mnp, NULL);

    gBS->CloseProtocol (
           MnpChildHandle,
           &gEfiManagedNetworkProtocolGuid,
           Image,
           Controller
           );
  }

  NetLibDestroyServiceChild (
    Controller,
    Image,
    &gEfiManagedNetworkServiceBindingProtocolGuid,
    MnpChildHandle
    );

  return Status;
}
Пример #8
0
/**
  Retrieve the host address using the EFI_DNS6_PROTOCOL.

  @param[in]  Private             The pointer to the driver's private data.
  @param[in]  HostName            Pointer to buffer containing hostname.
  @param[out] IpAddress           On output, pointer to buffer containing IPv6 address.

  @retval EFI_SUCCESS             Operation succeeded.
  @retval EFI_DEVICE_ERROR        An unexpected network error occurred.
  @retval Others                  Other errors as indicated.  
**/
EFI_STATUS
HttpBootDns (
  IN     HTTP_BOOT_PRIVATE_DATA   *Private,
  IN     CHAR16                   *HostName,
     OUT EFI_IPv6_ADDRESS         *IpAddress 
  )
{
  EFI_STATUS                      Status;
  EFI_DNS6_PROTOCOL               *Dns6;
  EFI_DNS6_CONFIG_DATA            Dns6ConfigData;
  EFI_DNS6_COMPLETION_TOKEN       Token;
  EFI_HANDLE                      Dns6Handle;
  EFI_IP6_CONFIG_PROTOCOL         *Ip6Config;
  EFI_IPv6_ADDRESS                *DnsServerList;
  UINTN                           DnsServerListCount;
  UINTN                           DataSize;
  BOOLEAN                         IsDone;  
  
  DnsServerList       = NULL;
  DnsServerListCount  = 0;
  Dns6                = NULL;
  Dns6Handle          = NULL;
  ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN));
  
  //
  // Get DNS server list from EFI IPv6 Configuration protocol.
  //
  Status = gBS->HandleProtocol (Private->Controller, &gEfiIp6ConfigProtocolGuid, (VOID **) &Ip6Config);
  if (!EFI_ERROR (Status)) {
    //
    // Get the required size.
    //
    DataSize = 0;
    Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, NULL);
    if (Status == EFI_BUFFER_TOO_SMALL) {
      DnsServerList = AllocatePool (DataSize);
      if (DnsServerList == NULL) {
        return EFI_OUT_OF_RESOURCES;
      }  

      Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, DnsServerList);
      if (EFI_ERROR (Status)) {
        FreePool (DnsServerList);
        DnsServerList = NULL;
      } else {
        DnsServerListCount = DataSize / sizeof (EFI_IPv6_ADDRESS);
      }
    }
  }
  //
  // Create a DNSv6 child instance and get the protocol.
  //
  Status = NetLibCreateServiceChild (
             Private->Controller,
             Private->Ip6Nic->ImageHandle,
             &gEfiDns6ServiceBindingProtocolGuid,
             &Dns6Handle
             );
  if (EFI_ERROR (Status)) {
    goto Exit;
  } 
  
  Status = gBS->OpenProtocol (
                  Dns6Handle,
                  &gEfiDns6ProtocolGuid,
                  (VOID **) &Dns6,
                  Private->Ip6Nic->ImageHandle,
                  Private->Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto Exit;
  }

  //
  // Configure DNS6 instance for the DNS server address and protocol.
  //
  ZeroMem (&Dns6ConfigData, sizeof (EFI_DNS6_CONFIG_DATA));
  Dns6ConfigData.DnsServerCount = (UINT32)DnsServerListCount;
  Dns6ConfigData.DnsServerList  = DnsServerList;
  Dns6ConfigData.EnableDnsCache = TRUE;
  Dns6ConfigData.Protocol       = EFI_IP_PROTO_UDP;
  IP6_COPY_ADDRESS (&Dns6ConfigData.StationIp,&Private->StationIp.v6);
  Status = Dns6->Configure (
                    Dns6,
                    &Dns6ConfigData
                    );
  if (EFI_ERROR (Status)) {
    goto Exit;
  }
  
  Token.Status = EFI_NOT_READY;
  IsDone       = FALSE;
  //
  // Create event to set the  IsDone flag when name resolution is finished.
  //
  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  HttpBootCommonNotify,
                  &IsDone,
                  &Token.Event
                  );
  if (EFI_ERROR (Status)) {
    goto Exit;
  }

  //
  // Start asynchronous name resolution.
  //
  Status = Dns6->HostNameToIp (Dns6, HostName, &Token);
  if (EFI_ERROR (Status)) {
    goto Exit;
  }

  while (!IsDone) {
    Dns6->Poll (Dns6);
  }
  
  //
  // Name resolution is done, check result.
  //
  Status = Token.Status;  
  if (!EFI_ERROR (Status)) {
    if (Token.RspData.H2AData == NULL) {
      Status = EFI_DEVICE_ERROR;
      goto Exit;
    }
    if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) {
      Status = EFI_DEVICE_ERROR;
      goto Exit;
    }
    //
    // We just return the first IPv6 address from DNS protocol.
    //
    IP6_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);
    Status = EFI_SUCCESS;
  }
Exit:

  if (Token.Event != NULL) {
    gBS->CloseEvent (Token.Event);
  }
  if (Token.RspData.H2AData != NULL) {
    if (Token.RspData.H2AData->IpList != NULL) {
      FreePool (Token.RspData.H2AData->IpList);
    }
    FreePool (Token.RspData.H2AData);
  }

  if (Dns6 != NULL) {
    Dns6->Configure (Dns6, NULL);
    
    gBS->CloseProtocol (
           Dns6Handle,
           &gEfiDns6ProtocolGuid,
           Private->Ip6Nic->ImageHandle,
           Private->Controller
           );
  }

  if (Dns6Handle != NULL) {
    NetLibDestroyServiceChild (
      Private->Controller,
      Private->Ip6Nic->ImageHandle,
      &gEfiDns6ServiceBindingProtocolGuid,
      Dns6Handle
      );
  }

  if (DnsServerList != NULL) {
    FreePool (DnsServerList);
  }
  
  return Status;  
}
Пример #9
0
/**
  Create a HTTP_IO to access the HTTP service. It will create and configure
  a HTTP child handle.

  @param[in]  Image          The handle of the driver image.
  @param[in]  Controller     The handle of the controller.
  @param[in]  IpVersion      IP_VERSION_4 or IP_VERSION_6.
  @param[in]  ConfigData     The HTTP_IO configuration data.
  @param[in]  Callback       Callback function which will be invoked when specified
                             HTTP_IO_CALLBACK_EVENT happened.
  @param[in]  Context        The Context data which will be passed to the Callback function.
  @param[out] HttpIo         The HTTP_IO.
  
  @retval EFI_SUCCESS            The HTTP_IO is created and configured.
  @retval EFI_INVALID_PARAMETER  One or more parameters are invalid.
  @retval EFI_UNSUPPORTED        One or more of the control options are not
                                 supported in the implementation.
  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
  @retval Others                 Failed to create the HTTP_IO or configure it.

**/
EFI_STATUS
HttpIoCreateIo (
  IN EFI_HANDLE             Image,
  IN EFI_HANDLE             Controller,
  IN UINT8                  IpVersion,
  IN HTTP_IO_CONFIG_DATA    *ConfigData,
  IN HTTP_IO_CALLBACK       Callback,
  IN VOID                   *Context,
  OUT HTTP_IO               *HttpIo
  )
{
  EFI_STATUS                Status;
  EFI_HTTP_CONFIG_DATA      HttpConfigData;
  EFI_HTTPv4_ACCESS_POINT   Http4AccessPoint;
  EFI_HTTPv6_ACCESS_POINT   Http6AccessPoint;
  EFI_HTTP_PROTOCOL         *Http;
  EFI_EVENT                 Event;
  
  if ((Image == NULL) || (Controller == NULL) || (ConfigData == NULL) || (HttpIo == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  if (IpVersion != IP_VERSION_4 && IpVersion != IP_VERSION_6) {
    return EFI_UNSUPPORTED;
  }

  ZeroMem (HttpIo, sizeof (HTTP_IO));
  
  //
  // Create the HTTP child instance and get the HTTP protocol.
  //  
  Status = NetLibCreateServiceChild (
             Controller,
             Image,
             &gEfiHttpServiceBindingProtocolGuid,
             &HttpIo->Handle
             );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  Status = gBS->OpenProtocol (
                  HttpIo->Handle,
                  &gEfiHttpProtocolGuid,
                  (VOID **) &Http,
                  Image,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status) || (Http == NULL)) {
    goto ON_ERROR;
  }

  //
  // Init the configuration data and configure the HTTP child.
  //
  HttpIo->Image       = Image;
  HttpIo->Controller  = Controller;
  HttpIo->IpVersion   = IpVersion;
  HttpIo->Http        = Http;
  HttpIo->Callback    = Callback;
  HttpIo->Context     = Context;

  ZeroMem (&HttpConfigData, sizeof (EFI_HTTP_CONFIG_DATA));
  HttpConfigData.HttpVersion        = HttpVersion11;
  HttpConfigData.TimeOutMillisec    = ConfigData->Config4.RequestTimeOut;
  if (HttpIo->IpVersion == IP_VERSION_4) {
    HttpConfigData.LocalAddressIsIPv6 = FALSE;
    
    Http4AccessPoint.UseDefaultAddress = ConfigData->Config4.UseDefaultAddress;
    Http4AccessPoint.LocalPort         = ConfigData->Config4.LocalPort;
    IP4_COPY_ADDRESS (&Http4AccessPoint.LocalAddress, &ConfigData->Config4.LocalIp);
    IP4_COPY_ADDRESS (&Http4AccessPoint.LocalSubnet, &ConfigData->Config4.SubnetMask);
    HttpConfigData.AccessPoint.IPv4Node = &Http4AccessPoint;   
  } else {
    HttpConfigData.LocalAddressIsIPv6 = TRUE;
    Http6AccessPoint.LocalPort        = ConfigData->Config6.LocalPort;
    IP6_COPY_ADDRESS (&Http6AccessPoint.LocalAddress, &ConfigData->Config6.LocalIp);
    HttpConfigData.AccessPoint.IPv6Node = &Http6AccessPoint;
  }
  
  Status = Http->Configure (Http, &HttpConfigData);
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  //
  // Create events for variuos asynchronous operations.
  //
  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  HttpIoNotify,
                  &HttpIo->IsTxDone,
                  &Event
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }
  HttpIo->ReqToken.Event = Event;
  HttpIo->ReqToken.Message = &HttpIo->ReqMessage;

  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  HttpIoNotify,
                  &HttpIo->IsRxDone,
                  &Event
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }
  HttpIo->RspToken.Event = Event;
  HttpIo->RspToken.Message = &HttpIo->RspMessage;

  //
  // Create TimeoutEvent for response
  //
  Status = gBS->CreateEvent (
                  EVT_TIMER,
                  TPL_CALLBACK,
                  NULL,
                  NULL,
                  &Event
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }
  HttpIo->TimeoutEvent = Event;

  return EFI_SUCCESS;
  
ON_ERROR:
  HttpIoDestroyIo (HttpIo);

  return Status;
}
Пример #10
0
/**
  Create a TCP socket with the specified configuration data. 

  @param[in]  Image      The handle of the driver image.
  @param[in]  Controller The handle of the controller.
  @param[in]  TcpVersion The version of Tcp, TCP_VERSION_4 or TCP_VERSION_6.
  @param[in]  ConfigData The Tcp configuration data.
  @param[out] TcpIo      The TcpIo.
  
  @retval EFI_SUCCESS            The TCP socket is created and configured.
  @retval EFI_INVALID_PARAMETER  One or more parameters are invalid.
  @retval EFI_UNSUPPORTED        One or more of the control options are not
                                 supported in the implementation.
  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
  @retval Others                 Failed to create the TCP socket or configure it.

**/
EFI_STATUS
EFIAPI
TcpIoCreateSocket (
  IN EFI_HANDLE             Image,
  IN EFI_HANDLE             Controller,
  IN UINT8                  TcpVersion,
  IN TCP_IO_CONFIG_DATA     *ConfigData,
  OUT TCP_IO                *TcpIo
  )
{
  EFI_STATUS                Status;
  EFI_EVENT                 Event;
  EFI_GUID                  *ServiceBindingGuid;
  EFI_GUID                  *ProtocolGuid;
  VOID                      **Interface;
  EFI_TCP4_OPTION           ControlOption;
  EFI_TCP4_CONFIG_DATA      Tcp4ConfigData;
  EFI_TCP4_ACCESS_POINT     *AccessPoint4;
  EFI_TCP4_PROTOCOL         *Tcp4;
  EFI_TCP6_CONFIG_DATA      Tcp6ConfigData;
  EFI_TCP6_ACCESS_POINT     *AccessPoint6;
  EFI_TCP6_PROTOCOL         *Tcp6;
  EFI_TCP4_RECEIVE_DATA     *RxData;

  if ((Image == NULL) || (Controller == NULL) || (ConfigData == NULL) || (TcpIo == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  Tcp4 = NULL;
  Tcp6 = NULL;

  ZeroMem (TcpIo, sizeof (TCP_IO));

  if (TcpVersion == TCP_VERSION_4) {
    ServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
    ProtocolGuid       = &gEfiTcp4ProtocolGuid;
    Interface          = (VOID **) (&TcpIo->Tcp.Tcp4);
  } else if (TcpVersion == TCP_VERSION_6) {
    ServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
    ProtocolGuid       = &gEfiTcp6ProtocolGuid;
    Interface          = (VOID **) (&TcpIo->Tcp.Tcp6);
  } else {
    return EFI_UNSUPPORTED;
  }

  TcpIo->TcpVersion = TcpVersion;

  //
  // Create the TCP child instance and get the TCP protocol.
  //  
  Status = NetLibCreateServiceChild (
             Controller,
             Image,
             ServiceBindingGuid,
             &TcpIo->Handle
             );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  Status = gBS->OpenProtocol (
                  TcpIo->Handle,
                  ProtocolGuid,
                  Interface,
                  Image,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status) || (*Interface == NULL)) {
    goto ON_ERROR;
  }

  if (TcpVersion == TCP_VERSION_4) {
    Tcp4             = TcpIo->Tcp.Tcp4;
  } else {
    Tcp6             = TcpIo->Tcp.Tcp6;
  }

  TcpIo->Image       = Image;
  TcpIo->Controller  = Controller;

  //
  // Set the configuration parameters.
  //
  ControlOption.ReceiveBufferSize       = 0x200000;
  ControlOption.SendBufferSize          = 0x200000;
  ControlOption.MaxSynBackLog           = 0;
  ControlOption.ConnectionTimeout       = 0;
  ControlOption.DataRetries             = 6;
  ControlOption.FinTimeout              = 0;
  ControlOption.TimeWaitTimeout         = 0;
  ControlOption.KeepAliveProbes         = 4;
  ControlOption.KeepAliveTime           = 0;
  ControlOption.KeepAliveInterval       = 0;
  ControlOption.EnableNagle             = FALSE;
  ControlOption.EnableTimeStamp         = FALSE;
  ControlOption.EnableWindowScaling     = TRUE;
  ControlOption.EnableSelectiveAck      = FALSE;
  ControlOption.EnablePathMtuDiscovery  = FALSE;

  if (TcpVersion == TCP_VERSION_4) {
    Tcp4ConfigData.TypeOfService        = 8;
    Tcp4ConfigData.TimeToLive           = 255;
    Tcp4ConfigData.ControlOption        = &ControlOption;

    AccessPoint4                        = &Tcp4ConfigData.AccessPoint;

    ZeroMem (AccessPoint4, sizeof (EFI_TCP4_ACCESS_POINT));
    AccessPoint4->StationPort           = ConfigData->Tcp4IoConfigData.StationPort;
    AccessPoint4->RemotePort            = ConfigData->Tcp4IoConfigData.RemotePort;
    AccessPoint4->ActiveFlag            = ConfigData->Tcp4IoConfigData.ActiveFlag;

    CopyMem (
      &AccessPoint4->StationAddress,
      &ConfigData->Tcp4IoConfigData.LocalIp,
      sizeof (EFI_IPv4_ADDRESS)
      );
    CopyMem (
      &AccessPoint4->SubnetMask,
      &ConfigData->Tcp4IoConfigData.SubnetMask,
      sizeof (EFI_IPv4_ADDRESS)
      );
    CopyMem (
      &AccessPoint4->RemoteAddress,
      &ConfigData->Tcp4IoConfigData.RemoteIp,
      sizeof (EFI_IPv4_ADDRESS)
      );

    ASSERT (Tcp4 != NULL);

    //
    // Configure the TCP4 protocol.
    //
    Status = Tcp4->Configure (Tcp4, &Tcp4ConfigData);
    if (EFI_ERROR (Status)) {
      goto ON_ERROR;
    }

    if (!EFI_IP4_EQUAL (&ConfigData->Tcp4IoConfigData.Gateway, &mZeroIp4Addr)) {
      //
      // The gateway is not zero. Add the default route manually.
      //
      Status = Tcp4->Routes (
                       Tcp4,
                       FALSE,
                       &mZeroIp4Addr,
                       &mZeroIp4Addr,
                       &ConfigData->Tcp4IoConfigData.Gateway
                       );
      if (EFI_ERROR (Status)) {
        goto ON_ERROR;
      }
    }
  } else {
    Tcp6ConfigData.TrafficClass         = 0;
    Tcp6ConfigData.HopLimit             = 255;
    Tcp6ConfigData.ControlOption        = (EFI_TCP6_OPTION *) &ControlOption;

    AccessPoint6                        = &Tcp6ConfigData.AccessPoint;

    ZeroMem (AccessPoint6, sizeof (EFI_TCP6_ACCESS_POINT));
    AccessPoint6->StationPort           = ConfigData->Tcp6IoConfigData.StationPort;
    AccessPoint6->RemotePort            = ConfigData->Tcp6IoConfigData.RemotePort;
    AccessPoint6->ActiveFlag            = ConfigData->Tcp6IoConfigData.ActiveFlag;

    IP6_COPY_ADDRESS (&AccessPoint6->RemoteAddress, &ConfigData->Tcp6IoConfigData.RemoteIp);


    ASSERT (Tcp6 != NULL);
    //
    // Configure the TCP6 protocol.
    //
    Status = Tcp6->Configure (Tcp6, &Tcp6ConfigData);
    if (Status == EFI_NO_MAPPING) {
      Status = TcpIoGetMapping (Tcp6, &Tcp6ConfigData);
    }

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

  //
  // Create events for variuos asynchronous operations.
  //
  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  TcpIoCommonNotify,
                  &TcpIo->IsConnDone,
                  &Event
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  TcpIo->ConnToken.Tcp4Token.CompletionToken.Event = Event;

  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  TcpIoCommonNotify,
                  &TcpIo->IsListenDone,
                  &Event
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  TcpIo->ListenToken.Tcp4Token.CompletionToken.Event = Event;

  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  TcpIoCommonNotify,
                  &TcpIo->IsTxDone,
                  &Event
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  TcpIo->TxToken.Tcp4Token.CompletionToken.Event = Event;


  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  TcpIoCommonNotify,
                  &TcpIo->IsRxDone,
                  &Event
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  TcpIo->RxToken.Tcp4Token.CompletionToken.Event = Event;

  RxData = (EFI_TCP4_RECEIVE_DATA *) AllocateZeroPool (sizeof (EFI_TCP4_RECEIVE_DATA));
  if (RxData == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_ERROR;
  }

  TcpIo->RxToken.Tcp4Token.Packet.RxData = RxData;

  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  TcpIoCommonNotify,
                  &TcpIo->IsCloseDone,
                  &Event
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  TcpIo->CloseToken.Tcp4Token.CompletionToken.Event = Event;


  return EFI_SUCCESS;

ON_ERROR:

  TcpIoDestroySocket (TcpIo);

  return Status;
}
Пример #11
0
/**
  Download an image from a TFTP server

  @param[in]   DevicePath           Device path of the TFTP boot option
  @param[in]   ControllerHandle     Handle of the network controller
  @param[in]   RemainingDevicePath  Device path of the TFTP boot option but
                                    the first node that identifies the network controller
  @param[in]   Type                 Type to allocate memory pages
  @param[out]  Image                Address of the bufer where the image is stored in
                                    case of success
  @param[out]  ImageSize            Size in number of bytes of the i;age in case of
                                    success

  @retval  EFI_SUCCESS   The image was returned.
  @retval  !EFI_SUCCESS  Something went wrong.

**/
EFI_STATUS
BdsTftpLoadImage (
  IN OUT EFI_DEVICE_PATH       **DevicePath,
  IN     EFI_HANDLE            ControllerHandle,
  IN     EFI_DEVICE_PATH       *RemainingDevicePath,
  IN     EFI_ALLOCATE_TYPE     Type,
  IN OUT EFI_PHYSICAL_ADDRESS  *Image,
  OUT    UINTN                 *ImageSize
  )
{
  EFI_STATUS               Status;
  EFI_HANDLE               Dhcp4ChildHandle;
  EFI_DHCP4_PROTOCOL       *Dhcp4;
  BOOLEAN                  Dhcp4ToStop;
  EFI_HANDLE               Mtftp4ChildHandle;
  EFI_MTFTP4_PROTOCOL      *Mtftp4;
  DHCP4_OPTION             ParaList;
  EFI_DHCP4_PACKET_OPTION  *OptionList[2];
  EFI_DHCP4_CONFIG_DATA    Dhcp4CfgData;
  EFI_DHCP4_MODE_DATA      Dhcp4Mode;
  EFI_MTFTP4_CONFIG_DATA   Mtftp4CfgData;
  IPv4_DEVICE_PATH         *IPv4DevicePathNode;
  FILEPATH_DEVICE_PATH     *FilePathDevicePathNode;
  CHAR8                    *AsciiFilePath;
  EFI_MTFTP4_TOKEN         Mtftp4Token;
  UINT64                   FileSize;
  UINT64                   TftpBufferSize;
  BDS_TFTP_CONTEXT         *TftpContext;

  ASSERT(IS_DEVICE_PATH_NODE (RemainingDevicePath, MESSAGING_DEVICE_PATH, MSG_IPv4_DP));
  IPv4DevicePathNode = (IPv4_DEVICE_PATH*)RemainingDevicePath;

  Dhcp4ChildHandle  = NULL;
  Dhcp4             = NULL;
  Dhcp4ToStop       = FALSE;
  Mtftp4ChildHandle = NULL;
  Mtftp4            = NULL;
  AsciiFilePath     = NULL;
  TftpContext       = NULL;

  if (!IPv4DevicePathNode->StaticIpAddress) {
    //
    // Using the DHCP4 Service Binding Protocol, create a child handle of the DHCP4 service and
    // install the DHCP4 protocol on it. Then, open the DHCP protocol.
    //
    Status = NetLibCreateServiceChild (
               ControllerHandle,
               gImageHandle,
               &gEfiDhcp4ServiceBindingProtocolGuid,
               &Dhcp4ChildHandle
               );
    if (!EFI_ERROR (Status)) {
      Status = gBS->OpenProtocol (
                      Dhcp4ChildHandle,
                      &gEfiDhcp4ProtocolGuid,
                      (VOID **) &Dhcp4,
                      gImageHandle,
                      ControllerHandle,
                      EFI_OPEN_PROTOCOL_BY_DRIVER
                      );
    }
    if (EFI_ERROR (Status)) {
      Print (L"Unable to open DHCP4 protocol\n");
      goto Error;
    }
  }

  //
  // Using the MTFTP4 Service Binding Protocol, create a child handle of the MTFTP4 service and
  // install the MTFTP4 protocol on it. Then, open the MTFTP4 protocol.
  //
  Status = NetLibCreateServiceChild (
             ControllerHandle,
             gImageHandle,
             &gEfiMtftp4ServiceBindingProtocolGuid,
             &Mtftp4ChildHandle
             );
  if (!EFI_ERROR (Status)) {
    Status = gBS->OpenProtocol (
                    Mtftp4ChildHandle,
                    &gEfiMtftp4ProtocolGuid,
                    (VOID **) &Mtftp4,
                    gImageHandle,
                    ControllerHandle,
                    EFI_OPEN_PROTOCOL_BY_DRIVER
                    );
  }
  if (EFI_ERROR (Status)) {
    Print (L"Unable to open MTFTP4 protocol\n");
    goto Error;
  }

  if (!IPv4DevicePathNode->StaticIpAddress) {
    //
    // Configure the DHCP4, all default settings. It is acceptable for the configuration to
    // fail if the return code is equal to EFI_ACCESS_DENIED which means that the configuration
    // has been done by another instance of the DHCP4 protocol or that the DHCP configuration
    // process has been started but is not completed yet.
    //
    ZeroMem (&Dhcp4CfgData, sizeof (EFI_DHCP4_CONFIG_DATA));
    ParaList.Head.OpCode     = DHCP_TAG_PARA_LIST;
    ParaList.Head.Length     = 2;
    ParaList.Head.Data[0]    = DHCP_TAG_NETMASK;
    ParaList.Route           = DHCP_TAG_ROUTER;
    OptionList[0]            = &ParaList.Head;
    Dhcp4CfgData.OptionCount = 1;
    Dhcp4CfgData.OptionList  = OptionList;

    Status = Dhcp4->Configure (Dhcp4, &Dhcp4CfgData);
    if (EFI_ERROR (Status)) {
      if (Status != EFI_ACCESS_DENIED) {
        Print (L"Error while configuring the DHCP4 protocol\n");
        goto Error;
      }
    }

    //
    // Start the DHCP configuration. This may have already been done thus do not leave in error
    // if the return code is EFI_ALREADY_STARTED.
    //
    Status = Dhcp4->Start (Dhcp4, NULL);
    if (EFI_ERROR (Status)) {
      if (Status != EFI_ALREADY_STARTED) {
        Print (L"DHCP configuration failed\n");
        goto Error;
      }
    } else {
      Dhcp4ToStop = TRUE;
    }

    Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4Mode);
    if (EFI_ERROR (Status)) {
      goto Error;
    }

    if (Dhcp4Mode.State != Dhcp4Bound) {
      Status = EFI_TIMEOUT;
      Print (L"DHCP configuration failed\n");
      goto Error;
    }
  }

  //
  // Configure the TFTP4 protocol
  //

  ZeroMem (&Mtftp4CfgData, sizeof (EFI_MTFTP4_CONFIG_DATA));
  Mtftp4CfgData.UseDefaultSetting = FALSE;
  Mtftp4CfgData.TimeoutValue      = 4;
  Mtftp4CfgData.TryCount          = 6;

  if (IPv4DevicePathNode->StaticIpAddress) {
    CopyMem (&Mtftp4CfgData.StationIp , &IPv4DevicePathNode->LocalIpAddress, sizeof (EFI_IPv4_ADDRESS));
    CopyMem (&Mtftp4CfgData.SubnetMask, &IPv4DevicePathNode->SubnetMask, sizeof (EFI_IPv4_ADDRESS));
    CopyMem (&Mtftp4CfgData.GatewayIp , &IPv4DevicePathNode->GatewayIpAddress, sizeof (EFI_IPv4_ADDRESS));
  } else {
    CopyMem (&Mtftp4CfgData.StationIp , &Dhcp4Mode.ClientAddress, sizeof (EFI_IPv4_ADDRESS));
    CopyMem (&Mtftp4CfgData.SubnetMask, &Dhcp4Mode.SubnetMask   , sizeof (EFI_IPv4_ADDRESS));
    CopyMem (&Mtftp4CfgData.GatewayIp , &Dhcp4Mode.RouterAddress, sizeof (EFI_IPv4_ADDRESS));
  }

  CopyMem (&Mtftp4CfgData.ServerIp  , &IPv4DevicePathNode->RemoteIpAddress, sizeof (EFI_IPv4_ADDRESS));

  Status = Mtftp4->Configure (Mtftp4, &Mtftp4CfgData);
  if (EFI_ERROR (Status)) {
    Print (L"Error while configuring the MTFTP4 protocol\n");
    goto Error;
  }

  //
  // Convert the Unicode path of the file to Ascii
  //

  FilePathDevicePathNode = (FILEPATH_DEVICE_PATH*)(IPv4DevicePathNode + 1);
  AsciiFilePath = AllocatePool ((StrLen (FilePathDevicePathNode->PathName) + 1) * sizeof (CHAR8));
  if (AsciiFilePath == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Error;
  }
  UnicodeStrToAsciiStr (FilePathDevicePathNode->PathName, AsciiFilePath);

  //
  // Try to get the size of the file in bytes from the server. If it fails,
  // start with a 8MB buffer to download the file.
  //
  FileSize = 0;
  if (Mtftp4GetFileSize (Mtftp4, AsciiFilePath, &FileSize) == EFI_SUCCESS) {
    TftpBufferSize = FileSize;
  } else {
    TftpBufferSize = SIZE_8MB;
  }

  TftpContext = AllocatePool (sizeof (BDS_TFTP_CONTEXT));
  if (TftpContext == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto Error;
  }
  TftpContext->FileSize = FileSize;

  for (; TftpBufferSize <= FixedPcdGet32 (PcdMaxTftpFileSize);
         TftpBufferSize = (TftpBufferSize + SIZE_8MB) & (~(SIZE_8MB-1))) {
    //
    // Allocate a buffer to hold the whole file.
    //
    Status = gBS->AllocatePages (
                    Type,
                    EfiBootServicesCode,
                    EFI_SIZE_TO_PAGES (TftpBufferSize),
                    Image
                    );
    if (EFI_ERROR (Status)) {
      Print (L"Failed to allocate space for image\n");
      goto Error;
    }

    TftpContext->DownloadedNbOfBytes   = 0;
    TftpContext->LastReportedNbOfBytes = 0;

    ZeroMem (&Mtftp4Token, sizeof (EFI_MTFTP4_TOKEN));
    Mtftp4Token.Filename    = (UINT8*)AsciiFilePath;
    Mtftp4Token.BufferSize  = TftpBufferSize;
    Mtftp4Token.Buffer      = (VOID *)(UINTN)*Image;
    Mtftp4Token.CheckPacket = Mtftp4CheckPacket;
    Mtftp4Token.Context     = (VOID*)TftpContext;

    Print (L"Downloading the file <%s> from the TFTP server\n", FilePathDevicePathNode->PathName);
    Status = Mtftp4->ReadFile (Mtftp4, &Mtftp4Token);
    Print (L"\n");
    if (EFI_ERROR (Status)) {
      gBS->FreePages (*Image, EFI_SIZE_TO_PAGES (TftpBufferSize));
      if (Status == EFI_BUFFER_TOO_SMALL) {
        Print (L"Downloading failed, file larger than expected.\n");
        continue;
      } else {
        goto Error;
      }
    }

    *ImageSize = Mtftp4Token.BufferSize;
    break;
  }

Error:
  if (Dhcp4ChildHandle != NULL) {
    if (Dhcp4 != NULL) {
      if (Dhcp4ToStop) {
        Dhcp4->Stop (Dhcp4);
      }
      gBS->CloseProtocol (
             Dhcp4ChildHandle,
             &gEfiDhcp4ProtocolGuid,
             gImageHandle,
             ControllerHandle
            );
    }
    NetLibDestroyServiceChild (
      ControllerHandle,
      gImageHandle,
      &gEfiDhcp4ServiceBindingProtocolGuid,
      Dhcp4ChildHandle
      );
  }

  if (Mtftp4ChildHandle != NULL) {
    if (Mtftp4 != NULL) {
      if (AsciiFilePath != NULL) {
        FreePool (AsciiFilePath);
      }
      if (TftpContext != NULL) {
        FreePool (TftpContext);
      }
      gBS->CloseProtocol (
             Mtftp4ChildHandle,
             &gEfiMtftp4ProtocolGuid,
             gImageHandle,
             ControllerHandle
            );
    }
    NetLibDestroyServiceChild (
      ControllerHandle,
      gImageHandle,
      &gEfiMtftp4ServiceBindingProtocolGuid,
      Mtftp4ChildHandle
      );
  }

  if (EFI_ERROR (Status)) {
    Print (L"Failed to download the file - Error=%r\n", Status);
  }

  return Status;
}
Пример #12
0
/**
  Retrieve the host address using the EFI_DNS4_PROTOCOL.

  @param[in]  Image               The handle of the driver image.
  @param[in]  Controller          The handle of the controller.
  @param[in, out]  NvData         The Session config data structure.

  @retval EFI_SUCCESS             Operation succeeded.
  @retval EFI_OUT_OF_RESOURCES    Failed to allocate needed resources.
  @retval EFI_DEVICE_ERROR        An unexpected network error occurred.
  @retval Others                  Other errors as indicated.

**/
EFI_STATUS
IScsiDns4 (
  IN     EFI_HANDLE                      Image,
  IN     EFI_HANDLE                      Controller,
  IN OUT ISCSI_SESSION_CONFIG_NVDATA     *NvData
  )
{
  EFI_STATUS                      Status;
  EFI_DNS4_PROTOCOL               *Dns4;
  EFI_DNS4_CONFIG_DATA            Dns4CfgData;
  EFI_DNS4_COMPLETION_TOKEN       Token;
  BOOLEAN                         IsDone;
  EFI_HANDLE                      Dns4Handle;
  EFI_IP4_CONFIG2_PROTOCOL        *Ip4Config2;
  EFI_IPv4_ADDRESS                *DnsServerList;
  UINTN                           DnsServerListCount;
  UINTN                           DataSize;
  CHAR16                          *HostName;

  DnsServerList      = NULL;
  DnsServerListCount = 0;
  Dns4Handle         = NULL;
  Dns4               = NULL;
  ZeroMem (&Token, sizeof (EFI_DNS4_COMPLETION_TOKEN));

  //
  // Get DNS server list from EFI IPv4 Configuration II protocol.
  //
  Status = gBS->HandleProtocol (Controller, &gEfiIp4Config2ProtocolGuid, (VOID **) &Ip4Config2);
  if (!EFI_ERROR (Status)) {
    //
    // Get the required size.
    //
    DataSize = 0;
    Status   = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeDnsServer, &DataSize, NULL);
    if (Status == EFI_BUFFER_TOO_SMALL) {
      DnsServerList = AllocatePool (DataSize);
      if (DnsServerList == NULL) {
        return EFI_OUT_OF_RESOURCES;
      }

      Status   = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeDnsServer, &DataSize, DnsServerList);
      if (EFI_ERROR (Status)) {
        FreePool (DnsServerList);
        DnsServerList = NULL;
      } else {
        DnsServerListCount = DataSize / sizeof (EFI_IPv4_ADDRESS);
      }
    }
  }


  //
  // Create a DNS child instance and get the protocol.
  //
  Status = NetLibCreateServiceChild (
             Controller,
             Image,
             &gEfiDns4ServiceBindingProtocolGuid,
             &Dns4Handle
             );
  if (EFI_ERROR (Status)) {
    goto Exit;
  }

  Status = gBS->OpenProtocol (
                  Dns4Handle,
                  &gEfiDns4ProtocolGuid,
                  (VOID **) &Dns4,
                  Image,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto Exit;
  }

  //
  // Configure DNS4 instance for the DNS server address and protocol.
  //
  ZeroMem (&Dns4CfgData, sizeof (Dns4CfgData));
  Dns4CfgData.DnsServerListCount = DnsServerListCount;
  Dns4CfgData.DnsServerList      = DnsServerList;
  Dns4CfgData.EnableDnsCache     = TRUE;
  IP4_COPY_ADDRESS (&Dns4CfgData.StationIp, &NvData->LocalIp);
  IP4_COPY_ADDRESS (&Dns4CfgData.SubnetMask, &NvData->SubnetMask);
  Dns4CfgData.Protocol           = EFI_IP_PROTO_UDP;
  Status = Dns4->Configure (
                   Dns4,
                   &Dns4CfgData
                   );
  if (EFI_ERROR (Status)) {
    goto Exit;
  }

  //
  // Create event to set the is done flag when name resolution is finished.
  //
  ZeroMem (&Token, sizeof (Token));
  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  IScsiCommonNotify,
                  &IsDone,
                  &Token.Event
                  );
  if (EFI_ERROR (Status)) {
    goto Exit;
  }

  //
  // Start asynchronous name resolution.
  //
  Token.Status = EFI_NOT_READY;
  IsDone       = FALSE;

  HostName = (CHAR16 *) AllocateZeroPool (ISCSI_NAME_MAX_SIZE);
  if (HostName == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  AsciiStrToUnicodeStrS (
    NvData->TargetUrl,
    HostName,
    ISCSI_NAME_MAX_SIZE
    );

  Status = Dns4->HostNameToIp (Dns4, HostName, &Token);
  if (EFI_ERROR (Status)) {
    goto Exit;
  }

  while (!IsDone) {
    Dns4->Poll (Dns4);
  }

  //
  // Name resolution is done, check result.
  //
  Status = Token.Status;
  if (!EFI_ERROR (Status)) {
    if (Token.RspData.H2AData == NULL) {
      Status = EFI_DEVICE_ERROR;
      goto Exit;
    }
    if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) {
      Status = EFI_DEVICE_ERROR;
      goto Exit;
    }
    //
    // We just return the first IP address from DNS protocol.
    //
    IP4_COPY_ADDRESS (&NvData->TargetIp.v4, Token.RspData.H2AData->IpList);
    Status = EFI_SUCCESS;
  }

Exit:

  if (Token.Event != NULL) {
    gBS->CloseEvent (Token.Event);
  }
  if (Token.RspData.H2AData != NULL) {
    if (Token.RspData.H2AData->IpList != NULL) {
      FreePool (Token.RspData.H2AData->IpList);
    }
    FreePool (Token.RspData.H2AData);
  }

  if (Dns4 != NULL) {
    Dns4->Configure (Dns4, NULL);

    gBS->CloseProtocol (
           Dns4Handle,
           &gEfiDns4ProtocolGuid,
           Image,
           Controller
           );
  }

  if (Dns4Handle != NULL) {
    NetLibDestroyServiceChild (
      Controller,
      Image,
      &gEfiDns4ServiceBindingProtocolGuid,
      Dns4Handle
      );
  }

  return Status;
}
Пример #13
0
/**
  Create a TCP socket with the specified configuration data. 

  @param[in]  Image      The handle of the driver image.
  @param[in]  Controller The handle of the controller.
  @param[in]  ConfigData The Tcp4 configuration data.
  @param[in]  Tcp4Io     The Tcp4Io.
  
  @retval EFI_SUCCESS    The TCP socket is created and configured.
  @retval Others         Failed to create the TCP socket or configure it.
**/
EFI_STATUS
Tcp4IoCreateSocket (
  IN EFI_HANDLE           Image,
  IN EFI_HANDLE           Controller,
  IN TCP4_IO_CONFIG_DATA  *ConfigData,
  IN TCP4_IO              *Tcp4Io
  )
{
  EFI_STATUS            Status;
  EFI_TCP4_PROTOCOL     *Tcp4;
  EFI_TCP4_CONFIG_DATA  Tcp4ConfigData;
  EFI_TCP4_OPTION       ControlOption;
  EFI_TCP4_ACCESS_POINT *AccessPoint;

  Tcp4Io->Handle = NULL;
  Tcp4Io->ConnToken.CompletionToken.Event = NULL;
  Tcp4Io->TxToken.CompletionToken.Event = NULL;
  Tcp4Io->RxToken.CompletionToken.Event = NULL;
  Tcp4Io->CloseToken.CompletionToken.Event = NULL;
  Tcp4 = NULL;

  //
  // Create the TCP4 child instance and get the TCP4 protocol.
  //
  Status = NetLibCreateServiceChild (
            Controller,
            Image,
            &gEfiTcp4ServiceBindingProtocolGuid,
            &Tcp4Io->Handle
            );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  Status = gBS->OpenProtocol (
                  Tcp4Io->Handle,
                  &gEfiTcp4ProtocolGuid,
                  (VOID **)&Tcp4Io->Tcp4,
                  Image,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Tcp4Io->Image       = Image;
  Tcp4Io->Controller  = Controller;
  Tcp4                = Tcp4Io->Tcp4;

  //
  // Set the configuration parameters.
  //
  ControlOption.ReceiveBufferSize       = 0x200000;
  ControlOption.SendBufferSize          = 0x200000;
  ControlOption.MaxSynBackLog           = 0;
  ControlOption.ConnectionTimeout       = 0;
  ControlOption.DataRetries             = 6;
  ControlOption.FinTimeout              = 0;
  ControlOption.TimeWaitTimeout         = 0;
  ControlOption.KeepAliveProbes         = 4;
  ControlOption.KeepAliveTime           = 0;
  ControlOption.KeepAliveInterval       = 0;
  ControlOption.EnableNagle             = FALSE;
  ControlOption.EnableTimeStamp         = FALSE;
  ControlOption.EnableWindowScaling     = TRUE;
  ControlOption.EnableSelectiveAck      = FALSE;
  ControlOption.EnablePathMtuDiscovery  = FALSE;

  Tcp4ConfigData.TypeOfService          = 8;
  Tcp4ConfigData.TimeToLive             = 255;
  Tcp4ConfigData.ControlOption          = &ControlOption;

  AccessPoint = &Tcp4ConfigData.AccessPoint;

  AccessPoint->UseDefaultAddress = FALSE;
  AccessPoint->StationPort = 0;
  AccessPoint->RemotePort = ConfigData->RemotePort;
  AccessPoint->ActiveFlag = TRUE;

  CopyMem (&AccessPoint->StationAddress, &ConfigData->LocalIp, sizeof (EFI_IPv4_ADDRESS));
  CopyMem (&AccessPoint->SubnetMask, &ConfigData->SubnetMask, sizeof (EFI_IPv4_ADDRESS));
  CopyMem (&AccessPoint->RemoteAddress, &ConfigData->RemoteIp, sizeof (EFI_IPv4_ADDRESS));

  //
  // Configure the TCP4 protocol.
  //
  Status = Tcp4->Configure (Tcp4, &Tcp4ConfigData);
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  if (!EFI_IP4_EQUAL (&ConfigData->Gateway, &mZeroIp4Addr)) {
    //
    // the gateway is not zero, add the default route by hand
    //
    Status = Tcp4->Routes (Tcp4, FALSE, &mZeroIp4Addr, &mZeroIp4Addr, &ConfigData->Gateway);
    if (EFI_ERROR (Status)) {
      goto ON_ERROR;
    }
  }
  //
  // Create events for variuos asynchronous operations.
  //
  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  Tcp4IoCommonNotify,
                  &Tcp4Io->IsConnDone,
                  &Tcp4Io->ConnToken.CompletionToken.Event
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  Tcp4IoCommonNotify,
                  &Tcp4Io->IsTxDone,
                  &Tcp4Io->TxToken.CompletionToken.Event
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  Tcp4IoCommonNotify,
                  &Tcp4Io->IsRxDone,
                  &Tcp4Io->RxToken.CompletionToken.Event
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Status = gBS->CreateEvent (
                  EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  Tcp4IoCommonNotify,
                  &Tcp4Io->IsCloseDone,
                  &Tcp4Io->CloseToken.CompletionToken.Event
                  );
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Tcp4Io->IsTxDone  = FALSE;
  Tcp4Io->IsRxDone  = FALSE;

  return EFI_SUCCESS;

ON_ERROR:

  if (Tcp4Io->RxToken.CompletionToken.Event != NULL) {
    gBS->CloseEvent (Tcp4Io->RxToken.CompletionToken.Event);
  }

  if (Tcp4Io->TxToken.CompletionToken.Event != NULL) {
    gBS->CloseEvent (Tcp4Io->TxToken.CompletionToken.Event);
  }

  if (Tcp4Io->ConnToken.CompletionToken.Event != NULL) {
    gBS->CloseEvent (Tcp4Io->ConnToken.CompletionToken.Event);
  }

  if (Tcp4 != NULL) {
    Tcp4->Configure (Tcp4, NULL);

    gBS->CloseProtocol (
          Tcp4Io->Handle,
          &gEfiTcp4ProtocolGuid,
          Image,
          Controller
          );
  }

  NetLibDestroyServiceChild (
    Controller,
    Image,
    &gEfiTcp4ServiceBindingProtocolGuid,
    Tcp4Io->Handle
    );

  return Status;
}
Пример #14
0
STATIC
EFI_STATUS
ArpCreateService (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_HANDLE        ControllerHandle,
  IN ARP_SERVICE_DATA  *ArpService
  )
/*++

Routine Description:

  Create and initialize the arp service context data.

Arguments:

  ImageHandle      - The image handle representing the loaded driver image.
  ControllerHandle - The controller handle the driver binds to.
  ArpService       - Pointer to the buffer containing the arp service context data.

Returns:

  EFI_SUCCESS - The arp service context is initialized.
  other       - Failed to initialize the arp service context.

--*/
{
  EFI_STATUS  Status;

  ASSERT (ArpService != NULL);

  ArpService->Signature = ARP_SERVICE_DATA_SIGNATURE;

  //
  // Init the servicebinding protocol members.
  //
  ArpService->ServiceBinding.CreateChild  = ArpServiceBindingCreateChild;
  ArpService->ServiceBinding.DestroyChild = ArpServiceBindingDestroyChild;

  //
  // Save the handles.
  //
  ArpService->ImageHandle      = ImageHandle;
  ArpService->ControllerHandle = ControllerHandle;

  //
  // Create a MNP child instance.
  //
  Status = NetLibCreateServiceChild (
             ControllerHandle, 
             ImageHandle, 
             &gEfiManagedNetworkServiceBindingProtocolGuid, 
             &ArpService->MnpChildHandle
             );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // Open the MNP protocol.
  //
  Status = gBS->OpenProtocol (
                  ArpService->MnpChildHandle,
                  &gEfiManagedNetworkProtocolGuid,
                  (VOID **)&ArpService->Mnp,
                  ImageHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    goto ERROR_EXIT;
  }

  //
  // Get the underlayer Snp mode data.
  //
  Status = ArpService->Mnp->GetModeData (ArpService->Mnp, NULL, &ArpService->SnpMode);
  if ((Status != EFI_NOT_STARTED) && EFI_ERROR (Status)) {
    goto ERROR_EXIT;
  }

  if (ArpService->SnpMode.IfType != NET_IFTYPE_ETHERNET) {
    //
    // Only support the ethernet.
    //
    Status = EFI_UNSUPPORTED;
    goto ERROR_EXIT;
  }

  //
  // Set the Mnp config parameters.
  //
  ArpService->MnpConfigData.ReceivedQueueTimeoutValue = 0;
  ArpService->MnpConfigData.TransmitQueueTimeoutValue = 0;
  ArpService->MnpConfigData.ProtocolTypeFilter        = ARP_ETHER_PROTO_TYPE;
  ArpService->MnpConfigData.EnableUnicastReceive      = TRUE;
  ArpService->MnpConfigData.EnableMulticastReceive    = FALSE;
  ArpService->MnpConfigData.EnableBroadcastReceive    = TRUE;
  ArpService->MnpConfigData.EnablePromiscuousReceive  = FALSE;
  ArpService->MnpConfigData.FlushQueuesOnReset        = TRUE;
  ArpService->MnpConfigData.EnableReceiveTimestamps   = FALSE;
  ArpService->MnpConfigData.DisableBackgroundPolling  = FALSE;

  //
  // Configure the Mnp child.
  //
  Status = ArpService->Mnp->Configure (ArpService->Mnp, &ArpService->MnpConfigData);
  if (EFI_ERROR (Status)) {
    goto ERROR_EXIT;
  }

  //
  // Create the event used in the RxToken.
  //
  Status = gBS->CreateEvent (
                  EFI_EVENT_NOTIFY_SIGNAL,
                  NET_TPL_EVENT,
                  ArpOnFrameRcvd,
                  ArpService,
                  &ArpService->RxToken.Event
                  );
  if (EFI_ERROR (Status)) {
    goto ERROR_EXIT;
  }

  //
  // Create the Arp heartbeat timer.
  //
  Status = gBS->CreateEvent (
                  EFI_EVENT_NOTIFY_SIGNAL | EFI_EVENT_TIMER,
                  NET_TPL_TIMER,
                  ArpTimerHandler,
                  ArpService,
                  &ArpService->PeriodicTimer
                  );
  if (EFI_ERROR (Status)) {
    goto ERROR_EXIT;
  }

  //
  // Start the heartbeat timer.
  //
  Status = gBS->SetTimer (
                  ArpService->PeriodicTimer,
                  TimerPeriodic,
                  ARP_PERIODIC_TIMER_INTERVAL
                  );
  if (EFI_ERROR (Status)) {
    goto ERROR_EXIT;
  }

  //
  // Init the lists.
  //
  NetListInit (&ArpService->ChildrenList);
  NetListInit (&ArpService->PendingRequestTable);
  NetListInit (&ArpService->DeniedCacheTable);
  NetListInit (&ArpService->ResolvedCacheTable);

ERROR_EXIT:

  return Status;
}
Пример #15
0
/**
  Create an IP child, use it to start the auto configuration, then destroy it.

  @param[in] Controller       The controller which has the service installed.
  @param[in] Image            The image handle used to open service.

  @retval EFI_SUCCESS         The configuration is done.
**/
EFI_STATUS
EFIAPI
IfConfigStartIp4(
  IN  EFI_HANDLE            Controller,
  IN  EFI_HANDLE            Image
  )
{
  EFI_IP4_PROTOCOL              *Ip4;
  EFI_HANDLE                    Ip4Handle;
  EFI_IP4_CONFIG_DATA           Ip4ConfigData;
  EFI_STATUS                    Status;

  //
  // Get the Ip4ServiceBinding Protocol
  //
  Ip4Handle     = NULL;
  Ip4           = NULL;

  Status = NetLibCreateServiceChild (
             Controller,
             Image,
             &gEfiIp4ServiceBindingProtocolGuid,
             &Ip4Handle
             );

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

  Status = gBS->OpenProtocol (
                 Ip4Handle,
                 &gEfiIp4ProtocolGuid,
                 (VOID **) &Ip4,
                 Controller,
                 Image,
                 EFI_OPEN_PROTOCOL_GET_PROTOCOL
                 );

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

  Ip4ConfigData.DefaultProtocol          = EFI_IP_PROTO_ICMP;
  Ip4ConfigData.AcceptAnyProtocol        = FALSE;
  Ip4ConfigData.AcceptIcmpErrors         = FALSE;
  Ip4ConfigData.AcceptBroadcast          = FALSE;
  Ip4ConfigData.AcceptPromiscuous        = FALSE;
  Ip4ConfigData.UseDefaultAddress        = TRUE;
  ZeroMem (&Ip4ConfigData.StationAddress, sizeof (EFI_IPv4_ADDRESS));
  ZeroMem (&Ip4ConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
  Ip4ConfigData.TypeOfService            = 0;
  Ip4ConfigData.TimeToLive               = 1;
  Ip4ConfigData.DoNotFragment            = FALSE;
  Ip4ConfigData.RawData                  = FALSE;
  Ip4ConfigData.ReceiveTimeout           = 0;
  Ip4ConfigData.TransmitTimeout          = 0;

  Ip4->Configure (Ip4, &Ip4ConfigData);
  
ON_EXIT: 
  NetLibDestroyServiceChild (
    Controller,
    Image,
    &gEfiIp4ServiceBindingProtocolGuid,
    Ip4Handle
    );
  
  return Status;
}
Пример #16
0
/**
  Create an IP child, use it to start the auto configuration, then destroy it.

  @param[in] Controller       The controller which has the service installed.
  @param[in] Image            The image handle used to open service.

  @retval EFI_SUCCESS         The configuration is done.
  @retval Others              Other errors as indicated.
**/
EFI_STATUS
EFIAPI
DnsStartIp4(
  IN  EFI_HANDLE            Controller,
  IN  EFI_HANDLE            Image
  )
{
  EFI_IP4_PROTOCOL              *Ip4;
  EFI_HANDLE                    Ip4Handle;
  EFI_EVENT                     TimerToGetMap;
  EFI_IP4_CONFIG_DATA           Ip4ConfigData;
  EFI_IP4_MODE_DATA             Ip4Mode;
  EFI_STATUS                    Status;

  BOOLEAN                       Timeout;

  //
  // Get the Ip4ServiceBinding Protocol
  //
  Ip4Handle     = NULL;
  Ip4           = NULL;
  TimerToGetMap = NULL;
  
  Timeout      = FALSE;

  Status = NetLibCreateServiceChild (
             Controller,
             Image,
             &gEfiIp4ServiceBindingProtocolGuid,
             &Ip4Handle
             );

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

  Status = gBS->OpenProtocol (
                 Ip4Handle,
                 &gEfiIp4ProtocolGuid,
                 (VOID **) &Ip4,
                 Controller,
                 Image,
                 EFI_OPEN_PROTOCOL_GET_PROTOCOL
                 );

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

  Ip4ConfigData.DefaultProtocol          = EFI_IP_PROTO_ICMP;
  Ip4ConfigData.AcceptAnyProtocol        = FALSE;
  Ip4ConfigData.AcceptIcmpErrors         = FALSE;
  Ip4ConfigData.AcceptBroadcast          = FALSE;
  Ip4ConfigData.AcceptPromiscuous        = FALSE;
  Ip4ConfigData.UseDefaultAddress        = TRUE;
  ZeroMem (&Ip4ConfigData.StationAddress, sizeof (EFI_IPv4_ADDRESS));
  ZeroMem (&Ip4ConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
  Ip4ConfigData.TypeOfService            = 0;
  Ip4ConfigData.TimeToLive               = 1;
  Ip4ConfigData.DoNotFragment            = FALSE;
  Ip4ConfigData.RawData                  = FALSE;
  Ip4ConfigData.ReceiveTimeout           = 0;
  Ip4ConfigData.TransmitTimeout          = 0;

  Status = Ip4->Configure (Ip4, &Ip4ConfigData);

  if (Status == EFI_NO_MAPPING) {
    Status  = gBS->CreateEvent (
                    EVT_NOTIFY_SIGNAL | EVT_TIMER,
                    TPL_CALLBACK,
                    TimeoutToGetMap,
                    &Timeout,
                    &TimerToGetMap
                    );
    
    if (EFI_ERROR (Status)) {
      goto ON_EXIT;
    }
    
    Status = gBS->SetTimer (
                   TimerToGetMap,
                   TimerRelative,
                   MultU64x32 (10000000, 5)
                   );
    
    if (EFI_ERROR (Status)) {
      goto ON_EXIT;
    }
    
    while (!Timeout) {
      Ip4->Poll (Ip4);
  
      if (!EFI_ERROR (Ip4->GetModeData (Ip4, &Ip4Mode, NULL, NULL)) && 
          Ip4Mode.IsConfigured) {       
        break;
      }
    }

    if (Timeout) {
      Status = EFI_DEVICE_ERROR;
    }
  }
  
ON_EXIT: 

  if (TimerToGetMap != NULL) {
    gBS->SetTimer (TimerToGetMap, TimerCancel, 0);
    gBS->CloseEvent (TimerToGetMap);
  }

  NetLibDestroyServiceChild (
    Controller,
    Image,
    &gEfiIp4ServiceBindingProtocolGuid,
    Ip4Handle
    );
  
  return Status;
}