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/*! @file 14 @brief CPIO File Server main source file. 15 16 The main role of the fileserver in the system is to provide the executable file contents via 17 the dataspace interface. It does some book-keeping and simple management of clients. 18 19 @image html fileserv.png 20 21 The CPIO file server: 22 <ul> 23 <li>Supports providing pager service to clients.</li> 24 <li>Supports providing content-initialisation for another dataserver.</li> 25 <li>Supports parameter buffers using an external dataspace (i.e. a dataspace provided by 26 another dataserver).</li> 27 <li>Does NOT support parameter buffers using an internal dataspace (i.e. a dataspace 28 provided the fileserver itself).</li> 29 <li>Does NOT support having its dataspace content-initalised by an external dataspace.</li> 30 <li>Ignores nBytes parameter in open() method (actual CPIO file size is used).</li> 31 </ul> 32 33 The CPIO file server provides access to files stored in a CPIO archive inside the server. 34 The CPIO archive is a simple format file archive stored inside a parent program's ELF section. 35 This is a similar idea to something like creating a 36 > const char data[] = { 0x3F, 0xFF, 0x23 ...etc} 37 38 The CPIO file server is used to store the RefOS userland app ELF binaries, and any additional 39 data files. It provides a simple example of a dataserver, and may serve as the means to boot 40 more complex dataspace servers involving flash memory / SATA drivers and so forth. 41*/ 42 43#include <stdio.h> 44#include <stdlib.h> 45#include <assert.h> 46#include <sel4/sel4.h> 47#include <cpio/cpio.h> 48 49#include <refos/refos.h> 50#include <refos-io/morecore.h> 51#include <refos-io/stdio.h> 52#include <refos-util/init.h> 53#include <refos-util/serv_connect.h> 54 55#include "state.h" 56#include "dispatchers/dispatch.h" 57#include "dispatchers/serv_dispatch.h" 58#include "dispatchers/cpio_dspace.h" 59#include "dispatchers/fault_notify.h" 60 61#define MMAP_SIZE 0x200000 /*!< 32MB.. */ 62static char mmapRegion[MMAP_SIZE]; 63 64/*! @brief File server's system call table. */ 65extern uintptr_t __vsyscall_ptr; 66 67/*! @brief Fake time generator used by dprintf(). */ 68uint32_t faketime() { 69 static uint32_t _faketime = 0; 70 return _faketime++; 71} 72 73/*! @brief Handle messages received by the CPIO file server. 74 @param s The global file server state. (No ownership transfer) 75 @param msg The received message. (No ownership transfer) 76 @return DISPATCH_SUCCESS if message dispatched, DISPATCH_ERROR if unknown message. 77*/ 78static int 79fileserv_handle_message(struct fs_state *s, srv_msg_t *msg) 80{ 81 int result; 82 int label = seL4_GetMR(0); 83 void *userptr; 84 (void) result; 85 86 if (dispatch_notification(msg) == DISPATCH_SUCCESS) { 87 return DISPATCH_SUCCESS; 88 } 89 90 if (check_dispatch_serv(msg, &userptr) == DISPATCH_SUCCESS) { 91 result = rpc_sv_serv_dispatcher(userptr, label); 92 assert(result == DISPATCH_SUCCESS); 93 return DISPATCH_SUCCESS; 94 } 95 96 if (check_dispatch_data(msg, &userptr) == DISPATCH_SUCCESS) { 97 result = rpc_sv_data_dispatcher(userptr, label); 98 assert(result == DISPATCH_SUCCESS); 99 return DISPATCH_SUCCESS; 100 } 101 102 dprintf("Unknown message (badge = %d msgInfo = %d label = %d (0x%x)).\n", 103 msg->badge, seL4_MessageInfo_get_label(msg->message), label, label); 104 ROS_ERROR("File server unknown message."); 105 assert(!"File server unknown message."); 106 107 return DISPATCH_ERROR; 108} 109 110/*! @brief Main CPIO file server message loop. Simply loops through recieving and dispatching 111 messages repeatedly. */ 112static void 113fileserv_mainloop(void) 114{ 115 struct fs_state *s = &fileServ; 116 srv_msg_t msg; 117 118 while (1) { 119 dvprintf("Fileserver blocking for message...\n"); 120 msg.message = seL4_Recv(fileServCommon->anonEP, &msg.badge); 121 fileserv_handle_message(s, &msg); 122 client_table_postaction(&fileServCommon->clientTable); 123 } 124} 125 126/*! @brief Main CPIO file server entry point. */ 127int 128main() 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("File server could not find system call table."); 146 assert("!File server could not find system call table."); 147 return 0; 148 } 149 150 refosio_setup_morecore_override(mmapRegion, MMAP_SIZE); 151 refos_initialise_os_minimal(); 152 refos_setup_dataspace_stdio(REFOS_DEFAULT_STDIO_DSPACE); 153 154 fileserv_init(); 155 fileserv_mainloop(); 156 157 return 0; 158} 159