public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Wang Fan <fan.wang@intel.com>
To: edk2-devel@lists.01.org
Cc: Ye Ting <ting.ye@intel.com>, Fu Siyuan <siyuan.fu@intel.com>,
	Wu Jiaxin <jiaxin.wu@intel.com>
Subject: [Patch V2] NetworkPkg: Add WiFi Connection Manager to NetworkPkg
Date: Fri, 22 Feb 2019 15:48:25 +0800	[thread overview]
Message-ID: <20190222074825.8864-1-fan.wang@intel.com> (raw)

* V2

* Remove Arch dependency in Inf file
* Add a global guid for WiFi formset and set other guids to module levels
* Open supplicant and EapConfig by BY_DRIVER
* Remove token free function to avoid potential NULL reference
* Update WifiMgrUpdateConnectMessage() to only display message for Current Nic
* Fix the potential NULL reference in AIP call


* REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1492

Add WiFi Connection Manager in NetworkPkg to provide UI for users to scan
networks, connect or disconnect to networks.

This connection manager won't include the UNDI driver, supplicant driver,
or other device specific drivers and is therefor not a complete solution
stack for UEFI Wi-Fi, users can seek help for Wireless card vendors.

Cc: Ye Ting <ting.ye@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Wu Jiaxin <jiaxin.wu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Wang Fan <fan.wang@intel.com>
---
 .../Include/Guid/WifiConnectionManagerConfigHii.h  |   25 +
 NetworkPkg/NetworkPkg.dec                          |    3 +
 NetworkPkg/NetworkPkg.dsc                          |    1 +
 NetworkPkg/WifiConnectionManagerDxe/EapContext.h   |   28 +
 .../WifiConnectionManagerDxe.inf                   |   87 +
 .../WifiConnectionManagerDxe.vfr                   |  353 ++++
 .../WifiConnectionManagerDxeStrings.uni            |  109 ++
 .../WifiConnectionMgrComponentName.c               |  191 ++
 .../WifiConnectionMgrComponentName.h               |   99 +
 .../WifiConnectionMgrConfig.h                      |   74 +
 .../WifiConnectionMgrConfigHii.h                   |   35 +
 .../WifiConnectionMgrConfigNVDataStruct.h          |  158 ++
 .../WifiConnectionMgrDriver.c                      |  621 ++++++
 .../WifiConnectionMgrDriverBinding.h               |  148 ++
 .../WifiConnectionMgrDxe.h                         |  327 ++++
 .../WifiConnectionMgrFileUtil.c                    |  308 +++
 .../WifiConnectionMgrFileUtil.h                    |   77 +
 .../WifiConnectionMgrHiiConfigAccess.c             | 2014 ++++++++++++++++++++
 .../WifiConnectionMgrHiiConfigAccess.h             |  247 +++
 .../WifiConnectionMgrImpl.c                        | 1292 +++++++++++++
 .../WifiConnectionMgrImpl.h                        |  105 +
 .../WifiConnectionMgrMisc.c                        |  750 ++++++++
 .../WifiConnectionMgrMisc.h                        |  268 +++
 23 files changed, 7320 insertions(+)
 create mode 100644 NetworkPkg/Include/Guid/WifiConnectionManagerConfigHii.h
 create mode 100644 NetworkPkg/WifiConnectionManagerDxe/EapContext.h
 create mode 100644 NetworkPkg/WifiConnectionManagerDxe/WifiConnectionManagerDxe.inf
 create mode 100644 NetworkPkg/WifiConnectionManagerDxe/WifiConnectionManagerDxe.vfr
 create mode 100644 NetworkPkg/WifiConnectionManagerDxe/WifiConnectionManagerDxeStrings.uni
 create mode 100644 NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrComponentName.c
 create mode 100644 NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrComponentName.h
 create mode 100644 NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrConfig.h
 create mode 100644 NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrConfigHii.h
 create mode 100644 NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrConfigNVDataStruct.h
 create mode 100644 NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrDriver.c
 create mode 100644 NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrDriverBinding.h
 create mode 100644 NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrDxe.h
 create mode 100644 NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrFileUtil.c
 create mode 100644 NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrFileUtil.h
 create mode 100644 NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrHiiConfigAccess.c
 create mode 100644 NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrHiiConfigAccess.h
 create mode 100644 NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrImpl.c
 create mode 100644 NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrImpl.h
 create mode 100644 NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrMisc.c
 create mode 100644 NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrMisc.h

diff --git a/NetworkPkg/Include/Guid/WifiConnectionManagerConfigHii.h b/NetworkPkg/Include/Guid/WifiConnectionManagerConfigHii.h
new file mode 100644
index 0000000000..af150784f8
--- /dev/null
+++ b/NetworkPkg/Include/Guid/WifiConnectionManagerConfigHii.h
@@ -0,0 +1,25 @@
+/** @file
+  GUIDs used as HII FormSet and HII Package list GUID in WiFi Connection Manager.
+
+Copyright (c) 2019, 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 that 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.
+
+**/
+
+#ifndef __WIFI_CONNECTION_MANAGER_HII_GUID_H__
+#define __WIFI_CONNECTION_MANAGER_HII_GUID_H__
+
+#define WIFI_CONNECTION_MANAGER_CONFIG_GUID \
+  { \
+    0x9f94d327, 0x0b18, 0x4245, { 0x8f, 0xf2, 0x83, 0x2e, 0x30, 0xd, 0x2c, 0xef } \
+  }
+
+extern EFI_GUID gWifiConfigGuid;
+
+#endif
diff --git a/NetworkPkg/NetworkPkg.dec b/NetworkPkg/NetworkPkg.dec
index 6672d90fe1..a922de6ebe 100644
--- a/NetworkPkg/NetworkPkg.dec
+++ b/NetworkPkg/NetworkPkg.dec
@@ -47,10 +47,13 @@
   gEfiTlsCaCertificateGuid      = { 0xfd2340D0, 0x3dab, 0x4349, { 0xa6, 0xc7, 0x3b, 0x4f, 0x12, 0xb4, 0x8e, 0xae }}
 
   # Include/Guid/HttpTlsCipherList.h
   gEdkiiHttpTlsCipherListGuid   = { 0x46ddb415, 0x5244, 0x49c7, { 0x93, 0x74, 0xf0, 0xe2, 0x98, 0xe7, 0xd3, 0x86 }}
 
+  # Include/Guid/WifiConnectionManagerConfigHii.h
+  gWifiConfigGuid               = { 0x9f94d327, 0x0b18, 0x4245, { 0x8f, 0xf2, 0x83, 0x2e, 0x30, 0xd, 0x2c, 0xef }}
+
 [PcdsFixedAtBuild]
   ## The max attempt number will be created by iSCSI driver.
   # @Prompt Max attempt number.
   gEfiNetworkPkgTokenSpaceGuid.PcdMaxIScsiAttemptNumber|0x08|UINT8|0x0000000D
 
diff --git a/NetworkPkg/NetworkPkg.dsc b/NetworkPkg/NetworkPkg.dsc
index b543caa08f..b17df46542 100644
--- a/NetworkPkg/NetworkPkg.dsc
+++ b/NetworkPkg/NetworkPkg.dsc
@@ -114,10 +114,11 @@
   NetworkPkg/Mtftp6Dxe/Mtftp6Dxe.inf
   NetworkPkg/DnsDxe/DnsDxe.inf
   NetworkPkg/HttpDxe/HttpDxe.inf
   NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesDxe.inf
   NetworkPkg/HttpBootDxe/HttpBootDxe.inf
+  NetworkPkg/WifiConnectionManagerDxe/WifiConnectionManagerDxe.inf
 
   NetworkPkg/Application/IpsecConfig/IpSecConfig.inf
   NetworkPkg/Application/VConfig/VConfig.inf
 
 [Components.IA32, Components.X64]
diff --git a/NetworkPkg/WifiConnectionManagerDxe/EapContext.h b/NetworkPkg/WifiConnectionManagerDxe/EapContext.h
new file mode 100644
index 0000000000..b8a474cd2b
--- /dev/null
+++ b/NetworkPkg/WifiConnectionManagerDxe/EapContext.h
@@ -0,0 +1,28 @@
+/** @file
+  Eap configuration data structure definitions for EAP connections.
+
+  Copyright (c) 2019, 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.
+
+**/
+
+#ifndef __EFI_WIFI_EAP_CONTEXT_H__
+#define __EFI_WIFI_EAP_CONTEXT_H__
+
+typedef struct {
+
+  BOOLEAN                   IsEncrypted;
+  CHAR16                    EncryptPassword[PASSWORD_STORAGE_SIZE];
+  UINTN                     KeySize;
+  UINT8                     KeyData[1];
+
+} EFI_EAP_PRIVATE_KEY;
+
+#endif
diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionManagerDxe.inf b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionManagerDxe.inf
new file mode 100644
index 0000000000..e431f2b710
--- /dev/null
+++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionManagerDxe.inf
@@ -0,0 +1,87 @@
+## @file
+#  WiFi Connection Manager.
+#
+#  This module is an example of how to make use of UEFI WiFi connection capabilities.
+#  User can scan, connect and diconnect to networks through UI operations.
+#
+#  Supported networks include:
+#  1). Open Network
+#  2). WPA2 Personal Network
+#  3). EAP Networks (EAP-TLS, EAP-TTLS/MSCHAPv2 and PEAPv0/MSCHAPv2)
+#
+#  Copyright (c) 2019, 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.
+#
+##
+
+[Defines]
+  INF_VERSION               = 0x00010005
+  BASE_NAME                 = WifiConnectionManagerDxe
+  FILE_GUID                 = c6df98f2-5ec0-4a94-8c11-9a9828ef03f2
+  MODULE_TYPE               = DXE_DRIVER
+  VERSION_STRING            = 0.1
+  ENTRY_POINT               = WifiMgrDxeDriverEntryPoint
+
+[Sources]
+  WifiConnectionMgrDxe.h
+  WifiConnectionMgrDriverBinding.h
+  WifiConnectionMgrConfig.h
+  WifiConnectionMgrMisc.h
+  WifiConnectionMgrImpl.h
+  WifiConnectionMgrConfigNVDataStruct.h
+  WifiConnectionMgrHiiConfigAccess.h
+  WifiConnectionMgrComponentName.h
+  WifiConnectionMgrFileUtil.h
+  WifiConnectionMgrDriver.c
+  WifiConnectionMgrComponentName.c
+  WifiConnectionMgrMisc.c
+  WifiConnectionMgrHiiConfigAccess.c
+  WifiConnectionMgrImpl.c
+  WifiConnectionMgrFileUtil.c
+  WifiConnectionManagerDxeStrings.uni
+  WifiConnectionManagerDxe.vfr
+  EapContext.h
+  WifiConnectionMgrConfigHii.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  NetworkPkg/NetworkPkg.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  MemoryAllocationLib
+  BaseMemoryLib
+  BaseLib
+  UefiLib
+  DevicePathLib
+  DebugLib
+  HiiLib
+  PrintLib
+  UefiHiiServicesLib
+  NetLib
+  FileExplorerLib
+
+[Protocols]
+  gEfiHiiConfigAccessProtocolGuid               ## PRODUCES
+  gEfiWiFi2ProtocolGuid                         ## TO_START
+  gEfiAdapterInformationProtocolGuid            ## SOMETIMES_CONSUMES
+  gEfiSupplicantProtocolGuid                    ## SOMETIMES_CONSUMES
+  gEfiEapConfigurationProtocolGuid              ## SOMETIMES_CONSUMES
+
+[Guids]
+  gWifiConfigGuid                               ## PRODUCES  ## GUID
+  gEfiIfrTianoGuid                              ## CONSUMES  ## GUID (Extended IFR Guid Opcode)
+  gEfiAdapterInfoMediaStateGuid                 ## SOMETIMES_CONSUMES  ## GUID  # Indicate the current media state status
+
+[Depex]
+  gEfiHiiConfigRoutingProtocolGuid
diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionManagerDxe.vfr b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionManagerDxe.vfr
new file mode 100644
index 0000000000..66c6e9b62a
--- /dev/null
+++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionManagerDxe.vfr
@@ -0,0 +1,353 @@
+/** @file
+  Vfr files used in WiFi Connection Manager.
+
+  Copyright (c) 2019, 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 "WifiConnectionMgrConfigNVDataStruct.h"
+
+#define EFI_NETWORK_DEVICE_CLASS  0x04
+
+formset
+  guid     = WIFI_CONNECTION_MANAGER_CONFIG_GUID,
+  title    = STRING_TOKEN(STR_WIFI_MGR_FORM_TITLE),
+  help     = STRING_TOKEN(STR_WIFI_MGR_FORM_HELP),
+  class    = EFI_NETWORK_DEVICE_CLASS,
+  subclass = 0x03,
+
+  varstore WIFI_MANAGER_IFR_NVDATA,
+    varid = MANAGER_VARSTORE_ID,
+    name  = WIFI_MANAGER_IFR_NVDATA,
+    guid  = WIFI_CONNECTION_MANAGER_CONFIG_GUID;
+
+  form formid = FORMID_MAC_SELECTION,
+    title = STRING_TOKEN(STR_WIFI_MAC_FORM_TITLE);
+
+    suppressif TRUE;
+      text
+        help   = STRING_TOKEN(STR_NULL_STRING),
+        text   = STRING_TOKEN(STR_NULL_STRING),
+        flags  = INTERACTIVE,
+        key    = KEY_MAC_LIST;
+      endif;
+
+    label LABEL_MAC_ENTRY;
+    label LABEL_END;
+  endform;
+
+  form formid = FORMID_WIFI_MAINPAGE,
+    title = STRING_TOKEN(STR_NETWORK_MANAGEMENT_TITLE);
+
+    text
+      help   = STRING_TOKEN(STR_MAC_ADDRESS_HELP),      // Help string
+      text   = STRING_TOKEN(STR_MAC_ADDRESS_TITLE),     // Prompt string
+        text   = STRING_TOKEN(STR_MAC_ADDRESS);         // TextTwo
+
+    text
+      help   = STRING_TOKEN(STR_NULL_STRING),           // Help string
+      text   = STRING_TOKEN(STR_CONNECTION_INFO),       // Prompt string
+        text   = STRING_TOKEN(STR_CONNECTED_SSID);      // TextTwo;
+
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+    goto FORMID_NETWORK_LIST,
+         prompt = STRING_TOKEN(STR_NETWORK_LIST),
+         help   = STRING_TOKEN(STR_NETWORK_LIST_HELP),
+         flags  = INTERACTIVE,
+         key    = KEY_NETWORK_LIST;
+
+    goto FORMID_WIFI_SETTINGS,
+         prompt = STRING_TOKEN(STR_WIFI_SETTINGS),
+         help   = STRING_TOKEN(STR_WIFI_SETTINGS_HELP),
+         flags  = INTERACTIVE,
+         key    = KEY_WIFI_SETTINGS;
+
+    action
+         questionid  = KEY_REFRESH_TITLE_CONNECTION_STATUS,
+         prompt      = STRING_TOKEN(STR_NULL_STRING),
+         help        = STRING_TOKEN(STR_NULL_STRING),
+         flags       = INTERACTIVE,
+         config      = STRING_TOKEN(STR_NULL_STRING),
+         refreshguid = WIFI_CONFIG_MAIN_FORM_REFRESH_GUID,
+    endaction;
+
+  endform;
+
+  form formid = FORMID_NETWORK_LIST,
+    title = STRING_TOKEN(STR_NETWORK_LIST);
+
+    numeric varid   = WIFI_MANAGER_IFR_NVDATA.ProfileCount,
+            prompt  = STRING_TOKEN(STR_REFRESH_NETWORK_COUNT),
+            help    = STRING_TOKEN(STR_REFRESH_NETWORK_COUNT_HELP),
+            flags   = INTERACTIVE | READ_ONLY,
+            key     = KEY_REFRESH_NETWORK_LIST,
+            minimum = 0,
+            maximum = 0xffffffff,
+            step    = 0,
+            default = 0,
+            refreshguid = WIFI_CONFIG_NETWORK_LIST_REFRESH_GUID,
+    endnumeric;
+
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+    label LABEL_NETWORK_LIST_ENTRY;
+    label LABEL_END;
+  endform;
+
+  form formid = FORMID_CONNECT_NETWORK,
+    title = STRING_TOKEN(STR_NETWORK_CONFIGURATION);
+
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+    text
+      help   = STRING_TOKEN(STR_CONNECT_STATUS_TITLE_HELP), // Help string
+      text   = STRING_TOKEN(STR_CONNECT_STATUS_TITLE),      // Prompt string
+        text   = STRING_TOKEN(STR_CONNECT_STATUS);          // TextTwo
+
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+    text
+      help   = STRING_TOKEN(STR_SSID_HELP),     // Help string
+      text   = STRING_TOKEN(STR_SSID_TITLE),    // Prompt string
+        text   = STRING_TOKEN(STR_SSID);        // TextTwo
+
+    text
+      help   = STRING_TOKEN(STR_SECURITY_TYPE_HELP),       // Help string
+      text   = STRING_TOKEN(STR_SECURITY_TYPE_TITLE),      // Prompt string
+        text   = STRING_TOKEN(STR_SECURITY_TYPE);          // TextTwo
+
+
+    suppressif NOT ideqval WIFI_MANAGER_IFR_NVDATA.SecurityType == SECURITY_TYPE_WPA2_PERSONAL;
+      password  varid    = WIFI_MANAGER_IFR_NVDATA.Password,
+                prompt   = STRING_TOKEN(STR_PASSWORD),
+                help     = STRING_TOKEN(STR_PASSWORD_HELP),
+                flags    = INTERACTIVE,
+                key      = KEY_PASSWORD_CONNECT_NETWORK,
+                minsize  = PASSWORD_MIN_LEN,
+                maxsize  = PASSWORD_MAX_LEN,
+      endpassword;
+    endif;
+
+    suppressif NOT ideqval WIFI_MANAGER_IFR_NVDATA.SecurityType == SECURITY_TYPE_WPA2_ENTERPRISE;
+
+      oneof varid       = WIFI_MANAGER_IFR_NVDATA.EapAuthMethod,
+            questionid  = KEY_EAP_AUTH_METHOD_CONNECT_NETWORK,
+            prompt      = STRING_TOKEN(STR_EAP_AUTH_METHOD),
+            help        = STRING_TOKEN(STR_EAP_AUTH_METHOD_HELP),
+            flags       = INTERACTIVE,
+            option text = STRING_TOKEN(STR_EAP_AUTH_METHOD_TTLS), value = EAP_AUTH_METHOD_TTLS, flags = DEFAULT;
+            option text = STRING_TOKEN(STR_EAP_AUTH_METHOD_PEAP), value = EAP_AUTH_METHOD_PEAP, flags = 0;
+            option text = STRING_TOKEN(STR_EAP_AUTH_METHOD_TLS),  value = EAP_AUTH_METHOD_TLS,  flags = 0;
+      endoneof;
+
+      suppressif NOT ideqvallist WIFI_MANAGER_IFR_NVDATA.EapAuthMethod == EAP_AUTH_METHOD_TLS
+                                                                          EAP_AUTH_METHOD_TTLS
+                                                                          EAP_AUTH_METHOD_PEAP;
+
+        goto FORMID_ENROLL_CERT,
+           prompt = STRING_TOKEN(STR_EAP_ENROLL_CA_CERT),
+           help   = STRING_TOKEN(STR_EAP_ENROLL_CA_CERT_HELP),
+           flags  = INTERACTIVE,
+           key    = KEY_ENROLL_CA_CERT_CONNECT_NETWORK;
+
+        suppressif NOT ideqval WIFI_MANAGER_IFR_NVDATA.EapAuthMethod == EAP_AUTH_METHOD_TLS;
+
+            goto FORMID_ENROLL_CERT,
+               prompt = STRING_TOKEN(STR_EAP_ENROLL_CLIENT_CERT),
+               help   = STRING_TOKEN(STR_EAP_ENROLL_CLIENT_CERT_HELP),
+               flags  = INTERACTIVE,
+               key    = KEY_ENROLL_CLIENT_CERT_CONNECT_NETWORK;
+
+            goto FORMID_ENROLL_PRIVATE_KEY,
+               prompt = STRING_TOKEN(STR_EAP_ENROLL_CLIENT_KEY),
+               help   = STRING_TOKEN(STR_EAP_ENROLL_CLIENT_KEY_HELP),
+               flags  = INTERACTIVE,
+               key    = KEY_ENROLL_PRIVATE_KEY_CONNECT_NETWORK;
+
+        endif;
+
+        suppressif NOT ideqvallist WIFI_MANAGER_IFR_NVDATA.EapAuthMethod == EAP_AUTH_METHOD_TTLS
+                                                                            EAP_AUTH_METHOD_PEAP;
+
+            oneof varid       = WIFI_MANAGER_IFR_NVDATA.EapSecondAuthMethod,
+                  questionid  = KEY_EAP_SEAUTH_METHOD_CONNECT_NETWORK,
+                  prompt      = STRING_TOKEN(STR_EAP_SEAUTH_METHOD),
+                  help        = STRING_TOKEN(STR_EAP_SEAUTH_METHOD_HELP),
+                  flags       = INTERACTIVE,
+                  option text = STRING_TOKEN(STR_EAP_SEAUTH_METHOD_MSCHAPV2), value = EAP_SEAUTH_METHOD_MSCHAPV2, flags = DEFAULT;
+            endoneof;
+        endif;
+
+        string  varid  = WIFI_MANAGER_IFR_NVDATA.EapIdentity,
+                prompt  = STRING_TOKEN(STR_EAP_IDENTITY),
+                help    = STRING_TOKEN(STR_EAP_IDENTITY_HELP),
+                flags   = INTERACTIVE,
+                key     = KEY_EAP_IDENTITY_CONNECT_NETWORK,
+                minsize = 6,
+                maxsize = EAP_IDENTITY_LEN,
+        endstring;
+
+        suppressif NOT ideqvallist WIFI_MANAGER_IFR_NVDATA.EapAuthMethod == EAP_AUTH_METHOD_TTLS
+                                                                            EAP_AUTH_METHOD_PEAP;
+
+            password  varid    = WIFI_MANAGER_IFR_NVDATA.EapPassword,
+                      prompt   = STRING_TOKEN(STR_EAP_PASSWORD),
+                      help     = STRING_TOKEN(STR_EAP_PASSWORD_HELP),
+                      flags    = INTERACTIVE,
+                      key      = KEY_EAP_PASSWORD_CONNECT_NETWORK,
+                      minsize  = 0,
+                      maxsize  = PASSWORD_MAX_LEN,
+            endpassword;
+        endif;
+      endif;
+    endif;
+
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+    text
+      help   = STRING_TOKEN(STR_CONNECT_NOW_HELP),
+      text   = STRING_TOKEN(STR_CONNECT_NOW),
+      flags  = INTERACTIVE,
+      key    = KEY_CONNECT_ACTION;
+
+    action
+      questionid  = KEY_REFRESH_CONNECT_CONFIGURATION,
+      prompt      = STRING_TOKEN(STR_NULL_STRING),
+      help        = STRING_TOKEN(STR_NULL_STRING),
+      flags       = INTERACTIVE,
+      config      = STRING_TOKEN(STR_NULL_STRING),
+      refreshguid = WIFI_CONFIG_CONNECT_FORM_REFRESH_GUID,
+    endaction;
+
+  endform;
+
+  form formid = FORMID_ENROLL_CERT,
+    title = STRING_TOKEN(STR_EAP_ENROLL_CERT);
+
+    goto FORMID_ENROLL_CERT,
+         prompt = STRING_TOKEN(STR_EAP_ENROLL_CERT_FROM_FILE),
+         help   = STRING_TOKEN(STR_EAP_ENROLL_CERT_FROM_FILE_HELP),
+         flags  = INTERACTIVE,
+         key    = KEY_EAP_ENROLL_CERT_FROM_FILE;
+
+    text
+      help   = STRING_TOKEN(STR_NULL_STRING),
+      text   = STRING_TOKEN(STR_EAP_ENROLLED_CERT_NAME),
+      flags  = INTERACTIVE,
+      key    = KEY_ENROLLED_CERT_NAME;
+
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+    text
+      help   = STRING_TOKEN(STR_SAVE_EXIT_HELP),
+      text   = STRING_TOKEN(STR_SAVE_EXIT),
+      flags  = INTERACTIVE,
+      key    = KEY_SAVE_CERT_TO_MEM;
+
+    text
+      help   = STRING_TOKEN(STR_NO_SAVE_EXIT_HELP),
+      text   = STRING_TOKEN(STR_NO_SAVE_EXIT),
+      flags  = INTERACTIVE,
+      key    = KEY_NO_SAVE_CERT_TO_MEM;
+
+  endform;
+
+  form formid = FORMID_ENROLL_PRIVATE_KEY,
+    title = STRING_TOKEN(STR_EAP_ENROLL_CLIENT_KEY);
+
+    goto FORMID_ENROLL_PRIVATE_KEY,
+         prompt = STRING_TOKEN(STR_EAP_ENROLL_KEY_FROM_FILE),
+         help   = STRING_TOKEN(STR_EAP_ENROLL_KEY_FROM_FILE_HELP),
+         flags  = INTERACTIVE,
+         key    = KEY_EAP_ENROLL_PRIVATE_KEY_FROM_FILE;
+
+    text
+      help   = STRING_TOKEN(STR_NULL_STRING),
+      text   = STRING_TOKEN(STR_EAP_ENROLLED_PRIVATE_KEY_NAME),
+      flags  = INTERACTIVE,
+      key    = KEY_ENROLLED_PRIVATE_KEY_NAME;
+
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+    password  varid    = WIFI_MANAGER_IFR_NVDATA.PrivateKeyPassword,
+              prompt   = STRING_TOKEN(STR_EAP_CLIENT_KEY_PASSWORD),
+              help     = STRING_TOKEN(STR_NULL_STRING),
+              flags    = INTERACTIVE,
+              key      = KEY_PRIVATE_KEY_PASSWORD,
+              minsize  = 0,
+              maxsize  = PASSWORD_MAX_LEN,
+    endpassword;
+
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+    text
+      help   = STRING_TOKEN(STR_SAVE_EXIT_HELP),
+      text   = STRING_TOKEN(STR_SAVE_EXIT),
+      flags  = INTERACTIVE,
+      key    = KEY_SAVE_PRIVATE_KEY_TO_MEM;
+
+    text
+      help   = STRING_TOKEN(STR_NO_SAVE_EXIT_HELP),
+      text   = STRING_TOKEN(STR_NO_SAVE_EXIT),
+      flags  = INTERACTIVE,
+      key    = KEY_NO_SAVE_PRIVATE_KEY_TO_MEM;
+
+  endform;
+
+  form formid = FORMID_WIFI_SETTINGS,
+    title = STRING_TOKEN(STR_WIFI_SETTINGS_FORM_TITLE);
+
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);
+
+    goto FORMID_HIDDEN_NETWORK_LIST,
+         prompt = STRING_TOKEN(STR_HIDDEN_NETWORK),
+         help   = STRING_TOKEN(STR_HIDDEN_NETWORK_HELP),
+         flags  = INTERACTIVE,
+         key    = KEY_HIDDEN_NETWORK;
+
+  endform;
+
+  form formid = FORMID_HIDDEN_NETWORK_LIST,
+    title = STRING_TOKEN(STR_HIDDEN_NETWORK_FORM_TITLE);
+
+    string
+      varid   = WIFI_MANAGER_IFR_NVDATA.SSId,
+      prompt  = STRING_TOKEN(STR_SSID_TITLE),
+      help    = STRING_TOKEN(STR_SSID_HELP),
+      flags   = INTERACTIVE,
+      minsize = SSID_MIN_LEN,
+      maxsize = SSID_MAX_LEN,
+    endstring;
+
+    text
+      help   = STRING_TOKEN(STR_ADD_HIDDEN_NETWORK_HELP),
+      text   = STRING_TOKEN(STR_ADD_HIDDEN_NETWORK),
+      flags  = INTERACTIVE,
+      key    = KEY_ADD_HIDDEN_NETWORK;
+
+    subtitle text = STRING_TOKEN(STR_NULL_STRING);
+    subtitle text = STRING_TOKEN(STR_HIDDEN_NETWORK_LIST);
+
+    label LABEL_HIDDEN_NETWORK_ENTRY;
+    label LABEL_END;
+
+    text
+      help   = STRING_TOKEN(STR_REMOVE_HIDDEN_NETWORK_HELP),
+      text   = STRING_TOKEN(STR_REMOVE_HIDDEN_NETWORK),
+      flags  = INTERACTIVE,
+      key    = KEY_REMOVE_HIDDEN_NETWORK;
+
+  endform;
+
+endformset;
diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionManagerDxeStrings.uni b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionManagerDxeStrings.uni
new file mode 100644
index 0000000000..00078cb849
--- /dev/null
+++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionManagerDxeStrings.uni
@@ -0,0 +1,109 @@
+// /** @file
+//   String definitions for WiFi Connection Manager Forms.
+//
+//   Copyright (c) 2019, 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.
+//
+// **/
+
+#langdef en-US "English"
+
+#string STR_WIFI_MGR_FORM_TITLE           #language en-US "Wi-Fi Configuration"
+#string STR_WIFI_MGR_FORM_HELP            #language en-US "Configure the Wi-Fi parameters."
+
+#string STR_WIFI_MAC_FORM_TITLE           #language en-US "MAC Selection"
+#string STR_WIFI_MAC_FORM_HELP            #language en-US "Select a Nic"
+
+#string STR_MAC_ADDRESS_TITLE             #language en-US "MAC Address"
+#string STR_MAC_ADDRESS                   #language en-US "88-88-88-88-88-87"
+#string STR_MAC_ADDRESS_HELP              #language en-US "MAC Address"
+#string STR_CONNECTION_INFO               #language en-US "Disconnected"
+#string STR_CONNECTED_SSID                #language en-US ""
+#string STR_NULL_STRING                   #language en-US ""
+
+#string STR_NETWORK_MANAGEMENT_TITLE      #language en-US "Wi-Fi Network Management"
+#string STR_NETWORK_LIST                  #language en-US "Wi-Fi Network List"
+#string STR_NETWORK_LIST_HELP             #language en-US "Available Network List"
+#string STR_NETWORK_CONFIGURATION         #language en-US "Wi-Fi Network Configuration"
+
+#string STR_SSID_TITLE                    #language en-US "SSID"
+#string STR_SSID                          #language en-US ""
+#string STR_SSID_HELP                     #language en-US "SSID Length: 1 - 32 characters"
+#string STR_SECURITY_TYPE_TITLE           #language en-US "Security"
+#string STR_SECURITY_TYPE                 #language en-US ""
+#string STR_SECURITY_TYPE_HELP            #language en-US "Network Security Type"
+
+#string STR_EAP_AUTH_METHOD               #language en-US "EAP Authentication Method"
+#string STR_EAP_AUTH_METHOD_HELP          #language en-US "EAP Authentication Method"
+#string STR_EAP_SEAUTH_METHOD             #language en-US "EAP Second Authentication Method"
+#string STR_EAP_SEAUTH_METHOD_HELP        #language en-US "EAP Second Authentication Method"
+#string STR_SECURITY_NONE                 #language en-US "Open"
+#string STR_SECURITY_WEP                  #language en-US "WEP"
+#string STR_SECURITY_WPA_PERSONAL         #language en-US "WPA-Personal"
+#string STR_SECURITY_WPA_ENTERPRISE       #language en-US "WPA-Enterprise"
+#string STR_SECURITY_WPA2_PERSONAL        #language en-US "WPA2-Personal"
+#string STR_SECURITY_WPA2_ENTERPRISE      #language en-US "WPA2-Enterprise"
+#string STR_SECURITY_UNKNOWN              #language en-US "Unknown"
+#string STR_EAP_AUTH_METHOD_TLS           #language en-US "EAPTLS"
+#string STR_EAP_AUTH_METHOD_TTLS          #language en-US "TTLS"
+#string STR_EAP_AUTH_METHOD_PEAP          #language en-US "PEAP"
+#string STR_EAP_SEAUTH_METHOD_MSCHAPV2    #language en-US "MSCHAPv2"
+#string STR_EAP_SEAUTH_METHOD_GTC         #language en-US "GTC"
+
+#string STR_PASSWORD                      #language en-US "Password"
+#string STR_PASSWORD_HELP                 #language en-US "Password Length: 8 - 63 characters"
+#string STR_CONNECT_STATUS_TITLE          #language en-US "Connection Status:"
+#string STR_CONNECT_STATUS_TITLE_HELP     #language en-US ""
+#string STR_CONNECT_STATUS                #language en-US ""
+#string STR_CONNECT_STATUS_HELP           #language en-US ""
+
+#string STR_CONNECT_NOW                   #language en-US "Connect to network now"
+#string STR_CONNECT_NOW_HELP              #language en-US ""
+#string STR_DISCONNECT_NOW                #language en-US "Disconnect from this network"
+#string STR_DISCONNECT_NOW_HELP           #language en-US ""
+#string STR_REFRESH_NETWORK_COUNT         #language en-US "Number of Networks"
+#string STR_REFRESH_NETWORK_COUNT_HELP    #language en-US "The number of current available networks around"
+
+#string STR_EAP_IDENTITY                  #language en-US "Identity"
+#string STR_EAP_IDENTITY_HELP             #language en-US "It is used to query the identity of the peer."
+#string STR_EAP_PASSWORD                  #language en-US "EAP Password"
+#string STR_EAP_PASSWORD_HELP             #language en-US "Password Length: 1 - 63 characters"
+
+#string STR_SAVE_EXIT                     #language en-US "Commit Changes and Exit"
+#string STR_SAVE_EXIT_HELP                #language en-US ""
+#string STR_NO_SAVE_EXIT                  #language en-US "Discard Changes and Exit"
+#string STR_NO_SAVE_EXIT_HELP             #language en-US ""
+
+#string STR_EAP_ENROLL_CERT                   #language en-US "Enroll Certificate"
+#string STR_EAP_ENROLL_CA_CERT                #language en-US "Enroll CA Cert"
+#string STR_EAP_ENROLL_CA_CERT_HELP           #language en-US ""
+#string STR_EAP_ENROLL_CLIENT_CERT            #language en-US "Enroll Client Cert"
+#string STR_EAP_ENROLL_CLIENT_CERT_HELP       #language en-US ""
+#string STR_EAP_ENROLL_CLIENT_KEY             #language en-US "Enroll Client Private Key"
+#string STR_EAP_ENROLL_CLIENT_KEY_HELP        #language en-US ""
+#string STR_EAP_ENROLL_CERT_FROM_FILE         #language en-US "Enroll Cert Using File"
+#string STR_EAP_ENROLL_CERT_FROM_FILE_HELP    #language en-US ""
+#string STR_EAP_ENROLL_KEY_FROM_FILE          #language en-US "Enroll Private Key Using File"
+#string STR_EAP_ENROLL_KEY_FROM_FILE_HELP     #language en-US ""
+#string STR_EAP_CLIENT_KEY_PASSWORD           #language en-US "Client Private Key Password"
+#string STR_EAP_ENROLLED_CERT_NAME            #language en-US ""
+#string STR_EAP_ENROLLED_PRIVATE_KEY_NAME     #language en-US ""
+
+#string STR_WIFI_SETTINGS_FORM_TITLE          #language en-US "Wi-Fi Settings"
+#string STR_WIFI_SETTINGS                     #language en-US "Wi-Fi Settings"
+#string STR_WIFI_SETTINGS_HELP                #language en-US ""
+
+#string STR_HIDDEN_NETWORK_FORM_TITLE         #language en-US "Hidden Network Configuration"
+#string STR_HIDDEN_NETWORK                    #language en-US "Hidden Network Configuration"
+#string STR_HIDDEN_NETWORK_HELP               #language en-US ""
+#string STR_ADD_HIDDEN_NETWORK_HELP           #language en-US "Hidden Network List won't be saved in Storage, they will be cleaned after Reset!"
+#string STR_ADD_HIDDEN_NETWORK                #language en-US "Add Hidden Network"
+#string STR_HIDDEN_NETWORK_LIST               #language en-US "Hidden Network List"
+#string STR_REMOVE_HIDDEN_NETWORK_HELP        #language en-US ""
+#string STR_REMOVE_HIDDEN_NETWORK             #language en-US "Remove Hidden Network"
\ No newline at end of file
diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrComponentName.c b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrComponentName.c
new file mode 100644
index 0000000000..0d7d69567a
--- /dev/null
+++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrComponentName.c
@@ -0,0 +1,191 @@
+/** @file
+  UEFI Component Name(2) protocol implementation for WiFi Connection Manager.
+
+  Copyright (c) 2019, 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 "WifiConnectionMgrDxe.h"
+
+extern EFI_GUID mEfiWifiMgrPrivateGuid;
+
+///
+/// Component Name Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME_PROTOCOL  gWifiMgrDxeComponentName = {
+  (EFI_COMPONENT_NAME_GET_DRIVER_NAME)     WifiMgrDxeComponentNameGetDriverName,
+  (EFI_COMPONENT_NAME_GET_CONTROLLER_NAME) WifiMgrDxeComponentNameGetControllerName,
+  "eng"
+};
+
+///
+/// Component Name 2 Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME2_PROTOCOL  gWifiMgrDxeComponentName2 = {
+  WifiMgrDxeComponentNameGetDriverName,
+  WifiMgrDxeComponentNameGetControllerName,
+  "en"
+};
+
+///
+/// Table of driver names
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_UNICODE_STRING_TABLE mWifiMgrDxeDriverNameTable[] = {
+  {
+    "eng;en",
+    L"UEFI WiFi Connection Manager"
+  },
+  {
+    NULL,
+    NULL
+  }
+};
+
+///
+/// Table of controller names
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_UNICODE_STRING_TABLE mWifiMgrDxeControllerNameTable[] = {
+  {
+    "eng;en",
+    L"UEFI WiFi Connection Manager Controller"
+  },
+  {
+    NULL,
+    NULL
+  }
+};
+
+/**
+  Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+  @param  This       A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param  Language   A pointer to a three-character ISO 639-2 language identifier.
+                     This is the language of the driver name that that the caller
+                     is requesting, and it must match one of the languages specified
+                     in SupportedLanguages.  The number of languages supported by a
+                     driver is up to the driver writer.
+  @param  DriverName A pointer to the Unicode string to return.  This Unicode string
+                     is the name of the driver specified by This in the language
+                     specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by This
+                                and the language specified by Language was returned
+                                in DriverName.
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support the
+                                language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+WifiMgrDxeComponentNameGetDriverName (
+  IN EFI_COMPONENT_NAME2_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  )
+{
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mWifiMgrDxeDriverNameTable,
+           DriverName,
+           (BOOLEAN)(This != &gWifiMgrDxeComponentName2)
+           );
+}
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by an EFI Driver.
+
+  @param  This             A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param  ControllerHandle The handle of a controller that the driver specified by
+                           This is managing.  This handle specifies the controller
+                           whose name is to be returned.
+  @param  ChildHandle      The handle of the child controller to retrieve the name
+                           of.  This is an optional parameter that may be NULL.  It
+                           will be NULL for device drivers.  It will also be NULL
+                           for a bus drivers that wish to retrieve the name of the
+                           bus controller.  It will not be NULL for a bus driver
+                           that wishes to retrieve the name of a child controller.
+  @param  Language         A pointer to a three character ISO 639-2 language
+                           identifier.  This is the language of the controller name
+                           that the caller is requesting, and it must match one
+                           of the languages specified in SupportedLanguages.  The
+                           number of languages supported by a driver is up to the
+                           driver writer.
+  @param  ControllerName   A pointer to the Unicode string to return.  This Unicode
+                           string is the name of the controller specified by
+                           ControllerHandle and ChildHandle in the language specified
+                           by Language, from the point of view of the driver specified
+                           by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user-readable name in the
+                                language specified by Language for the driver
+                                specified by This was returned in DriverName.
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently managing
+                                the controller specified by ControllerHandle and
+                                ChildHandle.
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support the
+                                language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+WifiMgrDxeComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME2_PROTOCOL  *This,
+  IN  EFI_HANDLE                    ControllerHandle,
+  IN  EFI_HANDLE                    ChildHandle        OPTIONAL,
+  IN  CHAR8                         *Language,
+  OUT CHAR16                        **ControllerName
+  )
+{
+  EFI_STATUS                   Status;
+  WIFI_MGR_PRIVATE_PROTOCOL    *WifiMgrPrivate;
+
+  //
+  // ChildHandle must be NULL for a Device Driver
+  //
+  if (ControllerHandle == NULL || ChildHandle != NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Check Controller's handle
+  //
+  Status = gBS->OpenProtocol (
+                  ControllerHandle,
+                  &mEfiWifiMgrPrivateGuid,
+                  (VOID **) &WifiMgrPrivate,
+                  NULL,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mWifiMgrDxeControllerNameTable,
+           ControllerName,
+           (BOOLEAN)(This != &gWifiMgrDxeComponentName2)
+           );
+}
diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrComponentName.h b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrComponentName.h
new file mode 100644
index 0000000000..f69e682950
--- /dev/null
+++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrComponentName.h
@@ -0,0 +1,99 @@
+/** @file
+  UEFI Component Name(2) protocol implementation for WiFi Connection Manager.
+
+  Copyright (c) 2019, 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.
+
+**/
+
+#ifndef __EFI_WIFI_COMPONENT_NAME__
+#define __EFI_WIFI_COMPONENT_NAME__
+
+/**
+  Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+  @param  This       A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param  Language   A pointer to a three-character ISO 639-2 language identifier.
+                     This is the language of the driver name that that the caller
+                     is requesting, and it must match one of the languages specified
+                     in SupportedLanguages.  The number of languages supported by a
+                     driver is up to the driver writer.
+  @param  DriverName A pointer to the Unicode string to return.  This Unicode string
+                     is the name of the driver specified by This in the language
+                     specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by This
+                                and the language specified by Language was returned
+                                in DriverName.
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support the
+                                language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+WifiMgrDxeComponentNameGetDriverName (
+  IN EFI_COMPONENT_NAME2_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  );
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by an EFI Driver.
+
+  @param  This             A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param  ControllerHandle The handle of a controller that the driver specified by
+                           This is managing.  This handle specifies the controller
+                           whose name is to be returned.
+  @param  ChildHandle      The handle of the child controller to retrieve the name
+                           of.  This is an optional parameter that may be NULL.  It
+                           will be NULL for device drivers.  It will also be NULL
+                           for a bus drivers that wish to retrieve the name of the
+                           bus controller.  It will not be NULL for a bus driver
+                           that wishes to retrieve the name of a child controller.
+  @param  Language         A pointer to a three character ISO 639-2 language
+                           identifier.  This is the language of the controller name
+                           that the caller is requesting, and it must match one
+                           of the languages specified in SupportedLanguages.  The
+                           number of languages supported by a driver is up to the
+                           driver writer.
+  @param  ControllerName   A pointer to the Unicode string to return.  This Unicode
+                           string is the name of the controller specified by
+                           ControllerHandle and ChildHandle in the language specified
+                           by Language, from the point of view of the driver specified
+                           by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user-readable name in the
+                                language specified by Language for the driver
+                                specified by This was returned in DriverName.
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently managing
+                                the controller specified by ControllerHandle and
+                                ChildHandle.
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support the
+                                language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+WifiMgrDxeComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME2_PROTOCOL  *This,
+  IN  EFI_HANDLE                    ControllerHandle,
+  IN  EFI_HANDLE                    ChildHandle        OPTIONAL,
+  IN  CHAR8                         *Language,
+  OUT CHAR16                        **ControllerName
+  );
+
+#endif
diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrConfig.h b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrConfig.h
new file mode 100644
index 0000000000..f179fbc4ef
--- /dev/null
+++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrConfig.h
@@ -0,0 +1,74 @@
+/** @file
+  Define network structure used by the WiFi Connection Manager.
+
+  Copyright (c) 2019, 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.
+
+**/
+
+#ifndef _WIFI_MGR_CONFIG_H_
+#define _WIFI_MGR_CONFIG_H_
+
+#include "WifiConnectionMgrConfigNVDataStruct.h"
+
+extern UINT8        WifiConnectionManagerDxeBin[];
+extern UINT8        WifiConnectionManagerDxeStrings[];
+
+typedef struct {
+  UINT32               Signature;
+
+  //
+  // Link to the current profile list in NIC device data (WIFI_MGR_DEVICE_DATA)
+  //
+  LIST_ENTRY           Link;
+
+  UINT32               NicIndex;
+  UINT32               ProfileIndex;   // The unique identifier for network profile, starts from 1
+  CHAR16               SSId[SSID_STORAGE_SIZE];
+  CHAR16               Password[PASSWORD_STORAGE_SIZE];
+
+  UINT8                SecurityType;
+  UINT8                EapAuthMethod;
+
+  CHAR16               CACertName[WIFI_FILENAME_STR_MAX_SIZE];
+  VOID                 *CACertData;
+  UINTN                CACertSize;
+  CHAR16               ClientCertName[WIFI_FILENAME_STR_MAX_SIZE];
+  VOID                 *ClientCertData;
+  UINTN                ClientCertSize;
+  CHAR16               PrivateKeyName[WIFI_FILENAME_STR_MAX_SIZE];
+  VOID                 *PrivateKeyData;
+  UINTN                PrivateKeyDataSize;
+  CHAR16               PrivateKeyPassword[PASSWORD_STORAGE_SIZE];    //Password to protect private key file
+  CHAR16               EapIdentity[EAP_IDENTITY_SIZE];
+  CHAR16               EapPassword[PASSWORD_STORAGE_SIZE];
+  UINT8                EapSecondAuthMethod;
+
+  BOOLEAN              AKMSuiteSupported;
+  BOOLEAN              CipherSuiteSupported;
+  BOOLEAN              IsAvailable;
+  EFI_80211_NETWORK    Network;
+  UINT8                NetworkQuality;
+  EFI_STRING_ID        TitleToken;
+} WIFI_MGR_NETWORK_PROFILE;
+
+#define WIFI_MGR_PROFILE_SIGNATURE  SIGNATURE_32 ('W','M','N','P')
+
+#pragma pack(1)
+///
+/// HII specific Vendor Device Path definition.
+///
+typedef struct {
+  VENDOR_DEVICE_PATH               VendorDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL         End;
+} HII_VENDOR_DEVICE_PATH;
+#pragma pack()
+
+#endif
diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrConfigHii.h b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrConfigHii.h
new file mode 100644
index 0000000000..43c0f024f5
--- /dev/null
+++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrConfigHii.h
@@ -0,0 +1,35 @@
+/** @file
+  Module level GUIDs used in WiFi Connection Manager.
+
+  Copyright (c) 2019, 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.
+
+**/
+
+#ifndef __WIFI_CONFIG_HII_GUID_H__
+#define __WIFI_CONFIG_HII_GUID_H__
+
+// {36AF7790-0C2F-4055-9D3D-DB72A44953CB}
+#define WIFI_CONFIG_NETWORK_LIST_REFRESH_GUID \
+  { \
+    0xc5f3c7f9, 0xfb9d, 0x49f1, { 0xbe, 0x67, 0x8b, 0xad, 0x20, 0xa7, 0xc6, 0xac } \
+  }
+
+#define WIFI_CONFIG_CONNECT_FORM_REFRESH_GUID \
+  { \
+    0xe5faf2b2, 0x5ecc, 0x44ac, { 0x91, 0x75, 0xfb, 0x78, 0xb2, 0x8a, 0x59, 0x6c } \
+  }
+
+#define WIFI_CONFIG_MAIN_FORM_REFRESH_GUID \
+  { \
+    0xde609972, 0xcbcc, 0x4e82, { 0x8b, 0x3e, 0x6a, 0xc5, 0xcf, 0x56, 0x73, 0x8d } \
+  }
+
+#endif
diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrConfigNVDataStruct.h b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrConfigNVDataStruct.h
new file mode 100644
index 0000000000..d62b36dd76
--- /dev/null
+++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrConfigNVDataStruct.h
@@ -0,0 +1,158 @@
+/** @file
+  Define IFR NVData structures used by the WiFi Connection Manager.
+
+  Copyright (c) 2019, 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.
+
+**/
+
+#ifndef _WIFI_NVDATASTRUC_H_
+#define _WIFI_NVDATASTRUC_H_
+
+#include <Guid/WifiConnectionManagerConfigHii.h>
+#include "WifiConnectionMgrConfigHii.h"
+
+#define MANAGER_VARSTORE_ID           0x0802
+
+#define WIFI_STR_MAX_SIZE             224
+#define WIFI_FILENAME_STR_MAX_SIZE    224
+#define WIFI_MGR_MAX_MAC_STRING_LEN   96
+
+#define SSID_MIN_LEN                  1
+#define SSID_MAX_LEN                  32
+#define SSID_STORAGE_SIZE             33
+
+#define PASSWORD_MIN_LEN              8
+#define PASSWORD_MAX_LEN              63
+#define PASSWORD_STORAGE_SIZE         64
+
+#define EAP_IDENTITY_LEN              63
+#define EAP_IDENTITY_SIZE             64
+
+#define FORMID_NONE_FORM              0
+#define FORMID_MAC_SELECTION          1
+#define FORMID_WIFI_MAINPAGE          2
+#define FORMID_NETWORK_LIST           3
+#define FORMID_CONNECT_NETWORK        4
+#define FORMID_ENROLL_CERT            5
+#define FORMID_CA_LIST                6
+#define FORMID_ENROLL_PRIVATE_KEY     7
+#define FORMID_PRIVATE_KEY_LIST       8
+#define FORMID_WIFI_SETTINGS          9
+#define FORMID_HIDDEN_NETWORK_LIST    10
+
+//
+// Mac List Form Key
+//
+#define KEY_MAC_LIST                              0x100
+
+//
+// Main Form Key
+//
+#define KEY_REFRESH_TITLE_CONNECTION_STATUS       0x101
+
+//
+// Network List Form Key
+//
+#define KEY_NETWORK_LIST                          0x102
+#define KEY_REFRESH_NETWORK_LIST                  0x103
+#define KEY_WIFI_SETTINGS                         0x104
+
+//
+// Connect Network Form Key
+//
+#define KEY_PASSWORD_CONNECT_NETWORK              0x201
+#define KEY_CONNECT_ACTION                        0x202
+#define KEY_REFRESH_CONNECT_CONFIGURATION         0x203
+#define KEY_EAP_AUTH_METHOD_CONNECT_NETWORK       0x204
+#define KEY_EAP_SEAUTH_METHOD_CONNECT_NETWORK     0x205
+#define KEY_ENROLL_CA_CERT_CONNECT_NETWORK        0x206
+#define KEY_ENROLL_CLIENT_CERT_CONNECT_NETWORK    0x207
+#define KEY_ENROLL_PRIVATE_KEY_CONNECT_NETWORK    0x208
+#define KEY_EAP_IDENTITY_CONNECT_NETWORK          0x209
+#define KEY_EAP_PASSWORD_CONNECT_NETWORK          0x210
+
+//
+//Cert Form And Private Key Form
+//
+#define KEY_EAP_ENROLL_CERT_FROM_FILE             0x301
+#define KEY_EAP_ENROLL_PRIVATE_KEY_FROM_FILE      0x302
+#define KEY_SAVE_CERT_TO_MEM                      0x303
+#define KEY_NO_SAVE_CERT_TO_MEM                   0x304
+#define KEY_SAVE_PRIVATE_KEY_TO_MEM               0x305
+#define KEY_NO_SAVE_PRIVATE_KEY_TO_MEM            0x306
+#define KEY_PRIVATE_KEY_PASSWORD                  0x307
+#define KEY_ENROLLED_CERT_NAME                    0x308
+#define KEY_ENROLLED_PRIVATE_KEY_NAME             0x309
+
+//
+// Hidden Network Configuration Form
+//
+#define KEY_HIDDEN_NETWORK                        0x401
+#define KEY_ADD_HIDDEN_NETWORK                    0x402
+#define KEY_REMOVE_HIDDEN_NETWORK                 0x403
+
+//
+// Dynamic Lists
+//
+#define MAC_LIST_COUNT_MAX                        255
+#define LABEL_MAC_ENTRY                           0x1000
+#define KEY_MAC_ENTRY_BASE                        0x1100
+
+#define NETWORK_LIST_COUNT_MAX                    4095
+#define LABEL_NETWORK_LIST_ENTRY                  0x2000
+#define KEY_AVAILABLE_NETWORK_ENTRY_BASE          0x3000
+
+#define HIDDEN_NETWORK_LIST_COUNT_MAX             255
+#define LABEL_HIDDEN_NETWORK_ENTRY                0x4000
+#define KEY_HIDDEN_NETWORK_ENTRY_BASE             0x4100
+
+#define LABEL_END                                 0xffff
+
+//
+// Network Security Type
+//
+#define SECURITY_TYPE_NONE                        0
+#define SECURITY_TYPE_WPA_ENTERPRISE              1
+#define SECURITY_TYPE_WPA2_ENTERPRISE             2
+#define SECURITY_TYPE_WPA_PERSONAL                3
+#define SECURITY_TYPE_WPA2_PERSONAL               4
+#define SECURITY_TYPE_WEP                         5
+#define SECURITY_TYPE_UNKNOWN                     6
+#define SECURITY_TYPE_MAX                         7
+
+#define EAP_AUTH_METHOD_TTLS                      0
+#define EAP_AUTH_METHOD_PEAP                      1
+#define EAP_AUTH_METHOD_TLS                       2
+#define EAP_AUTH_METHOD_MAX                       3
+
+#define EAP_SEAUTH_METHOD_MSCHAPV2                0
+#define EAP_SEAUTH_METHOD_MAX                     1
+
+#define HIDDEN_NETWORK_LIST_VAR_OFFSET ((UINT16) OFFSET_OF (WIFI_MANAGER_IFR_NVDATA, HiddenNetworkList))
+
+#pragma pack(1)
+typedef struct _WIFI_MANAGER_IFR_NVDATA {
+
+  UINT32      ProfileCount;
+  CHAR16      SSId[SSID_STORAGE_SIZE];
+  CHAR16      Password[PASSWORD_STORAGE_SIZE];
+  CHAR16      PrivateKeyPassword[PASSWORD_STORAGE_SIZE];
+  CHAR16      EapIdentity[EAP_IDENTITY_SIZE];
+  CHAR16      EapPassword[PASSWORD_STORAGE_SIZE];
+  UINT8       SecurityType;
+  UINT8       EapAuthMethod;
+  UINT8       EapSecondAuthMethod;
+  UINT8       HiddenNetworkList[HIDDEN_NETWORK_LIST_COUNT_MAX];
+
+} WIFI_MANAGER_IFR_NVDATA;
+#pragma pack()
+
+#endif
diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrDriver.c b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrDriver.c
new file mode 100644
index 0000000000..1431cdc7ea
--- /dev/null
+++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrDriver.c
@@ -0,0 +1,621 @@
+/** @file
+  The driver binding protocol for the WiFi Connection Manager.
+
+  Copyright (c) 2019, 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 "WifiConnectionMgrDxe.h"
+
+///
+/// Driver Binding Protocol instance
+///
+EFI_DRIVER_BINDING_PROTOCOL gWifiMgrDxeDriverBinding = {
+  WifiMgrDxeDriverBindingSupported,
+  WifiMgrDxeDriverBindingStart,
+  WifiMgrDxeDriverBindingStop,
+  WIFI_MGR_DXE_VERSION,
+  NULL,
+  NULL
+};
+
+//
+//The private global data for WiFi Connection Manager
+//
+WIFI_MGR_PRIVATE_DATA    *mPrivate = NULL;
+
+//
+//The private guid to identify WiFi Connection Manager
+//
+EFI_GUID mEfiWifiMgrPrivateGuid            = EFI_WIFIMGR_PRIVATE_GUID;
+
+//
+//The Hii config guids
+//
+EFI_GUID gWifiConfigFormSetGuid            = WIFI_CONNECTION_MANAGER_CONFIG_GUID;
+EFI_GUID mWifiConfigNetworkListRefreshGuid = WIFI_CONFIG_NETWORK_LIST_REFRESH_GUID;
+EFI_GUID mWifiConfigConnectFormRefreshGuid = WIFI_CONFIG_CONNECT_FORM_REFRESH_GUID;
+EFI_GUID mWifiConfigMainFormRefreshGuid    = WIFI_CONFIG_MAIN_FORM_REFRESH_GUID;
+
+/**
+  Tests to see if this driver supports a given controller. If a child device is provided,
+  it further tests to see if this driver supports creating a handle for the specified child device.
+
+  This function checks to see if the driver specified by This supports the device specified by
+  ControllerHandle. Drivers will typically use the device path attached to
+  ControllerHandle and/or the services from the bus I/O abstraction attached to
+  ControllerHandle to determine if the driver supports ControllerHandle. This function
+  may be called many times during platform initialization. In order to reduce boot times, the tests
+  performed by this function must be very small, and take as little time as possible to execute. This
+  function must not change the state of any hardware devices, and this function must be aware that the
+  device specified by ControllerHandle may already be managed by the same driver or a
+  different driver. This function must match its calls to AllocatePages() with FreePages(),
+  AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+  Because ControllerHandle may have been previously started by the same driver, if a protocol is
+  already in the opened state, then it must not be closed with CloseProtocol(). This is required
+  to guarantee the state of ControllerHandle is not modified by this function.
+
+  @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle     The handle of the controller to test. This handle
+                                   must support a protocol interface that supplies
+                                   an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
+                                   parameter is ignored by device drivers, and is optional for bus
+                                   drivers. For bus drivers, if this parameter is not NULL, then
+                                   the bus driver must determine if the bus controller specified
+                                   by ControllerHandle and the child controller specified
+                                   by RemainingDevicePath are both supported by this
+                                   bus driver.
+
+  @retval EFI_SUCCESS              The device specified by ControllerHandle and
+                                   RemainingDevicePath is supported by the driver specified by This.
+  @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
+                                   RemainingDevicePath is already being managed by the driver
+                                   specified by This.
+  @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
+                                   RemainingDevicePath is already being managed by a different
+                                   driver or an application that requires exclusive access.
+                                   Currently not implemented.
+  @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
+                                   RemainingDevicePath is not supported by the driver specified by This.
+
+**/
+EFI_STATUS
+EFIAPI
+WifiMgrDxeDriverBindingSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath OPTIONAL
+  )
+{
+  EFI_STATUS    Status;
+
+  Status = gBS->OpenProtocol (
+                  ControllerHandle,
+                  &mEfiWifiMgrPrivateGuid,
+                  NULL,
+                  This->DriverBindingHandle,
+                  ControllerHandle,
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+                  );
+  if (!EFI_ERROR (Status)) {
+    return EFI_ALREADY_STARTED;
+  }
+
+  //
+  // Test for the wireless MAC connection 2 protocol
+  //
+  return gBS->OpenProtocol (
+                ControllerHandle,
+                &gEfiWiFi2ProtocolGuid,
+                NULL,
+                This->DriverBindingHandle,
+                ControllerHandle,
+                EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+                );
+}
+
+/**
+  Starts a device controller or a bus controller.
+
+  The Start() function is designed to be invoked from the EFI boot service ConnectController().
+  As a result, much of the error checking on the parameters to Start() has been moved into this
+  common boot service. It is legal to call Start() from other locations,
+  but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+  1. ControllerHandle must be a valid EFI_HANDLE.
+  2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+     EFI_DEVICE_PATH_PROTOCOL.
+  3. Prior to calling Start(), the Supported() function for the driver specified by This must
+     have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+  @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle     The handle of the controller to start. This handle
+                                   must support a protocol interface that supplies
+                                   an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
+                                   parameter is ignored by device drivers, and is optional for bus
+                                   drivers. For a bus driver, if this parameter is NULL, then handles
+                                   for all the children of Controller are created by this driver.
+                                   If this parameter is not NULL and the first Device Path Node is
+                                   not the End of Device Path Node, then only the handle for the
+                                   child device specified by the first Device Path Node of
+                                   RemainingDevicePath is created by this driver.
+                                   If the first Device Path Node of RemainingDevicePath is
+                                   the End of Device Path Node, no child handle is created by this
+                                   driver.
+
+  @retval EFI_SUCCESS              The device was started.
+  @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
+  @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
+  @retval Others                   The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+WifiMgrDxeDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath OPTIONAL
+  )
+{
+  EFI_STATUS                                 Status;
+  EFI_TPL                                    OldTpl;
+  UINTN                                      AddressSize;
+  WIFI_MGR_DEVICE_DATA                       *Nic;
+  EFI_WIRELESS_MAC_CONNECTION_II_PROTOCOL    *Wmp;
+  EFI_SUPPLICANT_PROTOCOL                    *Supplicant;
+  EFI_EAP_CONFIGURATION_PROTOCOL             *EapConfig;
+
+  Nic = NULL;
+
+  //
+  //Open Protocols
+  //
+  Status = gBS->OpenProtocol (
+                  ControllerHandle,
+                  &gEfiWiFi2ProtocolGuid,
+                  (VOID**) &Wmp,
+                  This->DriverBindingHandle,
+                  ControllerHandle,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = gBS->OpenProtocol (
+                  ControllerHandle,
+                  &gEfiSupplicantProtocolGuid,
+                  (VOID**) &Supplicant,
+                  This->DriverBindingHandle,
+                  ControllerHandle,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status)) {
+    Supplicant = NULL;
+  }
+
+  Status = gBS->OpenProtocol (
+                  ControllerHandle,
+                  &gEfiEapConfigurationProtocolGuid,
+                  (VOID**) &EapConfig,
+                  This->DriverBindingHandle,
+                  ControllerHandle,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status)) {
+    EapConfig = NULL;
+  }
+
+  //
+  //Initialize Nic device data
+  //
+  Nic = AllocateZeroPool (sizeof (WIFI_MGR_DEVICE_DATA));
+  if (Nic == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ERROR1;
+  }
+  Nic->Signature            = WIFI_MGR_DEVICE_DATA_SIGNATURE;
+  Nic->DriverHandle         = This->DriverBindingHandle;
+  Nic->ControllerHandle     = ControllerHandle;
+  Nic->Private              = mPrivate;
+  Nic->Wmp                  = Wmp;
+  Nic->Supplicant           = Supplicant;
+  Nic->EapConfig            = EapConfig;
+  Nic->UserSelectedProfile  = NULL;
+  Nic->OneTimeScanRequest   = FALSE;
+  Nic->ScanTickTime         = WIFI_SCAN_FREQUENCY;  //Initialize the first scan
+
+  if (Nic->Supplicant != NULL) {
+    WifiMgrGetSupportedSuites(Nic);
+  }
+
+  InitializeListHead (&Nic->ProfileList);
+
+  //
+  // Record the MAC address of the incoming NIC.
+  //
+  Status = NetLibGetMacAddress (
+             ControllerHandle,
+             (EFI_MAC_ADDRESS*) &Nic->MacAddress,
+             &AddressSize
+             );
+  if (EFI_ERROR (Status)) {
+    goto ERROR2;
+  }
+
+  //
+  // Create and start the timer for the status check
+  //
+  Status = gBS->CreateEvent (
+                  EVT_NOTIFY_SIGNAL | EVT_TIMER,
+                  TPL_CALLBACK,
+                  WifiMgrOnTimerTick,
+                  Nic,
+                  &Nic->TickTimer
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ERROR2;
+  }
+
+  Status = gBS->SetTimer (Nic->TickTimer, TimerPeriodic, EFI_TIMER_PERIOD_MILLISECONDS(500));
+  if (EFI_ERROR (Status)) {
+    goto ERROR3;
+  }
+
+  Nic->ConnectState = WifiMgrDisconnected;
+  Nic->ScanState    = WifiMgrScanFinished;
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+  InsertTailList (&mPrivate->NicList, &Nic->Link);
+  Nic->NicIndex = mPrivate->NicCount ++;
+  if (mPrivate->CurrentNic == NULL) {
+    mPrivate->CurrentNic = Nic;
+  }
+  gBS->RestoreTPL (OldTpl);
+
+  Status = gBS->InstallProtocolInterface (
+                  &ControllerHandle,
+                  &mEfiWifiMgrPrivateGuid,
+                  EFI_NATIVE_INTERFACE,
+                  &Nic->WifiMgrIdentifier
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ERROR4;
+  }
+
+  return EFI_SUCCESS;
+
+ERROR4:
+
+  gBS->SetTimer (Nic->TickTimer, TimerCancel, 0);
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+  RemoveEntryList (&Nic->Link);
+  mPrivate->NicCount--;
+  gBS->RestoreTPL (OldTpl);
+
+ERROR3:
+
+  gBS->CloseEvent (Nic->TickTimer);
+
+ERROR2:
+
+  if (Nic->Supplicant != NULL) {
+    if (Nic->SupportedSuites.SupportedAKMSuites != NULL) {
+      FreePool (Nic->SupportedSuites.SupportedAKMSuites);
+    }
+    if (Nic->SupportedSuites.SupportedSwCipherSuites != NULL) {
+      FreePool (Nic->SupportedSuites.SupportedSwCipherSuites);
+    }
+    if (Nic->SupportedSuites.SupportedHwCipherSuites != NULL) {
+      FreePool (Nic->SupportedSuites.SupportedHwCipherSuites);
+    }
+  }
+  FreePool (Nic);
+
+ERROR1:
+
+  if (Supplicant != NULL) {
+    gBS->CloseProtocol (
+           ControllerHandle,
+           &gEfiSupplicantProtocolGuid,
+           This->DriverBindingHandle,
+           ControllerHandle
+           );
+  }
+
+  if (EapConfig != NULL) {
+    gBS->CloseProtocol (
+           ControllerHandle,
+           &gEfiEapConfigurationProtocolGuid,
+           This->DriverBindingHandle,
+           ControllerHandle
+           );
+  }
+
+  gBS->CloseProtocol (
+         ControllerHandle,
+         &gEfiWiFi2ProtocolGuid,
+         This->DriverBindingHandle,
+         ControllerHandle
+         );
+
+  return Status;
+}
+
+/**
+  Stops a device controller or a bus controller.
+
+  The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+  As a result, much of the error checking on the parameters to Stop() has been moved
+  into this common boot service. It is legal to call Stop() from other locations,
+  but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+  1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+     same driver's Start() function.
+  2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+     EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+     Start() function, and the Start() function must have called OpenProtocol() on
+     ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+  @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
+                                support a bus specific I/O protocol for the driver
+                                to use to stop the device.
+  @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
+  @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
+                                if NumberOfChildren is 0.
+
+  @retval EFI_SUCCESS           The device was stopped.
+  @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+WifiMgrDxeDriverBindingStop (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     ControllerHandle,
+  IN UINTN                          NumberOfChildren,
+  IN EFI_HANDLE                     *ChildHandleBuffer OPTIONAL
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_TPL                      OldTpl;
+  WIFI_MGR_PRIVATE_PROTOCOL    *WifiMgrIdentifier;
+  WIFI_MGR_DEVICE_DATA         *Nic;
+
+  Status = gBS->OpenProtocol (
+                  ControllerHandle,
+                  &mEfiWifiMgrPrivateGuid,
+                  (VOID **) &WifiMgrIdentifier,
+                  This->DriverBindingHandle,
+                  ControllerHandle,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  Nic = WIFI_MGR_DEVICE_DATA_FROM_IDENTIFIER (WifiMgrIdentifier);
+  if (Nic == NULL) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Close Event
+  //
+  gBS->CloseEvent (Nic->TickTimer);
+
+  //
+  // Clean Supported Suites
+  //
+  if (Nic->Supplicant != NULL) {
+    if (Nic->SupportedSuites.SupportedAKMSuites != NULL) {
+      FreePool (Nic->SupportedSuites.SupportedAKMSuites);
+    }
+    if (Nic->SupportedSuites.SupportedSwCipherSuites != NULL) {
+      FreePool (Nic->SupportedSuites.SupportedSwCipherSuites);
+    }
+    if (Nic->SupportedSuites.SupportedHwCipherSuites != NULL) {
+      FreePool (Nic->SupportedSuites.SupportedHwCipherSuites);
+    }
+  }
+
+  //
+  // Close Protocols
+  //
+  Status = gBS->UninstallProtocolInterface (
+             ControllerHandle,
+             &mEfiWifiMgrPrivateGuid,
+             &Nic->WifiMgrIdentifier
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = gBS->CloseProtocol (
+             ControllerHandle,
+             &gEfiWiFi2ProtocolGuid,
+             Nic->DriverHandle,
+             Nic->ControllerHandle
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (Nic->Supplicant != NULL) {
+    Status = gBS->CloseProtocol (
+               ControllerHandle,
+               &gEfiSupplicantProtocolGuid,
+               Nic->DriverHandle,
+               Nic->ControllerHandle
+               );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  if (Nic->EapConfig != NULL) {
+    Status = gBS->CloseProtocol (
+               ControllerHandle,
+               &gEfiEapConfigurationProtocolGuid,
+               Nic->DriverHandle,
+               Nic->ControllerHandle
+               );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  //
+  // Remove this Nic from Nic list
+  //
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  RemoveEntryList (&Nic->Link);
+  mPrivate->NicCount--;
+  if (mPrivate->CurrentNic == Nic) {
+    mPrivate->CurrentNic = NULL;
+  }
+
+  gBS->RestoreTPL (OldTpl);
+
+  WifiMgrFreeProfileList (&Nic->ProfileList);
+  FreePool (Nic);
+
+  DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] Device Controller has been Disconnected!\n"));
+  return EFI_SUCCESS;
+}
+
+/**
+  This is the declaration of an EFI image entry point. This entry point is
+  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+  both device drivers and bus drivers.
+
+  @param  ImageHandle           The firmware allocated handle for the UEFI image.
+  @param  SystemTable           A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval Others                An unexpected error occurred.
+
+**/
+EFI_STATUS
+EFIAPI
+WifiMgrDxeDriverEntryPoint (
+  IN EFI_HANDLE          ImageHandle,
+  IN EFI_SYSTEM_TABLE    *SystemTable
+  )
+{
+  EFI_STATUS                       Status;
+
+  Status = EfiLibInstallDriverBindingComponentName2 (
+             ImageHandle,
+             SystemTable,
+             &gWifiMgrDxeDriverBinding,
+             ImageHandle,
+             &gWifiMgrDxeComponentName,
+             &gWifiMgrDxeComponentName2
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Initialize the global private data structure.
+  //
+  mPrivate = AllocateZeroPool (sizeof (WIFI_MGR_PRIVATE_DATA));
+  if (mPrivate == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ERROR1;
+  }
+  mPrivate->Signature    = WIFI_MGR_PRIVATE_DATA_SIGNATURE;
+  mPrivate->DriverHandle = ImageHandle;
+  InitializeListHead (&mPrivate->NicList);
+  mPrivate->NicCount = 0;
+  mPrivate->CurrentNic = NULL;
+  InitializeListHead (&mPrivate->HiddenNetworkList);
+  mPrivate->HiddenNetworkCount = 0;
+
+  //
+  //Create events for page refresh
+  //
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  WifiMgrInternalEmptyFunction,
+                  NULL,
+                  &mWifiConfigNetworkListRefreshGuid,
+                  &mPrivate->NetworkListRefreshEvent
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ERROR2;
+  }
+
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  WifiMgrInternalEmptyFunction,
+                  NULL,
+                  &mWifiConfigConnectFormRefreshGuid,
+                  &mPrivate->ConnectFormRefreshEvent
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ERROR3;
+  }
+
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  WifiMgrInternalEmptyFunction,
+                  NULL,
+                  &mWifiConfigMainFormRefreshGuid,
+                  &mPrivate->MainPageRefreshEvent
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ERROR4;
+  }
+
+  Status = WifiMgrDxeConfigFormInit (mPrivate);
+  if (EFI_ERROR (Status)) {
+    goto ERROR5;
+  }
+
+  return Status;
+
+ERROR5:
+  gBS->CloseEvent (mPrivate->MainPageRefreshEvent);
+
+ERROR4:
+  gBS->CloseEvent (mPrivate->ConnectFormRefreshEvent);
+
+ERROR3:
+  gBS->CloseEvent (mPrivate->NetworkListRefreshEvent);
+
+ERROR2:
+  if (mPrivate != NULL) {
+    FreePool (mPrivate);
+    mPrivate = NULL;
+  }
+
+ERROR1:
+  gBS->UninstallMultipleProtocolInterfaces (
+         ImageHandle,
+         &gEfiDriverBindingProtocolGuid,
+         &gWifiMgrDxeDriverBinding,
+         &gEfiComponentNameProtocolGuid,
+         &gWifiMgrDxeComponentName,
+         &gEfiComponentName2ProtocolGuid,
+         &gWifiMgrDxeComponentName2,
+         NULL
+         );
+
+  return Status;
+}
diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrDriverBinding.h b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrDriverBinding.h
new file mode 100644
index 0000000000..e557d67d66
--- /dev/null
+++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrDriverBinding.h
@@ -0,0 +1,148 @@
+/** @file
+  The driver binding protocol for the WiFi Connection Manager.
+
+  Copyright (c) 2019, 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.
+
+**/
+
+#ifndef __EFI_WIFI_DRIVER_BINDING__
+#define __EFI_WIFI_DRIVER_BINDING__
+
+/**
+  Tests to see if this driver supports a given controller. If a child device is provided,
+  it further tests to see if this driver supports creating a handle for the specified child device.
+
+  This function checks to see if the driver specified by This supports the device specified by
+  ControllerHandle. Drivers will typically use the device path attached to
+  ControllerHandle and/or the services from the bus I/O abstraction attached to
+  ControllerHandle to determine if the driver supports ControllerHandle. This function
+  may be called many times during platform initialization. In order to reduce boot times, the tests
+  performed by this function must be very small, and take as little time as possible to execute. This
+  function must not change the state of any hardware devices, and this function must be aware that the
+  device specified by ControllerHandle may already be managed by the same driver or a
+  different driver. This function must match its calls to AllocatePages() with FreePages(),
+  AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+  Because ControllerHandle may have been previously started by the same driver, if a protocol is
+  already in the opened state, then it must not be closed with CloseProtocol(). This is required
+  to guarantee the state of ControllerHandle is not modified by this function.
+
+  @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle     The handle of the controller to test. This handle
+                                   must support a protocol interface that supplies
+                                   an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
+                                   parameter is ignored by device drivers, and is optional for bus
+                                   drivers. For bus drivers, if this parameter is not NULL, then
+                                   the bus driver must determine if the bus controller specified
+                                   by ControllerHandle and the child controller specified
+                                   by RemainingDevicePath are both supported by this
+                                   bus driver.
+
+  @retval EFI_SUCCESS              The device specified by ControllerHandle and
+                                   RemainingDevicePath is supported by the driver specified by This.
+  @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
+                                   RemainingDevicePath is already being managed by the driver
+                                   specified by This.
+  @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
+                                   RemainingDevicePath is already being managed by a different
+                                   driver or an application that requires exclusive access.
+                                   Currently not implemented.
+  @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
+                                   RemainingDevicePath is not supported by the driver specified by This.
+
+**/
+EFI_STATUS
+EFIAPI
+WifiMgrDxeDriverBindingSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
+  );
+
+/**
+  Starts a device controller or a bus controller.
+
+  The Start() function is designed to be invoked from the EFI boot service ConnectController().
+  As a result, much of the error checking on the parameters to Start() has been moved into this
+  common boot service. It is legal to call Start() from other locations,
+  but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+  1. ControllerHandle must be a valid EFI_HANDLE.
+  2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+     EFI_DEVICE_PATH_PROTOCOL.
+  3. Prior to calling Start(), the Supported() function for the driver specified by This must
+     have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+  @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle     The handle of the controller to start. This handle
+                                   must support a protocol interface that supplies
+                                   an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
+                                   parameter is ignored by device drivers, and is optional for bus
+                                   drivers. For a bus driver, if this parameter is NULL, then handles
+                                   for all the children of Controller are created by this driver.
+                                   If this parameter is not NULL and the first Device Path Node is
+                                   not the End of Device Path Node, then only the handle for the
+                                   child device specified by the first Device Path Node of
+                                   RemainingDevicePath is created by this driver.
+                                   If the first Device Path Node of RemainingDevicePath is
+                                   the End of Device Path Node, no child handle is created by this
+                                   driver.
+
+  @retval EFI_SUCCESS              The device was started.
+  @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
+  @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
+  @retval Others                   The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+WifiMgrDxeDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
+  );
+
+/**
+  Stops a device controller or a bus controller.
+
+  The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+  As a result, much of the error checking on the parameters to Stop() has been moved
+  into this common boot service. It is legal to call Stop() from other locations,
+  but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+  1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+     same driver's Start() function.
+  2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+     EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+     Start() function, and the Start() function must have called OpenProtocol() on
+     ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+  @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
+                                support a bus specific I/O protocol for the driver
+                                to use to stop the device.
+  @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
+  @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
+                                if NumberOfChildren is 0.
+
+  @retval EFI_SUCCESS           The device was stopped.
+  @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+WifiMgrDxeDriverBindingStop (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN  EFI_HANDLE                  ControllerHandle,
+  IN  UINTN                       NumberOfChildren,
+  IN  EFI_HANDLE                  *ChildHandleBuffer OPTIONAL
+  );
+
+#endif
diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrDxe.h b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrDxe.h
new file mode 100644
index 0000000000..a7e67d6875
--- /dev/null
+++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrDxe.h
@@ -0,0 +1,327 @@
+/** @file
+  The miscellaneous structure definitions for WiFi connection driver.
+
+  Copyright (c) 2019, 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.
+
+**/
+
+#ifndef __EFI_WIFI_MGR_DXE_H__
+#define __EFI_WIFI_MGR_DXE_H__
+
+#include <Uefi.h>
+
+//
+// Libraries
+//
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HiiLib.h>
+#include <Library/NetLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiHiiServicesLib.h>
+#include <Library/FileExplorerLib.h>
+
+//
+// UEFI Driver Model Protocols
+//
+#include <Protocol/DriverBinding.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiPackageList.h>
+#include <Protocol/ComponentName2.h>
+#include <Protocol/ComponentName.h>
+
+//
+// Consumed Protocols
+//
+#include <Protocol/WiFi2.h>
+#include <Protocol/AdapterInformation.h>
+#include <Protocol/Supplicant.h>
+#include <Protocol/SimpleNetwork.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/EapConfiguration.h>
+
+//
+// Produced Protocols
+//
+#include <Protocol/HiiConfigAccess.h>
+
+//
+// Guids
+//
+#include <Guid/ImageAuthentication.h>
+#include <Guid/MdeModuleHii.h>
+#include <Guid/WifiConnectionManagerConfigHii.h>
+
+//
+// NvData struct definition
+//
+#include "WifiConnectionMgrConfigNVDataStruct.h"
+#include "WifiConnectionMgrConfig.h"
+#include "EapContext.h"
+#include "WifiConnectionMgrConfigHii.h"
+
+//
+// Driver Version
+//
+#define WIFI_MGR_DXE_VERSION  0xb
+
+#define OUI_IEEE_80211I 0xAC0F00
+
+typedef enum {
+  Ieee80211PairwiseCipherSuiteUseGroupCipherSuite = 0,
+  Ieee80211PairwiseCipherSuiteWEP40  = 1,
+  Ieee80211PairwiseCipherSuiteTKIP   = 2,
+  Ieee80211PairwiseCipherSuiteCCMP   = 4,
+  Ieee80211PairwiseCipherSuiteWEP104 = 5,
+  Ieee80211PairwiseCipherSuiteBIP    = 6,
+  //...
+} IEEE_80211_PAIRWISE_CIPHER_SUITE;
+
+#define IEEE_80211_PAIRWISE_CIPHER_SUITE_USE_GROUP   (OUI_IEEE_80211I | (Ieee80211PairwiseCipherSuiteUseGroupCipherSuite << 24))
+#define IEEE_80211_PAIRWISE_CIPHER_SUITE_WEP40       (OUI_IEEE_80211I | (Ieee80211PairwiseCipherSuiteWEP40 << 24))
+#define IEEE_80211_PAIRWISE_CIPHER_SUITE_TKIP        (OUI_IEEE_80211I | (Ieee80211PairwiseCipherSuiteTKIP << 24))
+#define IEEE_80211_PAIRWISE_CIPHER_SUITE_CCMP        (OUI_IEEE_80211I | (Ieee80211PairwiseCipherSuiteCCMP << 24))
+#define IEEE_80211_PAIRWISE_CIPHER_SUITE_WEP104      (OUI_IEEE_80211I | (Ieee80211PairwiseCipherSuiteWEP104 << 24))
+#define IEEE_80211_PAIRWISE_CIPHER_SUITE_BIP         (OUI_IEEE_80211I | (Ieee80211PairwiseCipherSuiteBIP << 24))
+
+typedef enum {
+  Ieee80211AkmSuite8021XOrPMKSA       = 1,
+  Ieee80211AkmSuitePSK                = 2,
+  Ieee80211AkmSuite8021XOrPMKSASHA256 = 5,
+  Ieee80211AkmSuitePSKSHA256          = 6
+  //...
+} IEEE_80211_AKM_SUITE;
+
+#define IEEE_80211_AKM_SUITE_8021X_OR_PMKSA         (OUI_IEEE_80211I | (Ieee80211AkmSuite8021XOrPMKSA << 24))
+#define IEEE_80211_AKM_SUITE_PSK                    (OUI_IEEE_80211I | (Ieee80211AkmSuitePSK << 24))
+#define IEEE_80211_AKM_SUITE_8021X_OR_PMKSA_SHA256  (OUI_IEEE_80211I | (Ieee80211AkmSuite8021XOrPMKSASHA256 << 24))
+#define IEEE_80211_AKM_SUITE_PSK_SHA256             (OUI_IEEE_80211I | (Ieee80211AkmSuitePSKSHA256 << 24))
+
+//
+// Protocol instances
+//
+extern EFI_DRIVER_BINDING_PROTOCOL       gWifiMgrDxeDriverBinding;
+extern EFI_COMPONENT_NAME2_PROTOCOL      gWifiMgrDxeComponentName2;
+extern EFI_COMPONENT_NAME_PROTOCOL       gWifiMgrDxeComponentName;
+extern EFI_HII_CONFIG_ACCESS_PROTOCOL    gWifiMgrDxeHiiConfigAccess;
+
+//
+// Private Context Data Structure
+//
+typedef enum {
+  WifiMgrDisconnected,
+  WifiMgrConnectingToAp,
+  WifiMgrConnectedToAp,
+  WifiMgrDisconnectingToAp,
+  WifiMgrConnectStateMaximum
+} WIFI_MGR_CONNECT_STATE;
+
+typedef enum {
+  WifiMgrScanFinished,
+  WifiMgrScanning,
+  WifiMgrScanStateMaximum
+} WIFI_MGR_SCAN_STATE;
+
+#define  WIFI_SCAN_FREQUENCY    30
+
+typedef struct _WIFI_MGR_SUPPORTED_SUITES {
+  EFI_80211_AKM_SUITE_SELECTOR     *SupportedAKMSuites;
+  EFI_80211_CIPHER_SUITE_SELECTOR  *SupportedSwCipherSuites;
+  EFI_80211_CIPHER_SUITE_SELECTOR  *SupportedHwCipherSuites;
+} WIFI_MGR_SUPPORTED_SUITES;
+
+#define EFI_WIFIMGR_PRIVATE_GUID \
+  { \
+    0x99b7c019, 0x4789, 0x4829, { 0xa7, 0xbd, 0x0d, 0x4b, 0xaa, 0x62, 0x28, 0x72 } \
+  }
+
+typedef struct _WIFI_MGR_PRIVATE_DATA  WIFI_MGR_PRIVATE_DATA;
+
+typedef struct _WIFI_MGR_PRIVATE_PROTOCOL {
+  UINT32  Reserved;
+} WIFI_MGR_PRIVATE_PROTOCOL;
+
+typedef struct _WIFI_MGR_FILE_CONTEXT {
+  EFI_FILE_HANDLE                   FHandle;
+  UINT16                            *FileName;
+} WIFI_MGR_FILE_CONTEXT;
+
+typedef enum {
+  FileTypeCACert,
+  FileTypeClientCert,
+  FileTypeMax
+} WIFI_MGR_FILE_TYPE;
+
+typedef struct {
+  UINT32                                     Signature;
+  EFI_HANDLE                                 DriverHandle;
+  EFI_HANDLE                                 ControllerHandle;
+  EFI_EVENT                                  TickTimer;
+  WIFI_MGR_PRIVATE_DATA                      *Private;
+
+  //
+  // Pointers to consumed protocols
+  //
+  EFI_WIRELESS_MAC_CONNECTION_II_PROTOCOL    *Wmp;
+  EFI_SUPPLICANT_PROTOCOL                    *Supplicant;
+  EFI_EAP_CONFIGURATION_PROTOCOL             *EapConfig;
+
+  //
+  // Produced protocols
+  //
+  WIFI_MGR_PRIVATE_PROTOCOL                   WifiMgrIdentifier;
+
+  //
+  // Private functions and data fields
+  //
+  LIST_ENTRY                                  Link;  // Link to the NicList in global private data structure.
+  UINT32                                      NicIndex;
+  EFI_80211_MAC_ADDRESS                       MacAddress;
+  WIFI_MGR_SUPPORTED_SUITES                   SupportedSuites;
+  EFI_ADAPTER_INFO_MEDIA_STATE                LastLinkState;
+
+  //
+  // The network is currently connected, connecting or disconnecting.
+  // Only one network can be operated at one time.
+  //
+  WIFI_MGR_NETWORK_PROFILE                    *CurrentOperateNetwork;
+  WIFI_MGR_NETWORK_PROFILE                    *ConnectPendingNetwork;
+  BOOLEAN                                     HasDisconnectPendingNetwork;
+
+  //
+  //Profile related data fields
+  //
+  LIST_ENTRY                                  ProfileList; // List of WIFI_MGR_NETWORK_PROFILE
+  UINT32                                      AvailableCount;
+  UINT32                                      MaxProfileIndex;
+  WIFI_MGR_NETWORK_PROFILE                    *UserSelectedProfile;
+
+  //
+  // Data fields for Hii functionlity
+  //
+  BOOLEAN                                     OneTimeScanRequest;
+  BOOLEAN                                     OneTimeConnectRequest;
+  BOOLEAN                                     OneTimeDisconnectRequest;
+  WIFI_MGR_SCAN_STATE                         ScanState;
+  UINTN                                       ScanTickTime;
+  WIFI_MGR_CONNECT_STATE                      ConnectState;
+  BOOLEAN                                     ConnectStateChanged;
+} WIFI_MGR_DEVICE_DATA;
+
+#define WIFI_MGR_DEVICE_DATA_SIGNATURE  SIGNATURE_32 ('W','M','D','D')
+
+#define WIFI_MGR_DEVICE_DATA_FROM_IDENTIFIER(Identifier) \
+  CR ( \
+    Identifier, \
+    WIFI_MGR_DEVICE_DATA, \
+    WifiMgrIdentifier, \
+    WIFI_MGR_DEVICE_DATA_SIGNATURE \
+    )
+
+typedef struct {
+  UINT32                                     Signature;
+  LIST_ENTRY                                 Link;
+  CHAR16                                     SSId[SSID_STORAGE_SIZE];
+} WIFI_HIDDEN_NETWORK_DATA;
+
+#define WIFI_MGR_HIDDEN_NETWORK_SIGNATURE  SIGNATURE_32 ('W','M','H','N')
+
+#define WIFI_MGR_HIDDEN_NETWORK_FROM_IDENTIFIER(Identifier) \
+  CR ( \
+    Identifier, \
+    WIFI_HIDDEN_NETWORK_DATA, \
+    WifiMgrIdentifier, \
+    WIFI_MGR_HIDDEN_NETWORK_SIGNATURE \
+    )
+
+//
+// Global private data struct
+//
+struct _WIFI_MGR_PRIVATE_DATA {
+
+  UINT32                            Signature;
+  EFI_HANDLE                        DriverHandle;
+  EFI_HII_HANDLE                    RegisteredHandle;
+  EFI_HII_CONFIG_ACCESS_PROTOCOL    ConfigAccess;
+
+  UINT32                            NicCount;
+  LIST_ENTRY                        NicList;
+  WIFI_MGR_DEVICE_DATA              *CurrentNic;
+
+  //
+  // Data fields for Hii functionlity
+  //
+  EFI_EVENT                         NetworkListRefreshEvent;        // Event to refresh the network list form
+  EFI_EVENT                         ConnectFormRefreshEvent;        // Event to refresh the connect form
+  EFI_EVENT                         MainPageRefreshEvent;           // Event to refresh the main page
+
+  //
+  //User Input Record
+  //
+  UINT8                             SecurityType;
+  UINT8                             EapAuthMethod;
+  UINT8                             EapSecondAuthMethod;
+  CHAR16                            EapIdentity[EAP_IDENTITY_SIZE];
+
+  WIFI_MGR_FILE_CONTEXT             *FileContext;
+  WIFI_MGR_FILE_TYPE                FileType;
+
+  UINT32                            HiddenNetworkCount;
+  LIST_ENTRY                        HiddenNetworkList;
+};
+
+#define WIFI_MGR_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('W','M','P','D')
+
+#define WIFI_MGR_PRIVATE_DATA_FROM_CONFIG_ACCESS(This) \
+  CR ( \
+    This, \
+    WIFI_MGR_PRIVATE_DATA, \
+    ConfigAccess, \
+    WIFI_MGR_PRIVATE_DATA_SIGNATURE \
+    )
+extern    WIFI_MGR_PRIVATE_DATA    *mPrivate;
+
+typedef enum {
+  TokenTypeGetNetworksToken,
+  TokenTypeConnectNetworkToken,
+  TokenTypeDisconnectNetworkToken,
+  TokenTypeMax,
+} WIFI_MGR_MAC_CONFIG_TOKEN_TYPE;
+
+typedef union {
+  EFI_80211_GET_NETWORKS_TOKEN         *GetNetworksToken;
+  EFI_80211_CONNECT_NETWORK_TOKEN      *ConnectNetworkToken;
+  EFI_80211_DISCONNECT_NETWORK_TOKEN   *DisconnectNetworkToken;
+} MAC_CONNECTION2_ADAPTER_TOKEN;
+
+typedef struct {
+  WIFI_MGR_DEVICE_DATA            *Nic;
+  WIFI_MGR_MAC_CONFIG_TOKEN_TYPE  Type;
+  MAC_CONNECTION2_ADAPTER_TOKEN   Token;
+} WIFI_MGR_MAC_CONFIG_TOKEN;
+
+//
+// Include files with function prototypes
+//
+#include "WifiConnectionMgrDriverBinding.h"
+#include "WifiConnectionMgrImpl.h"
+#include "WifiConnectionMgrComponentName.h"
+#include "WifiConnectionMgrHiiConfigAccess.h"
+#include "WifiConnectionMgrMisc.h"
+#include "WifiConnectionMgrFileUtil.h"
+
+#endif
diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrFileUtil.c b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrFileUtil.c
new file mode 100644
index 0000000000..6db1626f2d
--- /dev/null
+++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrFileUtil.c
@@ -0,0 +1,308 @@
+/** @file
+  The file operation functions for WiFi Connection Manager.
+
+  Copyright (c) 2019, 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 "WifiConnectionMgrFileUtil.h"
+
+CHAR16*  mDerPemEncodedSuffix[] = {
+  L".cer",
+  L".der",
+  L".crt",
+  L".pem",
+  NULL
+};
+
+/**
+  This code checks if the FileSuffix is one of the possible DER/PEM-encoded certificate suffix.
+
+  @param[in] FileSuffix     The suffix of the input certificate file
+
+  @retval    TRUE           It's a DER/PEM-encoded certificate.
+  @retval    FALSE          It's NOT a DER/PEM-encoded certificate.
+
+**/
+BOOLEAN
+IsDerPemEncodeCertificate (
+  IN CONST CHAR16         *FileSuffix
+)
+{
+  UINTN     Index;
+  for (Index = 0; mDerPemEncodedSuffix[Index] != NULL; Index++) {
+    if (StrCmp (FileSuffix, mDerPemEncodedSuffix[Index]) == 0) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+/**
+  Read file content into BufferPtr, the size of the allocate buffer
+  is *FileSize plus AddtionAllocateSize.
+
+  @param[in]       FileHandle            The file to be read.
+  @param[in, out]  BufferPtr             Pointers to the pointer of allocated buffer.
+  @param[out]      FileSize              Size of input file
+  @param[in]       AddtionAllocateSize   Addtion size the buffer need to be allocated.
+                                         In case the buffer need to contain others besides the file content.
+
+  @retval   EFI_SUCCESS                  The file was read into the buffer.
+  @retval   EFI_INVALID_PARAMETER        A parameter was invalid.
+  @retval   EFI_OUT_OF_RESOURCES         A memory allocation failed.
+  @retval   others                       Unexpected error.
+
+**/
+EFI_STATUS
+ReadFileContent (
+  IN      EFI_FILE_HANDLE           FileHandle,
+  IN OUT  VOID                      **BufferPtr,
+     OUT  UINTN                     *FileSize,
+  IN      UINTN                     AddtionAllocateSize
+  )
+{
+  UINTN      BufferSize;
+  UINT64     SourceFileSize;
+  VOID       *Buffer;
+  EFI_STATUS Status;
+
+  if ((FileHandle == NULL) || (FileSize == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Buffer = NULL;
+
+  //
+  // Get the file size
+  //
+  Status = FileHandle->SetPosition (FileHandle, (UINT64) -1);
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+  Status = FileHandle->GetPosition (FileHandle, &SourceFileSize);
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+  Status = FileHandle->SetPosition (FileHandle, 0);
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+  BufferSize = (UINTN) SourceFileSize + AddtionAllocateSize;
+  Buffer =  AllocateZeroPool(BufferSize);
+  if (Buffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  BufferSize = (UINTN) SourceFileSize;
+  *FileSize  = BufferSize;
+
+  Status = FileHandle->Read (FileHandle, &BufferSize, Buffer);
+  if (EFI_ERROR (Status) || BufferSize != *FileSize) {
+    FreePool (Buffer);
+    Buffer = NULL;
+    Status  = EFI_BAD_BUFFER_SIZE;
+    goto ON_EXIT;
+  }
+
+ON_EXIT:
+
+  *BufferPtr = Buffer;
+  return Status;
+}
+
+/**
+  This function converts an input device structure to a Unicode string.
+
+  @param[in] DevPath                  A pointer to the device path structure.
+
+  @return A new allocated Unicode string that represents the device path.
+
+**/
+CHAR16 *
+EFIAPI
+DevicePathToStr (
+  IN EFI_DEVICE_PATH_PROTOCOL     *DevPath
+  )
+{
+  return ConvertDevicePathToText (
+           DevPath,
+           FALSE,
+           TRUE
+           );
+}
+
+/**
+  Extract filename from device path. The returned buffer is allocated using AllocateCopyPool.
+  The caller is responsible for freeing the allocated buffer using FreePool(). If return NULL
+  means not enough memory resource.
+
+  @param DevicePath       Device path.
+
+  @retval NULL            Not enough memory resourece for AllocateCopyPool.
+  @retval Other           A new allocated string that represents the file name.
+
+**/
+CHAR16 *
+ExtractFileNameFromDevicePath (
+  IN   EFI_DEVICE_PATH_PROTOCOL    *DevicePath
+  )
+{
+  CHAR16          *String;
+  CHAR16          *MatchString;
+  CHAR16          *LastMatch;
+  CHAR16          *FileName;
+  UINTN           Length;
+
+  ASSERT(DevicePath != NULL);
+
+  String = DevicePathToStr(DevicePath);
+  if (String == NULL) {
+    return NULL;
+  }
+  MatchString = String;
+  LastMatch   = String;
+  FileName    = NULL;
+
+  while(MatchString != NULL){
+    LastMatch   = MatchString + 1;
+    MatchString = StrStr(LastMatch,L"\\");
+  }
+
+  Length = StrLen(LastMatch);
+  FileName = AllocateCopyPool ((Length + 1) * sizeof(CHAR16), LastMatch);
+  if (FileName != NULL) {
+    *(FileName + Length) = 0;
+  }
+
+  FreePool(String);
+
+  return FileName;
+}
+
+/**
+  Update the form base on the selected file.
+
+  @param[in]  Private             The pointer to the global private data structure.
+  @param[in]  FilePath            Point to the file path.
+  @param[in]  FormId              The form needs to display.
+
+  @retval TRUE   Exit caller function.
+  @retval FALSE  Not exit caller function.
+
+**/
+BOOLEAN
+UpdatePage(
+  IN  WIFI_MGR_PRIVATE_DATA       *Private,
+  IN  EFI_DEVICE_PATH_PROTOCOL    *FilePath,
+  IN  EFI_FORM_ID                 FormId
+  )
+{
+  CHAR16           *FileName;
+  EFI_STATUS       Status;
+
+  FileName = NULL;
+
+  if (FilePath != NULL) {
+    FileName = ExtractFileNameFromDevicePath(FilePath);
+  }
+  if (FileName == NULL) {
+    //
+    // FileName = NULL has two cases:
+    // 1. FilePath == NULL, not select file.
+    // 2. FilePath != NULL, but ExtractFileNameFromDevicePath return NULL not enough memory resource.
+    // In these two case, no need to update the form, and exit the caller function.
+    //
+    return TRUE;
+  }
+
+  //
+  // Close the previous file handle before open a new one.
+  //
+  if (Private->FileContext->FHandle != NULL) {
+    Private->FileContext->FHandle->Close (Private->FileContext->FHandle);
+  }
+  Private->FileContext->FHandle = NULL;
+
+  Status = EfiOpenFileByDevicePath (
+             &FilePath,
+             &Private->FileContext->FHandle,
+             EFI_FILE_MODE_READ,
+             0
+             );
+  if (EFI_ERROR (Status)) {
+    if (FormId == FORMID_ENROLL_CERT) {
+      HiiSetString (Private->RegisteredHandle,
+        STRING_TOKEN (STR_EAP_ENROLLED_CERT_NAME), L"", NULL);
+    } else if (FormId == FORMID_ENROLL_PRIVATE_KEY){
+      HiiSetString (Private->RegisteredHandle,
+        STRING_TOKEN (STR_EAP_ENROLLED_PRIVATE_KEY_NAME), L"", NULL);
+    }
+  } else {
+
+    if (Private->FileContext->FileName != NULL) {
+      FreePool (Private->FileContext->FileName);
+    }
+    Private->FileContext->FileName = FileName;
+
+    if (FormId == FORMID_ENROLL_CERT) {
+      HiiSetString (Private->RegisteredHandle,
+        STRING_TOKEN (STR_EAP_ENROLLED_CERT_NAME), FileName, NULL);
+    } else if (FormId == FORMID_ENROLL_PRIVATE_KEY){
+      HiiSetString (Private->RegisteredHandle,
+        STRING_TOKEN (STR_EAP_ENROLLED_PRIVATE_KEY_NAME), FileName, NULL);
+    }
+  }
+
+  return TRUE;
+}
+
+/**
+  Update the CA form base on the input file path info.
+
+  @param[in]  Private             The pointer to the global private data structure.
+  @param[in]  FilePath            Point to the file path.
+
+  @retval TRUE   Exit caller function.
+  @retval FALSE  Not exit caller function.
+
+**/
+BOOLEAN
+UpdateCAFromFile (
+  IN  WIFI_MGR_PRIVATE_DATA       *Private,
+  IN  EFI_DEVICE_PATH_PROTOCOL    *FilePath
+  )
+{
+  return UpdatePage(Private, FilePath, FORMID_ENROLL_CERT);
+}
+
+/**
+  Update the Private Key form base on the input file path info.
+
+  @param[in]  Private             The pointer to the global private data structure.
+  @param[in]  FilePath            Point to the file path.
+
+  @retval TRUE   Exit caller function.
+  @retval FALSE  Not exit caller function.
+
+**/
+BOOLEAN
+UpdatePrivateKeyFromFile (
+  IN  WIFI_MGR_PRIVATE_DATA       *Private,
+  IN  EFI_DEVICE_PATH_PROTOCOL    *FilePath
+  )
+{
+  return UpdatePage(Private, FilePath, FORMID_ENROLL_PRIVATE_KEY);
+}
+
diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrFileUtil.h b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrFileUtil.h
new file mode 100644
index 0000000000..5426a5f45d
--- /dev/null
+++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrFileUtil.h
@@ -0,0 +1,77 @@
+/** @file
+  The file operation functions for WiFi Connection Manager.
+
+  Copyright (c) 2019, 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.
+
+**/
+
+#ifndef __EFI_WIFI_MGR_FILE_UTIL__
+#define __EFI_WIFI_MGR_FILE_UTIL__
+
+#include "WifiConnectionMgrDxe.h"
+
+/**
+  Read file content into BufferPtr, the size of the allocate buffer
+  is *FileSize plus AddtionAllocateSize.
+
+  @param[in]       FileHandle            The file to be read.
+  @param[in, out]  BufferPtr             Pointers to the pointer of allocated buffer.
+  @param[out]      FileSize              Size of input file
+  @param[in]       AddtionAllocateSize   Addtion size the buffer need to be allocated.
+                                         In case the buffer need to contain others besides the file content.
+
+  @retval   EFI_SUCCESS                  The file was read into the buffer.
+  @retval   EFI_INVALID_PARAMETER        A parameter was invalid.
+  @retval   EFI_OUT_OF_RESOURCES         A memory allocation failed.
+  @retval   others                       Unexpected error.
+
+**/
+EFI_STATUS
+ReadFileContent (
+  IN      EFI_FILE_HANDLE           FileHandle,
+  IN OUT  VOID                      **BufferPtr,
+     OUT  UINTN                     *FileSize,
+  IN      UINTN                     AddtionAllocateSize
+  );
+
+/**
+  Update the CA cert base on the input file path info.
+
+  @param[in]  Private             The pointer to the global private data structure.
+  @param[in]  FilePath            Point to the file path.
+
+  @retval TRUE   Exit caller function.
+  @retval FALSE  Not exit caller function.
+
+**/
+BOOLEAN
+UpdateCAFromFile (
+  IN  WIFI_MGR_PRIVATE_DATA           *Private,
+  IN  EFI_DEVICE_PATH_PROTOCOL        *FilePath
+  );
+
+/**
+  Update the Private Key base on the input file path info.
+
+  @param[in]  Private             The pointer to the global private data structure.
+  @param[in]  FilePath            Point to the file path.
+
+  @retval TRUE   Exit caller function.
+  @retval FALSE  Not exit caller function.
+
+**/
+BOOLEAN
+UpdatePrivateKeyFromFile (
+  IN  WIFI_MGR_PRIVATE_DATA           *Private,
+  IN  EFI_DEVICE_PATH_PROTOCOL        *FilePath
+  );
+
+#endif
diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrHiiConfigAccess.c b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrHiiConfigAccess.c
new file mode 100644
index 0000000000..bfb6b6e5ca
--- /dev/null
+++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrHiiConfigAccess.c
@@ -0,0 +1,2014 @@
+/** @file
+  The Hii functions for WiFi Connection Manager.
+
+  Copyright (c) 2019, 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 "WifiConnectionMgrDxe.h"
+
+CHAR16  mVendorStorageName[] = L"WIFI_MANAGER_IFR_NVDATA";
+
+HII_VENDOR_DEVICE_PATH  mWifiMgrDxeHiiVendorDevicePath = {
+  {
+    {
+      HARDWARE_DEVICE_PATH,
+      HW_VENDOR_DP,
+      {
+        (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+      }
+    },
+    WIFI_CONNECTION_MANAGER_CONFIG_GUID
+  },
+  {
+    END_DEVICE_PATH_TYPE,
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,
+    {
+      (UINT8) (END_DEVICE_PATH_LENGTH),
+      (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
+    }
+  }
+};
+
+//
+// HII Config Access Protocol instance
+//
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_HII_CONFIG_ACCESS_PROTOCOL gWifiMgrDxeHiiConfigAccess = {
+  WifiMgrDxeHiiConfigAccessExtractConfig,
+  WifiMgrDxeHiiConfigAccessRouteConfig,
+  WifiMgrDxeHiiConfigAccessCallback
+};
+
+CHAR16*   mSecurityType[] = {
+  L"OPEN           ",
+  L"WPA-Enterprise ",
+  L"WPA2-Enterprise",
+  L"WPA-Personal   ",
+  L"WPA2-Personal  ",
+  L"WEP            ",
+  L"UnKnown        "
+};
+
+CHAR16*  mSignalStrengthBar[] = {
+  L"[-----]",
+  L"[*----]",
+  L"[**---]",
+  L"[***--]",
+  L"[****-]",
+  L"[*****]"
+};
+
+#define  RSSI_TO_SIGNAL_STRENGTH_BAR(Rssi)  mSignalStrengthBar[((Rssi + 19)/20)]
+
+#define  NET_LIST_FOR_EACH_FROM_NODE(Entry, Node, ListHead) \
+  for(Entry = Node->ForwardLink; Entry != (ListHead); Entry = Entry->ForwardLink)
+
+extern EFI_GUID    gWifiConfigFormSetGuid;
+
+/**
+  Create Hii Extend Label OpCode as the start opcode and end opcode.
+  The caller is responsible for freeing the OpCode with HiiFreeOpCodeHandle().
+
+  @param[in]  StartLabelNumber   The number of start label.
+  @param[out] StartOpCodeHandle  Points to the start opcode handle.
+  @param[out] EndOpCodeHandle    Points to the end opcode handle.
+
+  @retval EFI_OUT_OF_RESOURCES   Do not have sufficient resource to finish this
+                                 operation.
+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.
+  @retval EFI_SUCCESS            The operation is completed successfully.
+  @retval Other Errors           Returned errors when updating the HII form.
+
+**/
+EFI_STATUS
+WifiMgrCreateOpCode (
+  IN  UINT16    StartLabelNumber,
+  OUT VOID      **StartOpCodeHandle,
+  OUT VOID      **EndOpCodeHandle
+  )
+{
+  EFI_STATUS            Status;
+  EFI_IFR_GUID_LABEL    *InternalStartLabel;
+  EFI_IFR_GUID_LABEL    *InternalEndLabel;
+
+  if (StartOpCodeHandle == NULL || EndOpCodeHandle == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status             = EFI_OUT_OF_RESOURCES;
+  *StartOpCodeHandle = NULL;
+  *EndOpCodeHandle   = NULL;
+
+  //
+  // Initialize the container for dynamic opcodes.
+  //
+  *StartOpCodeHandle = HiiAllocateOpCodeHandle ();
+  if (*StartOpCodeHandle == NULL) {
+    goto Exit;
+  }
+  *EndOpCodeHandle = HiiAllocateOpCodeHandle ();
+  if (*EndOpCodeHandle == NULL) {
+    goto Exit;
+  }
+
+  //
+  // Create Hii Extend Label OpCode as the start opcode.
+  //
+  InternalStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
+                                                *StartOpCodeHandle,
+                                                &gEfiIfrTianoGuid,
+                                                NULL,
+                                                sizeof (EFI_IFR_GUID_LABEL)
+                                                );
+  if (InternalStartLabel == NULL) {
+    goto Exit;
+  }
+  InternalStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+  InternalStartLabel->Number       = StartLabelNumber;
+
+  //
+  // Create Hii Extend Label OpCode as the end opcode.
+  //
+  InternalEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
+                                              *EndOpCodeHandle,
+                                              &gEfiIfrTianoGuid,
+                                              NULL,
+                                              sizeof (EFI_IFR_GUID_LABEL)
+                                              );
+  if (InternalEndLabel == NULL) {
+    goto Exit;
+  }
+  InternalEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+  InternalEndLabel->Number       = LABEL_END;
+
+  return EFI_SUCCESS;
+
+Exit:
+
+  if (*StartOpCodeHandle != NULL) {
+    HiiFreeOpCodeHandle (*StartOpCodeHandle);
+  }
+  if (*EndOpCodeHandle != NULL) {
+    HiiFreeOpCodeHandle (*EndOpCodeHandle);
+  }
+  return Status;
+}
+
+/**
+  Display the Nic list contains all available Nics.
+
+  @param[in]  Private            The pointer to the global private data structure.
+
+  @retval EFI_INVALID_PARAMETER  Any input parameter is invalid.
+  @retval EFI_SUCCESS            The operation is completed successfully.
+
+**/
+EFI_STATUS
+WifiMgrShowNicList (
+  IN  WIFI_MGR_PRIVATE_DATA    *Private
+)
+{
+  EFI_STATUS              Status;
+  CHAR16                  MacString[WIFI_MGR_MAX_MAC_STRING_LEN];
+  CHAR16                  PortString[WIFI_STR_MAX_SIZE];
+  EFI_STRING_ID           PortTitleToken;
+  EFI_STRING_ID           PortTitleHelpToken;
+  WIFI_MGR_DEVICE_DATA    *Nic;
+  LIST_ENTRY              *Entry;
+  VOID                    *StartOpCodeHandle;
+  VOID                    *EndOpCodeHandle;
+
+  if (Private == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = WifiMgrCreateOpCode (
+             LABEL_MAC_ENTRY,
+             &StartOpCodeHandle,
+             &EndOpCodeHandle
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  NET_LIST_FOR_EACH (Entry, &Private->NicList) {
+    Nic = NET_LIST_USER_STRUCT_S (Entry, WIFI_MGR_DEVICE_DATA, Link, WIFI_MGR_DEVICE_DATA_SIGNATURE);
+    WifiMgrMacAddrToStr (&Nic->MacAddress, sizeof (MacString), MacString);
+    UnicodeSPrint (PortString, sizeof (PortString), L"MAC %s", MacString);
+    PortTitleToken = HiiSetString (
+                       Private->RegisteredHandle,
+                       0,
+                       PortString,
+                       NULL
+                       );
+    if (PortTitleToken == 0) {
+      Status = EFI_INVALID_PARAMETER;
+      goto Exit;
+    }
+
+    UnicodeSPrint (PortString, sizeof (PortString), L"MAC Address");
+    PortTitleHelpToken = HiiSetString (
+                           Private->RegisteredHandle,
+                           0,
+                           PortString,
+                           NULL
+                           );
+    if (PortTitleHelpToken == 0) {
+      Status = EFI_INVALID_PARAMETER;
+      goto Exit;
+    }
+
+    HiiCreateGotoOpCode (
+      StartOpCodeHandle,
+      FORMID_WIFI_MAINPAGE,
+      PortTitleToken,
+      PortTitleHelpToken,
+      EFI_IFR_FLAG_CALLBACK,
+      (UINT16) (KEY_MAC_ENTRY_BASE + Nic->NicIndex)
+      );
+  }
+
+  Status = HiiUpdateForm (
+             Private->RegisteredHandle,       // HII handle
+             &gWifiConfigFormSetGuid,         // Formset GUID
+             FORMID_MAC_SELECTION,            // Form ID
+             StartOpCodeHandle,               // Label for where to insert opcodes
+             EndOpCodeHandle                  // Replace data
+             );
+
+Exit:
+
+  HiiFreeOpCodeHandle (StartOpCodeHandle);
+  HiiFreeOpCodeHandle (EndOpCodeHandle);
+  return Status;
+}
+
+/**
+  Retreive the unicode string of the AKM Suite list of a profile.
+  The caller is responsible for freeing the string with FreePool().
+
+  @param[in]  Profile           The network profile contains a AKM suite list.
+
+  @return the unicode string of AKM suite list or "None".
+
+**/
+CHAR16*
+WifiMgrGetStrAKMList (
+  IN  WIFI_MGR_NETWORK_PROFILE         *Profile
+)
+{
+  UINT8     Index;
+  UINT16    AKMSuiteCount;
+  CHAR16    *AKMListDisplay;
+
+  AKMListDisplay = NULL;
+  if (Profile == NULL || Profile->Network.AKMSuite == NULL) {
+    goto Exit;
+  }
+
+  AKMSuiteCount = Profile->Network.AKMSuite->AKMSuiteCount;
+  if (AKMSuiteCount != 0) {
+
+    //
+    // Current AKM Suite is between 1-9
+    //
+    AKMListDisplay = (CHAR16 *) AllocateZeroPool(sizeof (CHAR16) * AKMSuiteCount * 2);
+    if (AKMListDisplay != NULL) {
+      for (Index = 0; Index < AKMSuiteCount; Index ++) {
+        UnicodeSPrint (
+          AKMListDisplay + (Index * 2),
+          sizeof (CHAR16) * 2,
+          L"%d ",
+          Profile->Network.AKMSuite->AKMSuiteList[Index].SuiteType
+          );
+        if (Index == AKMSuiteCount - 1) {
+          *(AKMListDisplay + (Index * 2 + 1)) = L'\0';
+        }
+      }
+    }
+  }
+
+Exit:
+
+  if (AKMListDisplay == NULL) {
+    AKMListDisplay = AllocateCopyPool (sizeof (L"None"), L"None");
+  }
+  return AKMListDisplay;
+}
+
+/**
+  Retreive the unicode string of the Cipher Suite list of a profile.
+  The caller is responsible for freeing the string with FreePool().
+
+  @param[in]  Profile           The network profile contains a Cipher suite list.
+
+  @return the unicode string of Cipher suite list or "None".
+
+**/
+CHAR16*
+WifiMgrGetStrCipherList (
+  IN  WIFI_MGR_NETWORK_PROFILE          *Profile
+)
+{
+  UINT8     Index;
+  UINT16    CipherSuiteCount;
+  CHAR16    *CipherListDisplay;
+
+  CipherListDisplay = NULL;
+  if (Profile == NULL || Profile->Network.CipherSuite == NULL) {
+    goto Exit;
+  }
+
+  CipherSuiteCount   = Profile->Network.CipherSuite->CipherSuiteCount;
+  if (CipherSuiteCount != 0) {
+
+    //
+    // Current Cipher Suite is between 1-9
+    //
+    CipherListDisplay = (CHAR16 *) AllocateZeroPool(sizeof (CHAR16) * CipherSuiteCount * 2);
+    if (CipherListDisplay != NULL) {
+      for (Index = 0; Index < CipherSuiteCount; Index ++) {
+        UnicodeSPrint (
+          CipherListDisplay + (Index * 2),
+          sizeof (CHAR16) * 2,
+          L"%d ",
+          Profile->Network.CipherSuite->CipherSuiteList[Index].SuiteType
+          );
+        if (Index == CipherSuiteCount - 1) {
+          *(CipherListDisplay + (Index * 2 + 1)) = L'\0';
+        }
+      }
+    }
+  }
+
+Exit:
+
+  if (CipherListDisplay == NULL) {
+    CipherListDisplay = AllocateCopyPool (sizeof (L"None"), L"None");
+  }
+  return CipherListDisplay;
+}
+
+/**
+  Refresh the network list display of the current Nic.
+
+  @param[in]   Private           The pointer to the global private data structure.
+  @param[out]  IfrNvData         The IFR NV data.
+
+  @retval EFI_SUCCESS            The operation is completed successfully.
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
+  @retval Other Errors           Returned errors when creating Opcodes or updating the
+                                 Hii form.
+
+**/
+EFI_STATUS
+WifiMgrRefreshNetworkList (
+  IN    WIFI_MGR_PRIVATE_DATA      *Private,
+  OUT   WIFI_MANAGER_IFR_NVDATA    *IfrNvData
+  )
+{
+  EFI_STATUS                         Status;
+  EFI_TPL                            OldTpl;
+  UINT32                             AvailableCount;
+  EFI_STRING_ID                      PortPromptToken;
+  EFI_STRING_ID                      PortTextToken;
+  EFI_STRING_ID                      PortHelpToken;
+  WIFI_MGR_NETWORK_PROFILE           *Profile;
+  LIST_ENTRY                         *Entry;
+  VOID                               *StartOpCodeHandle;
+  VOID                               *EndOpCodeHandle;
+  CHAR16                             *AKMListDisplay;
+  CHAR16                             *CipherListDisplay;
+  CHAR16                             PortString[WIFI_STR_MAX_SIZE];
+  UINTN                              PortStringSize;
+  WIFI_MGR_NETWORK_PROFILE           *ConnectedProfile;
+
+  if (Private->CurrentNic == NULL) {
+    return EFI_SUCCESS;
+  }
+
+  Status = WifiMgrCreateOpCode (
+             LABEL_NETWORK_LIST_ENTRY,
+             &StartOpCodeHandle,
+             &EndOpCodeHandle
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+  AvailableCount    = 0;
+  PortStringSize    = sizeof (PortString);
+  ConnectedProfile  = NULL;
+  AKMListDisplay    = NULL;
+  CipherListDisplay = NULL;
+
+  if (Private->CurrentNic->ConnectState == WifiMgrConnectedToAp) {
+
+    //
+    // Display the current connected network.
+    // Find the current operate network under connected status.
+    //
+    if (Private->CurrentNic->CurrentOperateNetwork != NULL &&
+      Private->CurrentNic->CurrentOperateNetwork->IsAvailable) {
+
+      Profile = Private->CurrentNic->CurrentOperateNetwork;
+      AvailableCount ++;
+
+      AKMListDisplay = WifiMgrGetStrAKMList (Profile);
+      if (AKMListDisplay == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+        goto Exit;
+      }
+      CipherListDisplay = WifiMgrGetStrCipherList(Profile);
+      if (CipherListDisplay == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+        goto Exit;
+      }
+
+      UnicodeSPrint (PortString, PortStringSize, L"%s (Connected)", Profile->SSId);
+      PortPromptToken = HiiSetString (Private->RegisteredHandle, 0, PortString, NULL);
+
+      if (Profile->SecurityType == SECURITY_TYPE_NONE) {
+        PortHelpToken = 0;
+      } else {
+        UnicodeSPrint (PortString, PortStringSize, L"AKMSuite: %s CipherSuite: %s", AKMListDisplay, CipherListDisplay);
+        PortHelpToken = HiiSetString (Private->RegisteredHandle, 0, PortString, NULL);
+      }
+      FreePool (AKMListDisplay);
+      FreePool (CipherListDisplay);
+
+      HiiCreateGotoOpCode (
+        StartOpCodeHandle,
+        FORMID_CONNECT_NETWORK,
+        PortPromptToken,
+        PortHelpToken,
+        EFI_IFR_FLAG_CALLBACK,
+        (UINT16) (KEY_AVAILABLE_NETWORK_ENTRY_BASE + Profile->ProfileIndex)
+        );
+
+      UnicodeSPrint (
+        PortString,
+        PortStringSize,
+        L"%s       %s %s",
+        (Profile->SecurityType != SECURITY_TYPE_NONE ? L"Secured" : L"Open   "),
+        mSecurityType[Profile->SecurityType],
+        RSSI_TO_SIGNAL_STRENGTH_BAR(Profile->NetworkQuality)
+        );
+      PortTextToken = HiiSetString (Private->RegisteredHandle, 0, PortString, NULL);
+
+      HiiCreateTextOpCode (
+        StartOpCodeHandle,
+        PortTextToken,
+        0,
+        0
+      );
+
+      ConnectedProfile = Profile;
+    } else {
+      Private->CurrentNic->HasDisconnectPendingNetwork = TRUE;
+    }
+  }
+
+  //
+  // Display all supported available networks.
+  //
+  NET_LIST_FOR_EACH (Entry, &Private->CurrentNic->ProfileList) {
+
+    Profile = NET_LIST_USER_STRUCT_S (
+                Entry,
+                WIFI_MGR_NETWORK_PROFILE,
+                Link,
+                WIFI_MGR_PROFILE_SIGNATURE
+                );
+    if (ConnectedProfile == Profile) {
+      continue;
+    }
+    if (Profile->IsAvailable && Profile->CipherSuiteSupported) {
+
+      AvailableCount ++;
+
+      AKMListDisplay = WifiMgrGetStrAKMList (Profile);
+      if (AKMListDisplay == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+        goto Exit;
+      }
+      CipherListDisplay = WifiMgrGetStrCipherList(Profile);
+      if (CipherListDisplay == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+        goto Exit;
+      }
+
+      PortPromptToken = HiiSetString (Private->RegisteredHandle, 0, Profile->SSId, NULL);
+      if (PortPromptToken == 0) {
+        Status = EFI_OUT_OF_RESOURCES;
+        goto Exit;
+      }
+
+      if (Profile->SecurityType == SECURITY_TYPE_NONE) {
+        PortHelpToken = 0;
+      } else {
+        UnicodeSPrint (
+          PortString,
+          PortStringSize,
+          L"AKMSuite: %s CipherSuite: %s",
+          AKMListDisplay, CipherListDisplay
+          );
+        PortHelpToken = HiiSetString (Private->RegisteredHandle, 0, PortString, NULL);
+        if (PortHelpToken == 0) {
+          Status = EFI_OUT_OF_RESOURCES;
+          goto Exit;
+        }
+      }
+      FreePool (AKMListDisplay);
+      FreePool (CipherListDisplay);
+
+      HiiCreateGotoOpCode (
+        StartOpCodeHandle,
+        FORMID_CONNECT_NETWORK,
+        PortPromptToken,
+        PortHelpToken,
+        EFI_IFR_FLAG_CALLBACK,
+        (UINT16) (KEY_AVAILABLE_NETWORK_ENTRY_BASE + Profile->ProfileIndex)
+        );
+
+      UnicodeSPrint (
+        PortString,
+        PortStringSize,
+        L"%s       %s %s",
+        (Profile->SecurityType != SECURITY_TYPE_NONE ? L"Secured" : L"Open   "),
+        mSecurityType[Profile->SecurityType],
+        RSSI_TO_SIGNAL_STRENGTH_BAR(Profile->NetworkQuality)
+        );
+      PortTextToken = HiiSetString (Private->RegisteredHandle, 0, PortString, NULL);
+      if (PortTextToken == 0) {
+        Status = EFI_OUT_OF_RESOURCES;
+        goto Exit;
+      }
+      HiiCreateTextOpCode (
+        StartOpCodeHandle,
+        PortTextToken,
+        0,
+        0
+        );
+    }
+  }
+
+  //
+  // Display all Unsupported available networks.
+  //
+  NET_LIST_FOR_EACH (Entry, &Private->CurrentNic->ProfileList) {
+
+    Profile = NET_LIST_USER_STRUCT_S (
+                Entry,
+                WIFI_MGR_NETWORK_PROFILE,
+                Link,
+                WIFI_MGR_PROFILE_SIGNATURE
+                );
+    if (ConnectedProfile == Profile) {
+      continue;
+    }
+    if (Profile->IsAvailable && !Profile->CipherSuiteSupported) {
+
+      AvailableCount ++;
+
+      AKMListDisplay = WifiMgrGetStrAKMList (Profile);
+      if (AKMListDisplay == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+        goto Exit;
+      }
+      CipherListDisplay = WifiMgrGetStrCipherList(Profile);
+      if (CipherListDisplay == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+        goto Exit;
+      }
+
+      PortPromptToken = HiiSetString (Private->RegisteredHandle, 0, Profile->SSId, NULL);
+
+      if (Profile->AKMSuiteSupported) {
+        UnicodeSPrint (
+          PortString,
+          PortStringSize,
+          L"AKMSuite: %s CipherSuite(UnSupported): %s",
+          AKMListDisplay, CipherListDisplay
+          );
+      } else {
+        UnicodeSPrint (
+          PortString,
+          PortStringSize,
+          L"AKMSuite(UnSupported): %s CipherSuite(UnSupported): %s",
+          AKMListDisplay, CipherListDisplay
+          );
+      }
+      FreePool (AKMListDisplay);
+      FreePool (CipherListDisplay);
+
+      PortHelpToken = HiiSetString (Private->RegisteredHandle, 0, PortString, NULL);
+
+      HiiCreateGotoOpCode (
+        StartOpCodeHandle,
+        FORMID_CONNECT_NETWORK,
+        PortPromptToken,
+        PortHelpToken,
+        EFI_IFR_FLAG_CALLBACK,
+        (UINT16) (KEY_AVAILABLE_NETWORK_ENTRY_BASE + Profile->ProfileIndex)
+        );
+
+      UnicodeSPrint (
+        PortString,
+        PortStringSize,
+        L"%s       %s %s",
+        L"UnSupported",
+        mSecurityType[Profile->SecurityType],
+        RSSI_TO_SIGNAL_STRENGTH_BAR(Profile->NetworkQuality)
+        );
+      PortTextToken = HiiSetString (Private->RegisteredHandle, 0, PortString, NULL);
+
+      HiiCreateTextOpCode (
+        StartOpCodeHandle,
+        PortTextToken,
+        0,
+        0
+        );
+    }
+  }
+
+  Status = HiiUpdateForm (
+             Private->RegisteredHandle,       // HII handle
+             &gWifiConfigFormSetGuid,         // Formset GUID
+             FORMID_NETWORK_LIST,             // Form ID
+             StartOpCodeHandle,               // Label for where to insert opcodes
+             EndOpCodeHandle                  // Replace data
+             );
+
+Exit:
+
+  gBS->RestoreTPL (OldTpl);
+
+  if (AKMListDisplay != NULL) {
+    FreePool (AKMListDisplay);
+  }
+  if (CipherListDisplay != NULL) {
+    FreePool (CipherListDisplay);
+  }
+
+  HiiFreeOpCodeHandle (StartOpCodeHandle);
+  HiiFreeOpCodeHandle (EndOpCodeHandle);
+
+  DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] Network List is Refreshed!\n"));
+  return Status;
+}
+
+/**
+  Refresh the hidden network list configured by user.
+
+  @param[in]   Private           The pointer to the global private data structure.
+
+  @retval EFI_SUCCESS            The operation is completed successfully.
+  @retval Other Errors           Returned errors when creating Opcodes or updating the
+                                 Hii form.
+**/
+EFI_STATUS
+WifiMgrRefreshHiddenList (
+  IN    WIFI_MGR_PRIVATE_DATA      *Private
+  )
+{
+  EFI_STATUS                       Status;
+  EFI_TPL                          OldTpl;
+  UINTN                            Index;
+  EFI_STRING_ID                    StringId;
+  VOID                             *StartOpCodeHandle;
+  VOID                             *EndOpCodeHandle;
+  WIFI_HIDDEN_NETWORK_DATA         *HiddenNetwork;
+  LIST_ENTRY                       *Entry;
+
+  if (Private == NULL) {
+    return EFI_SUCCESS;
+  }
+
+  Status = WifiMgrCreateOpCode (
+             LABEL_HIDDEN_NETWORK_ENTRY,
+             &StartOpCodeHandle,
+             &EndOpCodeHandle
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+  Index  = 0;
+
+  NET_LIST_FOR_EACH (Entry, &Private->HiddenNetworkList) {
+
+    HiddenNetwork = NET_LIST_USER_STRUCT_S (
+                      Entry,
+                      WIFI_HIDDEN_NETWORK_DATA,
+                      Link,
+                      WIFI_MGR_HIDDEN_NETWORK_SIGNATURE
+                      );
+    StringId = HiiSetString (Private->RegisteredHandle, 0, HiddenNetwork->SSId, NULL);
+
+    HiiCreateCheckBoxOpCode (
+      StartOpCodeHandle,
+      (EFI_QUESTION_ID) (KEY_HIDDEN_NETWORK_ENTRY_BASE + Index),
+      MANAGER_VARSTORE_ID,
+      (UINT16) (HIDDEN_NETWORK_LIST_VAR_OFFSET + Index),
+      StringId,
+      0,
+      0,
+      0,
+      NULL
+      );
+    Index ++;
+  }
+
+  Status = HiiUpdateForm (
+             Private->RegisteredHandle,       // HII handle
+             &gWifiConfigFormSetGuid,         // Formset GUID
+             FORMID_HIDDEN_NETWORK_LIST,      // Form ID
+             StartOpCodeHandle,               // Label for where to insert opcodes
+             EndOpCodeHandle                  // Replace data
+             );
+
+  gBS->RestoreTPL (OldTpl);
+  HiiFreeOpCodeHandle (StartOpCodeHandle);
+  HiiFreeOpCodeHandle (EndOpCodeHandle);
+  return Status;
+}
+
+
+/**
+  Callback function for user to select a Nic.
+
+  @param[in]  Private            The pointer to the global private data structure.
+  @param[in]  KeyValue           The key value received from HII input.
+
+  @retval EFI_NOT_FOUND          The corresponding Nic is not found.
+  @retval EFI_SUCCESS            The operation is completed successfully.
+
+**/
+EFI_STATUS
+WifiMgrSelectNic (
+  IN     WIFI_MGR_PRIVATE_DATA         *Private,
+  IN     EFI_QUESTION_ID               KeyValue
+  )
+{
+  WIFI_MGR_DEVICE_DATA    *Nic;
+  UINT32                  NicIndex;
+  CHAR16                  MacString[WIFI_MGR_MAX_MAC_STRING_LEN];
+
+  NicIndex = KeyValue - KEY_MAC_ENTRY_BASE;
+  Nic      = WifiMgrGetNicByIndex (Private, NicIndex);
+  if (Nic == NULL) {
+    return EFI_NOT_FOUND;
+  }
+  Private->CurrentNic = Nic;
+
+  WifiMgrMacAddrToStr (&Nic->MacAddress, sizeof (MacString), MacString);
+  HiiSetString (Private->RegisteredHandle, STRING_TOKEN(STR_MAC_ADDRESS), MacString, NULL);
+  return EFI_SUCCESS;
+}
+
+/**
+  Restore the NV data to be default.
+
+  @param[in]  Private             The pointer to the global private data structure.
+  @param[out] IfrNvData           The IFR NV data.
+
+**/
+VOID
+WifiMgrCleanUserInput (
+  IN  WIFI_MGR_PRIVATE_DATA      *Private
+  )
+{
+  Private->SecurityType        = SECURITY_TYPE_NONE;
+  Private->EapAuthMethod       = EAP_AUTH_METHOD_TTLS;
+  Private->EapSecondAuthMethod = EAP_SEAUTH_METHOD_MSCHAPV2;
+  Private->FileType            = FileTypeMax;
+}
+
+/**
+  UI handle function when user select a network to connect.
+
+  @param[in]  Private             The pointer to the global private data structure.
+  @param[in]  ProfileIndex        The profile index user selected to connect.
+
+  @retval EFI_INVALID_PARAMETER   Nic is null.
+  @retval EFI_NOT_FOUND           Profile could not be found.
+  @retval EFI_SUCCESS             The operation is completed successfully.
+
+**/
+EFI_STATUS
+WifiMgrUserSelectProfileToConnect(
+  IN     WIFI_MGR_PRIVATE_DATA         *Private,
+  IN     UINT32                        ProfileIndex
+  )
+{
+  WIFI_MGR_NETWORK_PROFILE         *Profile;
+  WIFI_MGR_DEVICE_DATA             *Nic;
+
+  Nic = Private->CurrentNic;
+  if (Nic == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  //Initialize the connection page
+  //
+  WifiMgrCleanUserInput(Private);
+
+  Profile = WifiMgrGetProfileByProfileIndex (ProfileIndex, &Nic->ProfileList);
+  if (Profile == NULL) {
+    return EFI_NOT_FOUND;
+  }
+  Private->CurrentNic->UserSelectedProfile = Profile;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Record password from a HII input string.
+
+  @param[in]  Private             The pointer to the global private data structure.
+  @param[in]  StringId            The QuestionId received from HII input.
+  @param[in]  StringBuffer        The unicode string buffer to store password.
+  @param[in]  StringBufferLen     The len of unicode string buffer.
+
+  @retval EFI_INVALID_PARAMETER   Any input parameter is invalid.
+  @retval EFI_NOT_FOUND           The password string is not found or invalid.
+  @retval EFI_SUCCESS             The operation is completed successfully.
+
+**/
+EFI_STATUS
+WifiMgrRecordPassword (
+  IN   WIFI_MGR_PRIVATE_DATA      *Private,
+  IN   EFI_STRING_ID              StringId,
+  IN   CHAR16                     *StringBuffer,
+  IN   UINTN                      StringBufferLen
+  )
+{
+  CHAR16                          *Password;
+
+  if (StringId == 0 || StringBuffer == NULL || StringBufferLen <= 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Password = HiiGetString (Private->RegisteredHandle, StringId, NULL);
+  if (Password == NULL) {
+    return EFI_NOT_FOUND;
+  }
+  if (StrLen (Password) > StringBufferLen) {
+    FreePool (Password);
+    return EFI_NOT_FOUND;
+  }
+  StrnCpyS (StringBuffer, StringBufferLen, Password, StrLen (Password));
+  ZeroMem (Password, (StrLen (Password) + 1) * sizeof (CHAR16));
+  FreePool (Password);
+
+  //
+  // Clean password in string package
+  //
+  HiiSetString (Private->RegisteredHandle, StringId, L"", NULL);
+  return EFI_SUCCESS;
+}
+
+/**
+  Update connection message on connect configuration page, and trigger related form refresh.
+
+  @param[in]   Nic                        The related Nic for updating message.
+  @param[in]   ConnectStateChanged        The tag to tell if the connection state has been changed, only
+                                          when the connection changes from "Connected" or "Disconnecting"
+                                          to "Disconnected", or from "Disconnected" or "Connecting" to
+                                          "Connected", this tag can be set as TRUE.
+  @param[in]   ConnectStatusMessage       The message to show on connected status bar, if NULL, will
+                                          use default message.
+
+**/
+VOID
+WifiMgrUpdateConnectMessage (
+  IN  WIFI_MGR_DEVICE_DATA      *Nic,
+  IN  BOOLEAN                   ConnectStateChanged,
+  IN  EFI_STRING                ConnectStatusMessage
+  )
+{
+  CHAR16                   ConnectStatusStr[WIFI_STR_MAX_SIZE];
+  WIFI_MGR_PRIVATE_DATA    *Private;
+
+  Private = Nic->Private;
+  if (Private == NULL || Private->CurrentNic != Nic) {
+    return;
+  }
+
+  //
+  // Update Connection Status Bar
+  //
+  if (ConnectStatusMessage != NULL) {
+    HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECT_STATUS), ConnectStatusMessage, NULL);
+  } else {
+    if (Nic->ConnectState == WifiMgrConnectedToAp) {
+
+      UnicodeSPrint (ConnectStatusStr, sizeof (ConnectStatusStr), L"Connected to %s",
+        Nic->CurrentOperateNetwork->SSId);
+      HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECT_STATUS), ConnectStatusStr, NULL);
+    } else if (Nic->ConnectState == WifiMgrDisconnected) {
+
+      HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECT_STATUS), L"Disconnected", NULL);
+    } else if (Nic->ConnectState == WifiMgrConnectingToAp) {
+
+      UnicodeSPrint (ConnectStatusStr, sizeof (ConnectStatusStr), L"Connecting to %s ...",
+        Nic->CurrentOperateNetwork->SSId);
+      HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECT_STATUS), ConnectStatusStr, NULL);
+    } else if (Nic->ConnectState == WifiMgrDisconnectingToAp) {
+
+      UnicodeSPrint (ConnectStatusStr, sizeof (ConnectStatusStr), L"Disconnecting from %s ...",
+        Nic->CurrentOperateNetwork->SSId);
+      HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECT_STATUS), ConnectStatusStr, NULL);
+    } else {
+      return;
+    }
+  }
+
+  //
+  // Update Connect Button
+  //
+  if (Nic->ConnectState == WifiMgrConnectedToAp && Nic->UserSelectedProfile == Nic->CurrentOperateNetwork) {
+
+    HiiSetString (Private->RegisteredHandle,
+      STRING_TOKEN (STR_CONNECT_NOW), L"Disconnect from this Network", NULL);
+  } else {
+    HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECT_NOW), L"Connect to this Network", NULL);
+  }
+  gBS->SignalEvent (Private->ConnectFormRefreshEvent);
+
+  //
+  // Update Main Page and Network List
+  //
+  if (ConnectStateChanged) {
+
+    if (Nic->ConnectState == WifiMgrConnectedToAp) {
+
+      HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECTION_INFO), L"Connected to", NULL);
+      HiiSetString (Private->RegisteredHandle,
+        STRING_TOKEN (STR_CONNECTED_SSID), Nic->CurrentOperateNetwork->SSId, NULL);
+    } else {
+      HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECTION_INFO), L"Disconnected", NULL);
+      HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_CONNECTED_SSID), L"", NULL);
+    }
+
+    gBS->SignalEvent (Private->NetworkListRefreshEvent);
+    gBS->SignalEvent (Private->MainPageRefreshEvent);
+  }
+}
+
+/**
+  Convert the driver configuration data into the IFR data.
+
+  @param[in]   Private            The pointer to the global private data structure.
+  @param[out]  IfrNvData          The IFR NV data.
+
+  @retval EFI_SUCCESS             The operation is completed successfully.
+
+**/
+EFI_STATUS
+WifiMgrConvertConfigDataToIfrNvData (
+  IN   WIFI_MGR_PRIVATE_DATA      *Private,
+  OUT  WIFI_MANAGER_IFR_NVDATA    *IfrNvData
+  )
+{
+  //
+  // Private shouldn't be NULL here, assert if Private is NULL.
+  //
+  ASSERT (Private != NULL);
+
+  if (Private->CurrentNic != NULL) {
+    IfrNvData->ProfileCount = Private->CurrentNic->AvailableCount;
+  } else {
+    IfrNvData->ProfileCount = 0;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Convert the IFR data into the driver configuration data.
+
+  @param[in]       Private             The pointer to the global private data structure.
+  @param[in, out]  IfrNvData           The IFR NV data.
+
+  @retval EFI_SUCCESS                  The operation is completed successfully.
+
+**/
+EFI_STATUS
+WifiMgrConvertIfrNvDataToConfigData (
+  IN     WIFI_MGR_PRIVATE_DATA         *Private,
+  IN OUT WIFI_MANAGER_IFR_NVDATA       *IfrNvData
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  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 This       Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+
+  @param 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.
+                    If a NULL is passed in for the Request field,
+                    all of the settings being abstracted by this function
+                    will be returned in the Results field.  In addition,
+                    if a ConfigHdr is passed in with no request elements,
+                    all of the settings being abstracted for that particular
+                    ConfigHdr reference will be returned in the Results Field.
+
+  @param 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 Results    A null-terminated Unicode string in
+                    <MultiConfigAltResp> 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.
+
+**/
+EFI_STATUS
+EFIAPI
+WifiMgrDxeHiiConfigAccessExtractConfig (
+  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
+  IN CONST  EFI_STRING                      Request,
+  OUT       EFI_STRING                      *Progress,
+  OUT       EFI_STRING                      *Results
+  )
+{
+  WIFI_MGR_PRIVATE_DATA             *Private;
+  WIFI_MANAGER_IFR_NVDATA           *IfrNvData;
+  EFI_STRING                        ConfigRequestHdr;
+  EFI_STRING                        ConfigRequest;
+  UINTN                             Size;
+  BOOLEAN                           AllocatedRequest;
+  UINTN                             BufferSize;
+  EFI_STATUS                        Status;
+
+  if (This == NULL || Progress == NULL || Results == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Progress = Request;
+  if ((Request != NULL) &&
+      !HiiIsConfigHdrMatch (Request, &gWifiConfigFormSetGuid, mVendorStorageName)) {
+    return EFI_NOT_FOUND;
+  }
+
+  ConfigRequestHdr = NULL;
+  ConfigRequest    = NULL;
+  AllocatedRequest = FALSE;
+  Size             = 0;
+
+  Private   = WIFI_MGR_PRIVATE_DATA_FROM_CONFIG_ACCESS (This);
+
+  BufferSize = sizeof (WIFI_MANAGER_IFR_NVDATA);
+  IfrNvData = AllocateZeroPool (BufferSize);
+  if (IfrNvData == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  WifiMgrConvertConfigDataToIfrNvData (Private, IfrNvData);
+
+  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 (
+                         &gWifiConfigFormSetGuid,
+                         mVendorStorageName,
+                         Private->DriverHandle);
+    if (ConfigRequestHdr == NULL) {
+      FreePool (IfrNvData);
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
+    ConfigRequest = AllocateZeroPool (Size);
+    if (ConfigRequest == NULL) {
+
+      FreePool (IfrNvData);
+      FreePool (ConfigRequestHdr);
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    AllocatedRequest = TRUE;
+    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 *) IfrNvData,
+                                BufferSize,
+                                Results,
+                                Progress
+                                );
+
+  FreePool (IfrNvData);
+  //
+  // Free the allocated config request string.
+  //
+  if (AllocatedRequest) {
+    FreePool (ConfigRequest);
+    ConfigRequest = NULL;
+  }
+  //
+  // 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.
+
+  @param This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+
+  @param Configuration  A null-terminated Unicode string in
+                        <ConfigString> format.
+
+  @param 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_RESOURCES    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
+WifiMgrDxeHiiConfigAccessRouteConfig (
+  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
+  IN CONST  EFI_STRING                      Configuration,
+  OUT       EFI_STRING                      *Progress
+  )
+{
+  EFI_STATUS                     Status;
+  UINTN                          BufferSize;
+  WIFI_MGR_PRIVATE_DATA          *Private;
+  WIFI_MANAGER_IFR_NVDATA        *IfrNvData;
+
+  if (Configuration == NULL || Progress == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  IfrNvData  = NULL;
+  *Progress  = Configuration;
+  BufferSize = sizeof (WIFI_MANAGER_IFR_NVDATA);
+  Private    = WIFI_MGR_PRIVATE_DATA_FROM_CONFIG_ACCESS (This);
+
+  if (!HiiIsConfigHdrMatch (Configuration, &gWifiConfigFormSetGuid, mVendorStorageName)) {
+    return EFI_NOT_FOUND;
+  }
+
+  IfrNvData = AllocateZeroPool (BufferSize);
+  if (IfrNvData == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  WifiMgrConvertConfigDataToIfrNvData (Private, IfrNvData);
+
+  Status = gHiiConfigRouting->ConfigToBlock (
+                                gHiiConfigRouting,
+                                Configuration,
+                                (UINT8*) IfrNvData,
+                                &BufferSize,
+                                Progress
+                                );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = WifiMgrConvertIfrNvDataToConfigData (Private, IfrNvData);
+  ZeroMem (IfrNvData, sizeof (WIFI_MANAGER_IFR_NVDATA));
+  FreePool (IfrNvData);
+
+  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  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param  Action                 Specifies the type of action taken by the browser.
+  @param  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 generated the callback.
+  @param  Type                   The type of value for the question.
+  @param  Value                  A pointer to the data being sent to the original
+                                 exporting driver.
+  @param  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.
+
+**/
+EFI_STATUS
+EFIAPI
+WifiMgrDxeHiiConfigAccessCallback (
+  IN     CONST EFI_HII_CONFIG_ACCESS_PROTOCOL    *This,
+  IN     EFI_BROWSER_ACTION                      Action,
+  IN     EFI_QUESTION_ID                         QuestionId,
+  IN     UINT8                                   Type,
+  IN OUT EFI_IFR_TYPE_VALUE                      *Value,
+  OUT    EFI_BROWSER_ACTION_REQUEST              *ActionRequest
+  )
+{
+  EFI_STATUS                         Status;
+  EFI_INPUT_KEY                      Key;
+  UINTN                              BufferSize;
+  WIFI_MGR_PRIVATE_DATA              *Private;
+  WIFI_MANAGER_IFR_NVDATA            *IfrNvData;
+  EFI_DEVICE_PATH_PROTOCOL           *FilePath;
+  WIFI_MGR_NETWORK_PROFILE           *Profile;
+  WIFI_MGR_NETWORK_PROFILE           *ProfileToConnect;
+  WIFI_HIDDEN_NETWORK_DATA           *HiddenNetwork;
+  UINTN                              TempDataSize;
+  VOID                               *TempData;
+  LIST_ENTRY                         *Entry;
+  UINT32                             Index;
+  UINT32                             RemoveCount;
+  CHAR16                             *TempPassword;
+  CHAR16                             *ErrorMessage;
+
+  if (Action != EFI_BROWSER_ACTION_FORM_OPEN &&
+      Action != EFI_BROWSER_ACTION_FORM_CLOSE &&
+      Action != EFI_BROWSER_ACTION_CHANGING &&
+      Action != EFI_BROWSER_ACTION_CHANGED &&
+      Action != EFI_BROWSER_ACTION_RETRIEVE) {
+
+    return EFI_UNSUPPORTED;
+  }
+  if ((Value == NULL) || (ActionRequest == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status  = EFI_SUCCESS;
+  Private = WIFI_MGR_PRIVATE_DATA_FROM_CONFIG_ACCESS (This);
+  if (Private->CurrentNic == NULL) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Retrieve uncommitted data from Browser
+  //
+  BufferSize = sizeof (WIFI_MANAGER_IFR_NVDATA);
+  IfrNvData = AllocateZeroPool (BufferSize);
+  if (IfrNvData == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  HiiGetBrowserData (&gWifiConfigFormSetGuid, mVendorStorageName, BufferSize, (UINT8 *) IfrNvData);
+
+  if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
+    switch (QuestionId) {
+
+    case KEY_MAC_LIST:
+
+      Status = WifiMgrShowNicList (Private);
+      break;
+
+    case KEY_REFRESH_NETWORK_LIST:
+
+      if (Private->CurrentNic->UserSelectedProfile != NULL) {
+
+        Profile = Private->CurrentNic->UserSelectedProfile;
+
+        //
+        // Erase secrets since user has left Connection Page
+        // Connection Page may direct to Network List Page or Eap Configuration Page,
+        // secrets only need to be erased when head to Network List Page
+        //
+        WifiMgrCleanProfileSecrets (Profile);
+
+        Private->CurrentNic->UserSelectedProfile = NULL;
+      }
+
+      break;
+
+    case KEY_CONNECT_ACTION:
+
+      if (Private->CurrentNic->UserSelectedProfile == NULL) {
+        break;
+      }
+      Profile = Private->CurrentNic->UserSelectedProfile;
+
+      //
+      //Enter the network connection configuration page
+      //Recovery from restored data
+      //
+      if (HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_SSID), Profile->SSId, NULL) == 0) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+      IfrNvData->SecurityType = Profile->SecurityType;
+      if (HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_SECURITY_TYPE),
+            mSecurityType[IfrNvData->SecurityType], NULL) == 0) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+
+      if (IfrNvData->SecurityType == SECURITY_TYPE_WPA2_ENTERPRISE) {
+
+        IfrNvData->EapAuthMethod        = Profile->EapAuthMethod;
+        IfrNvData->EapSecondAuthMethod  = Profile->EapSecondAuthMethod;
+        StrCpyS (IfrNvData->EapIdentity, EAP_IDENTITY_SIZE, Profile->EapIdentity);
+      }
+
+      break;
+
+    case KEY_ENROLLED_CERT_NAME:
+
+      if (Private->CurrentNic->UserSelectedProfile == NULL) {
+        break;
+      }
+      Profile = Private->CurrentNic->UserSelectedProfile;
+
+      //
+      //Enter the key enrollment page
+      //For TTLS and PEAP, only CA cert needs to be cared
+      //
+      if (Private->FileType == FileTypeCACert) {
+
+        if (Profile->CACertData != NULL) {
+          HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_EAP_ENROLLED_CERT_NAME), Profile->CACertName, NULL);
+        } else {
+          HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_EAP_ENROLLED_CERT_NAME), L"", NULL);
+        }
+      } else if (Private->FileType == FileTypeClientCert) {
+
+        if (Profile->ClientCertData != NULL) {
+          HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_EAP_ENROLLED_CERT_NAME), Profile->ClientCertName, NULL);
+        } else {
+          HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_EAP_ENROLLED_CERT_NAME), L"", NULL);
+        }
+      }
+      break;
+
+    case KEY_ENROLLED_PRIVATE_KEY_NAME:
+
+      if (Private->CurrentNic->UserSelectedProfile == NULL) {
+        break;
+      }
+      Profile = Private->CurrentNic->UserSelectedProfile;
+
+      if (Profile->PrivateKeyData != NULL) {
+        HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_EAP_ENROLLED_PRIVATE_KEY_NAME), Profile->PrivateKeyName, NULL);
+      } else {
+        HiiSetString (Private->RegisteredHandle, STRING_TOKEN (STR_EAP_ENROLLED_PRIVATE_KEY_NAME), L"", NULL);
+      }
+      break;
+
+    default:
+      break;
+    }
+  } else if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) {
+    switch (QuestionId) {
+
+    case KEY_CONNECT_ACTION:
+
+      if (Private->CurrentNic->UserSelectedProfile == NULL) {
+        break;
+      }
+      Profile = Private->CurrentNic->UserSelectedProfile;
+
+      //
+      //Restore User Config Data for Page recovery
+      //
+      if (IfrNvData->SecurityType == SECURITY_TYPE_WPA2_ENTERPRISE) {
+
+        Profile->EapAuthMethod        = IfrNvData->EapAuthMethod;
+        Profile->EapSecondAuthMethod  = IfrNvData->EapSecondAuthMethod;
+        StrCpyS (Profile->EapIdentity, EAP_IDENTITY_SIZE, IfrNvData->EapIdentity);
+      }
+      break;
+
+    default:
+      break;
+    }
+  } else if (Action == EFI_BROWSER_ACTION_CHANGING) {
+    switch (QuestionId) {
+
+    case KEY_NETWORK_LIST:
+
+      //
+      //User triggered a scan process.
+      //
+      Private->CurrentNic->OneTimeScanRequest = TRUE;
+      break;
+
+    case KEY_PASSWORD_CONNECT_NETWORK:
+    case KEY_EAP_PASSWORD_CONNECT_NETWORK:
+    case KEY_PRIVATE_KEY_PASSWORD:
+
+      if (Private->CurrentNic->UserSelectedProfile == NULL) {
+        break;
+      }
+      Profile = Private->CurrentNic->UserSelectedProfile;
+
+      if (QuestionId == KEY_PASSWORD_CONNECT_NETWORK) {
+        TempPassword = Profile->Password;
+      } else if (QuestionId == KEY_EAP_PASSWORD_CONNECT_NETWORK) {
+        TempPassword = Profile->EapPassword;
+      } else {
+        TempPassword = Profile->PrivateKeyPassword;
+      }
+
+      Status = WifiMgrRecordPassword (Private, Value->string, TempPassword, PASSWORD_STORAGE_SIZE);
+      if (EFI_ERROR (Status)) {
+        DEBUG ((DEBUG_ERROR, "[WiFi Connection Manager] Error: Failed to input password!"));
+        break;
+      }
+
+      //
+      // This password is not a new created password, so no need to confirm.
+      //
+      Status = EFI_NOT_FOUND;
+      break;
+
+    case KEY_CONNECT_ACTION:
+
+      ErrorMessage     = NULL;
+      ProfileToConnect = NULL;
+
+      if (Private->CurrentNic->UserSelectedProfile == NULL) {
+        break;
+      }
+      Profile = Private->CurrentNic->UserSelectedProfile;
+
+      if (Private->CurrentNic->ConnectState == WifiMgrDisconnected ||
+        Profile != Private->CurrentNic->CurrentOperateNetwork) {
+
+        //
+        // When this network is not currently connected, pend it to connect.
+        //
+        if (Profile->AKMSuiteSupported && Profile->CipherSuiteSupported) {
+
+          if (Profile->SecurityType == SECURITY_TYPE_NONE || Profile->SecurityType == SECURITY_TYPE_WPA2_PERSONAL) {
+
+            //
+            // For Open network, connect directly.
+            //
+            ProfileToConnect = Profile;
+
+          } else if (Profile->SecurityType == SECURITY_TYPE_WPA2_ENTERPRISE) {
+
+            //
+            // For WPA/WPA2-Enterprise network, conduct eap configuration first.
+            // Only EAP-TLS, TTLS and PEAP is supported now!
+            //
+            Profile->EapAuthMethod = IfrNvData->EapAuthMethod;
+            StrCpyS (Profile->EapIdentity, EAP_IDENTITY_SIZE, IfrNvData->EapIdentity);
+
+            if (IfrNvData->EapAuthMethod == EAP_AUTH_METHOD_TTLS || IfrNvData->EapAuthMethod == EAP_AUTH_METHOD_PEAP) {
+
+              Profile->EapSecondAuthMethod = IfrNvData->EapSecondAuthMethod;
+              ProfileToConnect = Profile;
+            } else if (IfrNvData->EapAuthMethod == EAP_AUTH_METHOD_TLS) {
+              ProfileToConnect = Profile;
+            } else {
+              ErrorMessage = L"ERROR: Only EAP-TLS, TTLS or PEAP is supported now!";
+            }
+          } else {
+            ErrorMessage = L"ERROR: Can't connect to this network!";
+          }
+        } else {
+          ErrorMessage = L"ERROR: This network is not supported!";
+        }
+
+        if (ErrorMessage != NULL) {
+          CreatePopUp (
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+            &Key,
+            ErrorMessage,
+            NULL
+            );
+        }
+
+        if (ProfileToConnect != NULL) {
+
+          Private->CurrentNic->OneTimeConnectRequest = TRUE;
+          Private->CurrentNic->ConnectPendingNetwork = ProfileToConnect;
+        }
+      } else if (Private->CurrentNic->ConnectState == WifiMgrConnectedToAp) {
+
+        //
+        // This network is currently connected, just disconnect from it.
+        //
+        Private->CurrentNic->OneTimeDisconnectRequest    = TRUE;
+        Private->CurrentNic->HasDisconnectPendingNetwork = TRUE;
+      }
+      break;
+
+    case KEY_ENROLL_CA_CERT_CONNECT_NETWORK:
+
+      Private->FileType = FileTypeCACert;
+      break;
+
+    case KEY_ENROLL_CLIENT_CERT_CONNECT_NETWORK:
+
+      Private->FileType = FileTypeClientCert;
+      break;
+
+    case KEY_EAP_ENROLL_PRIVATE_KEY_FROM_FILE:
+
+      FilePath = NULL;
+      ChooseFile (NULL, NULL, NULL, &FilePath);
+
+      if (FilePath != NULL) {
+
+        UpdatePrivateKeyFromFile(Private, FilePath);
+        FreePool (FilePath);
+      }
+      break;
+
+    case KEY_EAP_ENROLL_CERT_FROM_FILE:
+
+      //
+      //User will select a cert file from File Explore
+      //
+      FilePath = NULL;
+      ChooseFile( NULL, NULL, NULL, &FilePath);
+
+      if (FilePath != NULL) {
+
+        UpdateCAFromFile(Private, FilePath);
+        FreePool (FilePath);
+      }
+      break;
+
+    case KEY_SAVE_PRIVATE_KEY_TO_MEM:
+
+      if (Private->FileContext != NULL && Private->FileContext->FHandle != NULL &&
+        Private->CurrentNic->UserSelectedProfile != NULL) {
+
+        //
+        // Read Private Key file to Buffer
+        //
+        Profile = Private->CurrentNic->UserSelectedProfile;
+        if (Profile->PrivateKeyData != NULL) {
+
+          ZeroMem (Profile->PrivateKeyData, Profile->PrivateKeyDataSize);
+          FreePool (Profile->PrivateKeyData);
+        }
+
+        Status = WifiMgrReadFileToBuffer (
+                   Private->FileContext,
+                   &TempData,
+                   &TempDataSize
+                   );
+        if (EFI_ERROR (Status)) {
+          CreatePopUp (
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+            &Key,
+            L"ERROR: Can't read this private key file!",
+            NULL
+            );
+        } else {
+
+          ASSERT (Private->FileContext->FileName != NULL);
+
+          Profile->PrivateKeyData = TempData;
+          Profile->PrivateKeyDataSize = TempDataSize;
+          StrCpyS(Profile->PrivateKeyName, WIFI_FILENAME_STR_MAX_SIZE, Private->FileContext->FileName);
+
+          DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] Private Key: %s has been enrolled! Size: %d\n",
+            Profile->PrivateKeyName, Profile->PrivateKeyDataSize));
+        }
+      }
+      break;
+
+    case KEY_SAVE_CERT_TO_MEM:
+
+      if (Private->FileContext != NULL && Private->FileContext->FHandle != NULL &&
+        Private->CurrentNic->UserSelectedProfile != NULL) {
+
+        //
+        // Read Cert file to Buffer
+        //
+        Profile = Private->CurrentNic->UserSelectedProfile;
+
+        if (Private->FileType == FileTypeCACert) {
+          if (Profile->CACertData != NULL) {
+
+            ZeroMem (Profile->CACertData, Profile->CACertSize);
+            FreePool (Profile->CACertData);
+          }
+        } else if (Private->FileType == FileTypeClientCert) {
+          if (Profile->ClientCertData != NULL) {
+
+            ZeroMem (Profile->ClientCertData, Profile->ClientCertSize);
+            FreePool (Profile->ClientCertData);
+          }
+        } else {
+          break;
+        }
+
+        Status = WifiMgrReadFileToBuffer (
+                   Private->FileContext,
+                   &TempData,
+                   &TempDataSize
+                   );
+        if (EFI_ERROR (Status)) {
+          CreatePopUp (
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+            &Key,
+            L"ERROR: Can't read this certificate file!",
+            NULL
+            );
+        } else {
+
+          ASSERT (Private->FileContext->FileName != NULL);
+          if (Private->FileType == FileTypeCACert) {
+
+            Profile->CACertData = TempData;
+            Profile->CACertSize = TempDataSize;
+            StrCpyS(Profile->CACertName, WIFI_FILENAME_STR_MAX_SIZE, Private->FileContext->FileName);
+            DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] CA Cert: %s has been enrolled! Size: %d\n",
+              Profile->CACertName, Profile->CACertSize));
+          } else {
+
+            Profile->ClientCertData = TempData;
+            Profile->ClientCertSize = TempDataSize;
+            StrCpyS(Profile->ClientCertName, WIFI_FILENAME_STR_MAX_SIZE, Private->FileContext->FileName);
+            DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] Client Cert: %s has been enrolled! Size: %d\n",
+              Profile->ClientCertName, Profile->ClientCertSize));
+          }
+        }
+      }
+      break;
+
+    case KEY_ADD_HIDDEN_NETWORK:
+
+      //
+      // Add a Hidden Network
+      //
+      if (StrLen (IfrNvData->SSId) < SSID_MIN_LEN ||
+        Private->HiddenNetworkCount >= HIDDEN_NETWORK_LIST_COUNT_MAX) {
+
+        Status = EFI_ABORTED;
+        break;
+      } else {
+
+        //
+        // Check if this SSId is already in Hidden Network List
+        //
+        NET_LIST_FOR_EACH (Entry, &Private->HiddenNetworkList) {
+
+          HiddenNetwork = NET_LIST_USER_STRUCT_S (Entry, WIFI_HIDDEN_NETWORK_DATA,
+                            Link, WIFI_MGR_HIDDEN_NETWORK_SIGNATURE);
+          if (StrCmp (HiddenNetwork->SSId, IfrNvData->SSId) == 0) {
+
+            Status = EFI_ABORTED;
+            break;
+          }
+        }
+      }
+
+      HiddenNetwork = (WIFI_HIDDEN_NETWORK_DATA *) AllocateZeroPool (sizeof (WIFI_HIDDEN_NETWORK_DATA));
+      if (HiddenNetwork == NULL) {
+
+        Status = EFI_OUT_OF_RESOURCES;
+        break;
+      }
+      HiddenNetwork->Signature = WIFI_MGR_HIDDEN_NETWORK_SIGNATURE;
+      StrCpyS (HiddenNetwork->SSId, SSID_STORAGE_SIZE, IfrNvData->SSId);
+
+      InsertTailList (&Private->HiddenNetworkList, &HiddenNetwork->Link);
+      Private->HiddenNetworkCount ++;
+
+      WifiMgrRefreshHiddenList (Private);
+      break;
+
+    case KEY_REMOVE_HIDDEN_NETWORK:
+
+      //
+      // Remove Hidden Networks
+      //
+      Entry = GetFirstNode (&Private->HiddenNetworkList);
+      RemoveCount = 0;
+      for (Index = 0; Index < Private->HiddenNetworkCount; Index ++) {
+        if (IfrNvData->HiddenNetworkList[Index] != 0) {
+
+          HiddenNetwork = NET_LIST_USER_STRUCT_S (Entry, WIFI_HIDDEN_NETWORK_DATA, Link, WIFI_MGR_HIDDEN_NETWORK_SIGNATURE);
+          Entry = RemoveEntryList (Entry);
+          RemoveCount ++;
+
+          FreePool (HiddenNetwork);
+        } else {
+          Entry = GetNextNode (&Private->HiddenNetworkList, Entry);
+        }
+      }
+
+      Private->HiddenNetworkCount -= RemoveCount;
+      WifiMgrRefreshHiddenList (Private);
+      break;
+
+    default:
+
+      if (QuestionId >= KEY_MAC_ENTRY_BASE && QuestionId < KEY_MAC_ENTRY_BASE + Private->NicCount) {
+        //
+        // User selects a wireless NIC.
+        //
+        Status = WifiMgrSelectNic (Private, QuestionId);
+        if (EFI_ERROR (Status)) {
+          CreatePopUp (
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+            &Key,
+            L"ERROR: Fail to operate the wireless NIC!",
+            NULL
+          );
+        }
+      } else if (Private->CurrentNic != NULL) {
+        if (QuestionId >= KEY_AVAILABLE_NETWORK_ENTRY_BASE &&
+          QuestionId <= KEY_AVAILABLE_NETWORK_ENTRY_BASE + Private->CurrentNic->MaxProfileIndex) {
+
+          Status = WifiMgrUserSelectProfileToConnect (Private, QuestionId - KEY_AVAILABLE_NETWORK_ENTRY_BASE);
+          if (!EFI_ERROR (Status)) {
+            WifiMgrUpdateConnectMessage(Private->CurrentNic, FALSE, NULL);
+          }
+        }
+
+        if (EFI_ERROR (Status)) {
+          CreatePopUp (
+            EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+            &Key,
+            L"ERROR: Fail to operate this profile!",
+            NULL
+          );
+        }
+      }
+
+      break;
+    }
+  } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
+    switch (QuestionId) {
+
+    case KEY_SAVE_CERT_TO_MEM:
+    case KEY_SAVE_PRIVATE_KEY_TO_MEM:
+
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
+      break;
+
+    case KEY_NO_SAVE_CERT_TO_MEM:
+    case KEY_NO_SAVE_PRIVATE_KEY_TO_MEM:
+
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
+      break;
+
+    default:
+
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
+      break;
+    }
+  } else if (Action == EFI_BROWSER_ACTION_RETRIEVE) {
+
+    switch (QuestionId) {
+
+    case KEY_REFRESH_NETWORK_LIST:
+
+      WifiMgrRefreshNetworkList (Private, IfrNvData);
+      break;
+
+    default:
+      break;
+    }
+  }
+
+  if (!EFI_ERROR (Status)) {
+    //
+    // Pass changed uncommitted data back to Form Browser.
+    //
+    BufferSize = sizeof (WIFI_MANAGER_IFR_NVDATA);
+    HiiSetBrowserData (&gWifiConfigFormSetGuid, mVendorStorageName, BufferSize, (UINT8 *) IfrNvData, NULL);
+  }
+
+  ZeroMem (IfrNvData, sizeof (WIFI_MANAGER_IFR_NVDATA));
+  FreePool (IfrNvData);
+  return Status;
+}
+
+/**
+  Initialize the WiFi configuration form.
+
+  @param[in]  Private             The pointer to the global private data structure.
+
+  @retval EFI_SUCCESS             The configuration form is initialized.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+  @retval EFI_INVALID_PARAMETER   Any input parameter is invalid.
+  @retval Other Erros             Returned Errors when installing protocols.
+
+**/
+EFI_STATUS
+WifiMgrDxeConfigFormInit (
+  WIFI_MGR_PRIVATE_DATA    *Private
+)
+{
+  EFI_STATUS                      Status;
+
+  if (Private == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Private->ConfigAccess.ExtractConfig = WifiMgrDxeHiiConfigAccessExtractConfig;
+  Private->ConfigAccess.RouteConfig   = WifiMgrDxeHiiConfigAccessRouteConfig;
+  Private->ConfigAccess.Callback      = WifiMgrDxeHiiConfigAccessCallback;
+
+  //
+  // Install Device Path Protocol and Config Access protocol to driver handle.
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &Private->DriverHandle,
+                  &gEfiDevicePathProtocolGuid,
+                  &mWifiMgrDxeHiiVendorDevicePath,
+                  &gEfiHiiConfigAccessProtocolGuid,
+                  &Private->ConfigAccess,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Publish our HII data.
+  //
+  Private->RegisteredHandle = HiiAddPackages (
+                                &gWifiConfigFormSetGuid,
+                                Private->DriverHandle,
+                                WifiConnectionManagerDxeStrings,
+                                WifiConnectionManagerDxeBin,
+                                NULL
+                                );
+  if (Private->RegisteredHandle == NULL) {
+    gBS->UninstallMultipleProtocolInterfaces (
+           Private->DriverHandle,
+           &gEfiDevicePathProtocolGuid,
+           &mWifiMgrDxeHiiVendorDevicePath,
+           &gEfiHiiConfigAccessProtocolGuid,
+           &Private->ConfigAccess,
+           NULL
+           );
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Private->FileContext = AllocateZeroPool (sizeof (WIFI_MGR_FILE_CONTEXT));
+  if (Private->FileContext == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Unload the WiFi configuration form.
+
+  @param[in]  Private             The pointer to the global private data structure.
+
+  @retval EFI_SUCCESS             The configuration form is unloaded successfully.
+  @retval EFI_INVALID_PARAMETER   Any input parameter is invalid.
+  @retval Other Errors            Returned Erros when uninstalling protocols.
+
+**/
+EFI_STATUS
+WifiMgrDxeConfigFormUnload (
+  WIFI_MGR_PRIVATE_DATA    *Private
+)
+{
+  EFI_STATUS    Status;
+
+  if (Private == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Private->FileContext != NULL) {
+
+    if (Private->FileContext->FHandle != NULL) {
+      Private->FileContext->FHandle->Close (Private->FileContext->FHandle);
+    }
+
+    if (Private->FileContext->FileName != NULL) {
+      FreePool (Private->FileContext->FileName);
+    }
+    FreePool (Private->FileContext);
+  }
+
+  HiiRemovePackages(Private->RegisteredHandle);
+
+  Status = gBS->UninstallMultipleProtocolInterfaces (
+             Private->DriverHandle,
+             &gEfiDevicePathProtocolGuid,
+             &mWifiMgrDxeHiiVendorDevicePath,
+             &gEfiHiiConfigAccessProtocolGuid,
+             &Private->ConfigAccess,
+             NULL
+             );
+
+  return Status;
+}
diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrHiiConfigAccess.h b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrHiiConfigAccess.h
new file mode 100644
index 0000000000..41a11ca6e0
--- /dev/null
+++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrHiiConfigAccess.h
@@ -0,0 +1,247 @@
+/** @file
+  The Hii functions for WiFi Connection Manager.
+
+  Copyright (c) 2019, 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.
+
+**/
+
+#ifndef __EFI_WIFI_MGR_HII_CONFIG_ACCESS__
+#define __EFI_WIFI_MGR_HII_CONFIG_ACCESS__
+
+/**
+  Update connection message on connect configuration page, and trigger related form refresh.
+
+  @param[in]   Nic                        The related Nic for updating message.
+  @param[in]   ConnectStateChanged        The tag to tell if the connection state has been changed, only
+                                          when the connection changes from "Connected" or "Disconnecting"
+                                          to "Disconnected", or from "Disconnected" or "Connecting" to
+                                          "Connected", this tag can be set as TRUE.
+  @param[in]   ConnectStatusMessage       The message to show on connected status bar, if NULL, will
+                                          use default message.
+
+**/
+VOID
+WifiMgrUpdateConnectMessage (
+  IN  WIFI_MGR_DEVICE_DATA      *Nic,
+  IN  BOOLEAN                   ConnectStateChanged,
+  IN  EFI_STRING                ConnectStatusMessage
+  );
+
+/**
+  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 This       Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+
+  @param 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.
+                    If a NULL is passed in for the Request field,
+                    all of the settings being abstracted by this function
+                    will be returned in the Results field.  In addition,
+                    if a ConfigHdr is passed in with no request elements,
+                    all of the settings being abstracted for that particular
+                    ConfigHdr reference will be returned in the Results Field.
+
+  @param 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 Results    A null-terminated Unicode string in
+                    <MultiConfigAltResp> 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.
+
+**/
+EFI_STATUS
+EFIAPI
+WifiMgrDxeHiiConfigAccessExtractConfig (
+  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
+  IN CONST  EFI_STRING                      Request,
+  OUT       EFI_STRING                      *Progress,
+  OUT       EFI_STRING                      *Results
+  );
+
+/**
+  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.
+
+  @param This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+
+  @param Configuration  A null-terminated Unicode string in
+                        <ConfigString> format.
+
+  @param 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_RESOURCES    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
+WifiMgrDxeHiiConfigAccessRouteConfig (
+  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
+  IN CONST  EFI_STRING                      Configuration,
+  OUT       EFI_STRING                      *Progress
+  );
+
+/**
+  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  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param  Action                 Specifies the type of action taken by the browser.
+  @param  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 generated the callback.
+  @param  Type                   The type of value for the question.
+  @param  Value                  A pointer to the data being sent to the original
+                                 exporting driver.
+  @param  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.
+
+**/
+EFI_STATUS
+EFIAPI
+WifiMgrDxeHiiConfigAccessCallback (
+  IN     CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
+  IN     EFI_BROWSER_ACTION                     Action,
+  IN     EFI_QUESTION_ID                        QuestionId,
+  IN     UINT8                                  Type,
+  IN OUT EFI_IFR_TYPE_VALUE                     *Value,
+  OUT    EFI_BROWSER_ACTION_REQUEST             *ActionRequest
+  );
+
+/**
+  Initialize the WiFi configuration form.
+
+  @param[in]  Private             The pointer to the global private data structure.
+
+  @retval EFI_SUCCESS             The configuration form is initialized.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+  @retval Other Erros             Returned errors when installing protocols.
+
+**/
+EFI_STATUS
+WifiMgrDxeConfigFormInit (
+  WIFI_MGR_PRIVATE_DATA    *Private
+  );
+
+/**
+  Unload the WiFi configuration form.
+
+  @param[in]  Private      The pointer to the global private data structure.
+
+  @retval EFI_SUCCESS      The configuration form is unloaded successfully.
+  @retval Other Errors     Returned Erros when uninstalling protocols.
+
+**/
+EFI_STATUS
+WifiMgrDxeConfigFormUnload (
+  WIFI_MGR_PRIVATE_DATA    *Private
+  );
+
+/**
+  Refresh the network list display of the current Nic.
+
+  @param[in]   Private            The pointer to the global private data structure.
+  @param[out]  IfrNvData          The IFR NV data.
+
+  @retval EFI_SUCCESS             The operation is completed successfully.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+  @retval Other Errors            Returned errors when creating Opcodes or updating the
+                                  Hii form.
+
+**/
+EFI_STATUS
+WifiMgrRefreshNetworkList (
+  IN    WIFI_MGR_PRIVATE_DATA        *Private,
+  OUT   WIFI_MANAGER_IFR_NVDATA      *IfrNvData
+  );
+
+#endif
diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrImpl.c b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrImpl.c
new file mode 100644
index 0000000000..52ce18dfd8
--- /dev/null
+++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrImpl.c
@@ -0,0 +1,1292 @@
+/** @file
+  The Mac Connection2 Protocol adapter functions for WiFi Connection Manager.
+
+  Copyright (c) 2019, 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 "WifiConnectionMgrDxe.h"
+
+EFI_EAP_TYPE mEapAuthMethod[] = {
+  EFI_EAP_TYPE_TTLS,
+  EFI_EAP_TYPE_PEAP,
+  EFI_EAP_TYPE_EAPTLS
+};
+
+EFI_EAP_TYPE mEapSecondAuthMethod[] = {
+  EFI_EAP_TYPE_MSCHAPV2
+};
+
+/**
+  The callback function for scan operation. This function updates networks
+  according to the latest scan result, and trigger UI refresh.
+
+  ASSERT when errors occur in config token.
+
+  @param[in]  Event                 The GetNetworks token receive event.
+  @param[in]  Context               The context of the GetNetworks token.
+
+**/
+VOID
+EFIAPI
+WifiMgrOnScanFinished (
+  IN  EFI_EVENT                     Event,
+  IN  VOID                          *Context
+  )
+{
+  EFI_STATUS                        Status;
+  WIFI_MGR_MAC_CONFIG_TOKEN         *ConfigToken;
+  WIFI_MGR_DEVICE_DATA              *Nic;
+  WIFI_MGR_NETWORK_PROFILE          *Profile;
+  EFI_80211_NETWORK                 *Network;
+  UINTN                             DataSize;
+  EFI_80211_NETWORK_DESCRIPTION     *NetworkDescription;
+  EFI_80211_GET_NETWORKS_RESULT     *Result;
+  LIST_ENTRY                        *Entry;
+  UINT8                             SecurityType;
+  BOOLEAN                           AKMSuiteSupported;
+  BOOLEAN                           CipherSuiteSupported;
+  CHAR8                             *AsciiSSId;
+  UINTN                             Index;
+
+  ASSERT (Context != NULL);
+
+  ConfigToken = (WIFI_MGR_MAC_CONFIG_TOKEN *) Context;
+  ASSERT (ConfigToken->Nic != NULL);
+  ASSERT (ConfigToken->Type == TokenTypeGetNetworksToken);
+
+  //
+  // It is the GetNetworks token, set scan state to "ScanFinished"
+  //
+  ConfigToken->Nic->ScanState = WifiMgrScanFinished;
+
+  ASSERT (ConfigToken->Token.GetNetworksToken != NULL);
+  Result = ConfigToken->Token.GetNetworksToken->Result;
+  Nic    = ConfigToken->Nic;
+
+  //
+  // Clean previous result, and update network list according to the scan result
+  //
+  Nic->AvailableCount    = 0;
+
+  NET_LIST_FOR_EACH (Entry, &Nic->ProfileList) {
+    Profile = NET_LIST_USER_STRUCT_S (Entry, WIFI_MGR_NETWORK_PROFILE,
+                Link, WIFI_MGR_PROFILE_SIGNATURE);
+    Profile->IsAvailable = FALSE;
+  }
+
+  if (Result == NULL) {
+    gBS->SignalEvent (Nic->Private->NetworkListRefreshEvent);
+    WifiMgrFreeToken(ConfigToken);
+    return;
+  }
+
+  for (Index = 0; Index < Result->NumOfNetworkDesc; Index ++) {
+
+    NetworkDescription = Result->NetworkDesc + Index;
+    if (NetworkDescription == NULL) {
+      continue;
+    }
+
+    Network = &NetworkDescription->Network;
+    if (Network == NULL || Network->SSId.SSIdLen == 0) {
+      continue;
+    }
+
+    Status = WifiMgrCheckRSN (
+               Network->AKMSuite,
+               Network->CipherSuite,
+               Nic,
+               &SecurityType,
+               &AKMSuiteSupported,
+               &CipherSuiteSupported
+               );
+    if (EFI_ERROR (Status)) {
+
+      SecurityType          = SECURITY_TYPE_UNKNOWN;
+      AKMSuiteSupported     = FALSE;
+      CipherSuiteSupported  = FALSE;
+    }
+
+    AsciiSSId = (CHAR8*) AllocateZeroPool(sizeof (CHAR8) * (Network->SSId.SSIdLen + 1));
+    if (AsciiSSId == NULL) {
+      continue;
+    }
+    CopyMem(AsciiSSId, (CHAR8 *) Network->SSId.SSId, sizeof (CHAR8) * Network->SSId.SSIdLen);
+    *(AsciiSSId + Network->SSId.SSIdLen) = '\0';
+
+    Profile = WifiMgrGetProfileByAsciiSSId (AsciiSSId, SecurityType, &Nic->ProfileList);
+    if (Profile == NULL) {
+
+      if (Nic->MaxProfileIndex >= NETWORK_LIST_COUNT_MAX) {
+        FreePool (AsciiSSId);
+        continue;
+      }
+
+      //
+      // Create a new profile
+      //
+      Profile = AllocateZeroPool (sizeof (WIFI_MGR_NETWORK_PROFILE));
+      if (Profile == NULL) {
+        FreePool (AsciiSSId);
+        continue;
+      }
+      Profile->Signature    = WIFI_MGR_PROFILE_SIGNATURE;
+      Profile->NicIndex     = Nic->NicIndex;
+      Profile->ProfileIndex = Nic->MaxProfileIndex + 1;
+      AsciiStrToUnicodeStrS (AsciiSSId, Profile->SSId, SSID_STORAGE_SIZE);
+      InsertTailList (&Nic->ProfileList, &Profile->Link);
+      Nic->MaxProfileIndex ++;
+    }
+    FreePool (AsciiSSId);
+
+    //
+    //May receive duplicate networks in scan results, check if it has already
+    //been processed.
+    //
+    if (!Profile->IsAvailable) {
+
+      Profile->IsAvailable          = TRUE;
+      Profile->SecurityType         = SecurityType;
+      Profile->AKMSuiteSupported    = AKMSuiteSupported;
+      Profile->CipherSuiteSupported = CipherSuiteSupported;
+      Profile->NetworkQuality       = NetworkDescription->NetworkQuality;
+      Nic->AvailableCount ++;
+
+      //
+      //Copy BSSType and SSId
+      //
+      CopyMem(&Profile->Network, Network, sizeof (EFI_80211_NETWORK));
+
+      //
+      //Copy AKMSuite list
+      //
+      if (Network->AKMSuite != NULL) {
+
+        if (Network->AKMSuite->AKMSuiteCount == 0) {
+          DataSize = sizeof (EFI_80211_AKM_SUITE_SELECTOR);
+        } else {
+          DataSize = sizeof (EFI_80211_AKM_SUITE_SELECTOR) + sizeof (EFI_80211_SUITE_SELECTOR)
+                       * (Network->AKMSuite->AKMSuiteCount - 1);
+        }
+        Profile->Network.AKMSuite = (EFI_80211_AKM_SUITE_SELECTOR *) AllocateZeroPool (DataSize);
+        if (Profile->Network.AKMSuite == NULL) {
+          continue;
+        }
+        CopyMem (Profile->Network.AKMSuite, Network->AKMSuite, DataSize);
+      }
+
+      //
+      //Copy CipherSuite list
+      //
+      if (Network->CipherSuite != NULL) {
+
+        if (Network->CipherSuite->CipherSuiteCount == 0) {
+          DataSize = sizeof (EFI_80211_CIPHER_SUITE_SELECTOR);
+        } else {
+          DataSize = sizeof (EFI_80211_CIPHER_SUITE_SELECTOR) + sizeof (EFI_80211_SUITE_SELECTOR)
+                       * (Network->CipherSuite->CipherSuiteCount - 1);
+        }
+        Profile->Network.CipherSuite = (EFI_80211_CIPHER_SUITE_SELECTOR *) AllocateZeroPool (DataSize);
+        if (Profile->Network.CipherSuite == NULL) {
+          continue;
+        }
+        CopyMem (Profile->Network.CipherSuite, Network->CipherSuite, DataSize);
+      }
+    } else {
+      //
+      // A duplicate network, update signal quality
+      //
+      if (Profile->NetworkQuality < NetworkDescription->NetworkQuality) {
+        Profile->NetworkQuality = NetworkDescription->NetworkQuality;
+      }
+      continue;
+    }
+  }
+
+  FreePool (Result);
+  gBS->SignalEvent (Nic->Private->NetworkListRefreshEvent);
+
+  //
+  // The current connected network should always be available until disconnection
+  // happens in Wifi FW layer, even when it is not in this time's scan result.
+  //
+  if (Nic->ConnectState == WifiMgrConnectedToAp && Nic->CurrentOperateNetwork != NULL) {
+    if (!Nic->CurrentOperateNetwork->IsAvailable) {
+      Nic->CurrentOperateNetwork->IsAvailable = TRUE;
+      Nic->AvailableCount ++;
+    }
+  }
+
+  WifiMgrFreeToken(ConfigToken);
+}
+
+/**
+  Start scan operation, and send out a token to collect available networks.
+
+  @param[in]  Nic                 Pointer to the device data of the selected NIC.
+
+  @retval EFI_SUCCESS             The operation is completed.
+  @retval EFI_ALREADY_STARTED     A former scan operation is already ongoing.
+  @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+  @retval Other Errors            Return errors when getting networks from low layer.
+
+**/
+EFI_STATUS
+WifiMgrStartScan (
+  IN      WIFI_MGR_DEVICE_DATA        *Nic
+  )
+{
+  EFI_STATUS                          Status;
+  EFI_TPL                             OldTpl;
+  WIFI_MGR_MAC_CONFIG_TOKEN           *ConfigToken;
+  EFI_80211_GET_NETWORKS_TOKEN        *GetNetworksToken;
+  UINT32                              HiddenSSIdIndex;
+  UINT32                              HiddenSSIdCount;
+  EFI_80211_SSID                      *HiddenSSIdList;
+  WIFI_HIDDEN_NETWORK_DATA            *HiddenNetwork;
+  LIST_ENTRY                          *Entry;
+
+  if (Nic == NULL || Nic->Wmp == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Nic->ScanState == WifiMgrScanning) {
+    return EFI_ALREADY_STARTED;
+  }
+
+  Nic->ScanState  = WifiMgrScanning;
+  OldTpl          = gBS->RaiseTPL (TPL_CALLBACK);
+  Status          = EFI_SUCCESS;
+  HiddenSSIdList  = NULL;
+  HiddenSSIdCount = Nic->Private->HiddenNetworkCount;
+  HiddenSSIdIndex = 0;
+
+  //
+  //create a new get network token
+  //
+  ConfigToken     = AllocateZeroPool (sizeof (WIFI_MGR_MAC_CONFIG_TOKEN));
+  if (ConfigToken == NULL) {
+    gBS->RestoreTPL (OldTpl);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  ConfigToken->Type      = TokenTypeGetNetworksToken;
+  ConfigToken->Nic       = Nic;
+  ConfigToken->Token.GetNetworksToken = AllocateZeroPool (sizeof (EFI_80211_GET_NETWORKS_TOKEN));
+  if (ConfigToken->Token.GetNetworksToken == NULL) {
+    WifiMgrFreeToken(ConfigToken);
+    gBS->RestoreTPL (OldTpl);
+    return EFI_OUT_OF_RESOURCES;
+  }
+  GetNetworksToken = ConfigToken->Token.GetNetworksToken;
+
+  //
+  // There are some hidden networks to scan, add them into scan list
+  //
+  if (HiddenSSIdCount > 0) {
+    HiddenSSIdList = AllocateZeroPool(HiddenSSIdCount * sizeof (EFI_80211_SSID));
+    if (HiddenSSIdList == NULL) {
+      WifiMgrFreeToken(ConfigToken);
+      gBS->RestoreTPL (OldTpl);
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    HiddenSSIdIndex = 0;
+    NET_LIST_FOR_EACH (Entry, &Nic->Private->HiddenNetworkList) {
+
+      HiddenNetwork = NET_LIST_USER_STRUCT_S (Entry, WIFI_HIDDEN_NETWORK_DATA,
+                        Link, WIFI_MGR_HIDDEN_NETWORK_SIGNATURE);
+      HiddenSSIdList[HiddenSSIdIndex].SSIdLen = (UINT8) StrLen (HiddenNetwork->SSId);
+      UnicodeStrToAsciiStrS(HiddenNetwork->SSId,
+        (CHAR8 *) HiddenSSIdList[HiddenSSIdIndex].SSId, SSID_STORAGE_SIZE);
+      HiddenSSIdIndex ++;
+    }
+    GetNetworksToken->Data = AllocateZeroPool (sizeof (EFI_80211_GET_NETWORKS_DATA) +
+                               (HiddenSSIdCount - 1) * sizeof (EFI_80211_SSID));
+    if (GetNetworksToken->Data == NULL) {
+      FreePool (HiddenSSIdList);
+      WifiMgrFreeToken(ConfigToken);
+      gBS->RestoreTPL (OldTpl);
+      return EFI_OUT_OF_RESOURCES;
+    }
+    GetNetworksToken->Data->NumOfSSID = HiddenSSIdCount;
+    CopyMem(GetNetworksToken->Data->SSIDList, HiddenSSIdList, HiddenSSIdCount * sizeof (EFI_80211_SSID));
+    FreePool(HiddenSSIdList);
+  } else {
+
+    GetNetworksToken->Data = AllocateZeroPool (sizeof (EFI_80211_GET_NETWORKS_DATA));
+    if (GetNetworksToken->Data == NULL) {
+      WifiMgrFreeToken(ConfigToken);
+      gBS->RestoreTPL (OldTpl);
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    GetNetworksToken->Data->NumOfSSID = 0;
+  }
+
+  //
+  //Create a handle when scan process ends
+  //
+  Status = gBS->CreateEvent (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  WifiMgrOnScanFinished,
+                  ConfigToken,
+                  &GetNetworksToken->Event
+                  );
+  if (EFI_ERROR (Status)) {
+    WifiMgrFreeToken(ConfigToken);
+    gBS->RestoreTPL (OldTpl);
+    return Status;
+  }
+
+  //
+  //Start scan ...
+  //
+  Status = Nic->Wmp->GetNetworks (Nic->Wmp, GetNetworksToken);
+  if (EFI_ERROR (Status)) {
+    Nic->ScanState  = WifiMgrScanFinished;
+    WifiMgrFreeToken(ConfigToken);
+    gBS->RestoreTPL (OldTpl);
+    return Status;
+  }
+
+  gBS->RestoreTPL (OldTpl);
+  return EFI_SUCCESS;
+}
+
+/**
+  Configure password to supplicant before connecting to a secured network.
+
+  @param[in]  Nic                 Pointer to the device data of the selected NIC.
+  @param[in]  Profile             The target network to be connected.
+
+  @retval EFI_SUCCESS             The operation is completed.
+  @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+  @retval EFI_NOT_FOUND           No valid password is found to configure.
+  @retval Other Errors            Returned errors when setting data to supplicant.
+
+**/
+EFI_STATUS
+WifiMgrConfigPassword (
+  IN    WIFI_MGR_DEVICE_DATA              *Nic,
+  IN    WIFI_MGR_NETWORK_PROFILE          *Profile
+  )
+{
+  EFI_STATUS                 Status;
+  EFI_SUPPLICANT_PROTOCOL    *Supplicant;
+  EFI_80211_SSID             SSId;
+  UINT8                      *AsciiPassword;
+
+  if (Nic == NULL || Nic->Supplicant == NULL || Profile == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  Supplicant = Nic->Supplicant;
+  //
+  //Set SSId to supplicant
+  //
+  SSId.SSIdLen = Profile->Network.SSId.SSIdLen;
+  CopyMem(SSId.SSId, Profile->Network.SSId.SSId, sizeof (Profile->Network.SSId.SSId));
+  Status = Supplicant->SetData(Supplicant,EfiSupplicant80211TargetSSIDName,
+                         (VOID *)&SSId, sizeof(EFI_80211_SSID));
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  //
+  //Set password to supplicant
+  //
+  if (StrLen (Profile->Password) < PASSWORD_MIN_LEN) {
+    return EFI_NOT_FOUND;
+  }
+  AsciiPassword = AllocateZeroPool ((StrLen(Profile->Password) + 1) * sizeof (UINT8));
+  if (AsciiPassword == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  UnicodeStrToAsciiStrS (Profile->Password, (CHAR8 *) AsciiPassword, PASSWORD_STORAGE_SIZE);
+  Status = Supplicant->SetData (Supplicant, EfiSupplicant80211PskPassword,
+                         AsciiPassword, (StrLen(Profile->Password) + 1) * sizeof (UINT8));
+  ZeroMem (AsciiPassword, AsciiStrLen ((CHAR8 *) AsciiPassword) + 1);
+  FreePool(AsciiPassword);
+
+  return Status;
+}
+
+/**
+  Conduct EAP configuration to supplicant before connecting to a EAP network.
+  Current WiFi Connection Manager only supports three kinds of EAP networks:
+  1). EAP-TLS (Two-Way Authentication is required in our implementation)
+  2). EAP-TTLS/MSCHAPv2 (One-Way Authentication is required in our implementation)
+  3). PEAPv0/MSCHAPv2 (One-Way Authentication is required in our implementation)
+
+  @param[in]  Nic                 Pointer to the device data of the selected NIC.
+  @param[in]  Profile             The target network to be connected.
+
+  @retval EFI_SUCCESS             The operation is completed.
+  @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
+  @retval EFI_UNSUPPORTED         The expected EAP method is not supported.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+  @retval Other Errors            Returned errors when setting data to supplicant.
+
+**/
+EFI_STATUS
+WifiMgrConfigEap (
+  IN    WIFI_MGR_DEVICE_DATA              *Nic,
+  IN    WIFI_MGR_NETWORK_PROFILE          *Profile
+  )
+{
+  EFI_STATUS                        Status;
+  EFI_EAP_CONFIGURATION_PROTOCOL    *EapConfig;
+  EFI_EAP_TYPE                      EapAuthMethod;
+  EFI_EAP_TYPE                      EapSecondAuthMethod;
+  EFI_EAP_TYPE                      *AuthMethodList;
+  CHAR8                             *Identity;
+  UINTN                             IdentitySize;
+  CHAR16                            *Password;
+  UINTN                             PasswordSize;
+  UINTN                             EncryptPasswordLen;
+  CHAR8                             *AsciiEncryptPassword;
+  UINTN                             AuthMethodListSize;
+  UINTN                             Index;
+
+  if (Nic == NULL || Nic->EapConfig == NULL || Profile == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  EapConfig = Nic->EapConfig;
+
+  if (Profile->EapAuthMethod >= EAP_AUTH_METHOD_MAX) {
+    return EFI_INVALID_PARAMETER;
+  }
+  EapAuthMethod = mEapAuthMethod[Profile->EapAuthMethod];
+
+  if (EapAuthMethod != EFI_EAP_TYPE_EAPTLS) {
+    if (Profile->EapSecondAuthMethod >= EAP_SEAUTH_METHOD_MAX) {
+      return EFI_INVALID_PARAMETER;
+    }
+    EapSecondAuthMethod = mEapSecondAuthMethod[Profile->EapSecondAuthMethod];
+  }
+
+  //
+  //The first time to get Supported Auth Method list, return the size.
+  //
+  AuthMethodListSize  = 0;
+  AuthMethodList      = NULL;
+  Status = EapConfig->GetData (EapConfig, EFI_EAP_TYPE_ATTRIBUTE, EfiEapConfigEapSupportedAuthMethod,
+                        (VOID *) AuthMethodList, &AuthMethodListSize);
+  if (Status == EFI_SUCCESS) {
+    //
+    //No Supported Eap Auth Method
+    //
+    return EFI_UNSUPPORTED;
+  } else if (Status != EFI_BUFFER_TOO_SMALL) {
+    return Status;
+  }
+
+  //
+  // The second time to get Supported Auth Method list, return the list.
+  // In current design, only EAPTLS, TTLS and PEAP are supported
+  //
+  AuthMethodList = (EFI_EAP_TYPE *) AllocateZeroPool(AuthMethodListSize);
+  if (AuthMethodList == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  Status = EapConfig->GetData (EapConfig, EFI_EAP_TYPE_ATTRIBUTE, EfiEapConfigEapSupportedAuthMethod,
+                        (VOID *) AuthMethodList, &AuthMethodListSize);
+  if (EFI_ERROR (Status)) {
+    FreePool (AuthMethodList);
+    return Status;
+  }
+
+  //
+  //Check if EapAuthMethod is in supported Auth Method list, if found, skip the loop.
+  //
+  for (Index = 0; Index < AuthMethodListSize / sizeof (EFI_EAP_TYPE); Index ++) {
+    if (EapAuthMethod == AuthMethodList[Index]) {
+      break;
+    }
+  }
+  if (Index == AuthMethodListSize / sizeof (EFI_EAP_TYPE)) {
+    FreePool (AuthMethodList);
+    return EFI_UNSUPPORTED;
+  }
+  FreePool (AuthMethodList);
+
+  //
+  // Set Identity to Eap peer, Mandatory field for PEAP and TTLS
+  //
+  if (StrLen (Profile->EapIdentity) > 0) {
+
+    IdentitySize = sizeof(CHAR8) * (StrLen(Profile->EapIdentity) + 1);
+    Identity = AllocateZeroPool (IdentitySize);
+    if (Identity == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    UnicodeStrToAsciiStrS(Profile->EapIdentity, Identity, IdentitySize);
+    Status = EapConfig->SetData (EapConfig, EFI_EAP_TYPE_IDENTITY, EfiEapConfigIdentityString,
+                          (VOID *) Identity, IdentitySize - 1);
+    if (EFI_ERROR(Status)) {
+      FreePool (Identity);
+      return Status;
+    }
+    FreePool (Identity);
+  } else {
+    if (EapAuthMethod != EFI_EAP_TYPE_EAPTLS) {
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+
+  //
+  //Set Auth Method to Eap peer, Mandatory field
+  //
+  Status = EapConfig->SetData (EapConfig, EFI_EAP_TYPE_ATTRIBUTE, EfiEapConfigEapAuthMethod,
+                        (VOID *) &EapAuthMethod, sizeof (EapAuthMethod));
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  if (EapAuthMethod == EFI_EAP_TYPE_TTLS || EapAuthMethod == EFI_EAP_TYPE_PEAP) {
+
+    Status = EapConfig->SetData (EapConfig, EapAuthMethod, EfiEapConfigEap2ndAuthMethod,
+                          (VOID *) &EapSecondAuthMethod, sizeof (EapSecondAuthMethod));
+    if (EFI_ERROR(Status)) {
+      return Status;
+    }
+
+    //
+    // Set Password to Eap peer
+    //
+    if (StrLen (Profile->EapPassword) < PASSWORD_MIN_LEN) {
+
+      DEBUG ((DEBUG_ERROR, "[WiFi Connection Manager] Error: No Eap Password for Network: %s.\n", Profile->SSId));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    PasswordSize = sizeof (CHAR16) * (StrLen (Profile->EapPassword) + 1);
+    Password = AllocateZeroPool (PasswordSize);
+    if (Password == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    StrCpyS (Password, PasswordSize, Profile->EapPassword);;
+    Status = EapConfig->SetData (EapConfig, EFI_EAP_TYPE_MSCHAPV2, EfiEapConfigEapMSChapV2Password,
+               (VOID *) Password, PasswordSize);
+    ZeroMem (Password, PasswordSize);
+    FreePool (Password);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    //
+    //If CA cert is required, set it to Eap peer
+    //
+    if (Profile->CACertData != NULL) {
+
+      Status = EapConfig->SetData (EapConfig, EapAuthMethod, EfiEapConfigEapTlsCACert,
+                 Profile->CACertData, Profile->CACertSize);
+      if (EFI_ERROR(Status)) {
+        return Status;
+      }
+    } else {
+      return EFI_INVALID_PARAMETER;
+    }
+  } else if (EapAuthMethod == EFI_EAP_TYPE_EAPTLS) {
+
+    //
+    //Set CA cert to Eap peer
+    //
+    if (Profile->CACertData == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+    Status = EapConfig->SetData (EapConfig, EFI_EAP_TYPE_EAPTLS, EfiEapConfigEapTlsCACert,
+               Profile->CACertData, Profile->CACertSize);
+    if (EFI_ERROR(Status)) {
+      return Status;
+    }
+
+    //
+    //Set Client cert to Eap peer
+    //
+    if (Profile->ClientCertData == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+    Status = EapConfig->SetData (EapConfig, EFI_EAP_TYPE_EAPTLS, EfiEapConfigEapTlsClientCert,
+               Profile->ClientCertData, Profile->ClientCertSize);
+    if (EFI_ERROR(Status)) {
+      return Status;
+    }
+
+    //
+    //Set Private key to Eap peer
+    //
+    if (Profile->PrivateKeyData == NULL) {
+
+      DEBUG ((DEBUG_ERROR, "[WiFi Connection Manager]  Error: No Private Key for Network: %s.\n", Profile->SSId));
+      return EFI_INVALID_PARAMETER;
+    }
+
+    Status = EapConfig->SetData (EapConfig, EFI_EAP_TYPE_EAPTLS, EfiEapConfigEapTlsClientPrivateKeyFile,
+               Profile->PrivateKeyData, Profile->PrivateKeyDataSize);
+    if (EFI_ERROR(Status)) {
+      return Status;
+    }
+
+    if (StrLen (Profile->PrivateKeyPassword) > 0) {
+
+      EncryptPasswordLen = StrLen (Profile->PrivateKeyPassword);
+      AsciiEncryptPassword = AllocateZeroPool(EncryptPasswordLen + 1);
+      if (AsciiEncryptPassword == NULL) {
+        return EFI_OUT_OF_RESOURCES;
+      }
+      UnicodeStrToAsciiStrS(Profile->PrivateKeyPassword, AsciiEncryptPassword, EncryptPasswordLen + 1);
+      Status = EapConfig->SetData(EapConfig, EFI_EAP_TYPE_EAPTLS,
+                                    EfiEapConfigEapTlsClientPrivateKeyFilePassword,
+                                    (VOID *) AsciiEncryptPassword, EncryptPasswordLen + 1);
+      if (EFI_ERROR(Status)) {
+
+        ZeroMem (AsciiEncryptPassword, EncryptPasswordLen + 1);
+        FreePool (AsciiEncryptPassword);
+        return Status;
+      }
+
+      ZeroMem (AsciiEncryptPassword, EncryptPasswordLen + 1);
+      FreePool (AsciiEncryptPassword);
+    }
+  } else {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get current link state from low layer.
+
+  @param[in]   Nic                Pointer to the device data of the selected NIC.
+  @param[out]  LinkState          The pointer to buffer to retrieve link state.
+
+  @retval EFI_SUCCESS             The operation is completed.
+  @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
+  @retval EFI_UNSUPPORTED         Adapter information protocol is not supported.
+  @retval Other Errors            Returned errors when retrieving link state from low layer.
+
+**/
+EFI_STATUS
+WifiMgrGetLinkState (
+  IN   WIFI_MGR_DEVICE_DATA            *Nic,
+  OUT  EFI_ADAPTER_INFO_MEDIA_STATE    *LinkState
+  )
+{
+  EFI_STATUS                           Status;
+  EFI_TPL                              OldTpl;
+  UINTN                                DataSize;
+  EFI_ADAPTER_INFO_MEDIA_STATE         *UndiState;
+  EFI_ADAPTER_INFORMATION_PROTOCOL     *Aip;
+
+  if (Nic == NULL || LinkState == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+  Status = gBS->OpenProtocol (
+                  Nic->ControllerHandle,
+                  &gEfiAdapterInformationProtocolGuid,
+                  (VOID**) &Aip,
+                  Nic->DriverHandle,
+                  Nic->ControllerHandle,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    gBS->RestoreTPL (OldTpl);
+    return EFI_UNSUPPORTED;
+  }
+
+  Status = Aip->GetInformation(
+                  Aip,
+                  &gEfiAdapterInfoMediaStateGuid,
+                  (VOID **) &UndiState,
+                  &DataSize
+                  );
+  if (EFI_ERROR (Status)) {
+    gBS->RestoreTPL (OldTpl);
+    return Status;
+  }
+  gBS->RestoreTPL (OldTpl);
+
+  CopyMem (LinkState, UndiState, sizeof (EFI_ADAPTER_INFO_MEDIA_STATE));
+  FreePool (UndiState);
+  return EFI_SUCCESS;
+}
+
+/**
+  Prepare configuration work before connecting to the target network.
+  For WPA2 Personal networks, password should be checked; and for EAP networks, parameters
+  are different for different networks.
+
+  @param[in]  Nic                 Pointer to the device data of the selected NIC.
+  @param[in]  Profile             The target network to be connected.
+
+  @retval EFI_SUCCESS             The operation is completed.
+  @retval EFI_UNSUPPORTED         This network is not supported.
+  @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
+
+**/
+EFI_STATUS
+WifiMgrPrepareConnection (
+  IN    WIFI_MGR_DEVICE_DATA              *Nic,
+  IN    WIFI_MGR_NETWORK_PROFILE          *Profile
+  )
+{
+  EFI_STATUS           Status;
+  UINT8                SecurityType;
+  BOOLEAN              AKMSuiteSupported;
+  BOOLEAN              CipherSuiteSupported;
+
+  if (Profile == NULL || Nic == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = WifiMgrCheckRSN (Profile->Network.AKMSuite, Profile->Network.CipherSuite,
+             Nic, &SecurityType, &AKMSuiteSupported, &CipherSuiteSupported);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  if (AKMSuiteSupported && CipherSuiteSupported) {
+    switch (SecurityType) {
+      case SECURITY_TYPE_WPA2_PERSONAL:
+
+        Status = WifiMgrConfigPassword (Nic, Profile);
+        if (EFI_ERROR (Status)) {
+          if (Status == EFI_NOT_FOUND) {
+            if (Nic->OneTimeConnectRequest) {
+              WifiMgrUpdateConnectMessage (Nic, FALSE, L"Connect Failed: Invalid Password!");
+            }
+          }
+          return Status;
+        }
+        break;
+
+      case SECURITY_TYPE_WPA2_ENTERPRISE:
+
+        Status = WifiMgrConfigEap (Nic, Profile);
+        if (EFI_ERROR (Status)) {
+          if (Status == EFI_INVALID_PARAMETER) {
+            if (Nic->OneTimeConnectRequest) {
+              WifiMgrUpdateConnectMessage (Nic, FALSE, L"Connect Failed: Invalid Configuration!");
+            }
+          }
+          return Status;
+        }
+        break;
+
+      case SECURITY_TYPE_NONE:
+        break;
+
+      default:
+        return EFI_UNSUPPORTED;
+    }
+  } else {
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  The callback function for connect operation.
+
+  ASSERT when errors occur in config token.
+
+  @param[in]  Event                 The Connect token receive event.
+  @param[in]  Context               The context of the connect token.
+
+**/
+VOID
+EFIAPI
+WifiMgrOnConnectFinished (
+  IN  EFI_EVENT              Event,
+  IN  VOID                   *Context
+  )
+{
+  EFI_STATUS                         Status;
+  WIFI_MGR_MAC_CONFIG_TOKEN          *ConfigToken;
+  WIFI_MGR_NETWORK_PROFILE           *ConnectedProfile;
+  UINT8                              SecurityType;
+  UINT8                              SSIdLen;
+  CHAR8                              *AsciiSSId;
+
+  ASSERT (Context != NULL);
+
+  ConnectedProfile = NULL;
+  ConfigToken = (WIFI_MGR_MAC_CONFIG_TOKEN*) Context;
+  ASSERT (ConfigToken->Nic != NULL);
+
+  ConfigToken->Nic->ConnectState = WifiMgrDisconnected;
+  ASSERT (ConfigToken->Type == TokenTypeConnectNetworkToken);
+
+  ASSERT (ConfigToken->Token.ConnectNetworkToken != NULL);
+  if (ConfigToken->Token.ConnectNetworkToken->Status != EFI_SUCCESS) {
+
+    if (ConfigToken->Nic->OneTimeConnectRequest) {
+      //
+      // Only update message for user triggered connection
+      //
+      if (ConfigToken->Token.ConnectNetworkToken->Status == EFI_ACCESS_DENIED) {
+
+        WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, L"Connect Failed: Permission Denied!");
+      } else {
+        WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, L"Connect Failed!");
+      }
+      ConfigToken->Nic->OneTimeConnectRequest = FALSE;
+    }
+    ConfigToken->Nic->CurrentOperateNetwork = NULL;
+    return;
+  }
+
+  if (ConfigToken->Token.ConnectNetworkToken->ResultCode != ConnectSuccess) {
+
+    if (ConfigToken->Nic->OneTimeConnectRequest) {
+
+      if (ConfigToken->Token.ConnectNetworkToken->ResultCode == ConnectFailedReasonUnspecified) {
+        WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, L"Connect Failed: Wrong Password or Unexpected Error!");
+      } else {
+        WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, L"Connect Failed!");
+      }
+    }
+    goto Exit;
+  }
+
+  if (ConfigToken->Token.ConnectNetworkToken->Data == NULL ||
+    ConfigToken->Token.ConnectNetworkToken->Data->Network == NULL) {
+
+    //
+    // An unexpected error occurs, tell low layer to perform a disconnect
+    //
+    ConfigToken->Nic->HasDisconnectPendingNetwork = TRUE;
+    WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);
+    goto Exit;
+  }
+
+  //
+  // A correct connect token received, terminate the connection process
+  //
+  Status = WifiMgrCheckRSN(ConfigToken->Token.ConnectNetworkToken->Data->Network->AKMSuite,
+             ConfigToken->Token.ConnectNetworkToken->Data->Network->CipherSuite,
+             ConfigToken->Nic, &SecurityType, NULL, NULL);
+  if (EFI_ERROR(Status)) {
+    SecurityType = SECURITY_TYPE_UNKNOWN;
+  }
+
+  SSIdLen   = ConfigToken->Token.ConnectNetworkToken->Data->Network->SSId.SSIdLen;
+  AsciiSSId = (CHAR8*) AllocateZeroPool(sizeof (CHAR8) * (SSIdLen + 1));
+  if (AsciiSSId == NULL) {
+    ConfigToken->Nic->HasDisconnectPendingNetwork = TRUE;
+    WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);
+    goto Exit;
+  }
+
+  CopyMem(AsciiSSId, ConfigToken->Token.ConnectNetworkToken->Data->Network->SSId.SSId, SSIdLen);
+  *(AsciiSSId + SSIdLen) = '\0';
+
+  ConnectedProfile = WifiMgrGetProfileByAsciiSSId(AsciiSSId, SecurityType, &ConfigToken->Nic->ProfileList);
+  FreePool(AsciiSSId);
+  if (ConnectedProfile == NULL) {
+    ConfigToken->Nic->HasDisconnectPendingNetwork = TRUE;
+    WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);
+    goto Exit;
+  }
+
+  ConfigToken->Nic->ConnectState = WifiMgrConnectedToAp;
+  WifiMgrUpdateConnectMessage (ConfigToken->Nic, TRUE, NULL);
+
+Exit:
+
+  if (ConfigToken->Nic->ConnectState == WifiMgrDisconnected) {
+    ConfigToken->Nic->CurrentOperateNetwork = NULL;
+  }
+  ConfigToken->Nic->OneTimeConnectRequest = FALSE;
+  WifiMgrFreeToken(ConfigToken);
+}
+
+/**
+  Start connect operation, and send out a token to connect to a target network.
+
+  @param[in]  Nic                 Pointer to the device data of the selected NIC.
+  @param[in]  Profile             The target network to be connected.
+
+  @retval EFI_SUCCESS             The operation is completed.
+  @retval EFI_ALREADY_STARTED     Already in "connected" state, need to perform a disconnect
+                                  operation first.
+  @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+  @retval Other Errors            Return errors when connecting network on low layer.
+
+**/
+EFI_STATUS
+WifiMgrConnectToNetwork (
+  IN    WIFI_MGR_DEVICE_DATA              *Nic,
+  IN    WIFI_MGR_NETWORK_PROFILE          *Profile
+  )
+{
+  EFI_STATUS                             Status;
+  EFI_TPL                                OldTpl;
+  EFI_ADAPTER_INFO_MEDIA_STATE           LinkState;
+  WIFI_MGR_MAC_CONFIG_TOKEN              *ConfigToken;
+  EFI_80211_CONNECT_NETWORK_TOKEN        *ConnectToken;
+
+  if (Nic == NULL || Nic->Wmp == NULL || Profile == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = WifiMgrGetLinkState (Nic, &LinkState);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  if (LinkState.MediaState == EFI_SUCCESS) {
+    return EFI_ALREADY_STARTED;
+  }
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+  Status = WifiMgrPrepareConnection (Nic, Profile);
+  if (EFI_ERROR (Status)) {
+    gBS->RestoreTPL (OldTpl);
+    return Status;
+  }
+
+  //
+  // Create a new connect token
+  //
+  ConfigToken = AllocateZeroPool (sizeof (WIFI_MGR_MAC_CONFIG_TOKEN));
+  if (ConfigToken == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  ConfigToken->Type      = TokenTypeConnectNetworkToken;
+  ConfigToken->Nic       = Nic;
+  ConfigToken->Token.ConnectNetworkToken  = AllocateZeroPool (sizeof (EFI_80211_CONNECT_NETWORK_TOKEN));
+  if (ConfigToken->Token.ConnectNetworkToken == NULL) {
+    goto Exit;
+  }
+
+  ConnectToken           = ConfigToken->Token.ConnectNetworkToken;
+  ConnectToken->Data     = AllocateZeroPool (sizeof (EFI_80211_CONNECT_NETWORK_DATA));
+  if (ConnectToken->Data == NULL) {
+    goto Exit;
+  }
+
+  ConnectToken->Data->Network = AllocateZeroPool (sizeof (EFI_80211_NETWORK));
+  if (ConnectToken->Data->Network == NULL) {
+    goto Exit;
+  }
+  CopyMem(ConnectToken->Data->Network, &Profile->Network, sizeof (EFI_80211_NETWORK));
+
+  //
+  // Add event handle and start to connect
+  //
+  Status = gBS->CreateEvent (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  WifiMgrOnConnectFinished,
+                  ConfigToken,
+                  &ConnectToken->Event
+                  );
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  Nic->ConnectState = WifiMgrConnectingToAp;
+  Nic->CurrentOperateNetwork = Profile;
+  WifiMgrUpdateConnectMessage (Nic, FALSE, NULL);
+
+  //
+  //Start Connecting ...
+  //
+  Status = Nic->Wmp->ConnectNetwork (Nic->Wmp, ConnectToken);
+
+  //
+  // Erase secrets after connection is triggered
+  //
+  WifiMgrCleanProfileSecrets (Profile);
+
+  if (EFI_ERROR (Status)) {
+    if (Status == EFI_ALREADY_STARTED) {
+      Nic->ConnectState = WifiMgrConnectedToAp;
+      WifiMgrUpdateConnectMessage (Nic, TRUE, NULL);
+    } else {
+
+      Nic->ConnectState          = WifiMgrDisconnected;
+      Nic->CurrentOperateNetwork = NULL;
+
+      if (Nic->OneTimeConnectRequest) {
+        if (Status == EFI_NOT_FOUND) {
+          WifiMgrUpdateConnectMessage (Nic, FALSE, L"Connect Failed: Not Available!");
+        } else {
+          WifiMgrUpdateConnectMessage (Nic, FALSE, L"Connect Failed: Unexpected Error!");
+        }
+      }
+    }
+    goto Exit;
+  }
+
+Exit:
+
+  if (EFI_ERROR (Status)) {
+    WifiMgrFreeToken (ConfigToken);
+  }
+  gBS->RestoreTPL (OldTpl);
+
+  DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] WifiMgrConnectToNetwork: %r\n", Status));
+  return Status;
+}
+
+/**
+  The callback function for disconnect operation.
+
+  ASSERT when errors occur in config token.
+
+  @param[in]  Event                 The Disconnect token receive event.
+  @param[in]  Context               The context of the Disconnect token.
+
+**/
+VOID
+EFIAPI
+WifiMgrOnDisconnectFinished (
+  IN EFI_EVENT              Event,
+  IN VOID                   *Context
+  )
+{
+  WIFI_MGR_MAC_CONFIG_TOKEN         *ConfigToken;
+
+  ASSERT (Context != NULL);
+
+  ConfigToken = (WIFI_MGR_MAC_CONFIG_TOKEN*) Context;
+  ASSERT (ConfigToken->Nic != NULL);
+  ASSERT (ConfigToken->Type == TokenTypeDisconnectNetworkToken);
+
+  ASSERT (ConfigToken->Token.DisconnectNetworkToken != NULL);
+  if (ConfigToken->Token.DisconnectNetworkToken->Status != EFI_SUCCESS) {
+    ConfigToken->Nic->ConnectState          = WifiMgrConnectedToAp;
+    WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);
+    ConfigToken->Nic->OneTimeDisconnectRequest = FALSE;
+    goto Exit;
+  }
+
+  ConfigToken->Nic->ConnectState          = WifiMgrDisconnected;
+  ConfigToken->Nic->CurrentOperateNetwork = NULL;
+  WifiMgrUpdateConnectMessage (ConfigToken->Nic, TRUE, NULL);
+  ConfigToken->Nic->OneTimeDisconnectRequest = FALSE;
+
+  //
+  // Disconnected network may not be in network list now, trigger a scan again!
+  //
+  ConfigToken->Nic->OneTimeScanRequest       = TRUE;
+
+  Exit:
+    WifiMgrFreeToken(ConfigToken);
+    return;
+}
+
+/**
+  Start disconnect operation, and send out a token to disconnect from current connected
+  network.
+
+  @param[in]  Nic                 Pointer to the device data of the selected NIC.
+
+  @retval EFI_SUCCESS             The operation is completed.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+  @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
+  @retval Other Errors            Return errors when disconnecting a network on low layer.
+
+**/
+EFI_STATUS
+WifiMgrDisconnectToNetwork (
+  IN    WIFI_MGR_DEVICE_DATA             *Nic
+  )
+{
+  EFI_STATUS                             Status;
+  EFI_TPL                                OldTpl;
+  WIFI_MGR_MAC_CONFIG_TOKEN              *ConfigToken;
+  EFI_80211_DISCONNECT_NETWORK_TOKEN     *DisconnectToken;
+
+  if (Nic == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OldTpl      = gBS->RaiseTPL (TPL_CALLBACK);
+  Status      = EFI_SUCCESS;
+  ConfigToken = AllocateZeroPool (sizeof (WIFI_MGR_MAC_CONFIG_TOKEN));
+  if (ConfigToken == NULL) {
+    gBS->RestoreTPL (OldTpl);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  ConfigToken->Type      = TokenTypeDisconnectNetworkToken;
+  ConfigToken->Nic       = Nic;
+  ConfigToken->Token.DisconnectNetworkToken = AllocateZeroPool (sizeof (EFI_80211_DISCONNECT_NETWORK_TOKEN));
+  if (ConfigToken->Token.DisconnectNetworkToken == NULL) {
+    WifiMgrFreeToken(ConfigToken);
+    gBS->RestoreTPL (OldTpl);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  DisconnectToken = ConfigToken->Token.DisconnectNetworkToken;
+
+  Status = gBS->CreateEvent (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  WifiMgrOnDisconnectFinished,
+                  ConfigToken,
+                  &DisconnectToken->Event
+                  );
+  if (EFI_ERROR (Status)) {
+    WifiMgrFreeToken(ConfigToken);
+    gBS->RestoreTPL (OldTpl);
+    return Status;
+  }
+
+  Nic->ConnectState = WifiMgrDisconnectingToAp;
+  WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);
+
+  Status = Nic->Wmp->DisconnectNetwork (Nic->Wmp, DisconnectToken);
+  if (EFI_ERROR (Status)) {
+    if (Status == EFI_NOT_FOUND) {
+
+      Nic->ConnectState          = WifiMgrDisconnected;
+      Nic->CurrentOperateNetwork = NULL;
+
+      //
+      // This network is not in network list now, trigger a scan again!
+      //
+      Nic->OneTimeScanRequest    = TRUE;
+
+      //
+      // State has been changed from Connected to Disconnected
+      //
+      WifiMgrUpdateConnectMessage (ConfigToken->Nic, TRUE, NULL);
+      Status                     = EFI_SUCCESS;
+    } else {
+      if (Nic->OneTimeDisconnectRequest) {
+
+        WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, L"Disconnect Failed: Unexpected Error!");
+      }
+
+      Nic->ConnectState     = WifiMgrConnectedToAp;
+      WifiMgrUpdateConnectMessage (ConfigToken->Nic, FALSE, NULL);
+    }
+    WifiMgrFreeToken(ConfigToken);
+  }
+
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+}
+
+/**
+  The state machine of the connection manager, periodically check the state and
+  perform a corresponding operation.
+
+  @param[in]  Event                   The timer event to be triggered.
+  @param[in]  Context                 The context of the Nic device data.
+
+**/
+VOID
+EFIAPI
+WifiMgrOnTimerTick (
+  IN EFI_EVENT                        Event,
+  IN VOID                             *Context
+  )
+{
+  WIFI_MGR_DEVICE_DATA                *Nic;
+  EFI_STATUS                          Status;
+  EFI_ADAPTER_INFO_MEDIA_STATE        LinkState;
+  WIFI_MGR_NETWORK_PROFILE            *Profile;
+
+  if (Context == NULL) {
+    return;
+  }
+
+  Nic = (WIFI_MGR_DEVICE_DATA*) Context;
+  NET_CHECK_SIGNATURE (Nic, WIFI_MGR_DEVICE_DATA_SIGNATURE);
+
+  Status = WifiMgrGetLinkState (Nic, &LinkState);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] Error: Failed to get link state!\n"));
+    return;
+  }
+
+  if (Nic->LastLinkState.MediaState != LinkState.MediaState) {
+    if (Nic->LastLinkState.MediaState == EFI_SUCCESS && LinkState.MediaState == EFI_NO_MEDIA) {
+      Nic->HasDisconnectPendingNetwork = TRUE;
+    }
+    Nic->LastLinkState.MediaState = LinkState.MediaState;
+  }
+
+  Nic->ScanTickTime ++;
+  if ((Nic->ScanTickTime > WIFI_SCAN_FREQUENCY || Nic->OneTimeScanRequest) &&
+    Nic->ScanState == WifiMgrScanFinished) {
+
+    Nic->OneTimeScanRequest = FALSE;
+    Nic->ScanTickTime = 0;
+
+    DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] Scan is triggered.\n"));
+    WifiMgrStartScan (Nic);
+  }
+
+  if (Nic->AvailableCount > 0 && Nic->ScanState == WifiMgrScanFinished) {
+
+    switch (Nic->ConnectState) {
+    case WifiMgrDisconnected:
+
+      if (Nic->HasDisconnectPendingNetwork) {
+        Nic->HasDisconnectPendingNetwork = FALSE;
+      }
+
+      if (Nic->ConnectPendingNetwork != NULL) {
+
+        Profile   = Nic->ConnectPendingNetwork;
+        Status    = WifiMgrConnectToNetwork(Nic, Profile);
+        Nic->ConnectPendingNetwork = NULL;
+        if (EFI_ERROR (Status)) {
+          //
+          // Some error happened, don't wait for a return connect token!
+          //
+          Nic->OneTimeConnectRequest = FALSE;
+        }
+      }
+      break;
+
+    case WifiMgrConnectingToAp:
+      break;
+
+    case WifiMgrDisconnectingToAp:
+      break;
+
+    case WifiMgrConnectedToAp:
+
+      if (Nic->ConnectPendingNetwork != NULL || Nic->HasDisconnectPendingNetwork) {
+
+        Status    = WifiMgrDisconnectToNetwork(Nic);
+        if (EFI_ERROR (Status)) {
+          //
+          // Some error happened, don't wait for a return disconnect token!
+          //
+          Nic->OneTimeDisconnectRequest = FALSE;
+        }
+      }
+      break;
+
+    default:
+      break;
+    }
+  }
+}
diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrImpl.h b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrImpl.h
new file mode 100644
index 0000000000..f742db05ca
--- /dev/null
+++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrImpl.h
@@ -0,0 +1,105 @@
+/** @file
+  The Mac Connection2 Protocol adapter functions for WiFi Connection Manager.
+
+  Copyright (c) 2019, 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.
+
+**/
+
+#ifndef __EFI_WIFI_IMPL__
+#define __EFI_WIFI_IMPL__
+
+/**
+  Start scan operation, and send out a token to collect available networks.
+
+  @param[in]  Nic                 Pointer to the device data of the selected NIC.
+
+  @retval EFI_SUCCESS             The operation is completed.
+  @retval EFI_ALREADY_STARTED     A former scan operation is already ongoing.
+  @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+  @retval Other Errors            Return errors when getting networks from low layer.
+
+**/
+EFI_STATUS
+WifiMgrStartScan (
+  IN      WIFI_MGR_DEVICE_DATA        *Nic
+  );
+
+/**
+  Get current link state from low layer.
+
+  @param[in]   Nic                Pointer to the device data of the selected NIC.
+  @param[out]  LinkState          The pointer to buffer to retrieve link state.
+
+  @retval EFI_SUCCESS             The operation is completed.
+  @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
+  @retval EFI_UNSUPPORTED         Adapter information protocol is not supported.
+  @retval Other Errors            Returned errors when retrieving link state from low layer.
+
+**/
+EFI_STATUS
+WifiMgrGetLinkState (
+  IN    WIFI_MGR_DEVICE_DATA          *Nic,
+  OUT   EFI_ADAPTER_INFO_MEDIA_STATE  *LinkState
+  );
+
+/**
+  Start connect operation, and send out a token to connect to a target network.
+
+  @param[in]  Nic                 Pointer to the device data of the selected NIC.
+  @param[in]  Profile             The target network to be connected.
+
+  @retval EFI_SUCCESS             The operation is completed.
+  @retval EFI_ALREADY_STARTED     Already in "connected" state, need to perform a disconnect
+                                  operation first.
+  @retval EFI_INVALID_PARAMETER   One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+  @retval Other Errors            Return errors when connecting network on low layer.
+
+**/
+EFI_STATUS
+WifiMgrConnectToNetwork (
+  IN    WIFI_MGR_DEVICE_DATA              *Nic,
+  IN    WIFI_MGR_NETWORK_PROFILE          *Profile
+  );
+
+/**
+  Start disconnect operation, and send out a token to disconnect from current connected
+  network.
+
+  @param[in]  Nic                 Pointer to the device data of the selected NIC.
+
+  @retval EFI_SUCCESS             The operation is completed.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+  @retval Other Errors            Return errors when disconnecting a network on low layer.
+
+**/
+EFI_STATUS
+WifiMgrDisconnectToNetwork (
+  IN    WIFI_MGR_DEVICE_DATA              *Nic
+  );
+
+/**
+  The state machine of the connection manager, periodically check the state and
+  perform a corresponding operation.
+
+  @param[in]  Event                   The timer event to be triggered.
+  @param[in]  Context                 The context of the Nic device data.
+
+**/
+VOID
+EFIAPI
+WifiMgrOnTimerTick (
+  IN EFI_EVENT              Event,
+  IN VOID                   *Context
+  );
+
+#endif
diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrMisc.c b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrMisc.c
new file mode 100644
index 0000000000..baac907048
--- /dev/null
+++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrMisc.c
@@ -0,0 +1,750 @@
+/** @file
+  The Miscellaneous Routines for WiFi Connection Manager.
+
+  Copyright (c) 2019, 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 "WifiConnectionMgrDxe.h"
+
+/**
+  Empty function for event process function.
+
+  @param Event    The Event need to be process
+  @param Context  The context of the event.
+
+**/
+VOID
+EFIAPI
+WifiMgrInternalEmptyFunction (
+  IN  EFI_EVENT    Event,
+  IN  VOID         *Context
+  )
+{
+  return;
+}
+
+/**
+  Convert the mac address into a hexadecimal encoded ":" seperated string.
+
+  @param[in]  Mac     The mac address.
+  @param[in]  StrSize The size, in bytes, of the output buffer specified by Str.
+  @param[out] Str     The storage to return the mac string.
+
+**/
+VOID
+WifiMgrMacAddrToStr (
+  IN  EFI_80211_MAC_ADDRESS  *Mac,
+  IN  UINT32                 StrSize,
+  OUT CHAR16                 *Str
+  )
+{
+  if (Mac == NULL || Str == NULL) {
+    return;
+  }
+
+  UnicodeSPrint (
+    Str,
+    StrSize,
+    L"%02X:%02X:%02X:%02X:%02X:%02X",
+    Mac->Addr[0], Mac->Addr[1], Mac->Addr[2],
+    Mac->Addr[3], Mac->Addr[4], Mac->Addr[5]
+    );
+}
+
+/**
+  Read private key file to buffer.
+
+  @param[in]   FileContext           The file context of private key file.
+  @param[out]  PrivateKeyDataAddr    The buffer address to restore private key file, should be
+                                     freed by caller.
+  @param[out]  PrivateKeyDataSize    The size of read private key file.
+
+  @retval EFI_SUCCESS                Successfully read the private key file.
+  @retval EFI_INVALID_PARAMETER      One or more of the parameters is invalid.
+
+**/
+EFI_STATUS
+WifiMgrReadFileToBuffer (
+  IN   WIFI_MGR_FILE_CONTEXT          *FileContext,
+  OUT  VOID                           **DataAddr,
+  OUT  UINTN                          *DataSize
+  )
+{
+  EFI_STATUS    Status;
+
+  if (FileContext != NULL && FileContext->FHandle != NULL) {
+
+    Status = ReadFileContent (
+               FileContext->FHandle,
+               DataAddr,
+               DataSize,
+               0
+               );
+
+    if (FileContext->FHandle != NULL) {
+      FileContext->FHandle->Close (FileContext->FHandle);
+    }
+    FileContext->FHandle = NULL;
+    return Status;
+  }
+
+  return EFI_INVALID_PARAMETER;
+}
+
+/**
+  Get the Nic data by the NicIndex.
+
+  @param[in]  Private        The pointer to the global private data structure.
+  @param[in]  NicIndex       The index indicates the position of wireless NIC.
+
+  @return     Pointer to the Nic data, or NULL if not found.
+
+**/
+WIFI_MGR_DEVICE_DATA *
+WifiMgrGetNicByIndex (
+  IN WIFI_MGR_PRIVATE_DATA   *Private,
+  IN UINT32                  NicIndex
+  )
+{
+  LIST_ENTRY             *Entry;
+  WIFI_MGR_DEVICE_DATA   *Nic;
+
+  if (Private == NULL) {
+    return NULL;
+  }
+
+  NET_LIST_FOR_EACH (Entry, &Private->NicList) {
+    Nic = NET_LIST_USER_STRUCT_S (Entry, WIFI_MGR_DEVICE_DATA,
+            Link, WIFI_MGR_DEVICE_DATA_SIGNATURE);
+    if (Nic->NicIndex == NicIndex) {
+      return Nic;
+    }
+  }
+
+  return NULL;
+}
+
+/**
+  Find a network profile through its' SSId and securit type, and the SSId is an unicode string.
+
+  @param[in]  SSId                   The target network's SSId.
+  @param[in]  SecurityType           The target network's security type.
+  @param[in]  ProfileList            The profile list on a Nic.
+
+  @return Pointer to a network profile, or NULL if not found.
+
+**/
+WIFI_MGR_NETWORK_PROFILE *
+WifiMgrGetProfileByUnicodeSSId (
+  IN  CHAR16                         *SSId,
+  IN  UINT8                          SecurityType,
+  IN  LIST_ENTRY                     *ProfileList
+  )
+{
+  LIST_ENTRY                         *Entry;
+  WIFI_MGR_NETWORK_PROFILE           *Profile;
+
+  if (SSId == NULL || ProfileList == NULL) {
+    return NULL;
+  }
+
+  NET_LIST_FOR_EACH (Entry, ProfileList) {
+    Profile = NET_LIST_USER_STRUCT_S (Entry, WIFI_MGR_NETWORK_PROFILE,
+                Link, WIFI_MGR_PROFILE_SIGNATURE);
+    if (StrCmp (SSId, Profile->SSId) == 0 && SecurityType == Profile->SecurityType) {
+      return Profile;
+    }
+  }
+
+  return NULL;
+}
+
+/**
+  Find a network profile through its' SSId and securit type, and the SSId is an ascii string.
+
+  @param[in]  SSId               The target network's SSId.
+  @param[in]  SecurityType       The target network's security type.
+  @param[in]  ProfileList        The profile list on a Nic.
+
+  @return Pointer to a network profile, or NULL if not found.
+
+**/
+WIFI_MGR_NETWORK_PROFILE *
+WifiMgrGetProfileByAsciiSSId (
+  IN  CHAR8                      *SSId,
+  IN  UINT8                      SecurityType,
+  IN  LIST_ENTRY                 *ProfileList
+  )
+{
+  CHAR16   SSIdUniCode[SSID_STORAGE_SIZE];
+
+  if (SSId == NULL) {
+    return NULL;
+  }
+  if (AsciiStrToUnicodeStrS (SSId, SSIdUniCode, SSID_STORAGE_SIZE) != RETURN_SUCCESS) {
+    return NULL;
+  }
+
+  return WifiMgrGetProfileByUnicodeSSId (SSIdUniCode, SecurityType, ProfileList);
+}
+
+/**
+  Find a network profile through its' profile index.
+
+  @param[in]  ProfileIndex           The target network's profile index.
+  @param[in]  ProfileList            The profile list on a Nic.
+
+  @return Pointer to a network profile, or NULL if not found.
+
+**/
+WIFI_MGR_NETWORK_PROFILE *
+WifiMgrGetProfileByProfileIndex (
+  IN  UINT32                         ProfileIndex,
+  IN  LIST_ENTRY                     *ProfileList
+  )
+{
+  WIFI_MGR_NETWORK_PROFILE           *Profile;
+  LIST_ENTRY                         *Entry;
+
+  if (ProfileList == NULL) {
+    return NULL;
+  }
+  NET_LIST_FOR_EACH (Entry, ProfileList) {
+    Profile = NET_LIST_USER_STRUCT_S (Entry, WIFI_MGR_NETWORK_PROFILE,
+                Link, WIFI_MGR_PROFILE_SIGNATURE);
+    if (Profile->ProfileIndex == ProfileIndex) {
+      return Profile;
+    }
+  }
+  return NULL;
+}
+
+/**
+  To test if the AKMSuite is in supported AKMSuite list.
+
+  @param[in]  SupportedAKMSuiteCount       The count of the supported AKMSuites.
+  @param[in]  SupportedAKMSuiteList        The supported AKMSuite list.
+  @param[in]  AKMSuite                     The AKMSuite to be tested.
+
+  @return True if this AKMSuite is supported, or False if not.
+
+**/
+BOOLEAN
+WifiMgrSupportAKMSuite (
+  IN  UINT16                               SupportedAKMSuiteCount,
+  IN  UINT32                               *SupportedAKMSuiteList,
+  IN  UINT32                               *AKMSuite
+  )
+{
+  UINT16    Index;
+
+  if (AKMSuite == NULL || SupportedAKMSuiteList == NULL ||
+    SupportedAKMSuiteCount == 0) {
+    return FALSE;
+  }
+
+  for (Index = 0; Index < SupportedAKMSuiteCount; Index ++) {
+    if (SupportedAKMSuiteList[Index] == *AKMSuite) {
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+/**
+  To check if the CipherSuite is in supported CipherSuite list.
+
+  @param[in]  SupportedCipherSuiteCount       The count of the supported CipherSuites.
+  @param[in]  SupportedCipherSuiteList        The supported CipherSuite list.
+  @param[in]  CipherSuite                     The CipherSuite to be tested.
+
+  @return True if this CipherSuite is supported, or False if not.
+
+**/
+BOOLEAN
+WifiMgrSupportCipherSuite (
+  IN  UINT16                                  SupportedCipherSuiteCount,
+  IN  UINT32                                  *SupportedCipherSuiteList,
+  IN  UINT32                                  *CipherSuite
+  )
+{
+  UINT16  Index;
+
+  if (CipherSuite == NULL || SupportedCipherSuiteCount == 0 ||
+    SupportedCipherSuiteList == NULL) {
+    return FALSE;
+  }
+
+  for (Index = 0; Index < SupportedCipherSuiteCount; Index ++) {
+    if (SupportedCipherSuiteList[Index] == *CipherSuite) {
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+/**
+  Check an AKM suite list and a Cipher suite list to see if one or more AKM suites or Cipher suites
+  are supported and find the matchable security type.
+
+  @param[in]   AKMList                     The target AKM suite list to be checked.
+  @param[in]   CipherList                  The target Cipher suite list to be checked
+  @param[in]   Nic                         The Nic to operate, contains the supported AKMSuite list
+                                           and supported CipherSuite list
+  @param[out]  SecurityType                To identify a security type from the AKM suite list and
+                                           Cipher suite list
+  @param[out]  AKMSuiteSupported           To identify if this security type is supported. If it is
+                                           NULL, overcome this field
+  @param[out]  CipherSuiteSupported        To identify if this security type is supported. If it is
+                                           NULL, overcome this field
+
+  @retval EFI_SUCCESS                      This operation has completed successfully.
+  @retval EFI_INVALID_PARAMETER            No Nic found or the suite list is null.
+
+**/
+EFI_STATUS
+WifiMgrCheckRSN (
+  IN    EFI_80211_AKM_SUITE_SELECTOR       *AKMList,
+  IN    EFI_80211_CIPHER_SUITE_SELECTOR    *CipherList,
+  IN    WIFI_MGR_DEVICE_DATA               *Nic,
+  OUT   UINT8                              *SecurityType,
+  OUT   BOOLEAN                            *AKMSuiteSupported,
+  OUT   BOOLEAN                            *CipherSuiteSupported
+  )
+{
+  EFI_80211_AKM_SUITE_SELECTOR             *SupportedAKMSuites;
+  EFI_80211_CIPHER_SUITE_SELECTOR          *SupportedSwCipherSuites;
+  EFI_80211_CIPHER_SUITE_SELECTOR          *SupportedHwCipherSuites;
+  EFI_80211_SUITE_SELECTOR                 *AKMSuite;
+  EFI_80211_SUITE_SELECTOR                 *CipherSuite;
+  UINT16                                   AKMIndex;
+  UINT16                                   CipherIndex;
+
+  if (Nic == NULL || AKMList == NULL || CipherList == NULL|| SecurityType == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  SupportedAKMSuites      = Nic->SupportedSuites.SupportedAKMSuites;
+  SupportedSwCipherSuites = Nic->SupportedSuites.SupportedSwCipherSuites;
+  SupportedHwCipherSuites = Nic->SupportedSuites.SupportedHwCipherSuites;
+
+  *SecurityType = SECURITY_TYPE_UNKNOWN;
+  if (AKMSuiteSupported != NULL && CipherSuiteSupported != NULL) {
+    *AKMSuiteSupported    = FALSE;
+    *CipherSuiteSupported = FALSE;
+  }
+
+  if (AKMList->AKMSuiteCount == 0) {
+    if (CipherList->CipherSuiteCount == 0) {
+      *SecurityType = SECURITY_TYPE_NONE;
+      if (AKMSuiteSupported != NULL && CipherSuiteSupported != NULL) {
+        *AKMSuiteSupported    = TRUE;
+        *CipherSuiteSupported = TRUE;
+      }
+    }
+
+    return EFI_SUCCESS;
+  }
+
+  for (AKMIndex = 0; AKMIndex < AKMList->AKMSuiteCount; AKMIndex ++) {
+
+    AKMSuite = AKMList->AKMSuiteList + AKMIndex;
+    if (WifiMgrSupportAKMSuite(SupportedAKMSuites->AKMSuiteCount,
+      (UINT32*) SupportedAKMSuites->AKMSuiteList, (UINT32*) AKMSuite)) {
+
+      if (AKMSuiteSupported != NULL && CipherSuiteSupported != NULL) {
+        *AKMSuiteSupported = TRUE;
+      }
+      for (CipherIndex = 0; CipherIndex < CipherList->CipherSuiteCount; CipherIndex ++) {
+
+        CipherSuite = CipherList->CipherSuiteList + CipherIndex;
+
+        if (SupportedSwCipherSuites != NULL) {
+
+          if (WifiMgrSupportCipherSuite(SupportedSwCipherSuites->CipherSuiteCount,
+            (UINT32*) SupportedSwCipherSuites->CipherSuiteList, (UINT32*) CipherSuite)) {
+
+            *SecurityType = WifiMgrGetSecurityType ((UINT32*) AKMSuite, (UINT32*) CipherSuite);
+
+            if (*SecurityType != SECURITY_TYPE_UNKNOWN) {
+
+              if (AKMSuiteSupported != NULL && CipherSuiteSupported != NULL) {
+                *CipherSuiteSupported = TRUE;
+              }
+              return EFI_SUCCESS;
+            }
+          }
+        }
+
+        if (SupportedHwCipherSuites != NULL) {
+
+          if (WifiMgrSupportCipherSuite(SupportedHwCipherSuites->CipherSuiteCount,
+            (UINT32*) SupportedHwCipherSuites->CipherSuiteList, (UINT32*) CipherSuite)) {
+
+            *SecurityType = WifiMgrGetSecurityType ((UINT32*) AKMSuite, (UINT32*) CipherSuite);
+
+            if (*SecurityType != SECURITY_TYPE_UNKNOWN) {
+
+              if (AKMSuiteSupported != NULL && CipherSuiteSupported != NULL) {
+                *CipherSuiteSupported = TRUE;
+              }
+              return EFI_SUCCESS;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  *SecurityType = WifiMgrGetSecurityType ((UINT32*) AKMList->AKMSuiteList,
+                    (UINT32*) CipherList->CipherSuiteList);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Get the security type for a certain AKMSuite and CipherSuite.
+
+  @param[in]   AKMSuite             An certain AKMSuite.
+  @param[in]   CipherSuite          An certain CipherSuite.
+
+  @return a security type if found, or SECURITY_TYPE_UNKNOWN.
+
+**/
+UINT8
+WifiMgrGetSecurityType (
+  IN  UINT32    *AKMSuite,
+  IN  UINT32    *CipherSuite
+  )
+{
+  if (CipherSuite == NULL) {
+
+    if (AKMSuite == NULL) {
+      return SECURITY_TYPE_NONE;
+    } else {
+      return SECURITY_TYPE_UNKNOWN;
+    }
+  } else if (*CipherSuite == IEEE_80211_PAIRWISE_CIPHER_SUITE_USE_GROUP) {
+
+    if (AKMSuite == NULL) {
+      return SECURITY_TYPE_NONE;
+    } else {
+      return SECURITY_TYPE_UNKNOWN;
+    }
+  } else if (*CipherSuite == IEEE_80211_PAIRWISE_CIPHER_SUITE_WEP40 ||
+    *CipherSuite == IEEE_80211_PAIRWISE_CIPHER_SUITE_WEP104) {
+
+    return SECURITY_TYPE_WEP;
+  } else if (*CipherSuite == IEEE_80211_PAIRWISE_CIPHER_SUITE_CCMP) {
+
+    if (AKMSuite == NULL) {
+      return SECURITY_TYPE_UNKNOWN;
+    }
+
+    if (*AKMSuite == IEEE_80211_AKM_SUITE_8021X_OR_PMKSA ||
+      *AKMSuite == IEEE_80211_AKM_SUITE_8021X_OR_PMKSA_SHA256) {
+
+      return SECURITY_TYPE_WPA2_ENTERPRISE;
+    } else if (*AKMSuite == IEEE_80211_AKM_SUITE_PSK ||
+        *AKMSuite == IEEE_80211_AKM_SUITE_PSK_SHA256){
+
+      return SECURITY_TYPE_WPA2_PERSONAL;
+    }else {
+      return SECURITY_TYPE_UNKNOWN;
+    }
+  } else if (*CipherSuite == IEEE_80211_PAIRWISE_CIPHER_SUITE_TKIP) {
+
+    if (AKMSuite == NULL) {
+      return SECURITY_TYPE_UNKNOWN;
+    }
+
+    if (*AKMSuite == IEEE_80211_AKM_SUITE_8021X_OR_PMKSA ||
+      *AKMSuite == IEEE_80211_AKM_SUITE_8021X_OR_PMKSA_SHA256) {
+
+      return SECURITY_TYPE_WPA_ENTERPRISE;
+    } else if (*AKMSuite == IEEE_80211_AKM_SUITE_PSK ||
+        *AKMSuite == IEEE_80211_AKM_SUITE_PSK_SHA256){
+
+      return SECURITY_TYPE_WPA_PERSONAL;
+    }else {
+      return SECURITY_TYPE_UNKNOWN;
+    }
+  } else {
+    return SECURITY_TYPE_UNKNOWN;
+  }
+}
+
+/**
+  Get supported AKMSuites and CipherSuites from supplicant for a Nic.
+
+  @param[in]   Nic                      The Nic to operate.
+
+  @retval EFI_SUCCESS                   Get the supported suite list successfully.
+  @retval EFI_INVALID_PARAMETER         No Nic found or supplicant is NULL.
+
+**/
+EFI_STATUS
+WifiMgrGetSupportedSuites (
+  IN    WIFI_MGR_DEVICE_DATA            *Nic
+  )
+{
+  EFI_STATUS                            Status;
+  EFI_SUPPLICANT_PROTOCOL               *Supplicant;
+  EFI_80211_AKM_SUITE_SELECTOR          *SupportedAKMSuites;
+  EFI_80211_CIPHER_SUITE_SELECTOR       *SupportedSwCipherSuites;
+  EFI_80211_CIPHER_SUITE_SELECTOR       *SupportedHwCipherSuites;
+  UINTN                                 DataSize;
+
+  SupportedAKMSuites      = NULL;
+  SupportedSwCipherSuites = NULL;
+  SupportedHwCipherSuites = NULL;
+
+  if (Nic == NULL || Nic->Supplicant == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Supplicant = Nic->Supplicant;
+
+  DataSize  = 0;
+  Status = Supplicant->GetData (Supplicant, EfiSupplicant80211SupportedAKMSuites, NULL, &DataSize);
+  if (Status == EFI_BUFFER_TOO_SMALL && DataSize > 0) {
+
+    SupportedAKMSuites = AllocateZeroPool(DataSize);
+    if (SupportedAKMSuites == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    Status = Supplicant->GetData (Supplicant, EfiSupplicant80211SupportedAKMSuites,
+                           (UINT8 *) SupportedAKMSuites, &DataSize);
+    if (!EFI_ERROR (Status)) {
+      Nic->SupportedSuites.SupportedAKMSuites = SupportedAKMSuites;
+    } else {
+      FreePool (SupportedAKMSuites);
+    }
+  } else {
+    SupportedAKMSuites = NULL;
+  }
+
+  DataSize  = 0;
+  Status = Supplicant->GetData (Supplicant, EfiSupplicant80211SupportedSoftwareCipherSuites, NULL, &DataSize);
+  if (Status == EFI_BUFFER_TOO_SMALL && DataSize > 0) {
+
+
+    SupportedSwCipherSuites = AllocateZeroPool(DataSize);
+    if (SupportedSwCipherSuites == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    Status = Supplicant->GetData (Supplicant, EfiSupplicant80211SupportedSoftwareCipherSuites,
+                           (UINT8 *) SupportedSwCipherSuites, &DataSize);
+    if (!EFI_ERROR (Status)) {
+      Nic->SupportedSuites.SupportedSwCipherSuites = SupportedSwCipherSuites;
+    } else {
+      FreePool (SupportedSwCipherSuites);
+    }
+  } else {
+    SupportedSwCipherSuites = NULL;
+  }
+
+  DataSize  = 0;
+  Status = Supplicant->GetData (Supplicant, EfiSupplicant80211SupportedHardwareCipherSuites, NULL, &DataSize);
+  if (Status == EFI_BUFFER_TOO_SMALL && DataSize > 0) {
+
+    SupportedHwCipherSuites = AllocateZeroPool(DataSize);
+    if (SupportedHwCipherSuites == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    Status = Supplicant->GetData (Supplicant, EfiSupplicant80211SupportedHardwareCipherSuites,
+                           (UINT8 *) SupportedHwCipherSuites, &DataSize);
+    if (!EFI_ERROR (Status)) {
+      Nic->SupportedSuites.SupportedHwCipherSuites = SupportedHwCipherSuites;
+    } else {
+      FreePool (SupportedHwCipherSuites);
+    }
+  } else {
+    SupportedHwCipherSuites = NULL;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Clean secrets from a network profile.
+
+  @param[in]   Profile               The profile to be cleanned.
+
+**/
+VOID
+WifiMgrCleanProfileSecrets (
+  IN  WIFI_MGR_NETWORK_PROFILE       *Profile
+  )
+{
+  ZeroMem (Profile->Password, sizeof (CHAR16) * PASSWORD_STORAGE_SIZE);
+  ZeroMem (Profile->EapPassword, sizeof (CHAR16) * PASSWORD_STORAGE_SIZE);
+  ZeroMem (Profile->PrivateKeyPassword, sizeof (CHAR16) * PASSWORD_STORAGE_SIZE);
+
+  if (Profile->CACertData != NULL) {
+
+    ZeroMem (Profile->CACertData, Profile->CACertSize);
+    FreePool (Profile->CACertData);
+  }
+  Profile->CACertData = NULL;
+  Profile->CACertSize = 0;
+
+  if (Profile->ClientCertData != NULL) {
+
+    ZeroMem (Profile->ClientCertData, Profile->ClientCertSize);
+    FreePool (Profile->ClientCertData);
+  }
+  Profile->ClientCertData = NULL;
+  Profile->ClientCertSize = 0;
+
+  if (Profile->PrivateKeyData != NULL) {
+
+    ZeroMem (Profile->PrivateKeyData, Profile->PrivateKeyDataSize);
+    FreePool (Profile->PrivateKeyData);
+  }
+  Profile->PrivateKeyData     = NULL;
+  Profile->PrivateKeyDataSize = 0;
+}
+
+/**
+  Free all network profiles in a profile list.
+
+  @param[in]   ProfileList           The profile list to be freed.
+
+**/
+VOID
+WifiMgrFreeProfileList (
+  IN  LIST_ENTRY                     *ProfileList
+  )
+{
+  WIFI_MGR_NETWORK_PROFILE           *Profile;
+  LIST_ENTRY                         *Entry;
+  LIST_ENTRY                         *NextEntry;
+
+  if (ProfileList == NULL) {
+    return;
+  }
+
+  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, ProfileList) {
+
+    Profile = NET_LIST_USER_STRUCT_S (Entry, WIFI_MGR_NETWORK_PROFILE,
+                Link, WIFI_MGR_PROFILE_SIGNATURE);
+
+    WifiMgrCleanProfileSecrets (Profile);
+
+    if (Profile->Network.AKMSuite != NULL) {
+      FreePool(Profile->Network.AKMSuite);
+    }
+
+    if (Profile->Network.CipherSuite != NULL) {
+      FreePool(Profile->Network.CipherSuite);
+    }
+
+    FreePool (Profile);
+  }
+}
+
+/**
+  Free user configured hidden network list.
+
+  @param[in]   HiddenList           The hidden network list to be freed.
+
+**/
+VOID
+WifiMgrFreeHiddenList (
+  IN  LIST_ENTRY                     *HiddenList
+  )
+{
+  WIFI_HIDDEN_NETWORK_DATA           *HiddenNetwork;
+  LIST_ENTRY                         *Entry;
+  LIST_ENTRY                         *NextEntry;
+
+  if (HiddenList == NULL) {
+    return;
+  }
+
+  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, HiddenList) {
+
+    HiddenNetwork = NET_LIST_USER_STRUCT_S (Entry, WIFI_HIDDEN_NETWORK_DATA,
+                      Link, WIFI_MGR_HIDDEN_NETWORK_SIGNATURE);
+    FreePool (HiddenNetwork);
+  }
+}
+
+
+/**
+  Free the resources of a config token.
+
+  @param[in]   ConfigToken          The config token to be freed.
+**/
+VOID
+WifiMgrFreeToken (
+  IN   WIFI_MGR_MAC_CONFIG_TOKEN    *ConfigToken
+  )
+{
+  EFI_80211_GET_NETWORKS_RESULT     *Result;
+
+  if (ConfigToken == NULL) {
+    return;
+  }
+
+  switch (ConfigToken->Type) {
+
+    case TokenTypeGetNetworksToken:
+
+      if (ConfigToken->Token.GetNetworksToken != NULL) {
+
+        gBS->CloseEvent (ConfigToken->Token.GetNetworksToken->Event);
+        if (ConfigToken->Token.GetNetworksToken->Data != NULL) {
+          FreePool(ConfigToken->Token.GetNetworksToken->Data);
+        }
+
+        Result = ConfigToken->Token.GetNetworksToken->Result;
+        if (Result != NULL) {
+          FreePool (Result);
+        }
+
+        FreePool(ConfigToken->Token.GetNetworksToken);
+      }
+
+      FreePool (ConfigToken);
+      break;
+
+    case TokenTypeConnectNetworkToken:
+
+      if (ConfigToken->Token.ConnectNetworkToken != NULL) {
+
+        gBS->CloseEvent (ConfigToken->Token.ConnectNetworkToken->Event);
+        if (ConfigToken->Token.ConnectNetworkToken->Data != NULL) {
+          FreePool(ConfigToken->Token.ConnectNetworkToken->Data);
+        }
+        FreePool(ConfigToken->Token.ConnectNetworkToken);
+      }
+      FreePool (ConfigToken);
+      break;
+
+    case TokenTypeDisconnectNetworkToken:
+
+      if (ConfigToken->Token.DisconnectNetworkToken != NULL) {
+
+        FreePool(ConfigToken->Token.DisconnectNetworkToken);
+      }
+
+      FreePool (ConfigToken);
+      break;
+
+    default :
+      break;
+  }
+}
diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrMisc.h b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrMisc.h
new file mode 100644
index 0000000000..6c8806897e
--- /dev/null
+++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrMisc.h
@@ -0,0 +1,268 @@
+/** @file
+  The Miscellaneous Routines for WiFi Connection Manager.
+
+  Copyright (c) 2019, 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.
+
+**/
+
+#ifndef __EFI_WIFI_MGR_MISC_H__
+#define __EFI_WIFI_MGR_MISC_H__
+
+/**
+  Empty function for event process function.
+
+  @param[in] Event    The Event needs to be processed
+  @param[in] Context  The context of the event
+
+**/
+VOID
+EFIAPI
+WifiMgrInternalEmptyFunction (
+  IN  EFI_EVENT   Event,
+  IN  VOID        *Context
+  );
+
+/**
+  Convert the mac address into a hexadecimal encoded ":" seperated string.
+
+  @param[in]  Mac     The mac address
+  @param[in]  StrSize The size, in bytes, of the output buffer specified by Str
+  @param[out] Str     The storage to return the mac string
+
+**/
+VOID
+WifiMgrMacAddrToStr (
+  IN  EFI_80211_MAC_ADDRESS     *Mac,
+  IN  UINT32                    StrSize,
+  OUT CHAR16                    *Str
+  );
+
+/**
+  Read private key file to buffer.
+
+  @param[in]   FileContext           The file context of private key file.
+  @param[out]  PrivateKeyDataAddr    The buffer address to restore private key file, should be
+                                     freed by caller.
+  @param[out]  PrivateKeyDataSize    The size of read private key file.
+
+  @retval EFI_SUCCESS                Successfully read the private key file.
+  @retval EFI_INVALID_PARAMETER      One or more of the parameters is invalid.
+
+**/
+EFI_STATUS
+WifiMgrReadFileToBuffer (
+  IN   WIFI_MGR_FILE_CONTEXT          *FileContext,
+  OUT  VOID                           **PrivateKeyDataAddr,
+  OUT  UINTN                          *PrivateKeyDataSize
+  );
+
+
+/**
+  Get the Nic data by the NicIndex.
+
+  @param[in]  Private        The pointer to the global private data structure.
+  @param[in]  NicIndex       The index indicates the position of wireless NIC.
+
+  @return     Pointer to the Nic data, or NULL if not found.
+
+**/
+WIFI_MGR_DEVICE_DATA *
+WifiMgrGetNicByIndex (
+  IN WIFI_MGR_PRIVATE_DATA      *Private,
+  IN UINT32                     NicIndex
+  );
+
+/**
+  Find a network profile through its' SSId and securit type, and the SSId is an unicode string.
+
+  @param[in]  SSId                   The target network's SSId.
+  @param[in]  SecurityType           The target network's security type.
+  @param[in]  ProfileList            The profile list on a Nic.
+
+  @return Pointer to a network profile, or NULL if not found.
+
+**/
+WIFI_MGR_NETWORK_PROFILE *
+WifiMgrGetProfileByUnicodeSSId (
+  IN  CHAR16                         *SSId,
+  IN  UINT8                          SecurityType,
+  IN  LIST_ENTRY                     *ProfileList
+  );
+
+/**
+  Find a network profile through its' SSId and securit type, and the SSId is an ascii string.
+
+  @param[in]  SSId                   The target network's SSId.
+  @param[in]  SecurityType           The target network's security type.
+  @param[in]  ProfileList            The profile list on a Nic.
+
+  @return Pointer to a network profile, or NULL if not found.
+
+**/
+WIFI_MGR_NETWORK_PROFILE *
+WifiMgrGetProfileByAsciiSSId (
+  IN  CHAR8                          *SSId,
+  IN  UINT8                          SecurityType,
+  IN  LIST_ENTRY                     *ProfileList
+  );
+
+/**
+  Find a network profile through its' profile index.
+
+  @param[in]  ProfileIndex           The target network's profile index.
+  @param[in]  ProfileList            The profile list on a Nic.
+
+  @return Pointer to a network profile, or NULL if not found.
+
+**/
+WIFI_MGR_NETWORK_PROFILE *
+WifiMgrGetProfileByProfileIndex (
+  IN UINT32                     ProfileIndex,
+  IN LIST_ENTRY                 *ProfileList
+  );
+
+/**
+  To test if the AKMSuite is in supported AKMSuite list.
+
+  @param[in]  SupportedAKMSuiteCount      The count of the supported AKMSuites.
+  @param[in]  SupportedAKMSuiteList       The supported AKMSuite list.
+  @param[in]  AKMSuite                    The AKMSuite to be tested.
+
+  @return True if this AKMSuite is supported, or False if not.
+
+**/
+BOOLEAN
+WifiMgrSupportAKMSuite (
+  IN  UINT16                              SupportedAKMSuiteCount,
+  IN  UINT32                              *SupportedAKMSuiteList,
+  IN  UINT32                              *AKMSuite
+  );
+
+/**
+  To check if the CipherSuite is in supported CipherSuite list.
+
+  @param[in]  SupportedCipherSuiteCount   The count of the supported CipherSuites.
+  @param[in]  SupportedCipherSuiteList    The supported CipherSuite list.
+  @param[in]  CipherSuite                 The CipherSuite to be tested.
+
+  @return True if this CipherSuite is supported, or False if not.
+
+**/
+BOOLEAN
+WifiMgrSupportCipherSuite (
+  IN  UINT16                              SupportedCipherSuiteCount,
+  IN  UINT32                              *SupportedCipherSuiteList,
+  IN  UINT32                              *CipherSuite
+  );
+
+/**
+  Check an AKM suite list and a Cipher suite list to see if one or more AKM suites or Cipher suites
+  are supported and find the matchable security type.
+
+  @param[in]   AKMList                     The target AKM suite list to be checked.
+  @param[in]   CipherList                  The target Cipher suite list to be checked
+  @param[in]   Nic                         The Nic to operate, contains the supported AKMSuite list
+                                           and supported CipherSuite list
+  @param[out]  SecurityType                To identify a security type from the AKM suite list and
+                                           Cipher suite list
+  @param[out]  AKMSuiteSupported           To identify if this security type is supported. If it is
+                                           NULL, overcome this field
+  @param[out]  CipherSuiteSupported        To identify if this security type is supported. If it is
+                                           NULL, overcome this field
+
+  @retval EFI_SUCCESS                      This operation has completed successfully.
+  @retval EFI_INVALID_PARAMETER            No Nic found or the suite list is null.
+
+**/
+EFI_STATUS
+WifiMgrCheckRSN (
+  IN    EFI_80211_AKM_SUITE_SELECTOR      *AKMList,
+  IN    EFI_80211_CIPHER_SUITE_SELECTOR   *CipherList,
+  IN    WIFI_MGR_DEVICE_DATA              *Nic,
+  OUT   UINT8                             *SecurityType,
+  OUT   BOOLEAN                           *AKMSuiteSupported,
+  OUT   BOOLEAN                           *CipherSuiteSupported
+  );
+
+/**
+  To get the security type for a certain AKMSuite and CipherSuite.
+
+  @param[in]   AKMSuite             An certain AKMSuite.
+  @param[in]   CipherSuite          An certain CipherSuite.
+
+  @return a security type if found, or SECURITY_TYPE_UNKNOWN.
+
+**/
+UINT8
+WifiMgrGetSecurityType (
+  IN    UINT32                          *AKMSuite,
+  IN    UINT32                          *CipherSuite
+  );
+
+/**
+  Get supported AKMSuites and CipherSuites from supplicant.
+
+  @param[in]   Nic                      The Nic to operate.
+
+  @retval EFI_SUCCESS                   Get the supported suite list successfully.
+  @retval EFI_INVALID_PARAMETER         No Nic found or supplicant is NULL.
+
+**/
+EFI_STATUS
+WifiMgrGetSupportedSuites (
+  IN    WIFI_MGR_DEVICE_DATA            *Nic
+  );
+
+/**
+  Clean secrets from a network profile.
+
+  @param[in]   Profile               The profile to be cleanned.
+
+**/
+VOID
+WifiMgrCleanProfileSecrets (
+  IN  WIFI_MGR_NETWORK_PROFILE       *Profile
+  );
+
+/**
+  Free all network profiles in a profile list.
+
+  @param[in]   ProfileList           The profile list to be freed.
+
+**/
+VOID
+WifiMgrFreeProfileList (
+  IN  LIST_ENTRY               *ProfileList
+  );
+
+/**
+  Free user configured hidden network list.
+
+  @param[in]   HiddenList           The hidden network list to be freed.
+
+**/
+VOID
+WifiMgrFreeHiddenList (
+  IN  LIST_ENTRY                     *HiddenList
+  );
+
+/**
+  Free the resources of a config token.
+
+  @param[in]   ConfigToken          The config token to be freed.
+
+**/
+VOID
+WifiMgrFreeToken (
+  IN   WIFI_MGR_MAC_CONFIG_TOKEN        *ConfigToken
+  );
+
+#endif
-- 
2.16.2.windows.1



             reply	other threads:[~2019-02-22  7:48 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-02-22  7:48 Wang Fan [this message]
2019-02-22  7:56 ` [Patch V2] NetworkPkg: Add WiFi Connection Manager to NetworkPkg Wu, Jiaxin

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=20190222074825.8864-1-fan.wang@intel.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