git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11140 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			913 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			913 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Helper functions for configuring or getting the parameters relating to Ip4.
 | 
						|
 | 
						|
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
 | 
						|
This program and the accompanying materials
 | 
						|
are licensed and made available under the terms and conditions of the BSD License
 | 
						|
which accompanies this distribution.  The full text of the license may be found at
 | 
						|
http://opensource.org/licenses/bsd-license.php
 | 
						|
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "Ip4ConfigNv.h"
 | 
						|
#include "NicIp4Variable.h"
 | 
						|
 | 
						|
EFI_GUID  mNicIp4ConfigNvDataGuid = EFI_NIC_IP4_CONFIG_NVDATA_GUID;
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Calculate the prefix length of the IPv4 subnet mask.
 | 
						|
 | 
						|
  @param[in]  SubnetMask The IPv4 subnet mask.
 | 
						|
 | 
						|
  @return The prefix length of the subnet mask.
 | 
						|
  @retval 0 Other errors as indicated.
 | 
						|
**/
 | 
						|
UINT8
 | 
						|
GetSubnetMaskPrefixLength (
 | 
						|
  IN EFI_IPv4_ADDRESS  *SubnetMask
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8   Len;
 | 
						|
  UINT32  ReverseMask;
 | 
						|
 | 
						|
  //
 | 
						|
  // The SubnetMask is in network byte order.
 | 
						|
  //
 | 
						|
  ReverseMask = SwapBytes32 (*(UINT32 *)&SubnetMask[0]);
 | 
						|
 | 
						|
  //
 | 
						|
  // Reverse it.
 | 
						|
  //
 | 
						|
  ReverseMask = ~ReverseMask;
 | 
						|
 | 
						|
  if ((ReverseMask & (ReverseMask + 1)) != 0) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  Len = 0;
 | 
						|
 | 
						|
  while (ReverseMask != 0) {
 | 
						|
    ReverseMask = ReverseMask >> 1;
 | 
						|
    Len++;
 | 
						|
  }
 | 
						|
 | 
						|
  return (UINT8) (32 - Len);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Convert the decimal dotted IPv4 address into the binary IPv4 address.
 | 
						|
 | 
						|
  @param[in]   Str             The UNICODE string.
 | 
						|
  @param[out]  Ip              The storage to return the IPv4 address.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The binary IP address is returned in Ip.
 | 
						|
  @retval EFI_INVALID_PARAMETER The IP string is malformatted.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Ip4StrToIp (
 | 
						|
  IN  CHAR16            *Str,
 | 
						|
  OUT EFI_IPv4_ADDRESS  *Ip
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN Index;
 | 
						|
  UINTN Number;
 | 
						|
 | 
						|
  Index = 0;
 | 
						|
 | 
						|
  while (*Str != L'\0') {
 | 
						|
 | 
						|
    if (Index > 3) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    Number = 0;
 | 
						|
    while ((*Str >= L'0') && (*Str <= L'9')) {
 | 
						|
      Number = Number * 10 + (*Str - L'0');
 | 
						|
      Str++;
 | 
						|
    }
 | 
						|
 | 
						|
    if (Number > 0xFF) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    Ip->Addr[Index] = (UINT8) Number;
 | 
						|
 | 
						|
    if ((*Str != L'\0') && (*Str != L'.')) {
 | 
						|
      //
 | 
						|
      // The current character should be either the NULL terminator or
 | 
						|
      // the dot delimiter.
 | 
						|
      //
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    if (*Str == L'.') {
 | 
						|
      //
 | 
						|
      // Skip the delimiter.
 | 
						|
      //
 | 
						|
      Str++;
 | 
						|
    }
 | 
						|
 | 
						|
    Index++;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Index != 4) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Convert the IPv4 address into a dotted string.
 | 
						|
 | 
						|
  @param[in]   Ip   The IPv4 address.
 | 
						|
  @param[out]  Str  The dotted IP string.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
Ip4ConfigIpToStr (
 | 
						|
  IN  EFI_IPv4_ADDRESS  *Ip,
 | 
						|
  OUT CHAR16            *Str
 | 
						|
  )
 | 
						|
{
 | 
						|
  UnicodeSPrint (Str, 2 * IP4_STR_MAX_SIZE, L"%d.%d.%d.%d", Ip->Addr[0], Ip->Addr[1], Ip->Addr[2], Ip->Addr[3]);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Convert the network configuration data into the IFR data.
 | 
						|
 | 
						|
  @param[in]   Ip4ConfigInstance The IP4Config instance
 | 
						|
  @param[out]  IfrFormNvData     The IFR nv data.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
Ip4ConfigConvertDeviceConfigDataToIfrNvData (
 | 
						|
  IN  IP4_CONFIG_INSTANCE       *Ip4ConfigInstance,
 | 
						|
  OUT IP4_CONFIG_IFR_NVDATA     *IfrFormNvData
 | 
						|
  )
 | 
						|
{
 | 
						|
  NIC_IP4_CONFIG_INFO  *NicConfig;
 | 
						|
 | 
						|
  NicConfig = EfiNicIp4ConfigGetInfo (Ip4ConfigInstance);
 | 
						|
  if (NicConfig != NULL) {
 | 
						|
    IfrFormNvData->Configure = 1;
 | 
						|
    Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured = TRUE;
 | 
						|
    if (NicConfig->Source == IP4_CONFIG_SOURCE_DHCP) {
 | 
						|
      IfrFormNvData->DhcpEnable = 1;
 | 
						|
      Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled = TRUE;
 | 
						|
    } else {
 | 
						|
      IfrFormNvData->DhcpEnable = 0;
 | 
						|
      Ip4ConfigIpToStr (&NicConfig->Ip4Info.StationAddress, IfrFormNvData->StationAddress);
 | 
						|
      Ip4ConfigIpToStr (&NicConfig->Ip4Info.SubnetMask, IfrFormNvData->SubnetMask);
 | 
						|
      Ip4ConfigIpToStr (&NicConfig->Ip4Info.RouteTable[1].GatewayAddress, IfrFormNvData->GatewayAddress);
 | 
						|
 | 
						|
      Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled = FALSE;
 | 
						|
      CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp, &NicConfig->Ip4Info.StationAddress, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
      CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask, &NicConfig->Ip4Info.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
      CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.Gateway, &NicConfig->Ip4Info.RouteTable[1].GatewayAddress, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
    }
 | 
						|
 | 
						|
    FreePool (NicConfig);
 | 
						|
  } else {
 | 
						|
    IfrFormNvData->Configure = 0;
 | 
						|
    Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured = FALSE;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Convert the IFR data into the network configuration data and set the IP
 | 
						|
  configure parameters for the NIC.
 | 
						|
 | 
						|
  @param[in]       IfrFormNvData     The IFR NV data.
 | 
						|
  @param[in, out]  Ip4ConfigInstance The IP4Config instance.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            The configure parameter for this NIC was
 | 
						|
                                 set successfully.
 | 
						|
  @retval EFI_ALREADY_STARTED    There is a pending auto configuration.
 | 
						|
  @retval EFI_NOT_FOUND          No auto configure parameter is found.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Ip4ConfigConvertIfrNvDataToDeviceConfigData (
 | 
						|
  IN     IP4_CONFIG_IFR_NVDATA     *IfrFormNvData,
 | 
						|
  IN OUT IP4_CONFIG_INSTANCE       *Ip4ConfigInstance
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  EFI_IP_ADDRESS            HostIp;
 | 
						|
  EFI_IP_ADDRESS            SubnetMask;
 | 
						|
  EFI_IP_ADDRESS            Gateway;
 | 
						|
  EFI_INPUT_KEY             Key;
 | 
						|
  NIC_IP4_CONFIG_INFO       *NicInfo;
 | 
						|
  EFI_IP_ADDRESS            Ip;
 | 
						|
 | 
						|
  ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo, sizeof (IP4_SETTING_INFO));
 | 
						|
 | 
						|
  Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured = IfrFormNvData->Configure;
 | 
						|
  Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled = IfrFormNvData->DhcpEnable;
 | 
						|
  Ip4StrToIp (IfrFormNvData->StationAddress, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp);
 | 
						|
  Ip4StrToIp (IfrFormNvData->SubnetMask, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask);
 | 
						|
  Ip4StrToIp (IfrFormNvData->GatewayAddress, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.Gateway);
 | 
						|
 | 
						|
  if (!Ip4ConfigInstance->Ip4ConfigCallbackInfo.Configured) {
 | 
						|
    //
 | 
						|
    // Clear the variable
 | 
						|
    //
 | 
						|
    ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo, sizeof (IP4_SETTING_INFO));
 | 
						|
 | 
						|
    Status = EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NULL, TRUE);
 | 
						|
    if (Status == EFI_NOT_FOUND) {
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  NicInfo = AllocateZeroPool (sizeof (NIC_IP4_CONFIG_INFO) + 2 * sizeof (EFI_IP4_ROUTE_TABLE));
 | 
						|
  ASSERT (NicInfo != NULL);
 | 
						|
 | 
						|
  NicInfo->Ip4Info.RouteTable = (EFI_IP4_ROUTE_TABLE *) (NicInfo + 1);
 | 
						|
 | 
						|
  if (!Ip4ConfigInstance->Ip4ConfigCallbackInfo.DhcpEnabled) {
 | 
						|
    CopyMem (&HostIp.v4, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp, sizeof (HostIp.v4));
 | 
						|
    CopyMem (&SubnetMask.v4, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask, sizeof (SubnetMask.v4));
 | 
						|
    CopyMem (&Gateway.v4, &Ip4ConfigInstance->Ip4ConfigCallbackInfo.Gateway, sizeof (Gateway.v4));
 | 
						|
 | 
						|
    if (!NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {
 | 
						|
      CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
    if (EFI_IP4_EQUAL (&SubnetMask, &mZeroIp4Addr)) {
 | 
						|
      CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((Gateway.Addr[0] != 0)) {
 | 
						|
      if (SubnetMask.Addr[0] == 0) {
 | 
						|
        CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Gateway address is set but subnet mask is zero.", NULL);
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
 | 
						|
      } else if (!IP4_NET_EQUAL (HostIp.Addr[0], Gateway.Addr[0], SubnetMask.Addr[0])) {
 | 
						|
        CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Local IP and Gateway are not in the same subnet.", NULL);
 | 
						|
        return EFI_INVALID_PARAMETER;      }
 | 
						|
    }
 | 
						|
 | 
						|
    NicInfo->Source = IP4_CONFIG_SOURCE_STATIC;
 | 
						|
    NicInfo->Ip4Info.RouteTableSize = 2;
 | 
						|
 | 
						|
    CopyMem (&NicInfo->Ip4Info.StationAddress, &HostIp.v4, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
    CopyMem (&NicInfo->Ip4Info.SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
 | 
						|
    Ip.Addr[0] = HostIp.Addr[0] & SubnetMask.Addr[0];
 | 
						|
 | 
						|
    CopyMem (&NicInfo->Ip4Info.RouteTable[0].SubnetAddress, &Ip.v4, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
    CopyMem (&NicInfo->Ip4Info.RouteTable[0].SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
    CopyMem (&NicInfo->Ip4Info.RouteTable[1].GatewayAddress, &Gateway.v4, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
 | 
						|
  } else {
 | 
						|
    NicInfo->Source = IP4_CONFIG_SOURCE_DHCP;
 | 
						|
    ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
    ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
    ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.Gateway, sizeof (EFI_IPv4_ADDRESS));
 | 
						|
  }
 | 
						|
 | 
						|
  NicInfo->Perment = TRUE;
 | 
						|
  CopyMem (&NicInfo->NicAddr, &Ip4ConfigInstance->NicAddr, sizeof (NIC_ADDR));
 | 
						|
 | 
						|
  return EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NicInfo, TRUE);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function allows the caller to request the current
 | 
						|
  configuration for one or more named elements. The resulting
 | 
						|
  string is in <ConfigAltResp> format. Any and all alternative
 | 
						|
  configuration strings shall also be appended to the end of the
 | 
						|
  current configuration string. If they are, they must appear
 | 
						|
  after the current configuration. They must contain the same
 | 
						|
  routing (GUID, NAME, PATH) as the current configuration string.
 | 
						|
  They must have an additional description indicating the type of
 | 
						|
  alternative configuration the string represents,
 | 
						|
  "ALTCFG=<StringToken>". That <StringToken> (when
 | 
						|
  converted from Hex UNICODE to binary) is a reference to a
 | 
						|
  string in the associated string pack.
 | 
						|
 | 
						|
  @param[in] This       Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
 | 
						|
  @param[in] Request    A null-terminated Unicode string in
 | 
						|
                        <ConfigRequest> format. Note that this
 | 
						|
                        includes the routing information as well as
 | 
						|
                        the configurable name / value pairs. It is
 | 
						|
                        invalid for this string to be in
 | 
						|
                        <MultiConfigRequest> format.
 | 
						|
  @param[out] Progress  On return, points to a character in the
 | 
						|
                        Request string. Points to the string's null
 | 
						|
                        terminator if request was successful. Points
 | 
						|
                        to the most recent "&" before the first
 | 
						|
                        failing name / value pair (or the beginning
 | 
						|
                        of the string if the failure is in the first
 | 
						|
                        name / value pair) if the request was not
 | 
						|
                        successful.
 | 
						|
  @param[out] Results   A null-terminated Unicode string in
 | 
						|
                        <ConfigAltResp> format which has all values
 | 
						|
                        filled in for the names in the Request string.
 | 
						|
                        String to be allocated by the called function.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The Results string is filled with the
 | 
						|
                                  values corresponding to all requested
 | 
						|
                                  names.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
 | 
						|
                                  parts of the results that must be
 | 
						|
                                  stored awaiting possible future
 | 
						|
                                  protocols.
 | 
						|
  @retval EFI_NOT_FOUND           Routing data doesn't match any
 | 
						|
                                  known driver. Progress set to the
 | 
						|
                                  first character in the routing header.
 | 
						|
                                  Note: There is no requirement that the
 | 
						|
                                  driver validate the routing data. It
 | 
						|
                                  must skip the <ConfigHdr> in order to
 | 
						|
                                  process the names.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Illegal syntax. Progress set
 | 
						|
                                  to most recent & before the
 | 
						|
                                  error or the beginning of the
 | 
						|
                                  string.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Unknown name. Progress points
 | 
						|
                                  to the & before the name in
 | 
						|
                                  question.Currently not implemented.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Ip4DeviceExtractConfig (
 | 
						|
  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
 | 
						|
  IN  CONST EFI_STRING                       Request,
 | 
						|
  OUT EFI_STRING                             *Progress,
 | 
						|
  OUT EFI_STRING                             *Results
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                       Status;
 | 
						|
  NIC_IP4_CONFIG_INFO              *IfrDeviceNvData;
 | 
						|
  NIC_IP4_CONFIG_INFO              *NicConfig;
 | 
						|
  IP4_CONFIG_INSTANCE              *Ip4ConfigInstance;
 | 
						|
  IP4_CONFIG_IFR_NVDATA            *IfrFormNvData;
 | 
						|
  EFI_STRING                       ConfigRequestHdr;
 | 
						|
  EFI_STRING                       ConfigRequest;
 | 
						|
  EFI_STRING                       DeviceResult;
 | 
						|
  EFI_STRING                       FormResult;
 | 
						|
  CHAR16                           *StrPointer;
 | 
						|
  BOOLEAN                          AllocatedRequest;
 | 
						|
  UINTN                            Size;
 | 
						|
  UINTN                            BufferSize;
 | 
						|
 | 
						|
  if (Progress == NULL || Results == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  *Progress     = Request;
 | 
						|
  Size          = 0;
 | 
						|
  DeviceResult  = NULL;
 | 
						|
  FormResult    = NULL;
 | 
						|
  ConfigRequest = NULL;
 | 
						|
  Status        = EFI_SUCCESS;
 | 
						|
  AllocatedRequest  = FALSE;
 | 
						|
  Ip4ConfigInstance = IP4_CONFIG_INSTANCE_FROM_CONFIG_ACCESS (This);
 | 
						|
 | 
						|
  //
 | 
						|
  // Check Request data in <ConfigHdr>.
 | 
						|
  //
 | 
						|
  if ((Request == NULL) || HiiIsConfigHdrMatch (Request, &gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
 | 
						|
    IfrDeviceNvData = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);
 | 
						|
    if (IfrDeviceNvData == NULL) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    NicConfig = EfiNicIp4ConfigGetInfo (Ip4ConfigInstance);
 | 
						|
    if (NicConfig == NULL) {
 | 
						|
      return EFI_NOT_FOUND;
 | 
						|
    }
 | 
						|
    CopyMem (IfrDeviceNvData, NicConfig, SIZEOF_NIC_IP4_CONFIG_INFO (NicConfig));
 | 
						|
    FreePool (NicConfig);
 | 
						|
 | 
						|
    ConfigRequest = Request;
 | 
						|
    if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
 | 
						|
      //
 | 
						|
      // Request has no request element, construct full request string.
 | 
						|
      // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
 | 
						|
      // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
 | 
						|
      //
 | 
						|
      ConfigRequestHdr = HiiConstructConfigHdr (&gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE, Ip4ConfigInstance->ChildHandle);
 | 
						|
      Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
 | 
						|
      ConfigRequest = AllocateZeroPool (Size);
 | 
						|
      ASSERT (ConfigRequest != NULL);
 | 
						|
      AllocatedRequest = TRUE;
 | 
						|
      BufferSize = NIC_ITEM_CONFIG_SIZE;
 | 
						|
      UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
 | 
						|
      FreePool (ConfigRequestHdr);
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
 | 
						|
    //
 | 
						|
    Status = gHiiConfigRouting->BlockToConfig (
 | 
						|
                                  gHiiConfigRouting,
 | 
						|
                                  ConfigRequest,
 | 
						|
                                  (UINT8 *) IfrDeviceNvData,
 | 
						|
                                  NIC_ITEM_CONFIG_SIZE,
 | 
						|
                                  &DeviceResult,
 | 
						|
                                  Progress
 | 
						|
                                  );
 | 
						|
 | 
						|
    FreePool (IfrDeviceNvData);
 | 
						|
    //
 | 
						|
    // Free the allocated config request string.
 | 
						|
    //
 | 
						|
    if (AllocatedRequest) {
 | 
						|
      FreePool (ConfigRequest);
 | 
						|
      ConfigRequest = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      goto Failure;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if ((Request == NULL) || HiiIsConfigHdrMatch (Request, &mNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
 | 
						|
 | 
						|
    IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG_IFR_NVDATA));
 | 
						|
    if (IfrFormNvData == NULL) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    Ip4ConfigConvertDeviceConfigDataToIfrNvData (Ip4ConfigInstance, IfrFormNvData);
 | 
						|
 | 
						|
    ConfigRequest = Request;
 | 
						|
    if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
 | 
						|
      //
 | 
						|
      // Request has no request element, construct full request string.
 | 
						|
      // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
 | 
						|
      // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
 | 
						|
      //
 | 
						|
      ConfigRequestHdr = HiiConstructConfigHdr (&mNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE, Ip4ConfigInstance->ChildHandle);
 | 
						|
      Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
 | 
						|
      ConfigRequest = AllocateZeroPool (Size);
 | 
						|
      ASSERT (ConfigRequest != NULL);
 | 
						|
      AllocatedRequest = TRUE;
 | 
						|
      BufferSize = sizeof (IP4_CONFIG_IFR_NVDATA);
 | 
						|
      UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
 | 
						|
      FreePool (ConfigRequestHdr);
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
 | 
						|
    //
 | 
						|
    Status = gHiiConfigRouting->BlockToConfig (
 | 
						|
                                  gHiiConfigRouting,
 | 
						|
                                  ConfigRequest,
 | 
						|
                                  (UINT8 *) IfrFormNvData,
 | 
						|
                                  sizeof (IP4_CONFIG_IFR_NVDATA),
 | 
						|
                                  &FormResult,
 | 
						|
                                  Progress
 | 
						|
                                  );
 | 
						|
 | 
						|
    FreePool (IfrFormNvData);
 | 
						|
    //
 | 
						|
    // Free the allocated config request string.
 | 
						|
    //
 | 
						|
    if (AllocatedRequest) {
 | 
						|
      FreePool (ConfigRequest);
 | 
						|
      ConfigRequest = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      goto Failure;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (Request == NULL) {
 | 
						|
    Size = StrLen (DeviceResult);
 | 
						|
    Size = Size + 1;
 | 
						|
    Size = Size + StrLen (FormResult) + 1;
 | 
						|
    *Results = AllocateZeroPool (Size * sizeof (CHAR16));
 | 
						|
    ASSERT (*Results != NULL);
 | 
						|
    StrPointer  = *Results;
 | 
						|
    StrCpy (StrPointer, DeviceResult);
 | 
						|
    StrPointer  = StrPointer + StrLen (StrPointer);
 | 
						|
    *StrPointer = L'&';
 | 
						|
    StrCpy (StrPointer + 1, FormResult);
 | 
						|
    FreePool (DeviceResult);
 | 
						|
    FreePool (FormResult);
 | 
						|
  } else if (HiiIsConfigHdrMatch (Request, &gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
 | 
						|
    *Results = DeviceResult;
 | 
						|
  } else if (HiiIsConfigHdrMatch (Request, &mNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
 | 
						|
    *Results = FormResult;
 | 
						|
  } else {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
Failure:
 | 
						|
  //
 | 
						|
  // Set Progress string to the original request string.
 | 
						|
  //
 | 
						|
  if (Request == NULL) {
 | 
						|
    *Progress = NULL;
 | 
						|
  } else if (StrStr (Request, L"OFFSET") == NULL) {
 | 
						|
    *Progress = Request + StrLen (Request);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function applies changes in a driver's configuration.
 | 
						|
  Input is a Configuration, which has the routing data for this
 | 
						|
  driver followed by name / value configuration pairs. The driver
 | 
						|
  must apply those pairs to its configurable storage. If the
 | 
						|
  driver's configuration is stored in a linear block of data
 | 
						|
  and the driver's name / value pairs are in <BlockConfig>
 | 
						|
  format, it may use the ConfigToBlock helper function (above) to
 | 
						|
  simplify the job. Currently not implemented.
 | 
						|
 | 
						|
  @param[in]  This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
 | 
						|
  @param[in]  Configuration  A null-terminated Unicode string in
 | 
						|
                             <ConfigString> format.
 | 
						|
  @param[out] Progress       A pointer to a string filled in with the
 | 
						|
                             offset of the most recent '&' before the
 | 
						|
                             first failing name / value pair (or the
 | 
						|
                             beginn ing of the string if the failure
 | 
						|
                             is in the first name / value pair) or
 | 
						|
                             the terminating NULL if all was
 | 
						|
                             successful.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The results have been distributed or are
 | 
						|
                                  awaiting distribution.
 | 
						|
  @retval EFI_OUT_OF_MEMORY       Not enough memory to store the
 | 
						|
                                  parts of the results that must be
 | 
						|
                                  stored awaiting possible future
 | 
						|
                                  protocols.
 | 
						|
  @retval EFI_INVALID_PARAMETERS  Passing in a NULL for the
 | 
						|
                                  Results parameter would result
 | 
						|
                                  in this type of error.
 | 
						|
  @retval EFI_NOT_FOUND           Target for the specified routing data
 | 
						|
                                  was not found.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Ip4DeviceRouteConfig (
 | 
						|
  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
 | 
						|
  IN  CONST EFI_STRING                       Configuration,
 | 
						|
  OUT EFI_STRING                             *Progress
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                       Status;
 | 
						|
  UINTN                            BufferSize;
 | 
						|
  NIC_IP4_CONFIG_INFO              *IfrDeviceNvData;
 | 
						|
  IP4_CONFIG_IFR_NVDATA            *IfrFormNvData;
 | 
						|
  NIC_IP4_CONFIG_INFO              *NicInfo;
 | 
						|
  IP4_CONFIG_INSTANCE              *Ip4ConfigInstance;
 | 
						|
  EFI_MAC_ADDRESS                  ZeroMac;
 | 
						|
 | 
						|
  if (Configuration == NULL || Progress == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Reclaim Ip4Config variable
 | 
						|
  //
 | 
						|
  Ip4ConfigReclaimVariable ();
 | 
						|
 | 
						|
  *Progress = Configuration;
 | 
						|
 | 
						|
  Ip4ConfigInstance = IP4_CONFIG_INSTANCE_FROM_CONFIG_ACCESS (This);
 | 
						|
 | 
						|
  //
 | 
						|
  // Check Routing data in <ConfigHdr>.
 | 
						|
  //
 | 
						|
  if (HiiIsConfigHdrMatch (Configuration, &mNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
 | 
						|
    //
 | 
						|
    // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
 | 
						|
    //
 | 
						|
    IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG_IFR_NVDATA));
 | 
						|
    if (IfrFormNvData == NULL) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    BufferSize = NIC_ITEM_CONFIG_SIZE;
 | 
						|
    Status = gHiiConfigRouting->ConfigToBlock (
 | 
						|
                                  gHiiConfigRouting,
 | 
						|
                                  Configuration,
 | 
						|
                                  (UINT8 *) IfrFormNvData,
 | 
						|
                                  &BufferSize,
 | 
						|
                                  Progress
 | 
						|
                                  );
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      Status = Ip4ConfigConvertIfrNvDataToDeviceConfigData (IfrFormNvData, Ip4ConfigInstance);
 | 
						|
    }
 | 
						|
 | 
						|
    FreePool (IfrFormNvData);
 | 
						|
 | 
						|
  } else if (HiiIsConfigHdrMatch (Configuration, &gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE)) {
 | 
						|
 | 
						|
    IfrDeviceNvData = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);
 | 
						|
    if (IfrDeviceNvData == NULL) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    BufferSize = NIC_ITEM_CONFIG_SIZE;
 | 
						|
    Status = gHiiConfigRouting->ConfigToBlock (
 | 
						|
                                  gHiiConfigRouting,
 | 
						|
                                  Configuration,
 | 
						|
                                  (UINT8 *) IfrDeviceNvData,
 | 
						|
                                  &BufferSize,
 | 
						|
                                  Progress
 | 
						|
                                  );
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      ZeroMem (&ZeroMac, sizeof (EFI_MAC_ADDRESS));
 | 
						|
      if (CompareMem (&IfrDeviceNvData->NicAddr.MacAddr, &ZeroMac, IfrDeviceNvData->NicAddr.Len) != 0) {
 | 
						|
        BufferSize = SIZEOF_NIC_IP4_CONFIG_INFO (IfrDeviceNvData);
 | 
						|
        NicInfo = AllocateCopyPool (BufferSize, IfrDeviceNvData);
 | 
						|
        if (NicInfo == NULL) {
 | 
						|
          return EFI_OUT_OF_RESOURCES;
 | 
						|
        }
 | 
						|
        Status = EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NicInfo, TRUE);
 | 
						|
        FreePool (NicInfo);
 | 
						|
      } else {
 | 
						|
        ZeroMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo, sizeof (IP4_SETTING_INFO));
 | 
						|
        Status = EfiNicIp4ConfigSetInfo (Ip4ConfigInstance, NULL, TRUE);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    FreePool (IfrDeviceNvData);
 | 
						|
 | 
						|
  } else {
 | 
						|
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function is called to provide results data to the driver.
 | 
						|
  This data consists of a unique key that is used to identify
 | 
						|
  which data is either being passed back or being asked for.
 | 
						|
 | 
						|
  @param[in]  This               Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
 | 
						|
  @param[in]  Action             Specifies the type of action taken by the browser.
 | 
						|
  @param[in]  QuestionId         A unique value which is sent to the original
 | 
						|
                                 exporting driver so that it can identify the type
 | 
						|
                                 of data to expect. The format of the data tends to
 | 
						|
                                 vary based on the opcode that enerated the callback.
 | 
						|
  @param[in]  Type               The type of value for the question.
 | 
						|
  @param[in]  Value              A pointer to the data being sent to the original
 | 
						|
                                 exporting driver.
 | 
						|
  @param[out]  ActionRequest     On return, points to the action requested by the
 | 
						|
                                 callback function.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            The callback successfully handled the action.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the
 | 
						|
                                 variable and its data.
 | 
						|
  @retval EFI_DEVICE_ERROR       The variable could not be saved.
 | 
						|
  @retval EFI_UNSUPPORTED        The specified Action is not supported by the
 | 
						|
                                 callback.Currently not implemented.
 | 
						|
  @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.
 | 
						|
  @retval Others                 Other errors as indicated.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
Ip4FormCallback (
 | 
						|
  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
 | 
						|
  IN  EFI_BROWSER_ACTION                     Action,
 | 
						|
  IN  EFI_QUESTION_ID                        QuestionId,
 | 
						|
  IN  UINT8                                  Type,
 | 
						|
  IN  EFI_IFR_TYPE_VALUE                     *Value,
 | 
						|
  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest
 | 
						|
  )
 | 
						|
{
 | 
						|
  IP4_CONFIG_INSTANCE       *Ip4ConfigInstance;
 | 
						|
  IP4_CONFIG_IFR_NVDATA     *IfrFormNvData;
 | 
						|
  EFI_IP_ADDRESS            HostIp;
 | 
						|
  EFI_IP_ADDRESS            SubnetMask;
 | 
						|
  EFI_IP_ADDRESS            Gateway;
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  EFI_INPUT_KEY             Key;
 | 
						|
 | 
						|
  if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) {
 | 
						|
    //
 | 
						|
    // Do nothing for UEFI OPEN/CLOSE Action
 | 
						|
    //
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  Ip4ConfigInstance = IP4_CONFIG_INSTANCE_FROM_CONFIG_ACCESS (This);
 | 
						|
 | 
						|
  IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG_IFR_NVDATA));
 | 
						|
  if (IfrFormNvData == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Retrive uncommitted data from Browser
 | 
						|
  //
 | 
						|
  if (!HiiGetBrowserData (&mNicIp4ConfigNvDataGuid, EFI_NIC_IP4_CONFIG_VARIABLE, sizeof (IP4_CONFIG_IFR_NVDATA), (UINT8 *) IfrFormNvData)) {
 | 
						|
    FreePool (IfrFormNvData);
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = EFI_SUCCESS;
 | 
						|
 | 
						|
  switch (QuestionId) {
 | 
						|
  case KEY_LOCAL_IP:
 | 
						|
    Status = Ip4StrToIp (IfrFormNvData->StationAddress, &HostIp.v4);
 | 
						|
    if (EFI_ERROR (Status) || !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {
 | 
						|
      CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);
 | 
						|
      Status = EFI_INVALID_PARAMETER;
 | 
						|
    } else {
 | 
						|
      CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.LocalIp, &HostIp.v4, sizeof (HostIp.v4));
 | 
						|
    }
 | 
						|
 | 
						|
    break;
 | 
						|
 | 
						|
  case KEY_SUBNET_MASK:
 | 
						|
    Status = Ip4StrToIp (IfrFormNvData->SubnetMask, &SubnetMask.v4);
 | 
						|
    if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {
 | 
						|
      CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);
 | 
						|
      Status = EFI_INVALID_PARAMETER;
 | 
						|
    } else {
 | 
						|
      CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));
 | 
						|
    }
 | 
						|
 | 
						|
    break;
 | 
						|
 | 
						|
  case KEY_GATE_WAY:
 | 
						|
    Status = Ip4StrToIp (IfrFormNvData->GatewayAddress, &Gateway.v4);
 | 
						|
    if (EFI_ERROR (Status) || ((Gateway.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), 0))) {
 | 
						|
      CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL);
 | 
						|
      Status = EFI_INVALID_PARAMETER;
 | 
						|
    } else {
 | 
						|
      CopyMem (&Ip4ConfigInstance->Ip4ConfigCallbackInfo.Gateway, &Gateway.v4, sizeof (Gateway.v4));
 | 
						|
    }
 | 
						|
 | 
						|
    break;
 | 
						|
 | 
						|
  case KEY_SAVE_CHANGES:
 | 
						|
    Status = Ip4ConfigConvertIfrNvDataToDeviceConfigData (IfrFormNvData, Ip4ConfigInstance);
 | 
						|
    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
    break;
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (IfrFormNvData);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Install HII Config Access protocol for network device and allocate resource.
 | 
						|
 | 
						|
  @param[in]  Instance            The IP4 Config instance.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS              The HII Config Access protocol is installed.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES     Failed to allocate memory.
 | 
						|
  @retval Others                   Other errors as indicated.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Ip4ConfigDeviceInit (
 | 
						|
  IN IP4_CONFIG_INSTANCE         *Instance
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                     Status;
 | 
						|
  EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
 | 
						|
  VENDOR_DEVICE_PATH             VendorDeviceNode;
 | 
						|
  EFI_SERVICE_BINDING_PROTOCOL   *MnpSb;
 | 
						|
  CHAR16                         *MacString;
 | 
						|
  CHAR16                         MenuString[128];
 | 
						|
  CHAR16                         PortString[128];
 | 
						|
  CHAR16                         *OldMenuString;
 | 
						|
 | 
						|
  ConfigAccess = &Instance->HiiConfigAccessProtocol;
 | 
						|
  ConfigAccess->ExtractConfig = Ip4DeviceExtractConfig;
 | 
						|
  ConfigAccess->RouteConfig   = Ip4DeviceRouteConfig;
 | 
						|
  ConfigAccess->Callback      = Ip4FormCallback;
 | 
						|
 | 
						|
  //
 | 
						|
  // Construct device path node for EFI HII Config Access protocol,
 | 
						|
  // which consists of controller physical device path and one hardware
 | 
						|
  // vendor guid node.
 | 
						|
  //
 | 
						|
  ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH));
 | 
						|
  VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;
 | 
						|
  VendorDeviceNode.Header.SubType = HW_VENDOR_DP;
 | 
						|
 | 
						|
  CopyGuid (&VendorDeviceNode.Guid, &gEfiNicIp4ConfigVariableGuid);
 | 
						|
 | 
						|
  SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH));
 | 
						|
  Instance->HiiVendorDevicePath = AppendDevicePathNode (
 | 
						|
                                    Instance->ParentDevicePath,
 | 
						|
                                    (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode
 | 
						|
                                    );
 | 
						|
 | 
						|
  Instance->ChildHandle = NULL;
 | 
						|
  //
 | 
						|
  // Install Device Path Protocol and Config Access protocol on new handle
 | 
						|
  //
 | 
						|
  Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                  &Instance->ChildHandle,
 | 
						|
                  &gEfiDevicePathProtocolGuid,
 | 
						|
                  Instance->HiiVendorDevicePath,
 | 
						|
                  &gEfiHiiConfigAccessProtocolGuid,
 | 
						|
                  ConfigAccess,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // Open the Parent Handle for the child
 | 
						|
    //
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                    Instance->Controller,
 | 
						|
                    &gEfiManagedNetworkServiceBindingProtocolGuid,
 | 
						|
                    (VOID **) &MnpSb,
 | 
						|
                    Instance->Image,
 | 
						|
                    Instance->ChildHandle,
 | 
						|
                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | 
						|
                    );
 | 
						|
  }
 | 
						|
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  //
 | 
						|
  // Publish our HII data
 | 
						|
  //
 | 
						|
  Instance->RegisteredHandle = HiiAddPackages (
 | 
						|
                                 &mNicIp4ConfigNvDataGuid,
 | 
						|
                                 Instance->ChildHandle,
 | 
						|
                                 Ip4ConfigDxeStrings,
 | 
						|
                                 Ip4ConfigDxeBin,
 | 
						|
                                 NULL
 | 
						|
                                 );
 | 
						|
  if (Instance->RegisteredHandle == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Append MAC string in the menu help string and tile help string
 | 
						|
  //
 | 
						|
  Status = NetLibGetMacString (Instance->Controller, Instance->Image, &MacString);
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    OldMenuString = HiiGetString (Instance->RegisteredHandle, STRING_TOKEN (STR_IP4_CONFIG_FORM_HELP), NULL);
 | 
						|
    UnicodeSPrint (MenuString, 128, L"%s (MAC:%s)", OldMenuString, MacString);
 | 
						|
    HiiSetString (Instance->RegisteredHandle, STRING_TOKEN (STR_IP4_CONFIG_FORM_HELP), MenuString, NULL);
 | 
						|
 | 
						|
    UnicodeSPrint (PortString, 128, L"MAC:%s", MacString);
 | 
						|
    HiiSetString (Instance->RegisteredHandle, STRING_TOKEN (STR_IP4_DEVICE_FORM_HELP), PortString, NULL);
 | 
						|
    FreePool (MacString);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Uninstall HII Config Access protocol for network device and free resource.
 | 
						|
 | 
						|
  @param[in]  Instance            The IP4 Config instance.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS             The HII Config Access protocol is uninstalled.
 | 
						|
  @retval Others                  Other errors as indicated.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Ip4ConfigDeviceUnload (
 | 
						|
  IN IP4_CONFIG_INSTANCE              *Instance
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // Remove HII package list
 | 
						|
  //
 | 
						|
  HiiRemovePackages (Instance->RegisteredHandle);
 | 
						|
 | 
						|
  //
 | 
						|
  // Close the child handle
 | 
						|
  //
 | 
						|
  gBS->CloseProtocol (
 | 
						|
         Instance->Controller,
 | 
						|
         &gEfiManagedNetworkServiceBindingProtocolGuid,
 | 
						|
         Instance->Image,
 | 
						|
         Instance->ChildHandle
 | 
						|
         );
 | 
						|
 | 
						|
  //
 | 
						|
  // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
 | 
						|
  //
 | 
						|
  gBS->UninstallMultipleProtocolInterfaces (
 | 
						|
         Instance->ChildHandle,
 | 
						|
         &gEfiDevicePathProtocolGuid,
 | 
						|
         Instance->HiiVendorDevicePath,
 | 
						|
         &gEfiHiiConfigAccessProtocolGuid,
 | 
						|
         &Instance->HiiConfigAccessProtocol,
 | 
						|
         NULL
 | 
						|
         );
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |