/** @file
  This file contains definitions and structures necessary for
  Command Queue interoperability between CSE Variable Storage
  Runtime DXE and SMM modules.

 @copyright
  INTEL CONFIDENTIAL
  Copyright 2016 - 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 an 'Intel Peripheral Driver' and is uniquely identified as
  "Intel Reference Module" and is licensed for Intel CPUs and chipsets under
  the terms of your license agreement with Intel or your vendor. This file may
  be modified by the user, subject to additional terms of the license agreement.

@par Specification Reference:
**/

#ifndef _CSE_VARIABLE_STORAGE_COMMAND_QUEUE_H_
#define _CSE_VARIABLE_STORAGE_COMMAND_QUEUE_H_

#include <Base.h>
#include <Uefi.h>

#include <Library/BaseLib.h>
#include <Library/Heci2MsgLib.h>
#include <Library/PcdLib.h>

//
// Set the bit below the upper bit to indicate an OEM defined status value
//
#define ENCODE_OEM_WARNING(a)         ((MAX_BIT >> 1) | (a))

//
// Define a warning to indicate a required Host OS driver is not present
//
#define EFI_WARN_OS_DRIVER_NOT_PRESENT ENCODE_OEM_WARNING (0x2B3E53BA)

// TODO: Some of these should be converted to Silicon PCDs and moved to other places.
//   They need to be made available in a generic build-file-level manner.
//   For now, performing calculations based on macros in Heci2MsgLib.
//
//   External values required: HECI2_BIOS_MAX_READ_MSG_SIZE, HECI2_BIOS_MAX_WRITE_MSG_SIZE,
//                             HECI2_TRUSTED_CHANNEL_BIOS_READ_RESP, HECI2_TRUSTED_CHANNEL_BIOS_WRITE_REQ,
//                             CMD_QUEUE_MAX_TRANS_COUNT, PcdMaxVariableSize

//
// Determine worst case scenario to calculate command queue buffer size required
//
#define CEILING(DATA_SIZE,CHUNK_SIZE) (((DATA_SIZE) + (CHUNK_SIZE) - 1) / (CHUNK_SIZE))

//
// Calculate actual maximum data chunk size (headers taken into account)
//
#define  HECI2_MAX_READ_TRANS_SIZE    ((HECI2_BIOS_MAX_READ_MSG_SIZE) - sizeof (HECI2_TRUSTED_CHANNEL_BIOS_READ_RESP))
#define  HECI2_MAX_WRITE_TRANS_SIZE   ((HECI2_BIOS_MAX_WRITE_MSG_SIZE) - sizeof (HECI2_TRUSTED_CHANNEL_BIOS_WRITE_REQ))

//
// Calculate chunks required for the respective maximum size
//
#define  HECI2_MAX_READ_CHUNKS        (CEILING (FixedPcdGet32 (PcdMaxVariableSize), HECI2_MAX_READ_TRANS_SIZE))
#define  HECI2_MAX_WRITE_CHUNKS       (CEILING (FixedPcdGet32 (PcdMaxVariableSize), HECI2_MAX_WRITE_TRANS_SIZE))

#define  CMD_QUEUE_MAX_TRANS_COUNT    5

//
// Total command queue buffer size needed for this silicon scenario
//
#define  CMD_QUEUE_TOTAL_BUFFER_SIZE  ( \
                                        (CMD_QUEUE_MAX_TRANS_COUNT) * \
                                        MAX (HECI2_MAX_READ_CHUNKS, HECI2_MAX_WRITE_CHUNKS) * \
                                        MAX (HECI2_MAX_READ_TRANS_SIZE, HECI2_MAX_WRITE_TRANS_SIZE) \
                                        )
#define CMD_QUEUE_SINGLE_CMD_BUFFER_SIZE ( \
                                           CMD_QUEUE_TOTAL_BUFFER_SIZE / \
                                           CMD_QUEUE_MAX_TRANS_COUNT \
                                           )
#pragma pack(push, 1)

//
// This structure is used for communication with CSE Variable Storage SMIs.
//
typedef struct {
  UINTN       Function;
  EFI_STATUS  ReturnStatus;
  UINT8       Data[1];
} SMM_CSE_VARIABLE_STORAGE_COMMUNICATE_HEADER;

//
// This structure is used in an SMI to get the communicate payload size from SMM.
//
typedef struct {
  UINTN       PayloadSize;
} SMM_CSE_VARIABLE_STORAGE_COMMUNICATE_GET_PAYLOAD_SIZE;

