]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/ned/server/src/ned.lua
dc42f930dfe41cf477bccce5011e2a66d26e7cf6
[l4.git] / l4 / pkg / ned / server / src / ned.lua
1 -- vim:set ft=lua:
2
3 module ("L4", package.seeall)
4
5 -- Add this alias, it sounds better for some cases
6 L4.Env.user_factory = L4.Env.mem_alloc;
7
8 -- L4 protocol constants
9 Proto = {
10   Dataspace = 0x4000,
11   Namespace = 0x4001,
12   Goos      = 0x4003,
13   Mem_alloc = 0x4004,
14   Rm        = 0x4005,
15   Irq       = -1,
16   Sigma0    = -6,
17   Log       = -13,
18   Scheduler = -14,
19   Factory   = -15,
20   Ipc_gate  = 0,
21 }
22
23 -- L4 rights flags
24 Rights = {
25   s   = 2,
26   w   = 1,
27   r   = 4,
28   ro  = 4,
29   rw  = 5,
30   rws = 7,
31 }
32
33 -- Ldr flags
34 Ldr_flags = {
35   eager_map    = 0x1, -- L4RE_AUX_LDR_FLAG_EAGER_MAP
36   all_segs_cow = 0x2, -- L4RE_AUX_LDR_FLAG_ALL_SEGS_COW
37   pinned_segs  = 0x4, -- L4RE_AUX_LDR_FLAG_PINNED_SEGS
38 }
39
40 -- L4Re debug constants
41 Dbg = {
42   Info       = 1,
43   Warn       = 2,
44   Boot       = 4,
45   Server     = 0x10,
46   Exceptions = 0x20,
47   Cmd_line   = 0x40,
48   Loader     = 0x80,
49   Name_space = 0x400,
50   All        = 0xffffffff,
51 }
52
53 -- Loader class, encapsulates a loader instance.
54 --  * A memory allocator
55 --  * A factory used for name-space creation (ns_fab)
56 --  * A factory used for region-map creation (rm_fab)
57 --  * A Factory used for log creation (log_fab)
58 --  * A Scheduler factory (sched_fab)
59
60 Loader = {};
61 Loader.__index = Loader;
62
63 Class = {};
64
65 function Class.check(obj, class)
66   if not obj or getmetatable(obj) ~= class then
67     error("method called with incompatible object", 3);
68   end
69 end
70
71 function Loader.new(proto)
72   local f = proto or {};
73
74   do
75     local lfab = f.loader or f.mem;
76     f.log_fab = f.log_fab or lfab;
77     f.ns_fab = f.ns_fab or lfab;
78     f.rm_fab = f.rm_fab or lfab;
79     f.sched_fab = f.sched_fab or lfab;
80     f.factory = f.factory or Env.factory;
81   end
82
83   setmetatable(f, Loader);
84   return f;
85 end
86
87 function mangle_class(n)
88   local m = "N";
89   for i in string.gmatch(n, "([^:%s]+)") do
90     m = m .. #i .. i;
91   end
92   return m .. "E"; 
93 end
94
95 function get_cap_class(id)
96   local t = type(id);
97   if t == "number" then
98     return _CAP_TYPES[id];
99   elseif t == "string" then
100     return _CAP_TYPES[mangle_class(id)];
101   else
102     return nil;
103   end
104 end
105
106 local ns_class = get_cap_class("L4Re::Namespace");
107 if ns_class then
108   ns_class.register = function (self, key, value, fab)
109     if type(value) == "function" then
110       value = value(self, key);
111     end
112
113     if value ~= nil then
114       if type(value) ~= "table" then
115         self:__register(key, value);
116       elseif (fab) then
117         self:__register(key, fab(value));
118       end
119     end
120   end
121   ns_class.r = ns_class.register;
122 else
123   error("Could not find type information for L4Re::Namespace");
124 end
125
126 ns_class = nil;
127
128 function Loader.fill_namespace(ns, tmpl, fab)
129   local function cns(value)
130     return self:create_namespace(value, fab);
131   end
132
133   for k, v in pairs(tmpl) do
134     ns:r(k, v, cns);
135   end
136 end
137
138
139 function Loader:create_namespace(n, fab)
140   Class.check(self, Loader);
141
142   if type(n) ~= "table" then
143     return n;
144   end
145
146   local ns_fab = fab or self.ns_fab;
147   local ns = ns_fab:create(Proto.Namespace);
148   self.fill_namespace(ns, n, ns_fab);
149   return ns;
150 end
151
152
153
154 App_env = {}
155 App_env.__index = App_env;
156
157 function App_env.new(proto)
158   local f = proto or {};
159
160   f.loader = f.loader or default_loader;
161   f.rm_fab = f.loader.rm_fab;
162   f.factory = f.factory or f.loader.factory or L4.Env.factory;
163   --  f.scheduler = f.scheduler or f.loader.scheduler;
164
165   f.mem = f.mem or f.loader.mem;
166
167   if type(f.log) == "table" then
168     f.log_tag, f.log_color = unpack(f.log);
169     f.log = nil;
170   elseif type(f.log) == "function" then
171     f.log = f.log()
172   end
173
174   setmetatable(f, App_env);
175
176   if type(f.ns) == "table" then
177     f.ns = f.loader:create_namespace(f.ns, f.ns_fab);
178   end
179
180   return f;
181 end
182
183 function App_env:log()
184   Class.check(self, App_env);
185   if self.loader.log_fab == nil or self.loader.log_fab.create == nil then
186     error ("Starting a application without valid log factory", 4);
187   end
188   return self.loader.log_fab:create(Proto.Log, self.log_tag, self.log_color);
189 end
190
191 function App_env:start(...)
192   Class.check(self, App_env);
193
194   local function fa(a)
195     return string.gsub(a, ".*/", "");
196   end
197   local old_log_tag = self.log_tag;
198   self.log_tag = self.log_tag or fa(...);
199   local res = exec(self, ...);
200   self.log_tag = old_log_tag;
201   return res;
202 end
203
204 function App_env:set_ns(tmpl)
205   Class.check(self, App_env);
206   self.ns = Namespace.new(tmpl, self.ns_fab);
207 end
208
209 function App_env:set_loader_fab(fab)
210   Class.check(self, App_env);
211   self.log_fab = fab;
212   self.ns_fab = fab;
213   self.rm_fab = fab;
214 end
215
216 function App_env:set_mem_alloc(mem)
217   Class.check(self, App_env);
218   self.mem = mem;
219 end
220
221 function Loader:startv(env, ...)
222   Class.check(self, Loader);
223
224   local caps = env.caps or {};
225
226   if (type(caps) == "table") then
227     caps.rom = caps.rom or Env.rom;
228   end
229
230   env.loader = self;
231   env.caps = caps;
232   env.l4re_dbg = env.l4re_dbg or L4.Dbg.Warn;
233   local e = App_env.new(env);
234   return e:start(...);
235 end
236
237 -- Create a new IPC gate for a client-server connection
238 function L4.Loader:new_channel()
239   return self.factory:create(Proto.Ipc_gate);
240 end
241
242 function Loader.split_args(cmd, posix_env)
243   local a = {};
244   local i = 1;
245   for w in string.gmatch(cmd, "[^%s]+") do
246     a[i] = w;
247     i = i + 1;
248   end
249   a[i] = posix_env;
250   return unpack(a);
251 end
252
253 function Loader:start(env, cmd, posix_env)
254   Class.check(self, Loader);
255   return self:startv(env, self.split_args(cmd, posix_env));
256 end
257
258 default_loader = Loader.new({factory = Env.factory, mem = Env.mem_alloc});