public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Marcin Wojtas <mw@semihalf.com>
To: edk2-devel@lists.01.org
Cc: feng.tian@intel.com, michael.d.kinney@intel.com,
	liming.gao@intel.com, leif.lindholm@linaro.org, mw@semihalf.com,
	jsd@semihalf.com, bsz@semihalf.com
Subject: [PATCH 1/2] MdeModulePkg: NetLib: introduce MAC address handling helper routines
Date: Fri,  4 Nov 2016 19:28:42 +0100	[thread overview]
Message-ID: <1478284123-4355-2-git-send-email-mw@semihalf.com> (raw)
In-Reply-To: <1478284123-4355-1-git-send-email-mw@semihalf.com>

This patch introduces three functions that can be used for handling
MAC address update. It's also a preparation commit for adding support
for this feature using 'ifconfig' shell command. New functions are as
following:

* NetLibSetMacAddress - locate simple network protocol associated with the
  Service Binding Handle and try to update/reset the MAC address from SNP,
  using Snp->StationAddress() callback.

* NetLibStrToMac - convert one Null-terminated Unicode string to
  EFI_MAC_ADDRESS format.

* NetLibAsciiStrToMac - convert one Null-terminated ASCII string to
  EFI_MAC_ADDRESS format.

* NetLibReconnectInterface - reconnect the service handle. When called
  after NetLibSetMacAddress() it allows for updating associated
  protocols with new MAC address information.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
---
 MdeModulePkg/Include/Library/NetLib.h      |  83 ++++++++++++
 MdeModulePkg/Library/DxeNetLib/DxeNetLib.c | 196 +++++++++++++++++++++++++++++
 2 files changed, 279 insertions(+)

diff --git a/MdeModulePkg/Include/Library/NetLib.h b/MdeModulePkg/Include/Library/NetLib.h
index 26709af..7a50f9c 100644
--- a/MdeModulePkg/Include/Library/NetLib.h
+++ b/MdeModulePkg/Include/Library/NetLib.h
@@ -523,6 +523,9 @@ extern IP4_ADDR gIp4AllMasks[IP4_MASK_NUM];
 extern EFI_IPv4_ADDRESS  mZeroIp4Addr;
 
 #define NET_IS_DIGIT(Ch)            (('0' <= (Ch)) && ((Ch) <= '9'))
+#define NET_IS_HEX(Ch)              ((('0' <= (Ch)) && ((Ch) <= '9')) || \
+                                     (('A' <= (Ch)) && ((Ch) <= 'F')) || \
+                                     (('a' <= (Ch)) && ((Ch) <= 'f')))
 #define NET_ROUNDUP(size, unit)     (((size) + (unit) - 1) & (~((unit) - 1)))
 #define NET_IS_LOWER_CASE_CHAR(Ch)  (('a' <= (Ch)) && ((Ch) <= 'z'))
 #define NET_IS_UPPER_CASE_CHAR(Ch)  (('A' <= (Ch)) && ((Ch) <= 'Z'))
