ip4config.c

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

C
778
字号
                  );

  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }
  
  //
  // Check the current DHCP status, if the DHCP process has 
  // already finished, return now.
  //
  Dhcp4  = Instance->Dhcp4;
  Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4Mode);

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

  if (Dhcp4Mode.State == Dhcp4Bound) {
    Ip4ConfigOnDhcp4Complete (NULL, Instance);
    return EFI_SUCCESS;
  }
  
  //
  // Try to start the DHCP process. Use most of the current
  // DHCP configuration to avoid problems if some DHCP client
  // yields the control of this DHCP service to us.
  //
  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;
  Dhcp4Mode.ConfigData.OptionCount = 1;
  Dhcp4Mode.ConfigData.OptionList  = OptionList;

  Status = Dhcp4->Configure (Dhcp4, &Dhcp4Mode.ConfigData);

  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }
  
  //
  // Start the DHCP process
  //
  Status = gBS->CreateEvent (
                  EFI_EVENT_NOTIFY_SIGNAL,
                  NET_TPL_EVENT,
                  Ip4ConfigOnDhcp4Complete,
                  Instance,
                  &Instance->Dhcp4Event
                  );

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

  Status = Dhcp4->Start (Dhcp4, Instance->Dhcp4Event);

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

  Instance->State  = IP4_CONFIG_STATE_STARTED;
  Instance->Result = EFI_NOT_READY;
  return EFI_SUCCESS;

ON_ERROR:
  Ip4ConfigCleanConfig (Instance);
  return Status;
}

EFI_STATUS
EFIAPI
EfiIp4ConfigStop (
  IN EFI_IP4_CONFIG_PROTOCOL  *This
  )
/*++

Routine Description:

  Stop the current auto configuration

Arguments:

  This  - The IP4 CONFIG protocol

Returns:

  EFI_INVALID_PARAMETER - This is NULL.
  EFI_NOT_STARTED       - The auto configuration hasn't been started.
  EFI_SUCCESS           - The auto configuration has been stopped.

--*/
{
  IP4_CONFIG_INSTANCE       *Instance;

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

  Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This);

  if (Instance->State == IP4_CONFIG_STATE_IDLE) {
    return EFI_NOT_STARTED;
  }

  //
  // Release all the configure parameters. Don't signal the user
  // event. The user wants to abort the configuration, this isn't
  // the configuration done or reconfiguration.
  //
  Ip4ConfigCleanConfig (Instance);
  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
EfiIp4ConfigGetData (
  IN  EFI_IP4_CONFIG_PROTOCOL *This,
  IN  OUT  UINTN              *ConfigDataSize,
  OUT EFI_IP4_IPCONFIG_DATA   *ConfigData           OPTIONAL
  )
/*++

Routine Description:

  Get the current outcome of the auto configuration process

Arguments:

  This            - The IP4 CONFIG protocol
  ConfigDataSize  - The size of the configure data
  ConfigData      - The buffer to save the configure data

Returns:

  EFI_INVALID_PARAMETER - This or ConfigDataSize is NULL
  EFI_BUFFER_TOO_SMALL  - The buffer is too small. The needed size is 
                          returned in the ConfigDataSize.
  EFI_SUCCESS           - The configure data is put in the buffer

--*/
{
  IP4_CONFIG_INSTANCE       *Instance;
  NIC_IP4_CONFIG_INFO       *NicConfig;
  EFI_STATUS                Status;
  UINTN                     Len;

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

  Instance  = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This);

  if (Instance->State == IP4_CONFIG_STATE_IDLE) {
    return EFI_NOT_STARTED;
  } else if (Instance->State == IP4_CONFIG_STATE_STARTED) {
    return EFI_NOT_READY;
  }

  //
  // Copy the configure data if auto configuration succeeds.
  //
  Status = Instance->Result;
  
  if (Status == EFI_SUCCESS) {
    ASSERT (Instance->NicConfig != NULL);

    NicConfig = Instance->NicConfig;
    Len       = SIZEOF_IP4_CONFIG_INFO (&NicConfig->Ip4Info);

    if ((*ConfigDataSize < Len) || (ConfigData == NULL)) {
      Status = EFI_BUFFER_TOO_SMALL;
    } else {
      NetCopyMem (ConfigData, &NicConfig->Ip4Info, Len);
    }

    *ConfigDataSize = Len;
  }

  return Status;
}

VOID
EFIAPI
Ip4ConfigOnDhcp4Complete (
  IN EFI_EVENT              Event,
  IN VOID                   *Context
  )
/*++

Routine Description:

  Callback function when DHCP process finished. It will save the 
  retrieved IP configure parameter from DHCP to the NVRam.

Arguments:

  Event   - The callback event
  Context - Opaque context to the callback

Returns:

  None

--*/
{
  IP4_CONFIG_INSTANCE       *Instance;
  EFI_DHCP4_MODE_DATA       Dhcp4Mode;
  EFI_IP4_IPCONFIG_DATA     *Ip4Config;
  EFI_STATUS                Status;
  BOOLEAN                   Perment;
  IP4_ADDR                  Subnet;

  Instance = (IP4_CONFIG_INSTANCE *) Context;
  ASSERT (Instance->Dhcp4 != NULL);

  Instance->State   = IP4_CONFIG_STATE_CONFIGURED;
  Instance->Result  = EFI_TIMEOUT;

  //
  // Get the DHCP retrieved parameters
  //
  Status = Instance->Dhcp4->GetModeData (Instance->Dhcp4, &Dhcp4Mode);

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

  if (Dhcp4Mode.State == Dhcp4Bound) {
    //
    // Save the new configuration retrieved by DHCP both in 
    // the instance and to NVRam. So, both the IP4 driver and
    // other user can get that address.
    //
    Perment = FALSE;

    if (Instance->NicConfig != NULL) {
      ASSERT (Instance->NicConfig->Source == IP4_CONFIG_SOURCE_DHCP);
      Perment = Instance->NicConfig->Perment;
      NetFreePool (Instance->NicConfig);
    }

    Instance->NicConfig = NetAllocatePool (sizeof (NIC_IP4_CONFIG_INFO) + 
                                           sizeof (EFI_IP4_ROUTE_TABLE));

    if (Instance->NicConfig == NULL) {
      Instance->Result = EFI_OUT_OF_RESOURCES;
      goto ON_EXIT;
    }

    Instance->NicConfig->NicAddr = Instance->NicAddr;
    Instance->NicConfig->Source  = IP4_CONFIG_SOURCE_DHCP;
    Instance->NicConfig->Perment = Perment;

    Ip4Config                    = &Instance->NicConfig->Ip4Info;
    Ip4Config->StationAddress    = Dhcp4Mode.ClientAddress;
    Ip4Config->SubnetMask        = Dhcp4Mode.SubnetMask;

    //
    // Create a route for the connected network
    //
    Ip4Config->RouteTableSize    = 1;

    Subnet = EFI_NTOHL (Dhcp4Mode.ClientAddress) & EFI_NTOHL (Dhcp4Mode.SubnetMask);

    EFI_IP4 (Ip4Config->RouteTable[0].SubnetAddress)  = HTONL (Subnet);
    Ip4Config->RouteTable[0].SubnetMask               = Dhcp4Mode.SubnetMask;
    EFI_IP4 (Ip4Config->RouteTable[0].GatewayAddress) = 0;

    //
    // Create a route if there is a default router.
    //
    if (EFI_IP4 (Dhcp4Mode.RouterAddress) != 0) {
      Ip4Config->RouteTableSize                         = 2;
      EFI_IP4 (Ip4Config->RouteTable[1].SubnetAddress)  = 0;
      EFI_IP4 (Ip4Config->RouteTable[1].SubnetMask)     = 0;
      Ip4Config->RouteTable[1].GatewayAddress           = Dhcp4Mode.RouterAddress;
    }

    Instance->Result = EFI_SUCCESS;

    //
    // ignore the return status of EfiNicIp4ConfigSetInfo. Network
    // stack can operate even that failed.
    //
    EfiNicIp4ConfigSetInfo (&Instance->NicIp4Protocol, Instance->NicConfig, FALSE); 
  }

ON_EXIT:
  gBS->SignalEvent (Instance->DoneEvent);
  Ip4ConfigCleanDhcp4 (Instance);
  return ;
}

VOID
Ip4ConfigCleanDhcp4 (
  IN IP4_CONFIG_INSTANCE    *This
  )
/*++

Routine Description:

  Release all the DHCP related resources.

Arguments:

  This  - The IP4 configure instance

Returns:

  None

--*/
{
  if (This->Dhcp4 != NULL) {
    This->Dhcp4->Stop (This->Dhcp4);

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

    This->Dhcp4 = NULL;
  }

  if (This->Dhcp4Handle != NULL) {
    NetLibDestroyServiceChild (
      This->Controller,
      This->Image,
      &gEfiDhcp4ServiceBindingProtocolGuid,
      This->Dhcp4Handle
      );

    This->Dhcp4Handle = NULL;
  }

  if (This->Dhcp4Event == NULL) {
    gBS->CloseEvent (This->Dhcp4Event);
    This->Dhcp4Event = NULL;
  }
}

VOID
Ip4ConfigCleanConfig (
  IN IP4_CONFIG_INSTANCE        *Instance
  )
/*++

Routine Description:

  Clean up all the configuration parameters

Arguments:

  Instance  - The IP4 configure instance

Returns:

  None

--*/
{
  if (Instance->NicConfig != NULL) {
    NetFreePool (Instance->NicConfig);
    Instance->NicConfig = NULL;
  }

  Instance->State         = IP4_CONFIG_STATE_IDLE;
  Instance->DoneEvent     = NULL;
  Instance->ReconfigEvent = NULL;

  Ip4ConfigCleanDhcp4 (Instance);
}

EFI_IP4_CONFIG_PROTOCOL     mIp4ConfigProtocolTemplate = {
  EfiIp4ConfigStart,
  EfiIp4ConfigStop,
  EfiIp4ConfigGetData
};

EFI_NIC_IP4_CONFIG_PROTOCOL mNicIp4ConfigProtocolTemplate = {
  EfiNicIp4ConfigGetName,
  EfiNicIp4ConfigGetInfo,
  EfiNicIp4ConfigSetInfo
};

⌨️ 快捷键说明

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