]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/io/server/src/main.cc
0b5b7aee4fd9358cbb7f30549c8543420ef35dc4
[l4.git] / l4 / pkg / io / server / src / main.cc
1 /*
2  * (c) 2010 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/sys/capability>
11 #include <l4/re/env>
12 #include <l4/re/util/cap_alloc>
13 #include <l4/re/namespace>
14 #include <l4/sys/icu>
15 #include <l4/re/error_helper>
16 #include <l4/re/dataspace>
17 #include <l4/util/kip.h>
18 #include <l4/cxx/std_exc_io>
19
20 #include "main.h"
21 #include "hw_root_bus.h"
22 #include "hw_device.h"
23 #include "server.h"
24 #include "res.h"
25 #include "pci.h"
26 #include "__acpi.h"
27 #include "vbus.h"
28 #include "vbus_factory.h"
29 #include "phys_space.h"
30 #include "ux.h"
31 #include "cfg.h"
32
33 #include <cstdio>
34 #include <typeinfo>
35 #include <algorithm>
36 #include <string>
37 #include <getopt.h>
38 #include <sys/mman.h>
39 #include <sys/stat.h>
40 #include <stdio.h>
41 #include <fcntl.h>
42
43 #ifdef SUPPORT_LEGACY_CFG
44 #include "cfg_parser.h"
45 #endif
46
47 #include <lua.h>
48 #include <lauxlib.h>
49 #include <lualib.h>
50
51 #include "lua_glue.swg.h"
52
53 int luaopen_Io(lua_State *);
54
55 static const luaL_Reg libs[] =
56 {
57   {"", luaopen_base },
58   {LUA_STRLIBNAME, luaopen_string },
59   {LUA_LOADLIBNAME, luaopen_package},
60   {LUA_DBLIBNAME, luaopen_debug},
61   {LUA_TABLIBNAME, luaopen_table},
62   { NULL, NULL }
63 };
64
65 using L4Re::Util::Auto_cap;
66
67 class Io_config_x : public Io_config
68 {
69 public:
70   Io_config_x()
71   : _do_transparent_msi(false), _verbose_lvl(1) {}
72
73   bool transparent_msi(Hw::Device *) const
74   { return _do_transparent_msi; }
75
76   bool legacy_ide_resources(Hw::Device *) const
77   { return true; }
78
79   bool expansion_rom(Hw::Device *) const
80   { return false; }
81
82   void set_transparent_msi(bool v) { _do_transparent_msi = v; }
83
84   int verbose() const { return _verbose_lvl; }
85   void inc_verbosity() { ++_verbose_lvl; }
86
87 private:
88   bool _do_transparent_msi;
89   int _verbose_lvl;
90 };
91
92 static Io_config_x _my_cfg __attribute__((init_priority(30000)));
93 Io_config *Io_config::cfg = &_my_cfg;
94
95
96 Hw::Device *
97 system_bus()
98 {
99   static Hw::Root_bus _sb("System Bus");
100   return &_sb;
101 }
102
103 Hw_icu *
104 system_icu()
105 {
106   static Hw_icu _icu;
107   return &_icu;
108 }
109
110 template< typename X >
111 char const *type_name(X const &x)
112 {
113   char *n = const_cast<char *>(typeid(x).name());
114   strtol(n, &n, 0);
115   return n;
116 }
117
118 static void dump(Device *d)
119 {
120   Device::iterator i = Device::iterator(0, d, 100);
121   for (; i != d->end(); ++i)
122     {
123       for (int x = 0; x < i->depth(); ++x)
124         printf("  ");
125       printf("%s: %s \"%s\"\n",
126              type_name(*i), i->name(),
127              i->hid() ? i->hid() : "");
128       if (dlevel(DBG_INFO))
129         i->dump(i->depth() * 2);
130       if (dlevel(DBG_DEBUG))
131         for (Resource_list::const_iterator r = i->resources()->begin();
132              r != i->resources()->end(); ++r)
133           if (*r)
134             (*r)->dump(i->depth() * 2 + 2);
135     }
136 }
137
138 void dump_devs(Device *d);
139 int add_vbus(Vi::Device *dev);
140
141 void dump_devs(Device *d) { dump(d); }
142
143
144 Hw_icu::Hw_icu()
145 {
146   icu = L4Re::Env::env()->get_cap<L4::Icu>("icu");
147   if (icu.is_valid())
148     icu->info(&info);
149 }
150
151 int add_vbus(Vi::Device *dev)
152 {
153   Vi::System_bus *b = dynamic_cast<Vi::System_bus*>(dev);
154   if (!b)
155     {
156       d_printf(DBG_ERR, "ERROR: found non system-bus device as root device, ignored\n");
157       return -1;
158     }
159
160   b->request_child_resources();
161   b->allocate_pending_child_resources();
162   b->setup_resources();
163   if (!registry->register_obj(b, b->name()).is_valid())
164     {
165       d_printf(DBG_WARN, "WARNING: Service registration failed: '%s'\n", b->name());
166       return -1;
167     }
168   return 0;
169 }
170
171
172 struct Add_system_bus
173 {
174   void operator () (Vi::Device *dev)
175   {
176     Vi::System_bus *b = dynamic_cast<Vi::System_bus*>(dev);
177     if (!b)
178       {
179         d_printf(DBG_ERR, "ERROR: found non system-bus device as root device, ignored\n");
180         return;
181       }
182
183     b->request_child_resources();
184     b->allocate_pending_child_resources();
185     b->setup_resources();
186     if (!registry->register_obj(b, b->name()).is_valid())
187       {
188         d_printf(DBG_WARN, "WARNING: Service registration failed: '%s'\n", b->name());
189         return;
190       }
191   }
192 };
193
194
195 #ifdef SUPPORT_LEGACY_CFG
196 static void
197 print_cfg_error(char const *cfg, char const *lua_err, char const *msg, int err)
198 {
199   if (lua_err)
200     d_printf(DBG_ERR, "%s: error using as lua config: %s\n", cfg, lua_err);
201
202   if (msg)
203     d_printf(DBG_ERR, "%s: error (legacy format): %s (errno=%d)\n", cfg, msg, err);
204
205   if (errno < 0)
206     exit(1);
207 }
208 #endif
209
210 static int
211 read_config(char const *cfg_file, lua_State *lua)
212 {
213   d_printf(DBG_INFO, "Loading: config '%s'\n", cfg_file);
214
215   char const *lua_err = 0;
216   int err = luaL_loadfile(lua, cfg_file);
217
218   switch (err)
219     {
220     case 0:
221       if ((err = lua_pcall(lua, 0, LUA_MULTRET, 0)))
222         {
223           lua_err = lua_tostring(lua, -1);
224           d_printf(DBG_ERR, "%s: error executing lua config: %s\n", cfg_file, lua_err);
225           lua_pop(lua, lua_gettop(lua));
226           return -1;
227         }
228       lua_pop(lua, lua_gettop(lua));
229       return 0;
230       break;
231     case LUA_ERRSYNTAX:
232       lua_err = lua_tostring(lua, -1);
233       lua_pop(lua, lua_gettop(lua));
234       break;
235     case LUA_ERRMEM:
236       d_printf(DBG_ERR, "%s: out of memory while loading file\n", cfg_file);
237       exit(1);
238     case LUA_ERRFILE:
239       lua_err = lua_tostring(lua, -1);
240       d_printf(DBG_ERR, "%s: cannot open/read file: %s\n", cfg_file, lua_err);
241       exit(1);
242     default:
243       d_printf(DBG_ERR, "%s: unknown error: %s\n", cfg_file, lua_err);
244       exit(1);
245     }
246 #ifdef SUPPORT_LEGACY_CFG
247   // try old school config file parser
248   int fd = open(cfg_file, O_RDONLY);
249
250   if (fd < 0)
251     print_cfg_error(cfg_file, lua_err, "failed to open", errno);
252
253   struct stat sd;
254   if (fstat(fd, &sd))
255     print_cfg_error(cfg_file, lua_err, "cannot stat file", errno);
256
257   void *adr = mmap(NULL, sd.st_size, PROT_READ, MAP_SHARED, fd, 0);
258   if (adr == MAP_FAILED)
259     print_cfg_error(cfg_file, lua_err, "cannot mmap file", errno);
260
261   char const *config_file = (char const *)adr;
262   Vi::Device *vdev = 0;
263   int parse_errors = 0;
264   cfg::Scanner s(config_file, config_file + sd.st_size, cfg_file);
265   cfg::Parser p(&s, 0, vdev, system_bus(), parse_errors);
266   p.parse();
267
268   munmap(adr, sd.st_size);
269
270   if (parse_errors > 0)
271     print_cfg_error(cfg_file, lua_err, "parse errors", parse_errors);
272
273   if (!vdev)
274     return 0;
275
276   std::for_each(Vi::Device::iterator(0, vdev, 0), Vi::Device::end(), Add_system_bus());
277
278   if (dlevel(DBG_DEBUG))
279     dump(vdev);
280
281   return 0;
282 #else
283   d_printf(DBG_ERR, "%s: error using as lua config: %s\n", cfg_file, lua_err);
284   return -1;
285 #endif
286 }
287
288
289
290 static int
291 arg_init(int argc, char * const *argv, Io_config_x *cfg)
292 {
293   while (1)
294     {
295       int optidx = 0;
296       int c;
297       enum
298       {
299         OPT_TRANSPARENT_MSI   = 1,
300       };
301
302       struct option opts[] =
303       {
304         { "verbose",           0, 0, 'v' },
305         { "transparent-msi",   0, 0, OPT_TRANSPARENT_MSI },
306         { 0, 0, 0, 0 },
307       };
308
309       c = getopt_long(argc, argv, "v", opts, &optidx);
310       if (c == -1)
311         break;
312
313       switch (c)
314         {
315         case 'v':
316           _my_cfg.inc_verbosity();
317           break;
318         case OPT_TRANSPARENT_MSI:
319           d_printf(DBG_INFO, "Enabling transparent MSIs\n");
320           cfg->set_transparent_msi(true);
321           break;
322         }
323     }
324   return optind;
325 }
326
327 static
328 int
329 run(int argc, char * const *argv)
330 {
331   int argfileidx = arg_init(argc, argv, &_my_cfg);
332
333   printf("Io service\n");
334   set_debug_level(Io_config::cfg->verbose());
335
336   d_printf(DBG_INFO, "Verboseness level: %d\n", Io_config::cfg->verbose());
337
338   res_init();
339
340   if (dlevel(DBG_DEBUG))
341     Phys_space::space.dump();
342
343 #if defined(ARCH_x86) || defined(ARCH_amd64)
344   bool is_ux = l4util_kip_kernel_is_ux(l4re_kip());
345   //res_get_ioport(0xcf8, 4);
346   res_get_ioport(0, 16);
347
348   if (!is_ux)
349     acpica_init();
350 #endif
351
352   system_bus()->plugin();
353
354 #if defined(ARCH_x86) || defined(ARCH_amd64)
355   if (is_ux)
356     ux_setup(system_bus());
357 #endif
358
359   lua_State *lua = luaL_newstate();
360
361   if (!lua)
362     {
363       printf("ERROR: cannot allocate Lua state\n");
364       exit(1);
365     }
366
367   lua_newtable(lua);
368   lua_setglobal(lua, "Io");
369
370   for (int i = 0; libs[i].func; ++i)
371     {
372 #if 1 // lua 5.1
373       lua_pushcfunction(lua, libs[i].func);
374       lua_pushstring(lua,libs[i].name);
375       lua_call(lua, 1, 0);
376 #endif
377 #if 0  // lua 5.2
378       luaL_requiref(lua, libs[i].name, libs[i].func, 1);
379       lua_pop(lua, 1);
380 #endif
381     }
382
383   luaopen_Io(lua);
384
385   for (; argfileidx < argc; ++argfileidx)
386     read_config(argv[argfileidx], lua);
387
388   if (dlevel(DBG_DEBUG))
389     {
390       printf("Real Hardware -----------------------------------\n");
391       dump(system_bus());
392     }
393
394   fprintf(stderr, "Ready. Waiting for request.\n");
395   server_loop();
396
397   return 0;
398 }
399
400 int
401 main(int argc, char * const *argv)
402 {
403   try
404     {
405       return run(argc, argv);
406     }
407   catch (L4::Runtime_error &e)
408     {
409       std::cerr << "FATAL uncought exception: " << e
410                 << "\nterminating...\n";
411
412     }
413   catch (...)
414     {
415       std::cerr << "FATAL uncought exception of unknown type\n"
416                 << "terminating...\n";
417     }
418   return -1;
419 }