public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Fu, Siyuan" <siyuan.fu@intel.com>
To: "Wang, Fan" <fan.wang@intel.com>,
	"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Cc: "Ye, Ting" <ting.ye@intel.com>, "Wu, Jiaxin" <jiaxin.wu@intel.com>
Subject: Re: [Patch] NetworkPkg: Add WiFi Connection Manager to NetworkPkg
Date: Wed, 20 Feb 2019 03:57:40 +0000	[thread overview]
Message-ID: <B1FF2E9001CE9041BD10B825821D5BC58B6E9D2E@SHSMSX103.ccr.corp.intel.com> (raw)
In-Reply-To: <20190215030739.6816-1-fan.wang@intel.com>

Hi, Fan

See my comments embedded, thanks.

> -----Original Message-----
> From: Wang, Fan
> Sent: Friday, February 15, 2019 11:08 AM
> 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] NetworkPkg: Add WiFi Connection Manager to NetworkPkg
> 
> 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>
> ---
>  NetworkPkg/NetworkPkg.dsc                          |    1 +
>  NetworkPkg/WifiConnectionManagerDxe/EapContext.h   |   28 +
>  .../WifiConnectionManagerDxe.inf                   |   88 +
>  .../WifiConnectionManagerDxe.vfr                   |  353 ++++
>  .../WifiConnectionManagerDxeStrings.uni            |  109 ++
>  .../WifiConnectionMgrComponentName.c               |  191 ++
>  .../WifiConnectionMgrComponentName.h               |   99 +
>  .../WifiConnectionMgrConfig.h                      |   74 +
>  .../WifiConnectionMgrConfigHii.h                   |   41 +
>  .../WifiConnectionMgrConfigNVDataStruct.h          |  157 ++
>  .../WifiConnectionMgrDriver.c                      |  717 ++++++++
>  .../WifiConnectionMgrDriverBinding.h               |  148 ++
>  .../WifiConnectionMgrDxe.h                         |  344 ++++
>  .../WifiConnectionMgrFileUtil.c                    |  308 ++++
>  .../WifiConnectionMgrFileUtil.h                    |   77 +
>  .../WifiConnectionMgrHiiConfigAccess.c             | 1918
> ++++++++++++++++++++
>  .../WifiConnectionMgrHiiConfigAccess.h             |  228 +++
>  .../WifiConnectionMgrImpl.c                        | 1409 ++++++++++++++
>  .../WifiConnectionMgrImpl.h                        |  123 ++
>  .../WifiConnectionMgrMisc.c                        |  784 ++++++++
>  .../WifiConnectionMgrMisc.h                        |  279 +++
>  21 files changed, 7476 insertions(+)
>  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/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..f673428292
> --- /dev/null
> +++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionManagerDxe.inf
> @@ -0,0 +1,88 @@
> +## @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

Why WCM is a DXE driver instead of UEFI driver?

> +  VERSION_STRING            = 0.1
> +  ENTRY_POINT               = WifiMgrDxeDriverEntryPoint
> +  UNLOAD_IMAGE              = WifiMgrDxeUnload
> +
> +[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]
> +  gEfiIfrTianoGuid                              ## CONSUMES  ## GUID
> (Extended IFR Guid Opcode)
> +  gEfiAdapterInfoMediaStateGuid                 ## SOMETIMES_CONSUMES  ##
> GUID  # Indicate the current media state status
> +
> +[Depex]
> +  gEfiHiiConfigRoutingProtocolGuid AND
> +  gEfiRealTimeClockArchProtocolGuid

Why WCM depends on an ARCH protocol? Can we change the WCM to a pure UEFI driver
and remove the [Depex] section?

> diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionManagerDxe.vfr
> b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionManagerDxe.vfr
> new file mode 100644
> index 0000000000..2674372b11
> --- /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_CONFIG_FORM_SET_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_CONFIG_FORM_SET_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..36c38d3a3c
> --- /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"WifiConnectionManagerDxe"
> +  },
> +  {
> +    NULL,
> +    NULL
> +  }
> +};
> +
> +///
> +/// Table of controller names
> +///
> +GLOBAL_REMOVE_IF_UNREFERENCED
> +EFI_UNICODE_STRING_TABLE mWifiMgrDxeControllerNameTable[] = {
> +  {
> +    "eng;en",
> +    L"WifiConnectionManagerDxe Controller"

Suggest to change to "UEFI Wi-Fi Connection Manager..."

> +  },
> +  {
> +    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..99b7fa2083
> --- /dev/null
> +++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrConfigHii.h
> @@ -0,0 +1,41 @@
> +/** @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
> +  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__
> +
> +// {3441803E-5A88-4941-82F0-858A1085276C}
> +#define WIFI_CONFIG_FORM_SET_GUID \
> +  { \
> +    0x3441803e, 0x5a88, 0x4941, { 0x82, 0xf0, 0x85, 0x8a, 0x10, 0x85, 0x27,
> 0x6c } \
> +  }
> +
> +// {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..2581e080e3
> --- /dev/null
> +++
> b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrConfigNVDataStruct.h
> @@ -0,0 +1,157 @@
> +/** @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 "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..0abd95b4c6
> --- /dev/null
> +++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrDriver.c
> @@ -0,0 +1,717 @@
> +/** @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_CONFIG_FORM_SET_GUID;
> +EFI_GUID gWifiConfigNetworkListRefreshGuid =
> WIFI_CONFIG_NETWORK_LIST_REFRESH_GUID;
> +EFI_GUID gWifiConfigConnectFormRefreshGuid =
> WIFI_CONFIG_CONNECT_FORM_REFRESH_GUID;
> +EFI_GUID gWifiConfigMainFormRefreshGuid    =
> WIFI_CONFIG_MAIN_FORM_REFRESH_GUID;

Module level global variables should use prefix 'm', not 'g'.

> +
> +/**
> +  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_ADAPTER_INFORMATION_PROTOCOL           *Aip;
> +  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,
> +                  &gEfiAdapterInformationProtocolGuid,
> +                  (VOID**) &Aip,
> +                  This->DriverBindingHandle,
> +                  ControllerHandle,
> +                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    Aip = NULL;
> +  }
> +
> +  Status = gBS->OpenProtocol (
> +                  ControllerHandle,
> +                  &gEfiSupplicantProtocolGuid,
> +                  (VOID**) &Supplicant,
> +                  This->DriverBindingHandle,
> +                  ControllerHandle,
> +                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    Supplicant = NULL;
> +  }
> +
> +  Status = gBS->OpenProtocol (
> +                  ControllerHandle,
> +                  &gEfiEapConfigurationProtocolGuid,
> +                  (VOID**) &EapConfig,
> +                  This->DriverBindingHandle,
> +                  ControllerHandle,
> +                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    EapConfig = NULL;
> +  }

Can WCM open the supplicant and EapConfig protocol with BY_DRIVER attribute?
Otherwise WCM won't be stopped if these protocols are unstalled.

> +
> +  //
> +  //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->Aip                  = Aip;
> +  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);
> +  InitializeListHead (&Nic->TokenList);
> +
> +  //
> +  // 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 ++;
> +  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 (Aip != NULL) {
> +    gBS->CloseProtocol (
> +         ControllerHandle,
> +         &gEfiAdapterInformationProtocolGuid,
> +         This->DriverBindingHandle,
> +         ControllerHandle
> +         );

Open protocol by GET_PROTOCOL attr doesn't need close.

> +  }
> +
> +  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 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;
> +    }
> +  }

Again, if open by GET_PROTOCOL attribute, doesn't need to close these protocols.

> +
> +  Status = gBS->CloseProtocol (
> +             ControllerHandle,
> +             &gEfiAdapterInformationProtocolGuid,
> +             This->DriverBindingHandle,
> +             ControllerHandle
> +             );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  //Free List
> +  //
> +  WifiMgrFreeProfileList (&Nic->ProfileList);
> +  WifiMgrFreeTokenList (&Nic->TokenList);

What will happen here if there is a pending Token which has been passed to 
the Wmp protocol and not signaled for complete yet?

> +
> +  //
> +  // Close Event
> +  //
> +  gBS->CloseEvent (Nic->TickTimer);
> +
> +  //
> +  // Remove this Nic from Nic list
> +  //
> +  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
> +  RemoveEntryList (&Nic->Link);
> +  mPrivate->NicCount--;
> +  gBS->RestoreTPL (OldTpl);
> +
> +  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);
> +
> +  DEBUG ((DEBUG_INFO, "[WiFi Connection Manager] Device Controller has been
> Disconnected!\n"));
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Unload Wi-Fi Connection Manager driver.
> +
> +  @param  ImageHandle            Handle that identifies the image to be
> unloaded.
> +
> +  @retval EFI_SUCCESS            The driver is unloaded.
> +  @retval Others                 An unexpected error occurred.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +WifiMgrDxeUnload (
> +  IN EFI_HANDLE    ImageHandle
> +  )
> +{
> +  EFI_STATUS    Status;
> +  UINTN         NumberOfHandles;
> +  EFI_HANDLE    *Handles;
> +  UINTN         Index;
> +
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  &mEfiWifiMgrPrivateGuid,
> +                  NULL,
> +                  &NumberOfHandles,
> +                  &Handles
> +                  );
> +  if (!EFI_ERROR (Status)) {
> +
> +    for (Index = 0; Index < NumberOfHandles; Index ++) {
> +      Status = gBS->DisconnectController (
> +                      Handles[Index],
> +                      gWifiMgrDxeDriverBinding.DriverBindingHandle,
> +                      NULL
> +                      );
> +      if (EFI_ERROR (Status)) {
> +        return Status;
> +      }
> +    }
> +  }
> +
> +  Status = WifiMgrDxeConfigFormUnload (mPrivate);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Status =  gBS->UninstallMultipleProtocolInterfaces (
> +                   ImageHandle,
> +                   &gEfiDriverBindingProtocolGuid,
> +                   &gWifiMgrDxeDriverBinding,
> +                   &gEfiComponentNameProtocolGuid,
> +                   &gWifiMgrDxeComponentName,
> +                   &gEfiComponentName2ProtocolGuid,
> +                   &gWifiMgrDxeComponentName2,
> +                   NULL
> +                   );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  gBS->CloseEvent (mPrivate->MainPageRefreshEvent);
> +  gBS->CloseEvent (mPrivate->ConnectFormRefreshEvent);
> +  gBS->CloseEvent (mPrivate->NetworkListRefreshEvent);
> +
> +  WifiMgrFreeHiddenList (&mPrivate->HiddenNetworkList);
> +  FreePool (mPrivate);
> +  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;
> +  InitializeListHead (&mPrivate->HiddenNetworkList);
> +  mPrivate->HiddenNetworkCount = 0;
> +
> +  //
> +  //Create events for page refresh
> +  //
> +  Status = gBS->CreateEventEx (
> +                  EVT_NOTIFY_SIGNAL,
> +                  TPL_CALLBACK,
> +                  WifiMgrInternalEmptyFunction,
> +                  NULL,
> +                  &gWifiConfigNetworkListRefreshGuid,
> +                  &mPrivate->NetworkListRefreshEvent
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    goto ERROR2;
> +  }
> +
> +  Status = gBS->CreateEventEx (
> +                  EVT_NOTIFY_SIGNAL,
> +                  TPL_CALLBACK,
> +                  WifiMgrInternalEmptyFunction,
> +                  NULL,
> +                  &gWifiConfigConnectFormRefreshGuid,
> +                  &mPrivate->ConnectFormRefreshEvent
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    goto ERROR3;
> +  }
> +
> +  Status = gBS->CreateEventEx (
> +                  EVT_NOTIFY_SIGNAL,
> +                  TPL_CALLBACK,
> +                  WifiMgrInternalEmptyFunction,
> +                  NULL,
> +                  &gWifiConfigMainFormRefreshGuid,
> +                  &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..c12dfcca88
> --- /dev/null
> +++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrDxe.h
> @@ -0,0 +1,344 @@
> +/** @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>
> +
> +//
> +// NvData struct definition
> +//
> +#include "WifiConnectionMgrConfigNVDataStruct.h"
> +#include "WifiConnectionMgrConfig.h"
> +#include "EapContext.h"
> +#include "WifiConnectionMgrConfigHii.h"
> +
> +//
> +// Driver Version
> +//
> +#define WIFI_MGR_DXE_VERSION  0xb
> +
> +//---------------------
> +
> +#pragma pack (1)

Macro and enum doesn't need alignment, please remove it.

> +
> +#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))
> +
> +//------------------------------
> +
> +#pragma pack ()
> +
> +//
> +// 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_ADAPTER_INFORMATION_PROTOCOL           *Aip;
> +  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
> +  //
> +  LIST_ENTRY                                  TokenList;   // List of
> WIFI_MGR_MAC_CONFIG_TOKEN
> +  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 {
> +  UINT32                          Signature;
> +  WIFI_MGR_MAC_CONFIG_TOKEN_TYPE  Type;
> +  //
> +  // Link to the TokenList in device data structure.
> +  //
> +  LIST_ENTRY                      Link;
> +  WIFI_MGR_DEVICE_DATA            *Nic;
> +
> +  MAC_CONNECTION2_ADAPTER_TOKEN   Token;
> +} WIFI_MGR_MAC_CONFIG_TOKEN;
> +
> +#define WIFI_MGR_MAC_CONFIG_TOKEN_SIGNATURE  SIGNATURE_32 ('W','M','C','T')
> +
> +//
> +// 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
> +)

This function is exactly same with the one in NetworkPkg\TlsAuthConfigDxe\
TlsAuthConfigImpl.c
Consider to extract to a library interface?

> +{
> +  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..69f335263b
> --- /dev/null
> +++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrHiiConfigAccess.c
> @@ -0,0 +1,1918 @@
> +/** @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_CONFIG_FORM_SET_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));

Seems this only zero the memory buffer returned from HiiGetString(), is the
password in HII string package also cleaned?

> +  FreePool (Password);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  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);

IfrNvData may contain secret, please zero memory before free.

> +  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
> +        //
> +        WifiMgrCleanProfileSecrets (Profile);

This should be moved to the EFI_BROWSER_ACTION_FORM_CLOSE callback?

> +
> +        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, 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);
> +  }
> +
> +  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..cee8010e17
> --- /dev/null
> +++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrHiiConfigAccess.h
> @@ -0,0 +1,228 @@
> +/** @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__
> +
> +/**
> +  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..a8b458f85f
> --- /dev/null
> +++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrImpl.c
> @@ -0,0 +1,1409 @@
> +/** @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.
> +
> +  @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;
> +
> +  if (Context == NULL) {
> +    return;
> +  }
> +
> +  ConfigToken = (WIFI_MGR_MAC_CONFIG_TOKEN *) Context;
> +  if (ConfigToken->Nic == NULL) {

ConfigToken->Nic should never be NULL, right? Suggest to add ASSERT if yes.
And also the Signature and ConfigToken->Token.GetNetworksToken check.

> +    WifiMgrFreeToken(ConfigToken);
> +    return;
> +  }
> +
> +  if (ConfigToken->Signature != WIFI_MGR_MAC_CONFIG_TOKEN_SIGNATURE ||
> +    ConfigToken->Type != TokenTypeGetNetworksToken) {
> +
> +    WifiMgrFreeToken(ConfigToken);
> +    return;
> +  }
> +
> +  //
> +  // It is the GetNetworks token, set scan state to "ScanFinished"
> +  //
> +  ConfigToken->Nic->ScanState = WifiMgrScanFinished;
> +
> +  if (ConfigToken->Token.GetNetworksToken == NULL ||
> +    ConfigToken->Token.GetNetworksToken->Result == NULL) {
> +
> +    WifiMgrFreeToken(ConfigToken);
> +    return;
> +  }
> +
> +  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;
> +  }
> +  InsertTailList (&Nic->TokenList, &ConfigToken->Link);
> +
> +  ConfigToken->Signature = WIFI_MGR_MAC_CONFIG_TOKEN_SIGNATURE;
> +  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;
> +  UINTN                                DataSize;
> +  EFI_ADAPTER_INFO_MEDIA_STATE         *UndiState;
> +  EFI_ADAPTER_INFORMATION_PROTOCOL     *Aip;
> +
> +  if (Nic == NULL || LinkState == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (Nic->Aip == NULL) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  Aip = Nic->Aip;
> +  Status = Aip->GetInformation(
> +                  Aip,
> +                  &gEfiAdapterInfoMediaStateGuid,
> +                  (VOID **) &UndiState,
> +                  &DataSize
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  CopyMem (LinkState, UndiState, sizeof (EFI_ADAPTER_INFO_MEDIA_STATE));
> +  FreePool (UndiState);
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Update connection message on connect configuration page, and trigger
> related form refresh.
> +
> +  @param[in]   Private                    The pointer to the global private
> data structure.
> +  @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_PRIVATE_DATA     *Private,
> +  IN  BOOLEAN                   ConnectStateChanged,
> +  IN  EFI_STRING                ConnectStatusMessage
> +  )

Can we move this function to WifiConnectionMgrHiiConfigAccess.c if it's trying
to update HII related string?

> +{
> +  CHAR16    ConnectStatusStr[WIFI_STR_MAX_SIZE];
> +
> +  if (Private == NULL) {
> +    return;
> +  }
> +
> +  //
> +  // Update Connection Status Bar
> +  //
> +  if (ConnectStatusMessage != NULL) {
> +    HiiSetString (Private->RegisteredHandle, STRING_TOKEN
> (STR_CONNECT_STATUS), ConnectStatusMessage, NULL);
> +  } else {
> +    if (Private->CurrentNic->ConnectState == WifiMgrConnectedToAp) {
> +
> +      UnicodeSPrint (ConnectStatusStr, sizeof (ConnectStatusStr), L"Connected
> to %s",
> +        Private->CurrentNic->CurrentOperateNetwork->SSId);
> +      HiiSetString (Private->RegisteredHandle, STRING_TOKEN
> (STR_CONNECT_STATUS), ConnectStatusStr, NULL);

This function may be called from the WifiMgrOnTimerTick(), but it use the 
Private->CurrentNic, instead the Nic in WifiMgrOnTimerTick().
Is it intended or a bug? What will happened if the Nic and Private->CurrentNic
are point to different NIC instances?

> +    } else if (Private->CurrentNic->ConnectState == WifiMgrDisconnected) {
> +
> +      HiiSetString (Private->RegisteredHandle, STRING_TOKEN
> (STR_CONNECT_STATUS), L"Disconnected", NULL);
> +    } else if (Private->CurrentNic->ConnectState == WifiMgrConnectingToAp) {
> +
> +      UnicodeSPrint (ConnectStatusStr, sizeof (ConnectStatusStr),
> L"Connecting to %s ...",
> +        Private->CurrentNic->CurrentOperateNetwork->SSId);
> +      HiiSetString (Private->RegisteredHandle, STRING_TOKEN
> (STR_CONNECT_STATUS), ConnectStatusStr, NULL);
> +    } else if (Private->CurrentNic->ConnectState == WifiMgrDisconnectingToAp)
> {
> +
> +      UnicodeSPrint (ConnectStatusStr, sizeof (ConnectStatusStr),
> L"Disconnecting from %s ...",
> +        Private->CurrentNic->CurrentOperateNetwork->SSId);
> +      HiiSetString (Private->RegisteredHandle, STRING_TOKEN
> (STR_CONNECT_STATUS), ConnectStatusStr, NULL);
> +    } else {
> +      return;
> +    }
> +  }
> +
> +  //
> +  // Update Connect Button
> +  //
> +  if (Private->CurrentNic->ConnectState == WifiMgrConnectedToAp &&
> +    Private->CurrentNic->UserSelectedProfile == Private->CurrentNic-
> >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 (Private->CurrentNic->ConnectState == WifiMgrConnectedToAp) {
> +
> +      HiiSetString (Private->RegisteredHandle, STRING_TOKEN
> (STR_CONNECTION_INFO), L"Connected to", NULL);
> +      HiiSetString (Private->RegisteredHandle,
> +        STRING_TOKEN (STR_CONNECTED_SSID), Private->CurrentNic-
> >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);
> +  }
> +}
> +
> +/**
> +  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->Private, 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->Private, 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.
> +
> +  @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_PRIVATE_DATA              *Private;
> +  WIFI_MGR_MAC_CONFIG_TOKEN          *ConfigToken;
> +  WIFI_MGR_NETWORK_PROFILE           *ConnectedProfile;
> +  UINT8                              SecurityType;
> +  UINT8                              SSIdLen;
> +  CHAR8                              *AsciiSSId;
> +
> +  if (Context == NULL) {
> +    return;
> +  }
> +  ConnectedProfile = NULL;
> +  ConfigToken = (WIFI_MGR_MAC_CONFIG_TOKEN*) Context;
> +  if (ConfigToken->Nic == NULL || ConfigToken->Nic->Private == NULL) {
> +    return;
> +  }
> +  Private = ConfigToken->Nic->Private;
> +
> +  ConfigToken->Nic->ConnectState = WifiMgrDisconnected;
> +
> +  if (ConfigToken->Signature != WIFI_MGR_MAC_CONFIG_TOKEN_SIGNATURE ||
> +    ConfigToken->Type != TokenTypeConnectNetworkToken ||
> +    ConfigToken->Token.ConnectNetworkToken == NULL) {
> +
> +    WifiMgrUpdateConnectMessage (Private, FALSE, NULL);
> +    ConfigToken->Nic->OneTimeConnectRequest = FALSE;
> +    ConfigToken->Nic->CurrentOperateNetwork = NULL;
> +    return;
> +  }
> +
> +  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 (Private, FALSE, L"Connect Failed:
> Permission Denied!");
> +      } else {
> +        WifiMgrUpdateConnectMessage (Private, 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 (Private, FALSE, L"Connect Failed: Wrong
> Password or Unexpected Error!");
> +      } else {
> +        WifiMgrUpdateConnectMessage (Private, 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 (Private, 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 (Private, 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 (Private, FALSE, NULL);
> +    goto Exit;
> +  }
> +
> +  ConfigToken->Nic->ConnectState = WifiMgrConnectedToAp;
> +  WifiMgrUpdateConnectMessage (Private, 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;
> +  WIFI_MGR_PRIVATE_DATA                  *Private;
> +  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 || Nic->Private ==
> NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  Private = Nic->Private;
> +
> +  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;
> +  }
> +  InsertTailList (&Nic->TokenList, &ConfigToken->Link);
> +
> +  ConfigToken->Signature = WIFI_MGR_MAC_CONFIG_TOKEN_SIGNATURE;
> +  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 (Private, 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 (Private, TRUE, NULL);
> +    } else {
> +
> +      Nic->ConnectState          = WifiMgrDisconnected;
> +      Nic->CurrentOperateNetwork = NULL;
> +
> +      if (Nic->OneTimeConnectRequest) {
> +        if (Status == EFI_NOT_FOUND) {
> +          WifiMgrUpdateConnectMessage (Private, FALSE, L"Connect Failed: Not
> Available!");
> +        } else {
> +          WifiMgrUpdateConnectMessage (Private, 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.
> +
> +  @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;
> +
> +  if (Context == NULL) {
> +    return;
> +  }
> +
> +  ConfigToken = (WIFI_MGR_MAC_CONFIG_TOKEN*) Context;
> +  if (ConfigToken->Nic == NULL) {
> +    return;
> +  }
> +
> +  if (ConfigToken->Signature != WIFI_MGR_MAC_CONFIG_TOKEN_SIGNATURE ||
> +      ConfigToken->Type != TokenTypeDisconnectNetworkToken) {
> +    ConfigToken->Nic->ConnectState          = WifiMgrConnectedToAp;
> +    WifiMgrUpdateConnectMessage (ConfigToken->Nic->Private, FALSE, NULL);
> +    ConfigToken->Nic->OneTimeDisconnectRequest = FALSE;
> +    return;
> +  }
> +
> +  if (ConfigToken->Token.DisconnectNetworkToken->Status != EFI_SUCCESS) {
> +    ConfigToken->Nic->ConnectState          = WifiMgrConnectedToAp;
> +    WifiMgrUpdateConnectMessage (ConfigToken->Nic->Private, FALSE, NULL);
> +    ConfigToken->Nic->OneTimeDisconnectRequest = FALSE;
> +    goto Exit;
> +  }
> +
> +  ConfigToken->Nic->ConnectState          = WifiMgrDisconnected;
> +  ConfigToken->Nic->CurrentOperateNetwork = NULL;
> +  WifiMgrUpdateConnectMessage (ConfigToken->Nic->Private, 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;
> +  }
> +  InsertTailList (&Nic->TokenList, &ConfigToken->Link);
> +
> +  ConfigToken->Signature = WIFI_MGR_MAC_CONFIG_TOKEN_SIGNATURE;
> +  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->Private, 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->Private, TRUE, NULL);
> +      Status                     = EFI_SUCCESS;
> +    } else {
> +      if (Nic->OneTimeDisconnectRequest) {
> +
> +        WifiMgrUpdateConnectMessage (ConfigToken->Nic->Private, FALSE,
> L"Disconnect Failed: Unexpected Error!");
> +      }
> +
> +      Nic->ConnectState     = WifiMgrConnectedToAp;
> +      WifiMgrUpdateConnectMessage (ConfigToken->Nic->Private, 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..d38c391bbf
> --- /dev/null
> +++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrImpl.h
> @@ -0,0 +1,123 @@
> +/** @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
> +  );
> +
> +/**
> +  Update connection message on connect configuration page, and trigger
> related form refresh.
> +
> +  @param[in]   Private                    The pointer to the global private
> data structure.
> +  @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_PRIVATE_DATA     *Private,
> +  IN  BOOLEAN                   ConnectStateChanged,
> +  IN  EFI_STRING                ConnectStatusMessage
> +  );
> +
> +/**
> +  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..3562734040
> --- /dev/null
> +++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrMisc.c
> @@ -0,0 +1,784 @@
> +/** @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:
> +
> +      RemoveEntryList (&ConfigToken->Link);
> +
> +      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:
> +
> +      RemoveEntryList (&ConfigToken->Link);
> +
> +      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:
> +
> +      RemoveEntryList (&ConfigToken->Link);
> +
> +      if (ConfigToken->Token.DisconnectNetworkToken != NULL) {
> +
> +        FreePool(ConfigToken->Token.DisconnectNetworkToken);
> +      }
> +
> +      FreePool (ConfigToken);
> +      break;
> +
> +    default :
> +      break;
> +  }
> +}
> +
> +/**
> +  Free all tokens in a token list.
> +
> +  @param[in]   TokenList          The token list to be freed.
> +
> +**/
> +VOID
> +WifiMgrFreeTokenList (
> +  IN   LIST_ENTRY                 *TokenList
> +  )
> +{
> +  WIFI_MGR_MAC_CONFIG_TOKEN       *ConfigToken;
> +  LIST_ENTRY                      *Entry;
> +  LIST_ENTRY                      *NextEntry;
> +
> +  if (TokenList == NULL) {
> +    return;
> +  }
> +
> +  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, TokenList) {
> +
> +    ConfigToken = NET_LIST_USER_STRUCT_S (Entry, WIFI_MGR_MAC_CONFIG_TOKEN,
> +                    Link, WIFI_MGR_MAC_CONFIG_TOKEN_SIGNATURE);
> +    WifiMgrFreeToken (ConfigToken);
> +  }
> +}
> +
> diff --git a/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrMisc.h
> b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrMisc.h
> new file mode 100644
> index 0000000000..10e170fde0
> --- /dev/null
> +++ b/NetworkPkg/WifiConnectionManagerDxe/WifiConnectionMgrMisc.h
> @@ -0,0 +1,279 @@
> +/** @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
> +  );
> +
> +/**
> +  Free all tokens in a token list.
> +
> +  @param[in]   TokenList          The token list to be freed.
> +
> +**/
> +VOID
> +WifiMgrFreeTokenList (
> +  IN   LIST_ENTRY              *TokenList
> +  );
> +
> +#endif
> --
> 2.16.2.windows.1



  reply	other threads:[~2019-02-20  3:57 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-02-15  3:07 [Patch] NetworkPkg: Add WiFi Connection Manager to NetworkPkg Wang Fan
2019-02-20  3:57 ` Fu, Siyuan [this message]
2019-02-22  8:11   ` Wang, Fan
2019-02-22  9:01     ` Fu, Siyuan
2019-02-22  9:51       ` Wang, Fan

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=B1FF2E9001CE9041BD10B825821D5BC58B6E9D2E@SHSMSX103.ccr.corp.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