Files
system76-edk2/QuarkSocPkg/QuarkNorthCluster/Smm/DxeSmm/QncSmmDispatcher/QNCSmm.h
2019-04-09 10:58:22 -07:00

869 lines
20 KiB
C

/** @file
Prototypes and defines for the QNC SMM Dispatcher.
Copyright (c) 2013-2016 Intel Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef QNC_SMM_H
#define QNC_SMM_H
//
// Include common header file for this module.
//
#include "CommonHeader.h"
#include "QNCSmmRegisters.h"
extern EFI_HANDLE mQNCSmmDispatcherImageHandle;
//
// /////////////////////////////////////////////////////////////////////////////
// SUPPORTED PROTOCOLS
//
//
// Define an enumeration for all the supported protocols
//
typedef enum {
// UsbType, DELETE:on QuarkNcSocId, there is no usb smi supported
SxType,
SwType,
GpiType,
QNCnType,
PowerButtonType,
PeriodicTimerType,
NUM_PROTOCOLS
} QNC_SMM_PROTOCOL_TYPE;
//
// /////////////////////////////////////////////////////////////////////////////
// SPECIFYING A REGISTER
// We want a general way of referring to addresses. For this case, we'll only
// need addresses in the ACPI table (and the TCO entries within the ACPI table).
// However, it's interesting to consider what it would take to support other types
// of addresses. To address Will's concern, I think it prudent to accommodate it
// early on in the design.
//
// Addresses we need to consider:
//
// Type: Required:
// I/O Yes
// ACPI (special case of I/O) Only if we want to
// TCO (special case of ACPI) Only if we want to
// Memory (or Memory Mapped I/O) Only if we want to
// PCI Yes, for BiosWp
//
typedef enum {
//
// IO_ADDR_TYPE, // unimplemented
//
ACPI_ADDR_TYPE,
GPE_ADDR_TYPE,
//
// MEMORY_ADDR_TYPE, // unimplemented
//
MEMORY_MAPPED_IO_ADDRESS_TYPE,
PCI_ADDR_TYPE,
NUM_ADDR_TYPES, // count of items in this enum
QNC_SMM_ADDR_TYPE_NULL = -1 // sentinel to indicate NULL or to signal end of arrays
} ADDR_TYPE;
//
// Assumption: 32-bits -- enum's evaluate to integer
// Assumption: This code will only run on IA-32. Justification: IA-64 doesn't have SMIs.
// We don't have to worry about 64-bit addresses.
// Typedef the size of addresses in case the numbers I'm using are wrong or in case
// this changes. This is a good idea because PCI_ADDR will change, for example, when
// we add support for PciExpress.
//
typedef UINT16 IO_ADDR;
typedef IO_ADDR ACPI_ADDR; // can omit
typedef IO_ADDR GPE_ADDR; // can omit
typedef IO_ADDR TCO_ADDR; // can omit
typedef VOID *MEM_ADDR;
typedef MEM_ADDR MEMORY_MAPPED_IO_ADDRESS;
typedef union {
UINT32 Raw;
struct {
UINT8 Reg;
UINT8 Fnc;
UINT8 Dev;
UINT8 Bus;
} Fields;
} PCI_ADDR;
typedef struct {
ADDR_TYPE Type;
union {
//
// used to initialize during declaration/definition
//
UINTN raw;
//
// used to access useful data
//
IO_ADDR io;
ACPI_ADDR acpi;
GPE_ADDR gpe;
TCO_ADDR tco;
MEM_ADDR mem;
MEMORY_MAPPED_IO_ADDRESS Mmio;
PCI_ADDR pci;
} Data;
} QNC_SMM_ADDRESS;
//
// Assumption: total size is 64 bits (32 for type and 32 for data) or 8 bytes
//
#define EFI_PCI_ADDRESS_PORT 0xcf8
#define EFI_PCI_DATA_PORT 0xcfc
//
// /////////////////////////////////////////////////////////////////////////////
// SPECIFYING BITS WITHIN A REGISTER
// Here's a struct that helps us specify a source or enable bit.
//
typedef struct {
QNC_SMM_ADDRESS Reg;
UINT8 SizeInBytes; // of the register
UINT8 Bit;
} QNC_SMM_BIT_DESC;
//
// Sometimes, we'll have bit descriptions that are unused. It'd be great to have a
// way to easily identify them:
//
#define IS_BIT_DESC_NULL(BitDesc) ((BitDesc).Reg.Type == QNC_SMM_ADDR_TYPE_NULL) // "returns" true when BitDesc is NULL
#define NULL_THIS_BIT_DESC(BitDesc) ((BitDesc).Reg.Type = QNC_SMM_ADDR_TYPE_NULL) // will "return" an integer w/ value of 0
#define NULL_BIT_DESC_INITIALIZER \
{ \
{ \
QNC_SMM_ADDR_TYPE_NULL, \
{ \
0 \
} \
}, \
0, 0 \
}
//
// I'd like a type to specify the callback's Sts & En bits because they'll
// be commonly used together:
//
#define NUM_EN_BITS 2
#define NUM_STS_BITS 1
//
// Flags
//
typedef UINT8 QNC_SMM_SOURCE_FLAGS;
//
// Flags required today
//
#define QNC_SMM_NO_FLAGS 0
#define QNC_SMM_SCI_EN_DEPENDENT (BIT0)
#define QNC_SMM_CLEAR_WITH_ZERO (BIT6)
//
// Flags that might be required tomorrow
// #define QNC_SMM_CLEAR_WITH_ONE 2 // may need to support bits that clear by writing 0
// #define QNC_SMM_MULTIBIT_FIELD 3 // may need to support status/enable fields 2 bits wide
//
typedef struct {
QNC_SMM_SOURCE_FLAGS Flags;
QNC_SMM_BIT_DESC En[NUM_EN_BITS];
QNC_SMM_BIT_DESC Sts[NUM_STS_BITS];
} QNC_SMM_SOURCE_DESC;
//
// 31 bytes, I think
//
#define NULL_SOURCE_DESC_INITIALIZER \
{ \
QNC_SMM_NO_FLAGS, \
{ \
NULL_BIT_DESC_INITIALIZER, NULL_BIT_DESC_INITIALIZER \
}, \
{ \
NULL_BIT_DESC_INITIALIZER \
} \
}
//
// /////////////////////////////////////////////////////////////////////////////
// CHILD CONTEXTS
// To keep consistent w/ the architecture, we'll need to provide the context
// to the child when we call its callback function. After talking with Will,
// we agreed that we'll need functions to "dig" the context out of the hardware
// in many cases (Sx, Trap, Gpi, etc), and we'll need a function to compare those
// contexts to prevent unnecessary dispatches. I'd like a general type for these
// "GetContext" functions, so I'll need a union of all the protocol contexts for
// our internal use:
//
typedef union {
//
// (in no particular order)
//
EFI_SMM_ICHN_REGISTER_CONTEXT QNCn;
EFI_SMM_SX_REGISTER_CONTEXT Sx;
EFI_SMM_PERIODIC_TIMER_REGISTER_CONTEXT PeriodicTimer;
EFI_SMM_SW_REGISTER_CONTEXT Sw;
EFI_SMM_POWER_BUTTON_REGISTER_CONTEXT PowerButton;
// EFI_SMM_USB_REGISTER_CONTEXT Usb; DELETE:on QuarkNcSocId, there is no usb smi supported
EFI_SMM_GPI_REGISTER_CONTEXT Gpi;
} QNC_SMM_CONTEXT;
typedef union {
//
// (in no particular order)
//
EFI_SMM_SW_CONTEXT Sw;
EFI_SMM_PERIODIC_TIMER_CONTEXT PeriodicTimer;
} QNC_SMM_BUFFER;
//
// Assumption: PeriodicTimer largest at 3x64-bits or 24 bytes
//
typedef struct _DATABASE_RECORD DATABASE_RECORD;
typedef
VOID
(EFIAPI *GET_CONTEXT) (
IN DATABASE_RECORD * Record,
OUT QNC_SMM_CONTEXT * Context
);
//
// Assumption: the GET_CONTEXT function will be as small and simple as possible.
// Assumption: We don't need to pass in an enumeration for the protocol because each
// GET_CONTEXT function is written for only one protocol.
// We also need a function to compare contexts to see if the child should be dispatched
//
typedef
BOOLEAN
(EFIAPI *CMP_CONTEXT) (
IN QNC_SMM_CONTEXT * Context1,
IN QNC_SMM_CONTEXT * Context2
);
/*
Returns: True when contexts are equivalent; False otherwise
*/
//
// This function is used to get the content of CommBuffer that will be passed
// to Callback function
//
typedef
VOID
(EFIAPI *GET_BUFFER) (
IN DATABASE_RECORD * Record
);
//
// Finally, every protocol will require a "Get Context", "Compare Context"
// and "Get CommBuffer" call, so we may as well wrap that up in a table, too.
//
typedef struct {
GET_CONTEXT GetContext;
CMP_CONTEXT CmpContext;
GET_BUFFER GetBuffer;
} CONTEXT_FUNCTIONS;
extern CONTEXT_FUNCTIONS ContextFunctions[NUM_PROTOCOLS];
//
// /////////////////////////////////////////////////////////////////////////////
// MAPPING CONTEXT TO BIT DESCRIPTIONS
// I'd like to have a general approach to mapping contexts to bit descriptions.
// Sometimes, we'll find that we can use table lookups or CONSTant assignments;
// other times, we'll find that we'll need to use a function to perform the mapping.
// If we define a macro to mask that process, we'll never have to change the code.
// I don't know if this is desirable or not -- if it isn't, then we can get rid
// of the macros and just use function calls or variable assignments. Doesn't matter
// to me.
// Mapping complex contexts requires a function
//
// DELETE:on QuarkNcSocId, there is no usb smi supported
//EFI_STATUS
//EFIAPI
//MapUsbToSrcDesc (
// IN QNC_SMM_CONTEXT *RegisterContext,
// OUT QNC_SMM_SOURCE_DESC *SrcDesc
// )
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
RegisterContext - GC_TODO: add argument description
SrcDesc - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
EFI_STATUS
MapPeriodicTimerToSrcDesc (
IN QNC_SMM_CONTEXT *RegisterContext,
OUT QNC_SMM_SOURCE_DESC *SrcDesc
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
RegisterContext - GC_TODO: add argument description
SrcDesc - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
//
// Mapping simple contexts can be done by assignment or lookup table
//
extern CONST QNC_SMM_SOURCE_DESC SW_SOURCE_DESC;
extern CONST QNC_SMM_SOURCE_DESC SX_SOURCE_DESC;
//
// With the changes we've made to the protocols, we can now use table
// lookups for the following protocols:
//
extern CONST QNC_SMM_SOURCE_DESC GPI_SOURCE_DESC;
extern QNC_SMM_SOURCE_DESC QNCN_SOURCE_DESCS[NUM_ICHN_TYPES];
//
// For QNCx, APMC is UINT8 port, so the MAX SWI Value is 0xFF.
//
#define MAXIMUM_SWI_VALUE 0xFF
//
// Open: Need to make sure this kind of type cast will actually work.
// May need an intermediate form w/ two VOID* arguments. I'll figure
// that out when I start compiling.
///////////////////////////////////////////////////////////////////////////////
//
typedef
VOID
(EFIAPI *QNC_SMM_CLEAR_SOURCE) (
QNC_SMM_SOURCE_DESC * SrcDesc
);
//
// /////////////////////////////////////////////////////////////////////////////
// "DATABASE" RECORD
// Linked list data structures
//
#define DATABASE_RECORD_SIGNATURE SIGNATURE_32 ('D', 'B', 'R', 'C')
struct _DATABASE_RECORD {
UINT32 Signature;
LIST_ENTRY Link;
BOOLEAN Processed;
//
// Status and Enable bit description
//
QNC_SMM_SOURCE_DESC SrcDesc;
//
// Callback function
//
EFI_SMM_HANDLER_ENTRY_POINT2 Callback;
QNC_SMM_CONTEXT ChildContext;
VOID *CallbackContext;
QNC_SMM_BUFFER CommBuffer;
UINTN BufferSize;
//
// Special handling hooks -- init them to NULL if unused/unneeded
//
QNC_SMM_CLEAR_SOURCE ClearSource; // needed for SWSMI timer
// Functions required to make callback code general
//
CONTEXT_FUNCTIONS ContextFunctions;
//
// The protocol that this record dispatches
//
QNC_SMM_PROTOCOL_TYPE ProtocolType;
};
#define DATABASE_RECORD_FROM_LINK(_record) CR (_record, DATABASE_RECORD, Link, DATABASE_RECORD_SIGNATURE)
#define DATABASE_RECORD_FROM_CONTEXT(_record) CR (_record, DATABASE_RECORD, ChildContext, DATABASE_RECORD_SIGNATURE)
//
// /////////////////////////////////////////////////////////////////////////////
// HOOKING INTO THE ARCHITECTURE
//
typedef
EFI_STATUS
(EFIAPI *QNC_SMM_GENERIC_REGISTER) (
IN VOID **This,
IN VOID *DispatchFunction,
IN VOID *RegisterContext,
OUT EFI_HANDLE * DispatchHandle
);
typedef
EFI_STATUS
(EFIAPI *QNC_SMM_GENERIC_UNREGISTER) (
IN VOID **This,
IN EFI_HANDLE DispatchHandle
);
//
// Define a memory "stamp" equivalent in size and function to most of the protocols
//
typedef struct {
QNC_SMM_GENERIC_REGISTER Register;
QNC_SMM_GENERIC_UNREGISTER Unregister;
UINTN Extra1;
UINTN Extra2; // may not need this one
} QNC_SMM_GENERIC_PROTOCOL;
EFI_STATUS
QNCSmmCoreRegister (
IN QNC_SMM_GENERIC_PROTOCOL *This,
IN EFI_SMM_HANDLER_ENTRY_POINT2 DispatchFunction,
IN QNC_SMM_CONTEXT *RegisterContext,
OUT EFI_HANDLE *DispatchHandle
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
This - GC_TODO: add argument description
DispatchFunction - GC_TODO: add argument description
RegisterContext - GC_TODO: add argument description
DispatchHandle - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
EFI_STATUS
QNCSmmCoreUnRegister (
IN QNC_SMM_GENERIC_PROTOCOL *This,
IN EFI_HANDLE DispatchHandle
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
This - GC_TODO: add argument description
DispatchHandle - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
typedef union {
QNC_SMM_GENERIC_PROTOCOL Generic;
// EFI_SMM_USB_DISPATCH2_PROTOCOL Usb; DELETE:on QuarkNcSocId, there is no usb smi supported
EFI_SMM_SX_DISPATCH2_PROTOCOL Sx;
EFI_SMM_SW_DISPATCH2_PROTOCOL Sw;
EFI_SMM_GPI_DISPATCH2_PROTOCOL Gpi;
EFI_SMM_ICHN_DISPATCH2_PROTOCOL QNCn;
EFI_SMM_POWER_BUTTON_DISPATCH2_PROTOCOL PowerButton;
EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL PeriodicTimer;
} QNC_SMM_PROTOCOL;
//
// Define a structure to help us identify the generic protocol
//
#define PROTOCOL_SIGNATURE SIGNATURE_32 ('P', 'R', 'O', 'T')
typedef struct {
UINTN Signature;
QNC_SMM_PROTOCOL_TYPE Type;
EFI_GUID *Guid;
QNC_SMM_PROTOCOL Protocols;
} QNC_SMM_QUALIFIED_PROTOCOL;
#define QUALIFIED_PROTOCOL_FROM_GENERIC(_generic) \
CR (_generic, \
QNC_SMM_QUALIFIED_PROTOCOL, \
Protocols, \
PROTOCOL_SIGNATURE \
)
//
// Create private data for the protocols that we'll publish
//
typedef struct {
LIST_ENTRY CallbackDataBase;
EFI_HANDLE SmiHandle;
EFI_HANDLE InstallMultProtHandle;
QNC_SMM_QUALIFIED_PROTOCOL Protocols[NUM_PROTOCOLS];
} PRIVATE_DATA;
extern PRIVATE_DATA mPrivateData;
//
// /////////////////////////////////////////////////////////////////////////////
//
VOID
EFIAPI
SwGetContext (
IN DATABASE_RECORD *Record,
OUT QNC_SMM_CONTEXT *Context
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Record - GC_TODO: add argument description
Context - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
BOOLEAN
EFIAPI
SwCmpContext (
IN QNC_SMM_CONTEXT *Context1,
IN QNC_SMM_CONTEXT *Context2
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Context1 - GC_TODO: add argument description
Context2 - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
VOID
SwGetBuffer (
IN DATABASE_RECORD * Record
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Record - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
VOID
EFIAPI
SxGetContext (
IN DATABASE_RECORD *Record,
OUT QNC_SMM_CONTEXT *Context
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Record - GC_TODO: add argument description
Context - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
BOOLEAN
EFIAPI
SxCmpContext (
IN QNC_SMM_CONTEXT *Context1,
IN QNC_SMM_CONTEXT *Context2
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Context1 - GC_TODO: add argument description
Context2 - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
VOID
EFIAPI
PeriodicTimerGetContext (
IN DATABASE_RECORD *Record,
OUT QNC_SMM_CONTEXT *Context
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Record - GC_TODO: add argument description
Context - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
BOOLEAN
EFIAPI
PeriodicTimerCmpContext (
IN QNC_SMM_CONTEXT *Context1,
IN QNC_SMM_CONTEXT *Context2
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Context1 - GC_TODO: add argument description
Context2 - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
VOID
PeriodicTimerGetBuffer (
IN DATABASE_RECORD * Record
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Record - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
VOID
EFIAPI
PowerButtonGetContext (
IN DATABASE_RECORD *Record,
OUT QNC_SMM_CONTEXT *Context
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Record - GC_TODO: add argument description
Context - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
BOOLEAN
EFIAPI
PowerButtonCmpContext (
IN QNC_SMM_CONTEXT *Context1,
IN QNC_SMM_CONTEXT *Context2
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Context1 - GC_TODO: add argument description
Context2 - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
//
// /////////////////////////////////////////////////////////////////////////////
//
VOID
EFIAPI
QNCSmmPeriodicTimerClearSource (
QNC_SMM_SOURCE_DESC *SrcDesc
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
SrcDesc - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
EFI_STATUS
QNCSmmPeriodicTimerDispatchGetNextShorterInterval (
IN CONST EFI_SMM_PERIODIC_TIMER_DISPATCH2_PROTOCOL *This,
IN OUT UINT64 **SmiTickInterval
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
This - GC_TODO: add argument description
SmiTickInterval - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
VOID
QNCSmmSxGoToSleep (
VOID
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
None
Returns:
GC_TODO: add return values
--*/
;
VOID
EFIAPI
QNCSmmQNCnClearSource (
QNC_SMM_SOURCE_DESC *SrcDesc
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
SrcDesc - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
;
#endif