| /* |
| * Copyright 2017, Data61 |
| * Commonwealth Scientific and Industrial Research Organisation (CSIRO) |
| * ABN 41 687 119 230. |
| * |
| * This software may be distributed and modified according to the terms of |
| * the BSD 2-Clause license. Note that NO WARRANTY is provided. |
| * See "LICENSE_BSD2.txt" for details. |
| * |
| * @TAG(DATA61_BSD) |
| */ |
| #pragma once |
| |
| #include <stdint.h> |
| |
| #include <sel4/sel4.h> |
| |
| #include <simple/simple.h> |
| #include <sel4utils/thread.h> |
| #include <vka/vka.h> |
| #include <vka/object.h> |
| #include <vspace/vspace.h> |
| |
| /** @file APIs for managing and interacting with the serial server thread. |
| * |
| * Defines the constants for the protocol, messages, and server-side state, as |
| * well as the entry point and back-end routines for the server's API. |
| * |
| * All vka_t, vspace_t and simple_t instances that are supplied to this library |
| * by the developer must persist and be functional for the lifetime of the |
| * server thread. |
| */ |
| |
| #define SERSERVS "Serserv Server: " |
| #define SERSERVC "Serserv Client: " |
| #define SERSERVP "Serserv Parent: " |
| |
| #define SERIAL_SERVER_BADGE_VALUE_EMPTY (0) |
| |
| #define SERIAL_SERVER_SHMEM_MAX_SIZE (BIT(seL4_PageBits)) |
| |
| /* IPC values returned in the "label" message header. */ |
| enum serial_server_errors { |
| SERIAL_SERVER_NOERROR = 0, |
| /* No future collisions with seL4_Error.*/ |
| SERIAL_SERVER_ERROR_SHMEM_TOO_LARGE = seL4_NumErrors, |
| SERIAL_SERVER_ERROR_SERIAL_BIND_FAILED, |
| SERIAL_SERVER_ERROR_UNKNOWN |
| }; |
| |
| /* IPC Message register values for SSMSGREG_FUNC */ |
| enum serial_server_funcs { |
| FUNC_CONNECT_REQ = 0, |
| FUNC_CONNECT_ACK, |
| |
| FUNC_SERVER_SPAWN_SYNC_REQ, |
| FUNC_SERVER_SPAWN_SYNC_ACK, |
| |
| FUNC_PRINTF_REQ, |
| FUNC_PRINTF_ACK, |
| |
| FUNC_WRITE_REQ, |
| FUNC_WRITE_ACK, |
| |
| FUNC_DISCONNECT_REQ, |
| FUNC_DISCONNECT_ACK, |
| |
| FUNC_KILL_REQ, |
| FUNC_KILL_ACK, |
| }; |
| |
| /* Designated purposes of each message register in the mini-protocol. */ |
| enum serial_server_msgregs { |
| /* These four are fixed headers in every serserv message. */ |
| SSMSGREG_FUNC = 0, |
| /* This is a convenience label for IPC MessageInfo length. */ |
| SSMSGREG_LABEL0, |
| |
| SSMSGREG_CONNECT_REQ_SHMEM_SIZE = SSMSGREG_LABEL0, |
| SSMSGREG_CONNECT_REQ_END, |
| |
| SSMSGREG_CONNECT_ACK_MAX_SHMEM_SIZE = SSMSGREG_LABEL0, |
| SSMSGREG_CONNECT_ACK_END, |
| |
| SSMSGREG_SPAWN_SYNC_REQ_END = SSMSGREG_LABEL0, |
| |
| SSMSGREG_SPAWN_SYNC_ACK_END = SSMSGREG_LABEL0, |
| |
| SSMSGREG_PRINTF_REQ_FMT_STRLEN = SSMSGREG_LABEL0, |
| SSMSGREG_PRINTF_REQ_END, |
| |
| SSMSGREG_PRINTF_ACK_PRINTF_RET = SSMSGREG_LABEL0, |
| SSMSGREG_PRINTF_ACK_END, |
| |
| SSMSGREG_WRITE_REQ_BUFF_LEN = SSMSGREG_LABEL0, |
| SSMSGREG_WRITE_REQ_END, |
| |
| SSMSGREG_WRITE_ACK_N_BYTES_WRITTEN = SSMSGREG_LABEL0, |
| SSMSGREG_WRITE_ACK_END, |
| |
| SSMSGREG_DISCONNECT_REQ_END = SSMSGREG_LABEL0, |
| |
| SSMSGREG_DISCONNECT_ACK_END = SSMSGREG_LABEL0, |
| |
| SSMSGREG_KILL_REQ_END = SSMSGREG_LABEL0, |
| |
| SSMSGREG_KILL_ACK_END = SSMSGREG_LABEL0 |
| }; |
| |
| /* Per-client context maintained by the server. */ |
| typedef struct _serial_server_registry_entry { |
| seL4_Word badge_value; |
| volatile char *shmem; |
| seL4_CPtr *shmem_frame_caps; |
| size_t shmem_size; |
| } serial_server_registry_entry_t; |
| |
| /* State maintained by the server. */ |
| typedef struct _serial_server_context { |
| simple_t *server_simple; |
| vka_t *server_vka; |
| seL4_CPtr server_cspace; |
| cspacepath_t *frame_cap_recv_cspaths; |
| vspace_t *server_vspace; |
| sel4utils_thread_t server_thread; |
| vka_object_t server_ep_obj; |
| size_t shmem_max_size, shmem_max_n_pages; |
| |
| int registry_n_entries; |
| serial_server_registry_entry_t *registry; |
| |
| seL4_Word parent_badge_value; |
| cspacepath_t _badged_server_ep_cspath; |
| } serial_server_context_t; |
| |
| /* Global server instance accessor functions. */ |
| serial_server_context_t *get_serial_server(void); |
| |
| /** Internal library function: acts as the main() for the server thread. |
| */ |
| void serial_server_main(void); |
| |
| serial_server_registry_entry_t *serial_server_registry_get_entry_by_badge(seL4_Word badge_value); |
| |
| /** Determines whether or not a badge value has been reserved and given out. |
| * @param badge_value The badge value in question. |
| * @return True only if the badge value has been given out. |
| * False if the badge value is invalid, or hasn't been given out. |
| */ |
| bool serial_server_badge_is_allocated(seL4_Word badge_value); |
| |
| /** Returns an unused, unique badge value to the caller, and will NOT attempt |
| * to resize the pool of available badge values to fulfill the request. |
| * |
| * The server maintains a list of badge values, so it can also be used to |
| * allocate and ration out badge values. |
| * |
| * @return Returns a positive integer GREATER THAN 0 if successful. |
| * Returns 0 if unsuccessful. |
| */ |
| seL4_Word serial_server_badge_value_get_unused(void); |
| |
| /** Returns a new, unique badge value to the caller, and WILL allocate new |
| * badge values to satisfy the request. |
| * |
| * @return Returns a positive integer GREATER THAN 0 if successful. |
| * Returns 0 if unsuccessful. |
| */ |
| seL4_Word serial_server_badge_value_alloc(void); |
| |
| /** Returns a badge value to the pool of available badge values. |
| * @param badge_value The badge value to free. |
| */ |
| void serial_server_badge_value_free(seL4_Word badge_value); |