1 /*
2  * (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>
3  *     economic rights: Technische Universität Dresden (Germany)
4  *
5  * This file is part of TUD:OS and distributed under the terms of the
6  * GNU General Public License 2.
7  * Please see the COPYING-GPL-2 file for details.
8  */
9 #pragma once
10 #include "region.h"
11 #include "globals.h"
12 
13 #include <l4/re/env>
14 #include <l4/libloader/loader>
15 #include <l4/libloader/local_app_model>
16 #include <cstring>
17 #include <l4/re/l4aux.h>
18 
19 
20 class L4Re_stack
21 {
22 private:
23   l4_addr_t _addr;
24   unsigned long _size;
25   char *sp;
26 
27 public:
set_local_addr(l4_addr_t addr)28   void set_local_addr(l4_addr_t addr)
29   { sp = (char *)addr + _size; }
30 
set_target_stack(l4_addr_t addr,l4_size_t size)31   void set_target_stack(l4_addr_t addr, l4_size_t size)
32   { _addr = addr; _size = size; }
33 
stack_size()34   l4_size_t stack_size() const { return _size; }
target_addr()35   l4_addr_t target_addr() const { return _addr; }
36 
push_object(void const * src,unsigned long size)37   char *push_object(void const *src, unsigned long size)
38   {
39     sp -= size;
40     memcpy(sp, src, size);
41     return sp;
42   }
43 
44   template<typename T>
push(T const & v)45   T *push(T const &v)
46   { return reinterpret_cast<T*>(push_object(&v, sizeof(T))); }
47 
push_local_ptr(void const * p)48   void const **push_local_ptr(void const *p)
49   { return push(p); }
50 
align(unsigned long size)51   void align(unsigned long size)
52   {
53     l4_addr_t p = l4_addr_t(sp);
54     unsigned bits;
55     for (bits = 0; (1UL << bits) <= size; ++bits)
56       ;
57 
58     p &= ~0UL << bits;
59     sp = (char *)p;
60   }
61 
ptr()62   char const *ptr() const { return sp; }
ptr(char * p)63   void ptr(char *p) { sp = p; }
64 };
65 
66 struct L4Re_app_model : public Ldr::Base_app_model<L4Re_stack>
67 {
68   typedef L4::Cap<L4Re::Dataspace> Const_dataspace;
69   typedef L4::Cap<L4Re::Dataspace> Dataspace;
70 
71   L4::Cap<L4Re::Rm> _rm;
72 
L4Re_app_modelL4Re_app_model73   L4Re_app_model(L4::Cap<L4Re::Rm> rm, void *) : _rm(rm) {}
74 
75   Dataspace alloc_ds(unsigned long size) const;
76 
77   static Const_dataspace open_file(char const *name);
78 
79   void prog_attach_ds(l4_addr_t addr, unsigned long size,
80                       Const_dataspace ds, unsigned long offset,
81                       L4Re::Rm::Flags flags, char const *what);
82 
83   static void copy_ds(Dataspace dst, unsigned long dst_offs,
84                       Const_dataspace src, unsigned long src_offs,
85                       unsigned long size);
86 
87   static bool all_segs_cow();
88 
89   l4_addr_t local_attach_ds(Const_dataspace ds, unsigned long size,
90                             unsigned long offset) const;
91 
92   void local_detach_ds(l4_addr_t addr, unsigned long size) const;
93 
94   int prog_reserve_area(l4_addr_t *start, unsigned long size,
95                         L4Re::Rm::Flags flags, unsigned char align);
96 
97   Dataspace alloc_app_stack();
98 
init_progL4Re_app_model99   void init_prog()
100   {}
101 
reserved_areaL4Re_app_model102   static Const_dataspace reserved_area()
103   { return L4::Cap<L4Re::Dataspace>::Invalid; }
104 
local_kip_dsL4Re_app_model105   static Dataspace local_kip_ds()
106   {
107     return L4::Cap<L4Re::Dataspace>(Global::l4re_aux->kip_ds);
108   }
109 
local_kip_capL4Re_app_model110   static L4::Cap<void> local_kip_cap()
111   { return local_kip_ds(); }
112 
prog_kip_dsL4Re_app_model113   static L4::Cap<void> prog_kip_ds()
114   {
115     return L4::Cap<L4Re::Dataspace>(Global::l4re_aux->kip_ds);
116   }
117 
generate_l4auxL4Re_app_model118   void const *generate_l4aux(char const *) const
119   { return Global::l4re_aux; }
120 
121   void extra_elf_auxv();
122   void push_envp();
123   void push_argv();
124 
125   L4Re::Env *add_env();
126   void start_prog(L4Re::Env const *env);
127 };
128 
129 typedef Ldr::Local_app_model<L4Re_app_model> L4Re_x_app_model;
130 
131 class Loader
132 {
133 public:
134   bool start(L4::Cap<L4Re::Dataspace> bin, Region_map *rm, l4re_aux_t *aux);
135   bool __start(L4::Cap<L4Re::Dataspace> bin, Region_map *rm);
136   virtual bool launch(L4::Cap<L4Re::Dataspace> bin, L4::Cap<L4Re::Rm>) = 0;
~Loader()137   virtual ~Loader() {}
138 };
139