1/* 2 * Copyright 2016, 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(D61_BSD) 11 */ 12 13#include <stdio.h> 14#include <assert.h> 15#include <refos/refos.h> 16#include <refos-util/init.h> 17#include <refos-io/morecore.h> 18#include "state.h" 19#include "dispatchers/dspace/dspace.h" 20#include "dispatchers/dspace/stdio_dspace.h" 21#include "dispatchers/serv_dispatch.h" 22#include "dispatchers/client_watch.h" 23 24/*! @file 25 @brief Console Server main source file. 26 27 The RefOS Console server acts as a simple device driver server for basic system console input / 28 output functionality (eg. serial I/O for seeing things on the screen, EGA console output). It is 29 booted as a special system app in order for the system to to gain output functionality as early 30 as possible in the booting process. The only way to get output functionality before the console 31 server is up is to enable debug kernel mode and use seL4_DebugPutChar(). 32 33 @image html conserv.png 34 35 The Console server: 36 <ul> 37 <li>Does NOT support providing pager service to clients.</li> 38 <li>Does NOT support providing content-initialisation for another dataserver.</li> 39 <li>Does NOT supports parameter buffers using an external dataspace (i.e. a dataspace 40 provided by another dataserver).</li> 41 <li>Does NOT support parameter buffers using an internal dataspace (i.e. a dataspace 42 provided the fileserver itself).</li> 43 <li>Does NOT support having its dataspace content-initalised by an external dataspace.</li> 44 <li>Ignores nBytes parameter in open() method (device IO doesn't have a file size).</li> 45 </ul> 46 47 The Console server provides the dataspaces: `/dev_console/serial` and `/dev/_console/screen`. 48 <ul> 49 <li>Writing to `/dev_console/serial` results in outputting to serial device.</li> 50 <li>Reading from `/dev_console/serial` results in reading from serial device.</li> 51 <li>Writing to `/dev_console/screen` results in outputting to EGA screen buffer.</li> 52 <li>Reading from `/dev_console/screen` is unsupported.</li> 53 </ul> 54*/ 55 56/*! @brief Console server's static morecore region. */ 57static char conServMMapRegion[CONSERV_MMAP_REGION_SIZE]; 58 59/*! @brief Console server's system call table. */ 60extern uintptr_t __vsyscall_ptr; 61 62/*! @brief Handle messages recieved by the Console server. 63 @param s The global Console server state. (No ownership transfer) 64 @param msg The recieved message. (No ownership transfer) 65 @return DISPATCH_SUCCESS if message dispatched, DISPATCH_ERROR if unknown message. 66*/ 67static int 68console_server_handle_message(struct conserv_state *s, srv_msg_t *msg) 69{ 70 int result = DISPATCH_PASS; 71 int label = seL4_GetMR(0); 72 void *userptr; 73 74 if (dispatch_client_watch(msg) == DISPATCH_SUCCESS) { 75 result = DISPATCH_SUCCESS; 76 } 77 78 if (dev_dispatch_interrupt(&s->irqState, msg) == DISPATCH_SUCCESS) { 79 result = DISPATCH_SUCCESS; 80 } 81 82 if (result == DISPATCH_SUCCESS) { 83 return result; 84 } 85 86 if (check_dispatch_data(msg, &userptr) == DISPATCH_SUCCESS) { 87 result = rpc_sv_data_dispatcher(userptr, label); 88 assert(result == DISPATCH_SUCCESS); 89 return DISPATCH_SUCCESS; 90 } 91 92 if (check_dispatch_serv(msg, &userptr) == DISPATCH_SUCCESS) { 93 result = rpc_sv_serv_dispatcher(userptr, label); 94 assert(result == DISPATCH_SUCCESS); 95 return DISPATCH_SUCCESS; 96 } 97 98 dprintf("Unknown message (badge = %d msgInfo = %d label = %d).\n", 99 msg->badge, seL4_MessageInfo_get_label(msg->message), label); 100 ROS_ERROR("Console server unknown message."); 101 assert("!Console server unknown message."); 102 103 return DISPATCH_ERROR; 104} 105 106/*! @brief Main console server message loop. Simply loops through recieving and dispatching messages 107 repeatedly. */ 108static void 109console_server_mainloop(void) 110{ 111 struct conserv_state *s = &conServ; 112 srv_msg_t msg; 113 114 while (1) { 115 msg.message = seL4_Recv(conServCommon->anonEP, &msg.badge); 116 console_server_handle_message(s, &msg); 117 client_table_postaction(&conServCommon->clientTable); 118 } 119} 120 121uint32_t faketime() { 122 static uint32_t faketime = 0; 123 return faketime++; 124} 125 126/*! @brief Main Console server entry point. */ 127int 128main(void) 129{ 130 /* Future Work 4: 131 Eventually RefOS should be changed so that processes that are started 132 by the process server do not require that the their system call table be 133 explicitly referenced in the code like this. Without expliciting referencing 134 __vsyscall_ptr in main(), the compiler optimizes away __vsyscall_ptr 135 and then processes started by the process server can't find their system call 136 table. Each of the four places in RefOS where this explicit reference is 137 required is affected by a custom linker script (linker.lds), so it is possible 138 that the custom linker script (and then likely other things too) needs to be 139 modified. Also note that the ROS_ERROR() and assert() inside this if statement 140 would not actually be able to execute if __vsyscall_ptr() were ever not set. 141 The purpose of these calls to ROS_ERROR() and assert() is to show future 142 developers that __vsyscall_ptr needs to be defined. 143 */ 144 if (! __vsyscall_ptr) { 145 ROS_ERROR("Console server could not find system call table."); 146 assert("!Console server could not find system call table."); 147 return 0; 148 } 149 150 dprintf("Initialising RefOS Console server.\n"); 151 refosio_setup_morecore_override(conServMMapRegion, CONSERV_MMAP_REGION_SIZE); 152 refos_initialise_os_minimal(); 153 conserv_init(); 154 155 console_server_mainloop(); 156 157 return 0; 158} 159