You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
405 lines
17 KiB
405 lines
17 KiB
/*
|
|
* Copyright (C) 2017 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
#ifndef __CROS_EC_INCLUDE_APPLICATION_H
|
|
#define __CROS_EC_INCLUDE_APPLICATION_H
|
|
#include <stdint.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#ifndef __packed
|
|
#define __packed __attribute__((packed))
|
|
#endif
|
|
|
|
typedef const void * const __private;
|
|
|
|
/*
|
|
* Typical applications are independent tasks which are directed (or at least
|
|
* influenced) by some off-chip program. Communications with the applications
|
|
* are initiated by that off-chip Master and are routed to the application
|
|
* using a variety of methods.
|
|
*/
|
|
|
|
/****************************************************************************/
|
|
/*
|
|
* Datagram API:
|
|
*
|
|
* Nugget OS abstracts the bus protocol (SPI, USB, whatever) into two
|
|
* unidirectional "datagram" transactions:
|
|
*
|
|
* - Read (the master wants data from the application)
|
|
* - Write (the master sends data to the application)
|
|
*
|
|
* Each transaction consists of a four-byte Command from the Master, plus zero
|
|
* or more data bytes either to (Read) or from (Write) the Master.
|
|
*
|
|
* The Command indicates the direction of data transfer, the application it
|
|
* addresses, and various other parameters. The application is responsible for
|
|
* providing (Read) or accepting (Write) the data bytes.
|
|
*
|
|
* Note: This interface was first used on the SPI bus, which allows for
|
|
* simultaneous bidirectional data transfer. We limit this interface to
|
|
* unidirectional transfers, because none of the other buses support that
|
|
* feature.
|
|
*/
|
|
|
|
/****************************************************************************/
|
|
/* Application IDs */
|
|
|
|
/* These two App IDs shouldn't be changed or used for other purposes */
|
|
#define APP_ID_NUGGET 0x00 /* because we're selfish */
|
|
#define APP_ID_TPM_REGISTER_API 0xD4 /* mandated by the TCG */
|
|
/*
|
|
* Other App IDs are defined here. It will help avoid confusion if you use only
|
|
* the values from here and don't change them once they're set. But it's up to
|
|
* you. I'm a comment, not a cop.
|
|
*/
|
|
#define APP_ID_AVB 0x01
|
|
#define APP_ID_KEYMASTER 0x02
|
|
#define APP_ID_WEAVER 0x03
|
|
#define APP_ID_PROTOBUF 0x04
|
|
#define APP_ID_IDENTITY 0x05
|
|
#define APP_ID_GSC_FACEAUTH 0x06
|
|
|
|
/* Fake apps used only for testing */
|
|
#define APP_ID_AVB_TEST 0x11
|
|
#define APP_ID_TRANSPORT_TEST 0x12
|
|
#define APP_ID_FACEAUTH_TEST 0x13
|
|
|
|
/* This app ID should only be used by tests. */
|
|
#define APP_ID_TEST 0xff
|
|
|
|
/****************************************************************************/
|
|
/* Other command fields */
|
|
|
|
/*
|
|
* The Command encoding is:
|
|
*
|
|
* Bits 31-24 Control flags (reserved)
|
|
* Bits 23-16 Application ID
|
|
* Bits 15-0 Parameters (application-specific)
|
|
*/
|
|
|
|
/* Control flag bits */
|
|
#define CMD_IS_READ 0x80000000 /* 1=Read, 0=Write */
|
|
/* All other control flags bits are reserved */
|
|
|
|
/* Extracting fields from a command */
|
|
#define GET_APP_ID(cmd) (((cmd) & 0x00ff0000) >> 16)
|
|
#define GET_APP_PARAM(cmd) ((cmd) & 0x0000ffff)
|
|
|
|
/* Specifying command fields */
|
|
#define CMD_ID(id) (((id) & 0x000000ff) << 16)
|
|
#define CMD_PARAM(p) ((p) & 0x0000ffff)
|
|
#define CMD_SET_PARAM(cmd, p) cmd = ((cmd & 0xffff0000) | (p & 0x0000ffff))
|
|
|
|
/****************************************************************************/
|
|
/* Data transfer */
|
|
|
|
/*
|
|
* Functions of this type are invoked when the Master wants to read bytes from
|
|
* an application. The app should parse the Command, copy up to max_tx_size
|
|
* bytes into the tx_buffer provided, and return the number of bytes to send
|
|
* back to the Master.
|
|
*
|
|
* This is called in interrupt context, so act quickly.
|
|
*
|
|
* The last arg is for internal use. Just ignore it.
|
|
*/
|
|
typedef uint32_t (read_from_app_fn_t)(uint32_t command,
|
|
uint8_t *tx_buffer,
|
|
uint32_t max_tx_bytes,
|
|
__private priv);
|
|
|
|
/*
|
|
* Functions of this type are invoked when the Master has sent bytes to the
|
|
* application. The app should parse the Command and copy or process the
|
|
* expected number of bytes in the rx_buffer that the master has sent, up to
|
|
* rx_num_bytes.
|
|
*
|
|
* NOTE: Due to a quirk of the Citadel hardware, up to four extra bytes from
|
|
* the *next* transaction may be at the end of the rx_buffer. The application
|
|
* should only poke at the bytes it expects to see and ignore any extras.
|
|
*
|
|
* This is called in interrupt context, so act quickly.
|
|
*
|
|
* The last arg is for internal use. Just ignore it.
|
|
*/
|
|
typedef void (write_to_app_fn_t)(uint32_t command,
|
|
const uint8_t *rx_buffer,
|
|
uint32_t num_rx_bytes,
|
|
__private priv);
|
|
|
|
/*
|
|
* For apps that run asynchronously with little oversight, occasional
|
|
* Read/Write operations may be all that's necessary. An app that intercepts
|
|
* button presses, an accelerometer, or a fingerprint scanner can simply be
|
|
* told to start or stop and will send interrupts to the Master when its
|
|
* attention is required.
|
|
*
|
|
* Applications are free to define their own protcols and APIs using only the
|
|
* functions and constants above (and at least one app does just that).
|
|
*
|
|
* An app that wishes to handle its messaging using only the components
|
|
* described to this point would use the following macro to declare itself.
|
|
*/
|
|
|
|
/**
|
|
* This registers an application that communicates using the Datagram API,
|
|
* which deals only with the raw byte streams between Master (AP) and Slave
|
|
* (application).
|
|
*
|
|
* The name and version values may be exported to the Master by Nugget OS, so
|
|
* the Master can query what applications are available without blindly trying
|
|
* them all to see what works.
|
|
*
|
|
* @param Id The Application ID, defined above
|
|
* @param Name A human-readable string identifying the application
|
|
* @param Version An app-specific uint32_t number, for compability purposes
|
|
* @param From_fn A pointer to the app's read_from_app_fn_t handler
|
|
* @param To_fn A pointer to the app's write_to_app_fn_t handler
|
|
* @param Data App's private data
|
|
*/
|
|
#define DECLARE_APPLICATION_DATAGRAM(Id, Name, Version, From_fn, To_fn, Data) \
|
|
const struct app_info __keep CONCAT2(app_, Id) \
|
|
__attribute__((section(".rodata.app_info"))) \
|
|
= { .api = { .id = Id, \
|
|
.from_fn = From_fn, .to_fn = To_fn, \
|
|
.data = Data}, \
|
|
.version = Version, .name = Name }
|
|
|
|
/****************************************************************************/
|
|
/* Transport API */
|
|
/*
|
|
* Rather than handle unidirectonal datagrams themselves, many applications
|
|
* want to implement a request/response behavior, where the Master tells the
|
|
* app to do something and waits for it to finish and return the result.
|
|
*
|
|
* Seen from the AP's side, the application would be invoked using a blocking
|
|
* function something like this:
|
|
*
|
|
* uint32_t call_application(uint8_t app_id, uint16_t app_param,
|
|
* const uint8_t *args, uint16_t arg_len,
|
|
* uint8_t *reply, uint16_t *reply_len);
|
|
*
|
|
* The request or response may be larger than one bus transaction, and the AP
|
|
* may poll until the app finishes or wait for an interrupt before retrieving
|
|
* the reply (there's no difference from app's point of view).
|
|
*
|
|
* With this API, the application is initially idle. Nugget OS will marshall
|
|
* all the input from the Master before waking the application. The Application
|
|
* then performs the requested operation and transititions to a "done" state.
|
|
* The Master will retrieve the application status and any reply data from
|
|
* Nugget OS, after which the application is ready to handle the next command.
|
|
*/
|
|
|
|
#define TRANSPORT_V0 0x0000
|
|
#define TRANSPORT_V1 0x0001
|
|
|
|
/* Command information for the transport protocol. */
|
|
struct transport_command_info {
|
|
/* v1 fields */
|
|
uint16_t length; /* length of this message */
|
|
uint16_t version; /* max version used by master */
|
|
uint16_t crc; /* CRC of some command fields */
|
|
uint16_t reply_len_hint; /* max that the master will read */
|
|
} __packed;
|
|
|
|
#define COMMAND_INFO_MIN_LENGTH 8
|
|
#define COMMAND_INFO_MAX_LENGTH 32
|
|
/* If more data needs to be sent, chain a new struct to the end of this one. It
|
|
* will require its own CRC for data integrity and something to signify the
|
|
* presence of the extra data. */
|
|
|
|
struct transport_status {
|
|
/* v0 fields */
|
|
uint32_t status; /* status of the app */
|
|
uint16_t reply_len; /* length of available response data */
|
|
/* v1 fields */
|
|
uint16_t length; /* length of this message */
|
|
uint16_t version; /* max version used by slave */
|
|
uint16_t flags; /* space for more protocol state flags */
|
|
uint16_t crc; /* CRC of this status with crc set to 0 */
|
|
uint16_t reply_crc; /* CRC of the reply data */
|
|
} __packed;
|
|
|
|
/* Valid range of lengths for the status message */
|
|
#define STATUS_MIN_LENGTH 0x10
|
|
#define STATUS_MAX_LENGTH 0xff
|
|
|
|
/* Flags used in the status message */
|
|
#define STATUS_FLAG_WORKING 0x0001 /* added in v1 */
|
|
|
|
/* Pre-calculated CRCs for different status responses set in the interrupt
|
|
* context where the CRC would otherwise not be calculated. */
|
|
#define STATUS_CRC_FOR_IDLE 0x54c1
|
|
#define STATUS_CRC_FOR_WORKING 0x2101
|
|
#define STATUS_CRC_FOR_ERROR_TOO_MUCH 0x97c0
|
|
|
|
/*
|
|
* Applications that wish to use this transport API will need to declare a
|
|
* private struct app_transport which Nugget OS can use to maintain the state:
|
|
*/
|
|
struct app_transport {
|
|
void (*done_fn)(struct app_transport *); /* optional cleanup function */
|
|
/* Note: Any done_fn() is called in interrupt context. Be quick. */
|
|
uint8_t *const request; /* input data buffer */
|
|
uint8_t *const response; /* output data buffer */
|
|
const uint16_t max_request_len; /* input data buffer size */
|
|
const uint16_t max_response_len; /* output data buffer size */
|
|
/* The following are used for the incoming command. */
|
|
uint32_t command; /* from master */
|
|
union {
|
|
struct transport_command_info info;
|
|
uint8_t data[COMMAND_INFO_MAX_LENGTH]; /* space for future growth */
|
|
} command_info; /* extra info about the command */
|
|
uint16_t request_len; /* command data buffer size */
|
|
uint16_t response_idx; /* current index into response */
|
|
struct transport_status status[2]; /* current transport_status */
|
|
volatile uint8_t status_idx; /* index of active status */
|
|
};
|
|
|
|
/*
|
|
* Note that request and response buffers are transferred as byte streams.
|
|
* However, if they will eventually represent structs, the usual ABI alignment
|
|
* requirements will be required. Until we've declared all applications structs
|
|
* in a union, we will need to align the buffers manually. Use this to declare
|
|
* the uint8_t buffers until then:
|
|
*/
|
|
#define __TRANSPORT_ALIGNED__ __attribute__((aligned(8)))
|
|
|
|
/*
|
|
* The application will need to provide a write_to_app_fn_t function that will
|
|
* be invoked when a new request is ready to be processed. All command and data
|
|
* parameters will already be present in the app's struct app_transport, so it
|
|
* just needs to awaken the application task to do the work.
|
|
*
|
|
* When awakened, the application task must check that there were no errors in
|
|
* the transmission of the request by calling this function. If it returns
|
|
* true, the task should go back to sleep until the next request arrives.
|
|
*/
|
|
int request_is_invalid(struct app_transport *s);
|
|
/*
|
|
* When processing is finished, the app should call the app_reply() function to
|
|
* return its status code and specify the length of any data it has placed into
|
|
* the response buffer, and then it can go back to sleep until its next
|
|
* invocation. CAUTION: The Master polls for app completion independently, so
|
|
* it may immediately begin retrieving the results as soon as this function
|
|
* is called *without* waiting for the Nugget OS app to go to sleep.
|
|
*/
|
|
void app_reply(struct app_transport *st, uint32_t status, uint16_t reply_len);
|
|
|
|
/* Application status codes are uint32_t, but an enum is easier to read. */
|
|
enum app_status {
|
|
/* A few values are common to all applications */
|
|
APP_SUCCESS = 0,
|
|
APP_ERROR_BOGUS_ARGS, /* caller being stupid */
|
|
APP_ERROR_INTERNAL, /* application being stupid */
|
|
APP_ERROR_TOO_MUCH, /* caller sent too much data */
|
|
APP_ERROR_IO, /* problem sending or receiving data */
|
|
APP_ERROR_RPC, /* problem during RPC communication */
|
|
APP_ERROR_CHECKSUM, /* checksum failed, only used within protocol */
|
|
APP_ERROR_BUSY, /* the app is already working on a commnad */
|
|
APP_ERROR_TIMEOUT, /* the app took too long to respond */
|
|
APP_ERROR_NOT_READY, /* some required condition is not satisfied */
|
|
/* more? */
|
|
|
|
/*
|
|
* Applications can define their own app-specific error codes. For example,
|
|
* app_foobar.h can do:
|
|
*
|
|
* #define APP_ERROR_FOOBAR_BAZ (APP_SPECIFIC_ERROR + 0)
|
|
*
|
|
* Do not use (APP_SPECIFIC_ERROR + N) directly in your code, because the
|
|
* error definition, firmware which generates it, and host code which
|
|
* interprets it are all in different repos. You'll never be able to keep
|
|
* the constants straight without using a #define or enum in your app's
|
|
* header file that everyone can share.
|
|
*/
|
|
APP_SPECIFIC_ERROR = 0x20, /* "should be enough for anybody" */
|
|
|
|
/* For debugging, returning a line number might be helpful */
|
|
APP_LINE_NUMBER_BASE = 0x70000000,
|
|
#define APP_ERROR_LINENO (APP_LINE_NUMBER_BASE + __LINE__)
|
|
|
|
/* Bit 31 is reserved for internal use */
|
|
MAX_APP_STATUS = 0x7fffffff,
|
|
};
|
|
|
|
/**
|
|
* This registers an application that communicates using the Transport API.
|
|
*
|
|
* The name and version values may be exported to the Master by Nugget OS, so
|
|
* the Master can query what applications are available without blindly trying
|
|
* them all to see what works.
|
|
*
|
|
* @param Id The Application ID, defined above
|
|
* @param Name A human-readable string identifying the application
|
|
* @param Version An app-specific uint32_t number, for compability purposes
|
|
* @param State A pointer to the app's struct app_transport
|
|
* @param To_fn A pointer to the app's write_to_app_fn_t handler
|
|
*/
|
|
#define DECLARE_APPLICATION_TRANSPORT(Id, Name, Version, State, To_fn) \
|
|
const struct app_info __keep CONCAT2(app_, Id) \
|
|
__attribute__((section(".rodata.app_info"))) \
|
|
= { .api = { .id = Id, \
|
|
.from_fn = transaction_api_from_fn, \
|
|
.to_fn = transaction_api_to_fn, \
|
|
.data = &(const struct datagram_api) \
|
|
{ .id = Id, .to_fn = To_fn, \
|
|
.data = State } }, \
|
|
.version = Version, .name = Name }
|
|
|
|
/****************************************************************************/
|
|
/* Pay no attention to that man behind the curtain */
|
|
|
|
/* We'll allow 31 bits of application status. We need one bit for transport. */
|
|
#define APP_STATUS_IDLE 0x00000000 /* waiting for instructions */
|
|
#define APP_STATUS_DONE 0x80000000 /* finished, reply is ready */
|
|
#define APP_STATUS_CODE(res) ((res) & 0x7fffffff) /* actual status */
|
|
|
|
/* Datagram API needs this info */
|
|
struct datagram_api {
|
|
uint8_t id;
|
|
read_from_app_fn_t * const from_fn;
|
|
write_to_app_fn_t * const to_fn;
|
|
const void * const data;
|
|
};
|
|
|
|
/* Here's the struct that keeps track of registered applications */
|
|
struct app_info {
|
|
struct datagram_api api;
|
|
uint32_t version;
|
|
const char * const name;
|
|
};
|
|
|
|
/* These handle the Transport API */
|
|
extern read_from_app_fn_t transaction_api_from_fn;
|
|
extern write_to_app_fn_t transaction_api_to_fn;
|
|
|
|
/* Command flags used internally by Transport API messages */
|
|
#define CMD_TRANSPORT 0x40000000 /* 1=Transport API message */
|
|
/* When CMD_TRANSPORT is set, the following bits have meaning */
|
|
#define CMD_IS_DATA 0x20000000 /* 1=data msg 0=status msg */
|
|
#define CMD_MORE_TO_COME 0x10000000 /* 1=continued 0=new */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* __CROS_EC_INCLUDE_APPLICATION_H */
|