//
// This structure is used in an SMI to get the variable storage command queue from SMM.
// This represents the initial command structure in the queue.
//
typedef struct {
  UINTN                              CommandQueueCount;          ///< The total number of commands in the queue
  HECI2_TRUSTED_CHANNEL_BIOS_HEADER  CommandQueueDataBuffer[1];  ///< The command queue data (command requests)
} SMM_CSE_VARIABLE_STORAGE_COMMUNICATE_GET_COMMAND_QUEUE;

//
// This structure is used in an SMI to send HMAC response data to SMM for verification.
// This represents the header of the verification data payload.
//
typedef struct {
  BOOLEAN                            IsLastCommand;             ///< Indicates if this is the final command in the current
                                                                ///< dispatch sequence.
  UINTN                              TrustedChannelHeaderSize;  ///< Total size of the trusted channel response header.
                                                                ///< E.g. read or write response trusted header.
  HECI2_TRUSTED_CHANNEL_BIOS_HEADER  Data[1];                   ///< The command response data to be verified
} SMM_CSE_VARIABLE_STORAGE_COMMUNICATE_VERIFY_RESPONSE;

//
// This structure is used in an SMI to get the CSE OS proxy driver HECI message header from SMM.
//
typedef enum {
  HeciProxyStateUnknown     = 0,
  HeciProxyStatePresent     = 1,
  HeciProxyStateNotPresent  = 2
} HECI_PROXY_STATE;

typedef struct {
  HECI2_TRUSTED_CHANNEL_BIOS_HEADER  MessageHeader;
  HECI_PROXY_STATE                   ProxyState;
} SMM_CSE_VARIABLE_STORAGE_COMMUNICATE_GET_PROXYSTATE_MSG_HEADER;

typedef struct {
  HECI_PROXY_STATE                   ProxyState;
} SMM_CSE_VARIABLE_STORAGE_COMMUNICATE_SET_PROXYSTATE_MSG_HEADER;

//
// This structure is used to output debug messages from within Runtime DXE
//
typedef struct {
  CHAR8       DebugMsg[100];
  UINT8       Length;
  UINT8       Datalength;
  UINT8       Data[4096];
} SMM_CSE_VARIABLE_STORAGE_COMMUNICATE_DEBUG_MSG;

#pragma pack(pop)

///
/// Size of the SMM communicate header excluding the payload.
///
#define SMM_COMMUNICATE_HEADER_SIZE  (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data))

///
/// Size of SMM CSE variable storage communicate header excluding the payload.
///
#define SMM_CSE_VARIABLE_STORAGE_COMMUNICATE_HEADER_SIZE  (OFFSET_OF (SMM_CSE_VARIABLE_STORAGE_COMMUNICATE_HEADER, Data))

//
// The payload for this function is SMM_CSE_VARIABLE_STORAGE_COMMUNICATE_GET_PAYLOAD_SIZE.
//
#define SMM_CSE_VARIABLE_STORAGE_FUNCTION_GET_PAYLOAD_SIZE           1

//
// The payload for this function is SMM_CSE_VARIABLE_STORAGE_COMMUNICATE_GET_COMMAND_QUEUE.
//
#define SMM_CSE_VARIABLE_STORAGE_FUNCTION_GET_COMMAND_QUEUE          2

//
// The payload for this function is SMM_CSE_VARIABLE_STORAGE_COMMUNICATE_VERIFY_RESPONSE.
//
#define SMM_CSE_VARIABLE_STORAGE_FUNCTION_VERIFY_RESPONSE            3

//
// The payload for this function is SMM_CSE_VARIABLE_STORAGE_COMMUNICATE_GET_PROXYSTATE_MSG_HEADER.
//
#define SMM_CSE_VARIABLE_STORAGE_FUNCTION_GET_PROXY_STATE            4

//
// There is no payload for this function
//
#define SMM_CSE_VARIABLE_STORAGE_FUNCTION_RESET_COMMAND_QUEUE        5

//
// The payload for this function is SMM_CSE_VARIABLE_STORAGE_COMMUNICATE_SET_PROXYSTATE_MSG_HEADER.
//
#define SMM_CSE_VARIABLE_STORAGE_FUNCTION_SET_PROXY_STATE            6

//
// Temporary for debug messages
//
#define SMM_CSE_VARIABLE_STORAGE_FUNCTION_DEBUG_MESSAGE              7

//
// Returns the total SMM communicate buffer size including the caller passed data size.
//
#define SMM_CSE_VARIABLE_STORAGE_GET_TOTAL_COMMUNICATE_BUFFER_SIZE(DataSize)\
  ((DataSize) + SMM_COMMUNICATE_HEADER_SIZE + SMM_CSE_VARIABLE_STORAGE_COMMUNICATE_HEADER_SIZE)

#endif
