1// vi:set ft=cpp: -*- Mode: C++ -*- 2/** 3 * \file 4 * Common factory related definitions. 5 */ 6/* 7 * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>, 8 * Alexander Warg <warg@os.inf.tu-dresden.de> 9 * economic rights: Technische Universität Dresden (Germany) 10 * 11 * This file is part of TUD:OS and distributed under the terms of the 12 * GNU General Public License 2. 13 * Please see the COPYING-GPL-2 file for details. 14 * 15 * As a special exception, you may use this file as part of a free software 16 * library without restriction. Specifically, if other files instantiate 17 * templates or use macros or inline functions from this file, or you compile 18 * this file and link it with other files to produce an executable, this 19 * file does not by itself cause the resulting executable to be covered by 20 * the GNU General Public License. This exception does not however 21 * invalidate any other reasons why the executable file might be covered by 22 * the GNU General Public License. 23 */ 24 25#pragma once 26 27#include <l4/sys/factory.h> 28#include <l4/sys/capability> 29#include <l4/sys/cxx/ipc_iface> 30#include <l4/sys/cxx/ipc_varg> 31 32namespace L4 { 33 34/** 35 * C++ %Factory interface. 36 * 37 * Factories provide an interface to create objects which are accessed via 38 * capabilities. 39 * 40 * For additional information about which objects can be created via this 41 * interface, see server-specific information in 42 * \ref l4re_concepts_kernel_factory and \ref l4re_servers. 43 * 44 * \includefile{l4/sys/factory} 45 * 46 * For the C interface refer to \ref l4_factory_api. 47 */ 48class Factory : public Kobject_t<Factory, Kobject, L4_PROTO_FACTORY> 49{ 50public: 51 52 typedef l4_mword_t Proto; 53 54 /** 55 * Special type to add a void argument into the factory create stream. 56 */ 57 struct Nil {}; 58 59 /** 60 * Special type to add a pascal string into the factory create stream. 61 * 62 * This encapsulates a string that has an explicit length. 63 */ 64 struct Lstr 65 { 66 /** 67 * The character buffer. 68 */ 69 char const *s; 70 71 /** 72 * The number of characters in the buffer. 73 */ 74 unsigned len; 75 76 /** 77 * \param s Pointer to the c-style string. 78 * \param len Length in number of characters of the string s. 79 */ 80 Lstr(char const *s, unsigned len) noexcept : s(s), len(len) {} 81 }; 82 83 /** 84 * Stream class for the create() argument stream. 85 * 86 * This stream allows a variable number of arguments to be 87 * added to a create() call. 88 */ 89 class S 90 { 91 private: 92 l4_utcb_t *u; 93 l4_msgtag_t t; 94 l4_cap_idx_t f; 95 96 template<typename T> 97 static T &&_move(T &c) { return static_cast<T &&>(c); } 98 99 public: 100 S(S const &) = delete; 101 S &operator = (S const &) & = delete; 102 103 /** 104 * Move ... 105 * 106 * \param o Instance of S to move. 107 */ 108 S(S &&o) noexcept 109 : u(o.u), t(o.t), f(o.f) 110 { o.t.raw = 0; } 111 112 S &operator = (S &&o) & noexcept 113 { 114 u = o.u; 115 t = o.t; 116 f = o.f; 117 o.t.raw = 0; 118 return *this; 119 } 120 121 /** 122 * Create a stream for a specific create() call. 123 * 124 * \param f The capability for the factory object (L4::Factory). 125 * \param obj The protocol ID to describe the type of the object 126 * that shall be created. 127 * \param[out] target The capability selector for the new object. The 128 * caller must allocate the capability slot. The kernel 129 * stores the new object's capability into this slot. 130 * \param utcb The UTCB to use for the operation. 131 */ 132 S(l4_cap_idx_t f, long obj, L4::Cap<void> target, 133 l4_utcb_t *utcb) noexcept 134 : u(utcb), t(l4_factory_create_start_u(obj, target.cap(), u)), f(f) 135 {} 136 137 /** 138 * Commit the operation in the destructor to have a cool syntax for 139 * create(). 140 */ 141 ~S() noexcept 142 { 143 if (t.raw) 144 l4_factory_create_commit_u(f, t, u); 145 } 146 147 /** 148 * Explicitly commits the operation and returns the result. 149 * 150 * \return The result of the create() operation. 151 */ 152 operator l4_msgtag_t () noexcept 153 { 154 l4_msgtag_t r = l4_factory_create_commit_u(f, t, u); 155 t.raw = 0; 156 return r; 157 } 158 159 /** 160 * Put a single l4_mword_t as next argument. 161 * 162 * \param i The value to add as next argument. 163 * 164 * \return Reference to this stream. 165 */ 166 void put(l4_mword_t i) noexcept 167 { 168 l4_factory_create_add_int_u(i, &t, u); 169 } 170 171 /** 172 * Put a single l4_umword_t as next argument. 173 * 174 * \param i The value to add as next argument. 175 * 176 * \return Reference to this stream. 177 */ 178 void put(l4_umword_t i) noexcept 179 { 180 l4_factory_create_add_uint_u(i, &t, u); 181 } 182 183 /** 184 * Add a zero-terminated string as next argument. 185 * 186 * \param s The string to add as next argument. 187 * 188 * \return Reference to this stream. 189 * 190 * The string will be added with the zero-terminator. 191 */ 192 void put(char const *s) & noexcept 193 { 194 l4_factory_create_add_str_u(s, &t, u); 195 } 196 197 /** 198 * Add a pascal string as next argument. 199 * 200 * \param s The string to add as next argument. 201 * 202 * \return Reference to this stream. 203 * 204 * The string will be added with the exact length given. It is the 205 * responsibility of the caller to make sure that the string is zero- 206 * terminated when that is required by the server. 207 */ 208 void put(Lstr const &s) & noexcept 209 { 210 l4_factory_create_add_lstr_u(s.s, s.len, &t, u); 211 } 212 213 /** 214 * Add an empty argument. 215 * 216 * \return Reference to this stream. 217 */ 218 void put(Nil) & noexcept 219 { 220 l4_factory_create_add_nil_u(&t, u); 221 } 222 223 /** 224 * Add a flex page as next argument. 225 * 226 * \param d The flex page to add (there will be no map operation). 227 * 228 * \return Reference to this stream. 229 */ 230 void put(l4_fpage_t d) & noexcept 231 { 232 l4_factory_create_add_fpage_u(d, &t, u); 233 } 234 235 template<typename T> 236 S &operator << (T const &d) & noexcept 237 { 238 put(d); 239 return *this; 240 } 241 242 template<typename T> 243 S &&operator << (T const &d) && noexcept 244 { 245 put(d); 246 return _move(*this); 247 } 248 }; 249 250 251public: 252 253 /** 254 * Generic create call to the factory. 255 * 256 * \param[out] target Capability selector for the new object. The caller 257 * must allocate the capability slot. The kernel stores 258 * the new objects's capability into this slot. 259 * \param obj The protocol ID that specifies which kind of object 260 * shall be created. 261 * \param utcb The UTCB to use for the operation. 262 * 263 * \return A create stream that allows additional arguments to be passed to 264 * the create() call via the left-shift (<<) operator. 265 * 266 * This method does not directly invoke the factory. The factory is invoked 267 * when the create stream returned by this method is converted to an 268 * `l4_msgtag_t`, or otherwise when the stream goes out of scope. 269 * 270 * \note The create stream uses the UTCB to store parameters for the service 271 * call. During the lifetime of a create stream or, until it is 272 * converted to a `l4_msgtag_t`, other UTCB-using operations must not 273 * be used. 274 * 275 * \see create(Cap<OBJ>, l4_utcb_t *) 276 */ 277 S create(Cap<void> target, long obj, l4_utcb_t *utcb = l4_utcb()) noexcept 278 { 279 return S(cap(), obj, target, utcb); 280 } 281 282 /** 283 * Create call for typed capabilities. 284 * 285 * \tparam OBJ Capability type of the object to be created. 286 * \param[out] target Capability of type OBJ. 287 * \param utcb UTCB to use. 288 * 289 * \return A create stream that allows additional arguments to be passed to 290 * the create() call via the left-shift (<<) operator. 291 * 292 * This method does not directly invoke the factory. The factory is invoked 293 * when the create stream returned by this method is converted to an 294 * `l4_msgtag_t`, or otherwise when the stream goes out of scope. 295 * 296 * \note The create stream uses the UTCB to store parameters for the service 297 * call. During the lifetime of a create stream or, until it is 298 * converted to a `l4_msgtag_t`, other UTCB-using operations must not 299 * be used. 300 * 301 * Usage: 302 * ~~~ 303 * L4::Cap<L4Re::Dataspace> ds = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>(); 304 * factory->create(ds) << l4_mword_t(size_in_bytes); 305 * ~~~ 306 */ 307 template<typename OBJ> 308 S create(Cap<OBJ> target, l4_utcb_t *utcb = l4_utcb()) noexcept 309 { 310 return S(cap(), OBJ::Protocol, target, utcb); 311 } 312 313 L4_INLINE_RPC_NF( 314 l4_msgtag_t, create, (L4::Ipc::Out<L4::Cap<void> > target, l4_mword_t obj, 315 L4::Ipc::Varg const *args), 316 L4::Ipc::Call_t<L4_CAP_FPAGE_S>); 317 318 /** 319 * Create a new task. 320 * 321 * \param[out] target_cap The kernel stores the new task's capability into 322 * this slot. 323 * \param utcb_area Flexpage that describes an area in the address 324 * space of the new task, where the kernel should 325 * map the kernel-allocated kernel-user memory to. 326 * The kernel uses the kernel-user memory to store 327 * UTCBs and vCPU state-save-areas of the new task. 328 * \param utcb The UTCB to use for the operation. 329 * 330 * \return Syscall return tag 331 * 332 * \note The size of the UTCB area specifies indirectly the number 333 * of UTCBs available for this task. Refer to L4::Task::add_ku_mem 334 * / l4_task_add_ku_mem() for adding more of this type of memory. 335 * 336 * \note This method is only guaranteed to work with the 337 * \ref l4re_concepts_kernel_factory. 338 * 339 * \see L4::Task 340 */ 341 l4_msgtag_t create_task(Cap<Task> const & target_cap, 342 l4_fpage_t const &utcb_area, 343 l4_utcb_t *utcb = l4_utcb()) noexcept 344 { return l4_factory_create_task_u(cap(), target_cap.cap(), utcb_area, utcb); } 345 346 /** 347 * Create a new factory. 348 * 349 * \param[out] target_cap The kernel stores the new factory's capability into 350 * this slot. 351 * \param limit Limit for the new factory in bytes. 352 * \param utcb The UTCB to use for the operation. 353 * 354 * \return Syscall return tag 355 * 356 * \note In addition to memory needed for internal data structures, the 357 * `limit` (quota) of the new factory is counted towards the quota of 358 * the creating factory. The `limit` must be within 359 * `1 ≤ limit ≤ 2^(8 * sizeof(l4_umword_t) − 1) − 2` otherwise the 360 * behavior is undefined. 361 * 362 * \note This method is only guaranteed to work with the 363 * \ref l4re_concepts_kernel_factory. For other services, use the 364 * generic create() method and consult the service documentation for 365 * information on the arguments that need to be passed to the create 366 * stream. 367 */ 368 l4_msgtag_t create_factory(Cap<Factory> const &target_cap, 369 unsigned long limit, 370 l4_utcb_t *utcb = l4_utcb()) noexcept 371 { return l4_factory_create_factory_u(cap(), target_cap.cap(), limit, utcb); } 372 373 /** 374 * Create a new IPC gate. 375 * 376 * \param[out] target_cap The kernel stores the new IPC gate's capability 377 * into this slot. 378 * \param thread_cap Optional capability selector of the thread to 379 * bind the gate to. Use #L4_INVALID_CAP to create 380 * an unbound IPC gate. 381 * \param label Optional label of the gate (is used if 382 * `thread_cap` is valid). 383 * \param utcb The UTCB to use for the operation. 384 * 385 * \return Syscall return tag containing one of the following return codes. 386 * 387 * \retval L4_EOK No error occurred. 388 * \retval -L4_ENOMEM Out-of-memory during allocation of the Ipc_gate object. 389 * \retval -L4_ENOENT `thread_cap` is void or points to something that is not 390 * a thread. 391 * \retval -L4_EPERM No #L4_CAP_FPAGE_S rights on `thread_cap`. 392 * 393 * An unbound IPC gate can be bound to a thread using 394 * L4::Ipc_gate::bind_thread(). 395 * 396 * \note This method is only guaranteed to work with the 397 * \ref l4re_concepts_kernel_factory. 398 * 399 * \see L4::Ipc_gate 400 */ 401 l4_msgtag_t create_gate(Cap<void> const &target_cap, 402 Cap<Thread> const &thread_cap, l4_umword_t label, 403 l4_utcb_t *utcb = l4_utcb()) noexcept 404 { return l4_factory_create_gate_u(cap(), target_cap.cap(), thread_cap.cap(), label, utcb); } 405 406 typedef L4::Typeid::Rpc_nocode<create_t> Rpcs; 407}; 408 409} 410