aboutsummaryrefslogtreecommitdiff
path: root/nugget/include/application.h
blob: 2f897b6ca2af224c746a6104d58468e58b5fbb25 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
/*
 * 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 (sizeof(struct transport_status)) /* 0x10 */

/* 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 */