source: mainline/uspace/srv/rd/rd.c@ 9239333

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 9239333 was 92fd52d7, checked in by Jiri Svoboda <jirik.svoboda@…>, 17 years ago

Nuke strcpy() and strcmp().

  • Property mode set to 100644
File size: 7.1 KB
RevLine 
[228b135]1/*
[ff3a34b]2 * Copyright (c) 2007 Michal Konopa
3 * Copyright (c) 2007 Martin Jelen
4 * Copyright (c) 2007 Peter Majer
[84947a4]5 * Copyright (c) 2007 Jakub Jermar
[228b135]6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * - Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * - Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * - The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/** @addtogroup rd
33 * @{
34 */
35
36/**
37 * @file rd.c
38 * @brief Initial RAM disk for HelenOS.
39 */
40
41#include <ipc/ipc.h>
42#include <ipc/services.h>
43#include <ipc/ns.h>
[7c34822e]44#include <sysinfo.h>
45#include <as.h>
46#include <ddi.h>
47#include <align.h>
48#include <bool.h>
[228b135]49#include <errno.h>
50#include <async.h>
[ff3a34b]51#include <align.h>
52#include <async.h>
[84947a4]53#include <futex.h>
[2f65fb0]54#include <stdio.h>
55#include <ipc/devmap.h>
[ff3a34b]56#include "rd.h"
[228b135]57
[2f65fb0]58#define NAME "rd"
59
[84947a4]60/** Pointer to the ramdisk's image. */
[ff3a34b]61static void *rd_addr;
[3ae470a]62/** Size of the ramdisk. */
63static size_t rd_size;
[228b135]64
[84947a4]65/**
66 * This futex protects the ramdisk's data.
67 * If we were to serve multiple requests (read + write or several writes)
68 * concurrently (i.e. from two or more threads), each read and write needs to be
69 * protected by this futex.
70 */
71atomic_t rd_futex = FUTEX_INITIALIZER;
72
73/** Handle one connection to ramdisk.
74 *
75 * @param iid Hash of the request that opened the connection.
76 * @param icall Call data of the request that opened the connection.
77 */
[228b135]78static void rd_connection(ipc_callid_t iid, ipc_call_t *icall)
79{
80 ipc_callid_t callid;
81 ipc_call_t call;
82 int retval;
[3ae470a]83 void *fs_va = NULL;
[c544c5d]84 off_t offset;
85 size_t block_size;
86 size_t maxblock_size;
[228b135]87
[84947a4]88 /*
[c544c5d]89 * Answer the first IPC_M_CONNECT_ME_TO call.
[84947a4]90 */
[c544c5d]91 ipc_answer_0(iid, EOK);
[84947a4]92
93 /*
94 * Now we wait for the client to send us its communication as_area.
95 */
[2f65fb0]96 int flags;
[c544c5d]97 if (ipc_share_out_receive(&callid, &maxblock_size, &flags)) {
98 fs_va = as_get_mappable_page(maxblock_size);
99 if (fs_va) {
[215e375]100 (void) ipc_share_out_finalize(callid, fs_va);
[84947a4]101 } else {
[b74959bd]102 ipc_answer_0(callid, EHANGUP);
[84947a4]103 return;
104 }
105 } else {
106 /*
107 * The client doesn't speak the same protocol.
108 * At this point we can't handle protocol variations.
109 * Close the connection.
110 */
[b74959bd]111 ipc_answer_0(callid, EHANGUP);
[84947a4]112 return;
113 }
114
[228b135]115 while (1) {
116 callid = async_get_call(&call);
117 switch (IPC_GET_METHOD(call)) {
[8b243f2]118 case IPC_M_PHONE_HUNGUP:
[84947a4]119 /*
120 * The other side has hung up.
[0f78e74]121 * Answer the message and exit the fibril.
[84947a4]122 */
[b74959bd]123 ipc_answer_0(callid, EOK);
[8b243f2]124 return;
[84947a4]125 case RD_READ_BLOCK:
126 offset = IPC_GET_ARG1(call);
[c544c5d]127 block_size = IPC_GET_ARG2(call);
128 if (block_size > maxblock_size) {
129 /*
130 * Maximum block size exceeded.
131 */
132 retval = ELIMIT;
133 break;
134 }
135 if (offset * block_size > rd_size - block_size) {
[3ae470a]136 /*
137 * Reading past the end of the device.
138 */
139 retval = ELIMIT;
140 break;
141 }
[84947a4]142 futex_down(&rd_futex);
[c544c5d]143 memcpy(fs_va, rd_addr + offset * block_size, block_size);
[84947a4]144 futex_up(&rd_futex);
145 retval = EOK;
146 break;
147 case RD_WRITE_BLOCK:
[8b243f2]148 offset = IPC_GET_ARG1(call);
[c544c5d]149 block_size = IPC_GET_ARG2(call);
150 if (block_size > maxblock_size) {
151 /*
152 * Maximum block size exceeded.
153 */
154 retval = ELIMIT;
155 break;
156 }
157 if (offset * block_size > rd_size - block_size) {
[3ae470a]158 /*
159 * Writing past the end of the device.
160 */
161 retval = ELIMIT;
162 break;
163 }
[84947a4]164 futex_up(&rd_futex);
[c544c5d]165 memcpy(rd_addr + offset * block_size, fs_va, block_size);
[84947a4]166 futex_down(&rd_futex);
[8b243f2]167 retval = EOK;
168 break;
169 default:
[84947a4]170 /*
171 * The client doesn't speak the same protocol.
172 * Instead of closing the connection, we just ignore
173 * the call. This can be useful if the client uses a
174 * newer version of the protocol.
175 */
[8b243f2]176 retval = EINVAL;
[84947a4]177 break;
[228b135]178 }
[b74959bd]179 ipc_answer_0(callid, retval);
[8b243f2]180 }
[228b135]181}
182
[2f65fb0]183static int driver_register(char *name)
184{
185 ipcarg_t retval;
186 aid_t req;
187 ipc_call_t answer;
188 int phone;
189 ipcarg_t callback_phonehash;
190
[430afff]191 phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_DEVMAP, DEVMAP_DRIVER, 0);
192 if (phone < 0) {
193 printf(NAME ": Failed to connect to device mapper\n");
194 return -1;
[2f65fb0]195 }
196
197 req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
198
[92fd52d7]199 retval = ipc_data_write_start(phone, (char *) name, str_size(name) + 1);
[2f65fb0]200
201 if (retval != EOK) {
202 async_wait_for(req, NULL);
203 return -1;
204 }
205
206 async_set_client_connection(rd_connection);
207
208 ipc_connect_to_me(phone, 0, 0, 0, &callback_phonehash);
209 async_wait_for(req, &retval);
210
211 return phone;
212}
213
214static int device_register(int driver_phone, char *name, int *handle)
215{
216 ipcarg_t retval;
217 aid_t req;
218 ipc_call_t answer;
219
220 req = async_send_2(driver_phone, DEVMAP_DEVICE_REGISTER, 0, 0, &answer);
221
[92fd52d7]222 retval = ipc_data_write_start(driver_phone, (char *) name,
223 str_size(name) + 1);
[2f65fb0]224
225 if (retval != EOK) {
226 async_wait_for(req, NULL);
227 return retval;
228 }
229
230 async_wait_for(req, &retval);
231
232 if (handle != NULL)
233 *handle = -1;
234
235 if (EOK == retval) {
236 if (NULL != handle)
237 *handle = (int) IPC_GET_ARG1(answer);
238 }
239
240 return retval;
241}
242
[84947a4]243/** Prepare the ramdisk image for operation. */
[7c34822e]244static bool rd_init(void)
[228b135]245{
[3ae470a]246 rd_size = sysinfo_value("rd.size");
[8b243f2]247 void *rd_ph_addr = (void *) sysinfo_value("rd.address.physical");
[7c34822e]248
[2f65fb0]249 if (rd_size == 0) {
250 printf(NAME ": No RAM disk found\n");
[7c34822e]251 return false;
[2f65fb0]252 }
[228b135]253
[ff3a34b]254 rd_addr = as_get_mappable_page(rd_size);
[228b135]255
[2f65fb0]256 int flags = AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE;
257 int retval = physmem_map(rd_ph_addr, rd_addr,
[8b243f2]258 ALIGN_UP(rd_size, PAGE_SIZE) >> PAGE_WIDTH, flags);
[ae318d3]259
[2f65fb0]260 if (retval < 0) {
261 printf(NAME ": Error mapping RAM disk\n");
262 return false;
263 }
264
265 printf(NAME ": Found RAM disk at %p, %d bytes\n", rd_ph_addr, rd_size);
266
267 int driver_phone = driver_register(NAME);
268 if (driver_phone < 0) {
269 printf(NAME ": Unable to register driver\n");
270 return false;
271 }
272
273 int dev_handle;
274 if (EOK != device_register(driver_phone, "initrd", &dev_handle)) {
275 ipc_hangup(driver_phone);
276 printf(NAME ": Unable to register device\n");
[ff3a34b]277 return false;
[2f65fb0]278 }
279
[7c34822e]280 return true;
281}
[228b135]282
[7c34822e]283int main(int argc, char **argv)
284{
[2f65fb0]285 printf(NAME ": HelenOS RAM disk server\n");
[7c34822e]286
[2f65fb0]287 if (!rd_init())
288 return -1;
289
290 printf(NAME ": Accepting connections\n");
291 async_manager();
292
293 /* Never reached */
294 return 0;
[228b135]295}
296
297/**
298 * @}
299 */
Note: See TracBrowser for help on using the repository browser.