# EDK2 Manageability Package

edk2 ManageabilityPkg is introduced to provide edk2 drivers and
libraries for industry platform management standards, such as PLDM (Platform
Level Data Model), MCTP (Management Component Transfer Protocol), IPMI
(Intelligent Platform Management Interface) and others. The framework of
ManageabilityPkg is designed to flexibly support the transport interfaces for above
industry standards, the transport interfaces such as KCS or I2C for IPMI, PCI VDM
(Vendor Defined Message), I2C or KCS for MCTP, or the OEM proprietary transports.

Below figure shows the driver stacks which are abstracted to support disparate
transports for specifications of platform management.
![Manageability Package Driver Stack](https://github.com/tianocore/edk2-platforms/blob/master/Features/ManageabilityPkg/Documents/Media/ManageabilityDriverStack.svg)

## Manageability Transport edk2 Driver Stack
edk2 manageability transport library is designed to incorporated with disparate
manageability protocols. In order to flexibly facilitating the transport
functionalities, below functions must be provided by manageability transport
library to compliant with the framework of ManageabilityPkg design.

* ### ***AcquireTransportSession()***
    edk2 manageability protocol driver invokes this function to acquire the
    transport session to transmit manageability packet. The implementation
    could reset the transport interface, initial the transport interface
    internal structure and the [Manageability Transport Function Structure](#manageability-transport-function-structure).
    The [Transport Token](#transfer-token) is returned to the caller for further manageability packet
    transmit and receive.


* ### ***GetTransportCapability()***
    edk2 Manageability protocol driver invokes this function to get the capabilities
    of transport interface. The implementation of manageability transport library
    can optionally support advanced features such as multi-sessions on transport
    interface or asynchronous transfer.

* ### ***ReleaseTransportSession()***
    edk2 manageability protocol driver invokes this function to release the transport
    session.

  ### **Manageability Transport Function Structure**

  Below is the function structure initiated by the manageability transport library and
  returned in the transport token when caller invokes [AcquireTransportSession](#acquiretransportsession)
  function.


    ***MANAGEABILITY_TRANSPORT_FUNCTION*** is declared as an union to accommodate
    different versions of transport function set. This allows the function added to
    support the new functionalities in the future and also keep the backward compatibility.
    Developers can not modify the previous version of function structure, instead
    developers can create a new function structure with the increased version number
    that includes the previous version of function set and new added functions.

```
    typedef union {
      MANAGEABILITY_TRANSPORT_FUNCTION_V1_0  *Version1_0;
    } MANAGEABILITY_TRANSPORT_FUNCTION;

    struct _MANAGEABILITY_TRANSPORT_FUNCTION_V1_0 {
      MANAGEABILITY_TRANSPORT_INIT              TransportInit;
      MANAGEABILITY_TRANSPORT_STATUS            TransportStatus;
      MANAGEABILITY_TRANSPORT_RESET             TransportReset;
      MANAGEABILITY_TRANSPORT_TRANSMIT_RECEIVE  TransportTransmitReceive;
    };
```
* ***TransportInit()***

    Manageability protocol driver invokes this function to initial the transport
    interface with the optional hardware configuration of the transport interface.
    Whether the transport interface requires initialization or not depends on the
    transport interface characteristics. The hardware information is optional passed to
    this function if the manageability protocol driver would like to use the different
    hardware configuration of transport interface. For example, the different I/O
    address of KCS interface, or the memory mapped I/O KCS interface. The structure
    format of hardware information is created according to the hardware design of
    transport interface.

* ***TransportStatus()***

    Manageability protocol driver invokes this function to get the status of transport
    interface. How does this function report the status depends on the transport
    interface characteristics and the implementation of this function.

* ***TransportReset()***

    Manageability protocol driver can invoke this function to reset and recover the
    transport interface in case the error status is reported by the transport
    interface. Whether the transport interface can be reset or not depends on the
    transport interface characteristics and the implementation of this function.

* ***TransportTransmitReceive()***
    Manageability protocol driver invokes this function to transmit and/or receive the
    packet. Caller has to setup the [Transfer Token](#transfer-token) when invoke to
    this function.

  ### **Transfer Token**

```
    struct _MANAGEABILITY_TRANSFER_TOKEN {
      EFI_EVENT                                  ReceiveEvent;
      MANAGEABILITY_TRANSPORT_HEADER             TransmitHeader;
      MANAGEABILITY_TRANSPORT_TRAILER            TransmitTrailer;
      MANAGEABILITY_TRANSMIT_PACKAGE             TransmitPackage;
      MANAGEABILITY_RECEIVE_PACKAGE              ReceivePackage;
      EFI_STATUS                                 TransferStatus;
      MANAGEABILITY_TRANSPORT_ADDITIONAL_STATUS  TransportAdditionalStatus;
    };
```

* ***ReceiveEvent***

    The optional EFI event is created to wait for the signal of response data
    readiness. The parameter is valid only if the transport interface supports
    asynchronous transfer. MANAGEABILITY_TRANSPORT_CAPABILITY_ASYNCHRONOUS_TRANSFER bit
    must be set in the returned *TransportCapability* parameter in
    [GetTransportCapability()](#gettransportcapability) to indicate the
    transport interface is capable for asynchronous transfer.

* ***TransmitHeader***

    The transmit header is different according to the disparate transport interfaces
    for the manageability protocol. For example, the transmit header is different when
    MCTP packet is transmitted over I2C and KCS. Having this header abstracted from
    manageability transport library to make the transport implementation agnostic to the
    manageability protocol specification.

* ***TransmitTrailer***

    The transmit trailer may be different according to the disparate transport
    interface for the manageability protocol. Having this header abstracted from
    manageability transport library to make the transport implementation agnostic to the
    manageability protocol specification.

* ***TransmitPackage***

    The buffer of packet to transmit, this could be a value of NULL if the manageability
    protocol is going to harvest the datagram sent by the management entity.

* ***ReceivePackage***

    The receive buffer, this could be a value of NULL if the manageability
    protocol is going to send the request to management endpoint which has no response
    required.

* ***TransferStatus***

    In order to support both synchronous and asynchronous transfer with a unified
    function, ***TransportTransmitReceive()*** is designed as a
    non return value function. Instead, the status of transmit/receive is returned
    in the transfer token. When the asynchronous transfer, manageability transport
    library has to set the status in transfer token before signal ***ReceiveEvent***.

* ***TransportAdditionalStatus***

    The additional transport status after the transfer.

## Industry Standard Manageability Protocol edk2 Driver Stack
The edk2 implementation of industry manageability standards such as IpmiProtocol and
MctpProtocol abstract the command layer and provide the unified protocol interface to
build up the manageability packet for subordinate specifications. edk2 manageability
protocol driver is linked with desired manageability transport library base on the
platform design.

## Transport Implementation

   The manageability transport library could have the implementation in library or
   invoke the existing edk2 protocol which is defined in UEFI or PI specifications.
   This is the implementation decision made by the developer when introduce a new
   manageability transport library.

## Build the Manageability Package
In order to use the modules provided by ManageabilityPkg, **PACKAGES_PATH** must
contains the path to point to [edk2-platform Features](https://github.com/tianocore/edk2-platforms/tree/master/Features):

```
$ export PACKAGES_PATH=$PWD/edk2:$PWD/edk2-platforms:$PWD/edk2-platforms/Features
```
