1/*
2 * Copyright 2017, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12#pragma once
13
14#include <stdint.h>
15
16#include <sel4/sel4.h>
17
18#include <simple/simple.h>
19#include <sel4utils/thread.h>
20#include <vka/vka.h>
21#include <vka/object.h>
22#include <vspace/vspace.h>
23
24/** @file APIs for managing and interacting with the serial server thread.
25 *
26 * Defines the constants for the protocol, messages, and server-side state, as
27 * well as the entry point and back-end routines for the server's API.
28 *
29 * All vka_t, vspace_t and simple_t instances that are supplied to this library
30 * by the developer must persist and be functional for the lifetime of the
31 * server thread.
32 */
33
34#define SERSERVS     "Serserv Server: "
35#define SERSERVC     "Serserv Client: "
36#define SERSERVP     "Serserv Parent: "
37
38#define SERIAL_SERVER_BADGE_VALUE_EMPTY (0)
39
40#define SERIAL_SERVER_SHMEM_MAX_SIZE (BIT(seL4_PageBits))
41
42/* IPC values returned in the "label" message header. */
43enum serial_server_errors {
44    SERIAL_SERVER_NOERROR = 0,
45    /* No future collisions with seL4_Error.*/
46    SERIAL_SERVER_ERROR_SHMEM_TOO_LARGE = seL4_NumErrors,
47    SERIAL_SERVER_ERROR_SERIAL_BIND_FAILED,
48    SERIAL_SERVER_ERROR_UNKNOWN
49};
50
51/* IPC Message register values for SSMSGREG_FUNC */
52enum serial_server_funcs {
53    FUNC_CONNECT_REQ = 0,
54    FUNC_CONNECT_ACK,
55
56    FUNC_SERVER_SPAWN_SYNC_REQ,
57    FUNC_SERVER_SPAWN_SYNC_ACK,
58
59    FUNC_PRINTF_REQ,
60    FUNC_PRINTF_ACK,
61
62    FUNC_WRITE_REQ,
63    FUNC_WRITE_ACK,
64
65    FUNC_DISCONNECT_REQ,
66    FUNC_DISCONNECT_ACK,
67
68    FUNC_KILL_REQ,
69    FUNC_KILL_ACK,
70};
71
72/* Designated purposes of each message register in the mini-protocol. */
73enum serial_server_msgregs {
74    /* These four are fixed headers in every serserv message. */
75    SSMSGREG_FUNC = 0,
76    /* This is a convenience label for IPC MessageInfo length. */
77    SSMSGREG_LABEL0,
78
79    SSMSGREG_CONNECT_REQ_SHMEM_SIZE = SSMSGREG_LABEL0,
80    SSMSGREG_CONNECT_REQ_END,
81
82    SSMSGREG_CONNECT_ACK_MAX_SHMEM_SIZE = SSMSGREG_LABEL0,
83    SSMSGREG_CONNECT_ACK_END,
84
85    SSMSGREG_SPAWN_SYNC_REQ_END = SSMSGREG_LABEL0,
86
87    SSMSGREG_SPAWN_SYNC_ACK_END = SSMSGREG_LABEL0,
88
89    SSMSGREG_PRINTF_REQ_FMT_STRLEN = SSMSGREG_LABEL0,
90    SSMSGREG_PRINTF_REQ_END,
91
92    SSMSGREG_PRINTF_ACK_PRINTF_RET = SSMSGREG_LABEL0,
93    SSMSGREG_PRINTF_ACK_END,
94
95    SSMSGREG_WRITE_REQ_BUFF_LEN = SSMSGREG_LABEL0,
96    SSMSGREG_WRITE_REQ_END,
97
98    SSMSGREG_WRITE_ACK_N_BYTES_WRITTEN = SSMSGREG_LABEL0,
99    SSMSGREG_WRITE_ACK_END,
100
101    SSMSGREG_DISCONNECT_REQ_END = SSMSGREG_LABEL0,
102
103    SSMSGREG_DISCONNECT_ACK_END = SSMSGREG_LABEL0,
104
105    SSMSGREG_KILL_REQ_END = SSMSGREG_LABEL0,
106
107    SSMSGREG_KILL_ACK_END = SSMSGREG_LABEL0
108};
109
110/* Per-client context maintained by the server. */
111typedef struct _serial_server_registry_entry {
112    seL4_Word badge_value;
113    volatile char *shmem;
114    seL4_CPtr *shmem_frame_caps;
115    size_t shmem_size;
116} serial_server_registry_entry_t;
117
118/* State maintained by the server. */
119typedef struct _serial_server_context {
120    simple_t *server_simple;
121    vka_t *server_vka;
122    seL4_CPtr server_cspace;
123    cspacepath_t *frame_cap_recv_cspaths;
124    vspace_t *server_vspace;
125    sel4utils_thread_t server_thread;
126    vka_object_t server_ep_obj;
127    size_t shmem_max_size, shmem_max_n_pages;
128
129    int registry_n_entries;
130    serial_server_registry_entry_t *registry;
131
132    seL4_Word parent_badge_value;
133    cspacepath_t _badged_server_ep_cspath;
134} serial_server_context_t;
135
136/* Global server instance accessor functions. */
137serial_server_context_t *get_serial_server(void);
138
139/** Internal library function: acts as the main() for the server thread.
140 */
141void serial_server_main(void);
142
143serial_server_registry_entry_t *serial_server_registry_get_entry_by_badge(seL4_Word badge_value);
144
145/** Determines whether or not a badge value has been reserved and given out.
146 * @param badge_value The badge value in question.
147 * @return True only if the badge value has been given out.
148 *         False if the badge value is invalid, or hasn't been given out.
149 */
150bool serial_server_badge_is_allocated(seL4_Word badge_value);
151
152/** Returns an unused, unique badge value to the caller, and will NOT attempt
153 * to resize the pool of available badge values to fulfill the request.
154 *
155 * The server maintains a list of badge values, so it can also be used to
156 * allocate and ration out badge values.
157 *
158 * @return Returns a positive integer GREATER THAN 0 if successful.
159 *         Returns 0 if unsuccessful.
160 */
161seL4_Word serial_server_badge_value_get_unused(void);
162
163/** Returns a new, unique badge value to the caller, and WILL allocate new
164 * badge values to satisfy the request.
165 *
166 * @return Returns a positive integer GREATER THAN 0 if successful.
167 *         Returns 0 if unsuccessful.
168 */
169seL4_Word serial_server_badge_value_alloc(void);
170
171/** Returns a badge value to the pool of available badge values.
172 * @param badge_value The badge value to free.
173 */
174void serial_server_badge_value_free(seL4_Word badge_value);
175