@@ -1180,6 +1183,49 @@ NetLibGetMacAddress (
   );
 
 /**
+  Update or reset MAC address associated with the network service handle.
+
+  Locate simple network protocol associated with the Service Binding Handle and
+  try to update/reset the mac address from SNP, using Snp->StationAddress().
+
+  @param[in]   ServiceHandle    The handle where network service binding protocols are
+                                installed on.
+  @param[in]   MacAddress       The pointer with new MAC address.
+  @param[in]   AddressSize      The length of set MAC address.
+  @param[in]   Reset            Reset MAC address to initial settings.
+
+  @retval EFI_SUCCESS           MAC address was updated/reset successfully.
+  @retval Others                Failed to set SNP MAC address.
+
+**/
+EFI_STATUS
+EFIAPI
+NetLibSetMacAddress (
+  IN EFI_HANDLE       ServiceHandle,
+  IN EFI_MAC_ADDRESS  *MacAddress,
+  IN UINT32            AddressSize,
+  IN BOOLEAN          Reset
+  );
+
+/**
+  Reconnect the network service handle.
+
+  Reconnect Service Binding Handle using Boot Services Dis/ConnectController() routines.
+
+  @param[in]   ServiceHandle    The handle where network service binding protocols are
+                                installed on.
+
+  @retval EFI_SUCCESS           Interface handle was reconnected successfully.
+  @retval Others                Failed to reconnect interface handle.
+
+**/
+EFI_STATUS
+EFIAPI
+NetLibReconnectInterface (
+  IN EFI_HANDLE             ServiceHandle
+  );
+
+/**
   Convert MAC address of the NIC associated with specified Service Binding Handle
   to a unicode string. Callers are responsible for freeing the string storage.
 
@@ -1348,6 +1394,24 @@ NetLibDefaultUnload (
   );
 
 /**
+  Convert one Null-terminated ASCII string to EFI_MAC_ADDRESS. The format of
+  the string has to be compliant with colon-separated EUI-48.
+
+  @param[in]      String         The pointer to the Ascii string.
+  @param[out]     MacAddress     The pointer to the converted MAC address.
+
+  @retval EFI_SUCCESS            Converted to an MAC address successfully.
+  @retval EFI_INVALID_PARAMETER  The string is malformated, or MacAddress is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+NetLibAsciiStrToMac (
+  IN CONST CHAR8                 *String,
+  OUT      EFI_MAC_ADDRESS       *MacAddress
+  );
+
+/**
   Convert one Null-terminated ASCII string (decimal dotted) to EFI_IPv4_ADDRESS.
 
   @param[in]      String         The pointer to the Ascii string.
@@ -1383,6 +1447,25 @@ NetLibAsciiStrToIp6 (
   );
 
 /**
+  Convert one Null-terminated Unicode string to EFI_MAC_ADDRESS. The format of
+  the string has to be compliant with colon-separated EUI-48.
+
+  @param[in]      String         The pointer to the Ascii string.
+  @param[out]     MacAddress     The pointer to the converted MAC address.
+
+  @retval EFI_SUCCESS            Converted to an MAC address successfully.
+  @retval EFI_INVALID_PARAMETER  The string is mal-formated or MacAddress is NULL.
+  @retval EFI_OUT_OF_RESOURCES   Failed to perform the operation due to lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+NetLibStrToMac (
+  IN CONST CHAR16                *String,
+  OUT      EFI_MAC_ADDRESS       *MacAddress
+  );
+
+/**
   Convert one Null-terminated Unicode string (decimal dotted) to EFI_IPv4_ADDRESS.
 
   @param[in]      String         The pointer to the Ascii string.
diff --git a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c
index 04d8345..f9ed863 100644
--- a/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c
+++ b/MdeModulePkg/Library/DxeNetLib/DxeNetLib.c
@@ -2189,6 +2189,90 @@ NetLibGetMacAddress (
 }
 
 /**
+  Update or reset MAC address associated with the network service handle.
+
+  Locate simple network protocol associated with the Service Binding Handle and
+  try to update/reset the mac address from SNP, using Snp->StationAddress().
+
+  @param[in]   ServiceHandle    The handle where network service binding protocols are
+                                installed on.
+  @param[in]   MacAddress       The pointer with new MAC address.
+  @param[in]   AddressSize      The length of set MAC address.
+  @param[in]   Reset            Reset MAC address to initial settings.
+
+  @retval EFI_SUCCESS           MAC address was updated/reset successfully.
+  @retval Others                Failed to set SNP MAC address.
+
+**/
+EFI_STATUS
+EFIAPI
+NetLibSetMacAddress (
+  IN EFI_HANDLE       ServiceHandle,
+  IN EFI_MAC_ADDRESS  *MacAddress,
+  IN UINT32           AddressSize,
+  IN BOOLEAN          Reset
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_SIMPLE_NETWORK_PROTOCOL  *Snp;
+  EFI_HANDLE                   *SnpHandle;
+
+  ASSERT (AddressSize == NET_ETHER_ADDR_LEN);
+
+  //
+  // Get SNP handle
+  //
+  Snp = NULL;
+  SnpHandle = NetLibGetSnpHandle (ServiceHandle, &Snp);
+
+  if (SnpHandle == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!Snp->StationAddress) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Invoke Snp->StationAddress()
+  //
+  Status = Snp->StationAddress (Snp, Reset, MacAddress);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Reconnect the network service handle.
+
+  Reconnect Service Binding Handle using Boot Services Dis/ConnectController() routines.
+
+  @param[in]   ServiceHandle    The handle where network service binding protocols are
+                                installed on.
+
+  @retval EFI_SUCCESS           Interface handle was reconnected successfully.
+  @retval Others                Failed to reconnect interface handle.
+
+**/
+EFI_STATUS
+EFIAPI
+NetLibReconnectInterface (
+  IN EFI_HANDLE             ServiceHandle
+  )
+{
+  EFI_STATUS Status;
+
+  Status = gBS->DisconnectController(ServiceHandle, NULL, NULL);
+  if (!EFI_ERROR (Status)) {
+    Status = gBS->ConnectController(ServiceHandle, NULL, NULL, TRUE);
+  }
+
+  return Status;
+}
+
+/**
   Convert MAC address of the NIC associated with specified Service Binding Handle
   to a unicode string. Callers are responsible for freeing the string storage.
 
@@ -2693,6 +2777,76 @@ NetLibGetNicHandle (
 }
 
 /**
+  Convert one Null-terminated ASCII string to EFI_MAC_ADDRESS. The format of
+  the string has to be compliant with colon-separated EUI-48.
+
+  @param[in]      String         The pointer to the Ascii string.
+  @param[out]     MacAddress     The pointer to the converted MAC address.
+
+  @retval EFI_SUCCESS            Convert to MAC address successfully.
+  @retval EFI_INVALID_PARAMETER  The string is mal-formated or MacAddress is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+NetLibAsciiStrToMac (
+  IN CONST CHAR8                 *String,
+  OUT      EFI_MAC_ADDRESS       *MacAddress
+  )
+{
+  UINT8                          Index;
+  CHAR8                          *MacStr;
+  CHAR8                          *TempStr;
+  UINTN                          NodeVal;
+
+  if ((String == NULL) || (MacAddress == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  MacStr = (CHAR8 *) String;
+
+  for (Index = 0; Index < 6; Index++) {
+    TempStr = MacStr;
+
+    while ((*MacStr != '\0') && (*MacStr != ':')) {
+      if (!NET_IS_HEX (*MacStr)) {
+        return EFI_INVALID_PARAMETER;
+      }
+      MacStr++;
+    }
+
+    //
+    // The MAC address is X:X:X:X:X:X
+    //
+    if (*MacStr == ':') {
+      if (Index == 5) {
+        return EFI_INVALID_PARAMETER;
+      }
+    } else {
+      if (Index != 5) {
+        return EFI_INVALID_PARAMETER;
+      }
+    }
+
+    //
+    // Convert the string to MAC address. AsciiStrHexToUintn stops at the
+    // first character that is not a valid hexadecimal character,
+    // ':' or '\0' here.
+    //
+    NodeVal = AsciiStrHexToUintn (TempStr);
+    if (NodeVal > 0xFF) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    MacAddress->Addr[Index] = (UINT8) NodeVal;
+
+    MacStr++;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
   Convert one Null-terminated ASCII string (decimal dotted) to EFI_IPv4_ADDRESS.
 
   @param[in]      String         The pointer to the Ascii string.
@@ -2957,6 +3111,48 @@ NetLibAsciiStrToIp6 (
   return EFI_SUCCESS;
 }
 
+/**
+  Convert one Null-terminated Unicode string to EFI_MAC_ADDRESS. The format of
+  the string has to be compliant with colon-separated EUI-48.
+
+  @param[in]      String         The pointer to the Ascii string.
+  @param[out]     MacAddress     The pointer to the converted MAC address.
+
+  @retval EFI_SUCCESS            Convert to MAC address successfully.
+  @retval EFI_INVALID_PARAMETER  The string is mal-formated or MacAddress is NULL.
+  @retval EFI_OUT_OF_RESOURCES   Fail to perform the operation due to lack of resource.
+
+**/
+EFI_STATUS
+EFIAPI
+NetLibStrToMac (
+  IN CONST CHAR16                *String,
+  OUT      EFI_MAC_ADDRESS       *MacAddress
+  )
+{
+  CHAR8                          *MacStr;
+  UINTN                          StringSize;
+  EFI_STATUS                     Status;
+
+  if ((String == NULL) || (MacAddress == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  StringSize = StrLen (String) + 1;
+  MacStr = (CHAR8 *) AllocatePool (StringSize * sizeof (CHAR8));
+  if (MacStr == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  UnicodeStrToAsciiStrS (String, MacStr, StringSize);
+
+  Status = NetLibAsciiStrToMac (MacStr, MacAddress);
+
+  FreePool (MacStr);
+
+  return Status;
+}
+
 
 /**
   Convert one Null-terminated Unicode string (decimal dotted) to EFI_IPv4_ADDRESS.
-- 
1.8.3.1



  reply	other threads:[~2016-11-04 18:27 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-04 18:28 [PATCH 0/2] MAC address configuration from Shell Marcin Wojtas
2016-11-04 18:28 ` Marcin Wojtas [this message]
2016-11-04 18:28 ` [PATCH 2/2] ShellPkg/Ifconfig: Enable setting MAC address Marcin Wojtas
2016-11-04 20:38   ` Carsey, Jaben
2016-11-07 11:54     ` Marcin Wojtas
2016-11-07 18:16       ` Carsey, Jaben

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1478284123-4355-2-git-send-email-mw@semihalf.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox