/** @file
  Header file for the SC Bios Write Protect Driver.

@copyright
  INTEL CONFIDENTIAL
  Copyright 2011 - 2017 Intel Corporation.

  The source code contained or described herein and all documents related to the
  source code ("Material") are owned by Intel Corporation or its suppliers or
  licensors. Title to the Material remains with Intel Corporation or its suppliers
  and licensors. The Material may contain trade secrets and proprietary and
  confidential information of Intel Corporation and its suppliers and licensors,
  and is protected by worldwide copyright and trade secret laws and treaty
  provisions. No part of the Material may be used, copied, reproduced, modified,
  published, uploaded, posted, transmitted, distributed, or disclosed in any way
  without Intel's prior express written permission.

  No license under any patent, copyright, trade secret or other intellectual
  property right is granted to or conferred upon you by disclosure or delivery
  of the Materials, either expressly, by implication, inducement, estoppel or
  otherwise. Any license under such intellectual property rights must be
  express and approved by Intel in writing.

  Unless otherwise agreed by Intel in writing, you may not remove or alter
  this notice or any other notice embedded in Materials by Intel or
  Intel's suppliers or licensors in any way.

  This file contains a 'Sample Driver' and is licensed as such under the terms
  of your license agreement with Intel or your vendor. This file may be modified
  by the user, subject to the additional terms of the license agreement.

@par Specification
**/

#ifndef _ESPI_SMI_H_
#define _ESPI_SMI_H_

#include <Library/IoLib.h>
#include <Library/DebugLib.h>
#include <Library/HobLib.h>
#include <ScAccess.h>
#include <Protocol/SmmIchnDispatch.h>
#include <Protocol/SmmSwDispatch2.h>

#include <Protocol/ScEspiSmiDispatch.h>
#include <Private/Guid/ScPolicyHobGuid.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/SmmServicesTableLib.h>
#include <Library/MmPciLib.h>


#include "ScSmmHelpers.h"



#define ESPI_SMI_INSTANCE_SIGNATURE       SIGNATURE_32 ('E', 'S', 'P', 'I')

#define ESPI_SMI_INSTANCE_SIGNATURE       SIGNATURE_32 ('E', 'S', 'P', 'I')
#define ESPI_SMI_RECORD_SIGNATURE         SIGNATURE_32 ('E', 'S', 'R', 'C')

#define ESPI_INSTANCE_FROM_THIS(_this)      CR (_this, ESPI_SMI_INSTANCE, EfiEspiSmiDispatchProtocol, ESPI_SMI_INSTANCE_SIGNATURE)
#define ESPI_RECORD_FROM_LINK(_link)        CR (_link, ESPI_SMI_RECORD, Link, ESPI_SMI_RECORD_SIGNATURE)

typedef enum {
  EspiBiosWrProtect,    ///< BIOS Write Protect
  EspiSerialIrq,        ///< eSPI Master Asserted SMI
  EspiPmc,              ///< eSPI PMC SMI
  EspiTopLevelTypeMax
} ESPI_TOP_LEVEL_TYPE;

typedef enum {
  BiosWrProtect,        ///< BIOS Write Protect
  BiosWrReport,         ///< Peripheral Channel BIOS Write Protect
  PcNonFatalErr,        ///< Peripheral Channel Non Fatal Error
  PcFatalErr,           ///< Peripheral Channel Fatal Error
  VwNonFatalErr,        ///< Virtual Wire Non Fatal Error
  VwFatalErr,           ///< Virtual Wire Fatal Error
  FlashNonFatalErr,     ///< Flash Channel Non Fatal Error
  FlashFatalErr,        ///< Flash Channel Fatal Error
  LnkType1Err,          ///< Link Error
  EspiSlaveSmi,         ///< Espi Slave SMI
  EspiSmiTypeMax
} ESPI_SMI_TYPE;

typedef struct {
  ESPI_SMI_TYPE Start;
  ESPI_SMI_TYPE End;
} ESPI_SMI_TYPE_BARRIER;


typedef struct _ESPI_SMI_INSTANCE {
  ///
  /// Signature associated with this instance
  ///
  UINT32                          Signature;
  ///
  /// EFI_HANDLE acquired when installing PchEspiSmiDispatchProtocol
  ///
  EFI_HANDLE                      Handle;
  ///
  /// The protocol to register or unregister eSPI SMI callbacks
  ///
  SC_ESPI_SMI_DISPATCH_PROTOCOL  ScEspiSmiDispatchProtocol;
  ///
  /// The handle acquired when registering eSPI SMI callback to PchSmiDispatch
  ///
  EFI_HANDLE                      ScSmiEspiHandle[EspiTopLevelTypeMax];
  ///
  /// The linked list for record database.
  ///
  LIST_ENTRY                      CallbackDataBase[EspiSmiTypeMax];
  ///
  /// This is an internal counter to track the number of eSPI master events have been registered.
  /// When unregistering, we can disable the SMI if the counter is zero
  ///
  UINTN                           EspiSmiEventCounter[EspiSmiTypeMax];
  ///
  /// Instance of barrier
  ///
  CONST ESPI_SMI_TYPE_BARRIER     Barrier[EspiTopLevelTypeMax];
} ESPI_SMI_INSTANCE;



typedef struct _ESPI_SMI_RECORD {
  UINT32                          Signature;
  LIST_ENTRY                      Link;
  SC_ESPI_SMI_DISPATCH_CALLBACK  Callback;
} ESPI_SMI_RECORD;


/**
  Installs and initialize this protocol

  @param[in]  ImageHandle   Not used

  @retval     EFI_SUCCESS   Installation succeed
  @retval     others        Installation failed
**/
EFI_STATUS
EFIAPI
InstallEspiSmi (
  IN EFI_HANDLE           ImageHandle
  );

EFI_STATUS
EFIAPI
EspiSlaveSmiRegister (
  IN  SC_ESPI_SMI_DISPATCH_PROTOCOL    *This,
  IN  SC_ESPI_SMI_DISPATCH_CALLBACK    DispatchFunction,
  OUT EFI_HANDLE                        *DispatchHandle
  );

/**
  eSPI SMI Dispatch Protocol instance to unregister a callback based on handle

  @param[in]  This                    Not used
  @param[in]  DispatchHandle          Handle acquired during registration

  @retval     EFI_SUCCESS             Unregister successful
  @retval     EFI_INVALID_PARAMETER   DispatchHandle is null
  @retval     EFI_INVALID_PARAMETER   DispatchHandle's forward link has bad pointer
  @retval     EFI_INVALID_PARAMETER   DispatchHandle does not exist in database
  @retval     EFI_ACCESS_DENIED       Unregistration is done after end of DXE
  @retval     EFI_ACCESS_DENIED       DispatchHandle is not allowed to unregistered
**/
EFI_STATUS
EFIAPI
EspiSmiUnRegister (
  IN  SC_ESPI_SMI_DISPATCH_PROTOCOL  *This,
  IN  EFI_HANDLE                      DispatchHandle
  );

EFI_STATUS
ScSmiRecordInsert (
  IN  SC_SMM_SOURCE_DESC               *SrcDesc,
  IN  SC_SMI_CALLBACK_FUNCTIONS        DispatchFunction,
  IN  EFI_SMM_ICHN_SMI_TYPE                     ScSmiType,
  OUT EFI_HANDLE                        *DispatchHandle
  );

#endif
