1 /*
2  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3  *               Alexander Warg <warg@os.inf.tu-dresden.de>
4  *     economic rights: Technische Universität Dresden (Germany)
5  *
6  * This file is part of TUD:OS and distributed under the terms of the
7  * GNU General Public License 2.
8  * Please see the COPYING-GPL-2 file for details.
9  */
10 #include <l4/re/namespace>
11 #include <l4/re/dataspace>
12 #include <l4/re/mem_alloc>
13 #include <l4/re/rm>
14 #include <l4/re/log>
15 #include <l4/re/env>
16 #include <l4/re/error_helper>
17 #include <l4/re/util/env_ns>
18 
19 #include <l4/cxx/exceptions>
20 #include <l4/cxx/iostream>
21 #include <l4/cxx/l4iostream>
22 #include <l4/sys/debugger.h>
23 #include <l4/sys/scheduler>
24 #include <l4/sys/thread>
25 #include <l4/sys/cxx/ipc_server_loop>
26 
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 
31 #include "region.h"
32 #include "globals.h"
33 #include "loader_elf.h"
34 #include "debug.h"
35 #include "dispatcher.h"
36 
37 #include <l4/re/elf_aux.h>
38 
39 extern char const __executable_start[];
40 L4RE_ELF_AUX_ELEM_T(l4re_elf_aux_mword_t, __stack_addr,
41                     L4RE_ELF_AUX_T_STACK_ADDR,
42                     (l4_addr_t)__executable_start + 0x1000000);
43 
44 using L4::Cap;
45 using L4Re::Dataspace;
46 
47 extern "C" int main(int argc, char const *argv[],
48                     char const *env[]);
49 
50 static Elf_loader loader;
51 L4::Cap<void> rcv_cap;
52 
53 class Loop_hooks :
54   public L4::Ipc_svr::Ignore_errors,
55   public L4::Ipc_svr::Default_timeout,
56   public L4::Ipc_svr::Compound_reply
57 {
58 public:
setup_wait(l4_utcb_t * utcb,bool)59   static void setup_wait(l4_utcb_t *utcb, bool)
60   {
61     l4_utcb_br_u(utcb)->br[0] = L4::Ipc::Small_buf(rcv_cap.cap(),
62                                                    L4_RCV_ITEM_LOCAL_ID).raw();
63     l4_utcb_br_u(utcb)->br[1] = 0;
64     l4_utcb_br_u(utcb)->bdr = 0;
65   }
66 };
67 
68 extern "C" void *__libc_alloc_initial_tls(unsigned long size);
69 
__libc_alloc_initial_tls(unsigned long)70 void *__libc_alloc_initial_tls(unsigned long)
71 {
72   // __libc_alloc_initial_tls must not be called here, this is just
73   // a safety measure
74   assert(0);
75   return nullptr;
76 }
77 
78 static L4::Server<Loop_hooks> server;
79 
insert_regions()80 static void insert_regions()
81 {
82   using L4Re::Rm;
83   using L4Re::Env;
84   int n;
85   l4_addr_t addr = 0;
86   Rm::Region const *rl;
87   while ((n = L4Re::Env::env()->rm()->get_regions(addr, &rl)) > 0)
88     {
89       for (int i = 0; i < n; ++i)
90         {
91           Rm::Region const *r = &rl[i];
92           auto pager = L4::cap_reinterpret_cast<L4Re::Dataspace>(Env::env()->rm());
93           void *x = Global::local_rm
94             ->attach((void*)r->start, r->end - r->start +1,
95                      Region_handler(pager, L4_INVALID_CAP, 0,
96                                     Rm::F::Pager | Rm::F::RWX), Rm::Flags(0));
97           if (!x)
98             {
99               L4::cerr << "l4re: error while initializing region mapper\n";
100               exit(1);
101             }
102 
103           addr = r->end + 1;
104         }
105 
106     }
107 
108   Rm::Area const *al;
109   while ((n = L4Re::Env::env()->rm()->get_areas(addr, &al)) > 0)
110     {
111       for (int i = 0; i < n; ++i)
112         {
113           Rm::Area const *r = &al[i];
114           l4_addr_t x
115             = Global::local_rm->attach_area(r->start, r->end - r->start + 1);
116           if (!x)
117             {
118               L4::cerr << "l4re: error while initializing region mapper\n";
119               exit(1);
120             }
121 
122           addr = r->end + 1;
123         }
124     }
125 }
126 
run(int argc,char const * argv[],char const * envp[])127 static int run(int argc, char const *argv[], char const *envp[])
128 {
129   Dbg::set_level(Dbg::Info | Dbg::Warn);
130 
131   Dbg boot(Dbg::Boot);
132 
133   Global::argc = argc;
134   Global::argv = argv;
135 
136   if (0)
137     {
138       L4::cout << "ARGC=" << argc << "\n"
139                << "ARGV=" << argv << "\n"
140                << "ENVP=" << envp << "\n";
141 
142       for (int i = 0; i < argc; ++i)
143         L4::cout << "  arg: '" << argv[i] << "'\n";
144 
145       for (char const *const *e = Global::envp; *e; ++e)
146         L4::cout << "  env: '" << *e << "'\n";
147     }
148 
149   L4Re::Env *const env = const_cast<L4Re::Env*>(L4Re::Env::env());
150 
151   if (0)
152       L4::cout << "AUX=" << Global::l4re_aux << "\n"
153                << "ENV=" << env << "\n"
154                << "Binary: " << Global::l4re_aux->binary << " " << env << "\n";
155 
156   if (!env || !Global::l4re_aux)
157     {
158       Err(Err::Fatal).printf("invalid AUX vectors...\n");
159       exit(1);
160     }
161 
162     {
163       char s[15];
164       char *t = strstr(Global::l4re_aux->binary, "rom/");
165       s[0] = '#';
166       strncpy(s + 1, t ? t + 4 : Global::l4re_aux->binary, sizeof(s) - 2);
167       s[sizeof(s) - 1] = 0;
168       l4_debugger_set_object_name(L4_BASE_THREAD_CAP, s);
169       l4_debugger_set_object_name(L4_BASE_TASK_CAP, s + 1);
170     }
171 
172   Dbg::set_level(Global::l4re_aux->dbg_lvl);
173   rcv_cap = Global::cap_alloc->alloc<void>();
174   boot.printf("adding regions from remote region mapper\n");
175   insert_regions();
176 
177   L4::Cap<Dataspace> file;
178 
179   boot.printf("load binary '%s'\n", Global::l4re_aux->binary);
180 
181   file = L4Re_app_model::open_file(Global::l4re_aux->binary);
182 
183   loader.start(file, Global::local_rm, Global::l4re_aux);
184 
185   // Raise RM prio to its MCP
186   env->scheduler()->run_thread(env->main_thread(),
187                                l4_sched_param(L4_SCHED_MAX_PRIO));
188 
189   boot.printf("Start server loop\n");
190   server.loop<L4::Runtime_error>(Dispatcher());
191 }
192 
main(int argc,char const * argv[],char const * envp[])193 int main(int argc, char const *argv[], char const *envp[])
194 {
195   try
196     {
197       return run(argc, argv, envp);
198     }
199   catch (L4::Runtime_error const &e)
200     {
201       Err(Err::Fatal).printf("Exception %s: '%s'\n", e.str(), e.extra_str());
202       L4::cerr << e;
203       return 1;
204     }
205   catch (L4::Base_exception const &e)
206     {
207       Err(Err::Fatal).printf("Exception %s\n", e.str());
208       L4::cerr << e;
209       return 1;
210     }
211 
212   return 0;
213 }
214