1 /*        $NetBSD: lua.c,v 1.28 2022/03/31 19:30:17 pgoyette Exp $ */
2 
3 /*
4  * Copyright (c) 2011 - 2017 by Marc Balmer <mbalmer@NetBSD.org>.
5  * Copyright (c) 2014 by Lourival Vieira Neto <lneto@NetBSD.org>.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the Author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 /* Lua device driver */
33 
34 #include <sys/param.h>
35 #include <sys/fcntl.h>
36 #include <sys/conf.h>
37 #include <sys/condvar.h>
38 #include <sys/device.h>
39 #include <sys/ioctl.h>
40 #include <sys/kmem.h>
41 #include <sys/lock.h>
42 #include <sys/lua.h>
43 #include <sys/module.h>
44 #include <sys/mutex.h>
45 #include <sys/namei.h>
46 #include <sys/queue.h>
47 #include <sys/sysctl.h>
48 #include <sys/vnode.h>
49 #include <sys/cpu.h>
50 
51 #include <lauxlib.h>
52 
53 #include "luavar.h"
54 
55 struct lua_softc {
56           device_t             sc_dev;
57 
58           kmutex_t             sc_lock;
59           kcondvar_t                     sc_inuse_cv;
60           bool                           sc_inuse;
61 
62           /* Locking access to state queues */
63           kmutex_t             sc_state_lock;
64           kcondvar_t                     sc_state_cv;
65           bool                           sc_state;
66 
67           struct sysctllog    *sc_log;
68 };
69 
70 static device_t     sc_self;
71 static bool         lua_autoload_on = true;
72 static bool         lua_require_on = true;
73 static bool         lua_bytecode_on = false;
74 static int          lua_verbose;
75 static int          lua_max_instr;
76 
77 static LIST_HEAD(, lua_state) lua_states =
78     LIST_HEAD_INITIALIZER(lua_states);
79 static LIST_HEAD(, lua_module)          lua_modules =
80     LIST_HEAD_INITIALIZER(lua_modules);
81 
82 static int lua_match(device_t, cfdata_t, void *);
83 static void lua_attach(device_t, device_t, void *);
84 static int lua_detach(device_t, int);
85 static klua_State *klua_find(const char *);
86 static const char *lua_reader(lua_State *, void *, size_t *);
87 static void lua_maxcount(lua_State *, lua_Debug *);
88 
89 static int lua_require(lua_State *);
90 
91 CFATTACH_DECL_NEW(lua, sizeof(struct lua_softc),
92           lua_match, lua_attach, lua_detach, NULL);
93 
94 dev_type_open(luaopen);
95 dev_type_close(luaclose);
96 dev_type_ioctl(luaioctl);
97 
98 const struct cdevsw lua_cdevsw = {
99           .d_open = luaopen,
100           .d_close = luaclose,
101           .d_read = noread,
102           .d_write = nowrite,
103           .d_ioctl = luaioctl,
104           .d_stop = nostop,
105           .d_tty = notty,
106           .d_poll = nopoll,
107           .d_mmap = nommap,
108           .d_kqfilter = nokqfilter,
109           .d_discard = nodiscard,
110           .d_flag = D_OTHER | D_MPSAFE
111 };
112 
113 struct lua_loadstate {
114           struct vnode        *vp;
115           size_t               size;
116           off_t                off;
117 };
118 
119 extern struct cfdriver lua_cd;
120 
121 static int
lua_match(device_t parent,cfdata_t match,void * aux)122 lua_match(device_t parent, cfdata_t match, void *aux)
123 {
124           return 1;
125 }
126 
127 static void
lua_attach(device_t parent,device_t self,void * aux)128 lua_attach(device_t parent, device_t self, void *aux)
129 {
130           struct lua_softc *sc;
131           const struct sysctlnode *node;
132 
133           if (sc_self)
134                     return;
135 
136           sc = device_private(self);
137           sc->sc_dev = self;
138           sc_self = self;
139 
140           mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM);
141           cv_init(&sc->sc_inuse_cv, "luactl");
142 
143           mutex_init(&sc->sc_state_lock, MUTEX_DEFAULT, IPL_VM);
144           cv_init(&sc->sc_state_cv, "luastate");
145 
146           if (!pmf_device_register(self, NULL, NULL))
147                     aprint_error_dev(self, "couldn't establish power handler\n");
148 
149           /* Sysctl to provide some control over behaviour */
150         sysctl_createv(&sc->sc_log, 0, NULL, &node,
151             CTLFLAG_OWNDESC,
152             CTLTYPE_NODE, "lua",
153             SYSCTL_DESCR("Lua options"),
154             NULL, 0, NULL, 0,
155             CTL_KERN, CTL_CREATE, CTL_EOL);
156 
157         if (node == NULL) {
158                     aprint_error(": can't create sysctl node\n");
159                 return;
160           }
161 
162           /*
163            * XXX Some of the sysctl values must not be changed after the
164            * securelevel has been raised.
165            */
166         sysctl_createv(&sc->sc_log, 0, &node, NULL,
167             CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
168             CTLTYPE_BOOL, "require",
169             SYSCTL_DESCR("Enable the require command"),
170             NULL, 0, &lua_require_on, 0,
171               CTL_CREATE, CTL_EOL);
172 
173         sysctl_createv(&sc->sc_log, 0, &node, NULL,
174             CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
175             CTLTYPE_BOOL, "autoload",
176             SYSCTL_DESCR("Enable automatic load of modules"),
177             NULL, 0, &lua_autoload_on, 0,
178               CTL_CREATE, CTL_EOL);
179 
180         sysctl_createv(&sc->sc_log, 0, &node, NULL,
181             CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
182             CTLTYPE_BOOL, "bytecode",
183             SYSCTL_DESCR("Enable loading of bytecode"),
184             NULL, 0, &lua_bytecode_on, 0,
185               CTL_CREATE, CTL_EOL);
186 
187         sysctl_createv(&sc->sc_log, 0, &node, NULL,
188             CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
189             CTLTYPE_INT, "verbose",
190             SYSCTL_DESCR("Enable verbose output"),
191             NULL, 0, &lua_verbose, 0,
192               CTL_CREATE, CTL_EOL);
193 
194         sysctl_createv(&sc->sc_log, 0, &node, NULL,
195             CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
196             CTLTYPE_INT, "maxcount",
197             SYSCTL_DESCR("Limit maximum instruction count"),
198             NULL, 0, &lua_max_instr, 0,
199               CTL_CREATE, CTL_EOL);
200 
201           aprint_normal_dev(self, "%s\n", LUA_COPYRIGHT);
202 }
203 
204 static int
lua_detach(device_t self,int flags)205 lua_detach(device_t self, int flags)
206 {
207           struct lua_softc *sc;
208           struct lua_state *s;
209 
210           sc = device_private(self);
211           pmf_device_deregister(self);
212 
213           if (sc->sc_log != NULL) {
214                     sysctl_teardown(&sc->sc_log);
215                     sc->sc_log = NULL;
216           }
217 
218           /* Traverse the list of states and close them */
219           while ((s = LIST_FIRST(&lua_states)) != NULL) {
220                     LIST_REMOVE(s, lua_next);
221                     klua_close(s->K);
222                     if (lua_verbose)
223                               device_printf(self, "state %s destroyed\n",
224                                   s->lua_name);
225                     kmem_free(s, sizeof(struct lua_state));
226           }
227           mutex_destroy(&sc->sc_lock);
228           cv_destroy(&sc->sc_inuse_cv);
229           mutex_destroy(&sc->sc_state_lock);
230           cv_destroy(&sc->sc_state_cv);
231           sc_self = NULL;
232           return 0;
233 }
234 
235 int
luaopen(dev_t dev,int flag,int mode,struct lwp * l)236 luaopen(dev_t dev, int flag, int mode, struct lwp *l)
237 {
238           struct lua_softc *sc;
239           int error = 0;
240 
241           if (minor(dev) > 0)
242                     return ENXIO;
243 
244           sc = device_lookup_private(&lua_cd, minor(dev));
245           if (sc == NULL)
246                     return ENXIO;
247 
248           mutex_enter(&sc->sc_lock);
249           while (sc->sc_inuse == true) {
250                     error = cv_wait_sig(&sc->sc_inuse_cv, &sc->sc_lock);
251                     if (error)
252                               break;
253           }
254           if (!error)
255                     sc->sc_inuse = true;
256           mutex_exit(&sc->sc_lock);
257 
258           if (error)
259                     return error;
260           return 0;
261 }
262 
263 int
luaclose(dev_t dev,int flag,int mode,struct lwp * l)264 luaclose(dev_t dev, int flag, int mode, struct lwp *l)
265 {
266           struct lua_softc *sc;
267 
268           if (minor(dev) > 0)
269                     return ENXIO;
270           sc = device_lookup_private(&lua_cd, minor(dev));
271           mutex_enter(&sc->sc_lock);
272           sc->sc_inuse = false;
273           cv_signal(&sc->sc_inuse_cv);
274           mutex_exit(&sc->sc_lock);
275           return 0;
276 }
277 
278 int
luaioctl(dev_t dev,u_long cmd,void * data,int flag,struct lwp * l)279 luaioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
280 {
281           struct lua_softc *sc;
282           struct lua_info *info;
283           struct lua_create *create;
284           struct lua_require *require;
285           struct lua_load *load;
286           struct lua_state *s;
287           struct lua_module *m;
288           kauth_cred_t cred;
289           struct vnode *vp;
290           struct pathbuf *pb;
291           struct vattr va;
292           struct lua_loadstate ls;
293           struct lua_state_info *states;
294           int error, n;
295           klua_State *K;
296 
297           sc = device_lookup_private(&lua_cd, minor(dev));
298           if (!device_is_active(sc->sc_dev))
299                     return EBUSY;
300 
301           switch (cmd) {
302           case LUAINFO:
303                     info = data;
304                     if (info->states == NULL) {
305                               info->num_states = 0;
306                               LIST_FOREACH(s, &lua_states, lua_next)
307                                         info->num_states++;
308                     } else {
309                               n = 0;
310                               LIST_FOREACH(s, &lua_states, lua_next) {
311                                         if (n > info->num_states)
312                                                   break;
313                                         n++;
314                               }
315                               info->num_states = n;
316                               states = kmem_alloc(sizeof(*states) * n, KM_SLEEP);
317                               if (copyin(info->states, states, sizeof(*states) * n)
318                                   == 0) {
319                                         n = 0;
320                                         LIST_FOREACH(s, &lua_states, lua_next) {
321                                                   if (n > info->num_states)
322                                                             break;
323                                                   strcpy(states[n].name, s->lua_name);
324                                                   strcpy(states[n].desc, s->lua_desc);
325                                                   states[n].user = s->K->ks_user;
326                                                   n++;
327                                         }
328                                         copyout(states, info->states,
329                                             sizeof(*states) * n);
330                                         kmem_free(states, sizeof(*states) * n);
331                               }
332                     }
333                     break;
334           case LUACREATE:
335                     create = data;
336 
337                     if (*create->name == '_') {
338                               if (lua_verbose)
339                                         device_printf(sc->sc_dev, "names of user "
340                                             "created states must not begin with '_'");
341                                         return ENXIO;
342                     }
343                     LIST_FOREACH(s, &lua_states, lua_next)
344                               if (!strcmp(s->lua_name, create->name)) {
345                                         if (lua_verbose)
346                                                   device_printf(sc->sc_dev,
347                                                       "state %s exists\n", create->name);
348                                         return EBUSY;
349                               }
350 
351                     K = kluaL_newstate(create->name, create->desc, IPL_NONE);
352 
353                     if (K == NULL)
354                               return ENOMEM;
355 
356                     K->ks_user = true;
357 
358                     if (lua_verbose)
359                               device_printf(sc->sc_dev, "state %s created\n",
360                                   create->name);
361                     break;
362           case LUADESTROY:
363                     create = data;
364 
365                     K = klua_find(create->name);
366 
367                     if (K != NULL && (K->ks_user == true)) {
368                               klua_close(K);
369                               return 0;
370                     }
371                     return EBUSY;
372           case LUAREQUIRE:    /* 'require' a module in a State */
373                     require = data;
374                     LIST_FOREACH(s, &lua_states, lua_next)
375                               if (!strcmp(s->lua_name, require->state)) {
376                                         LIST_FOREACH(m, &s->lua_modules, mod_next)
377                                                   if (!strcmp(m->mod_name, require->module))
378                                                             return ENXIO;
379                                         LIST_FOREACH(m, &lua_modules, mod_next)
380                                                   if (!strcmp(m->mod_name,
381                                                       require->module)) {
382                                                             if (lua_verbose)
383                                                                       device_printf(
384                                                                           sc->sc_dev,
385                                                                           "requiring module "
386                                                                           "%s to state %s\n",
387                                                                           m->mod_name,
388                                                                           s->lua_name);
389                                                             klua_lock(s->K);
390                                                             luaL_requiref(
391                                                                       s->K->L,
392                                                                       m->mod_name,
393                                                                       m->open,
394                                                                       1);
395                                                             klua_unlock(s->K);
396                                                             m->refcount++;
397                                                             LIST_INSERT_HEAD(
398                                                                 &s->lua_modules, m,
399                                                                 mod_next);
400                                                             return 0;
401                                                   }
402                               }
403                     return ENXIO;
404           case LUALOAD:
405                     load = data;
406                     if (strrchr(load->path, '/') == NULL)
407                               return ENXIO;
408 
409                     LIST_FOREACH(s, &lua_states, lua_next)
410                               if (!strcmp(s->lua_name, load->state)) {
411                                         if (lua_verbose)
412                                                   device_printf(sc->sc_dev,
413                                                       "loading %s into state %s\n",
414                                                       load->path, s->lua_name);
415                                         cred = kauth_cred_get();
416                                         pb = pathbuf_create(load->path);
417                                         if (pb == NULL)
418                                                   return ENOMEM;
419                                         error = vn_open(NULL, pb, NOCHROOT, FREAD, 0,
420                                             &vp, NULL, NULL);
421                                         pathbuf_destroy(pb);
422                                         if (error) {
423                                                   if (lua_verbose)
424                                                             device_printf(sc->sc_dev,
425                                                                 "error vn_open %d\n",
426                                                                 error);
427                                                   return error;
428                                         }
429                                         error = VOP_GETATTR(vp, &va,
430                                             kauth_cred_get());
431                                         if (error) {
432                                                   VOP_UNLOCK(vp);
433                                                   vn_close(vp, FREAD,
434                                                       kauth_cred_get());
435                                                   if (lua_verbose)
436                                                             device_printf(sc->sc_dev,
437                                                                 "erro VOP_GETATTR %d\n",
438                                                                 error);
439                                                   return error;
440                                         }
441                                         if (va.va_type != VREG) {
442                                                   VOP_UNLOCK(vp);
443                                                   vn_close(vp, FREAD,
444                                                       kauth_cred_get());
445                                                   return EINVAL;
446                                         }
447                                         ls.vp = vp;
448                                         ls.off = 0L;
449                                         ls.size = va.va_size;
450                                         VOP_UNLOCK(vp);
451                                         klua_lock(s->K);
452                                         error = lua_load(s->K->L, lua_reader, &ls,
453                                             strrchr(load->path, '/') + 1, "bt");
454                                         vn_close(vp, FREAD, cred);
455                                         switch (error) {
456                                         case 0:   /* no error */
457                                                   break;
458                                         case LUA_ERRSYNTAX:
459                                                   if (lua_verbose)
460                                                             device_printf(sc->sc_dev,
461                                                                 "syntax error\n");
462                                                   klua_unlock(s->K);
463                                                   return EINVAL;
464                                         case LUA_ERRMEM:
465                                                   if (lua_verbose)
466                                                             device_printf(sc->sc_dev,
467                                                                 "memory error\n");
468                                                   klua_unlock(s->K);
469                                                   return ENOMEM;
470                                         default:
471                                                   if (lua_verbose)
472                                                             device_printf(sc->sc_dev,
473                                                                 "load error %d: %s\n",
474                                                                 error,
475                                                                 lua_tostring(s->K->L, -1));
476                                                   klua_unlock(s->K);
477                                                   return EINVAL;
478                                         }
479                                         if (lua_max_instr > 0)
480                                                   lua_sethook(s->K->L, lua_maxcount,
481                                                       LUA_MASKCOUNT, lua_max_instr);
482                                         error = lua_pcall(s->K->L, 0, LUA_MULTRET, 0);
483                                         if (error) {
484                                                   if (lua_verbose) {
485                                                             device_printf(sc->sc_dev,
486                                                                 "execution error: %s\n",
487                                                                 lua_tostring(s->K->L, -1));
488                                                   }
489                                                   klua_unlock(s->K);
490                                                   return EINVAL;
491                                         }
492                                         klua_unlock(s->K);
493                                         return 0;
494                               }
495                     return ENXIO;
496           }
497           return 0;
498 }
499 
500 static int
lua_require(lua_State * L)501 lua_require(lua_State *L)
502 {
503           struct lua_state *s;
504           struct lua_module *m, *md;
505           const char *module;
506           char name[MAXPATHLEN];
507 
508           module = lua_tostring(L, -1);
509           md = NULL;
510           LIST_FOREACH(m, &lua_modules, mod_next)
511                     if (!strcmp(m->mod_name, module)) {
512                               md = m;
513                               break;
514                     }
515 
516           if (md == NULL && lua_autoload_on && strchr(module, '/') == NULL) {
517                     snprintf(name, sizeof name, "lua%s", module);
518                     if (lua_verbose)
519                               device_printf(sc_self, "autoload %s\n", name);
520                     module_autoload(name, MODULE_CLASS_MISC);
521                     LIST_FOREACH(m, &lua_modules, mod_next)
522                               if (!strcmp(m->mod_name, module)) {
523                                         md = m;
524                                         break;
525                               }
526           }
527 
528           if (md != NULL)
529                     LIST_FOREACH(s, &lua_states, lua_next)
530                               if (s->K->L == L) {
531                                         if (lua_verbose)
532                                                   device_printf(sc_self,
533                                                       "require module %s\n",
534                                                       md->mod_name);
535                                         luaL_requiref(L, md->mod_name, md->open, 0);
536 
537                                         LIST_FOREACH(m, &s->lua_modules, mod_next)
538                                                   if (m == md)
539                                                             return 1;
540 
541                                         md->refcount++;
542                                         LIST_INSERT_HEAD(&s->lua_modules, md, mod_next);
543                                         return 1;
544                               }
545 
546           lua_pushstring(L, "module not found");
547           return lua_error(L);
548 }
549 
550 typedef struct {
551           size_t size;
552 } alloc_header_t;
553 
554 static void *
lua_alloc(void * ud,void * ptr,size_t osize,size_t nsize)555 lua_alloc(void *ud, void *ptr, size_t osize, size_t nsize)
556 {
557           void *nptr = NULL;
558 
559           /*
560            * Make sure that buffers allocated by lua_alloc() are aligned to
561            * 8-byte boundaries as done by kmem_alloc(9).
562            */
563           const size_t hdr_size = roundup(sizeof(alloc_header_t), 8);
564           alloc_header_t *hdr = (alloc_header_t *) ((char *) ptr - hdr_size);
565 
566           if (nsize == 0) { /* freeing */
567                     if (ptr != NULL)
568                               kmem_intr_free(hdr, hdr->size);
569           } else if (ptr != NULL && nsize <= hdr->size - hdr_size) /* shrinking */
570                     return ptr; /* don't need to reallocate */
571           else { /* creating or expanding */
572                     km_flag_t sleep = cpu_intr_p() || cpu_softintr_p() ?
573                               KM_NOSLEEP : KM_SLEEP;
574 
575                     size_t alloc_size = nsize + hdr_size;
576                     alloc_header_t *nhdr = kmem_intr_alloc(alloc_size, sleep);
577                     if (nhdr == NULL) /* failed to allocate */
578                               return NULL;
579 
580                     nhdr->size = alloc_size;
581                     nptr = (void *) ((char *) nhdr + hdr_size);
582 
583                     if (ptr != NULL) { /* expanding */
584                               memcpy(nptr, ptr, osize);
585                               kmem_intr_free(hdr, hdr->size);
586                     }
587           }
588           return nptr;
589 }
590 
591 static const char *
lua_reader(lua_State * L,void * data,size_t * size)592 lua_reader(lua_State *L, void *data, size_t *size)
593 {
594           struct lua_loadstate *ls;
595           static char buf[1024];
596           size_t rsiz;
597 
598           ls = data;
599           if (ls->size < sizeof(buf))
600                     rsiz = ls->size;
601           else
602                     rsiz = sizeof(buf);
603           vn_rdwr(UIO_READ, ls->vp, buf, rsiz, ls->off, UIO_SYSSPACE,
604               0, curlwp->l_cred, NULL, curlwp);
605           if (ls->off == 0L && lua_bytecode_on == false && buf[0] == 0x1b) {
606                     *size = 0L;
607                     lua_pushstring(L, "loading of bytecode is not allowed");
608                     lua_error(L);
609                     return NULL;
610           } else {
611                     *size = rsiz;
612                     ls->off += *size;
613                     ls->size -= *size;
614           }
615           return buf;
616 }
617 
618 static void
lua_maxcount(lua_State * L,lua_Debug * d)619 lua_maxcount(lua_State *L, lua_Debug *d)
620 {
621           lua_pushstring(L, "maximum instruction count exceeded");
622           lua_error(L);
623 }
624 
625 int
klua_mod_register(const char * name,lua_CFunction open)626 klua_mod_register(const char *name, lua_CFunction open)
627 {
628           struct lua_module *m;
629 
630           LIST_FOREACH(m, &lua_modules, mod_next)
631                     if (!strcmp(m->mod_name, name))
632                               return EBUSY;
633           m = kmem_zalloc(sizeof(struct lua_module), KM_SLEEP);
634           strlcpy(m->mod_name, name, LUA_MAX_MODNAME);
635           m->open = open;
636           m->refcount = 0;
637           LIST_INSERT_HEAD(&lua_modules, m, mod_next);
638           if (lua_verbose)
639                     device_printf(sc_self, "registered lua module %s\n", name);
640           return 0;
641 }
642 
643 int
klua_mod_unregister(const char * name)644 klua_mod_unregister(const char *name)
645 {
646           struct lua_module *m;
647 
648           LIST_FOREACH(m, &lua_modules, mod_next)
649                     if (!strcmp(m->mod_name, name)) {
650                               if (m->refcount == 0) {
651                                         LIST_REMOVE(m, mod_next);
652                                         kmem_free(m, sizeof(struct lua_module));
653                                         if (lua_verbose)
654                                                   device_printf(sc_self,
655                                                       "unregistered lua module %s\n",
656                                                       name);
657                                         return 0;
658                               } else
659                                         return EBUSY;
660                     }
661           return 0;
662 }
663 
664 klua_State *
klua_newstate(lua_Alloc f,void * ud,const char * name,const char * desc,int ipl)665 klua_newstate(lua_Alloc f, void *ud, const char *name, const char *desc,
666     int ipl)
667 {
668           klua_State *K;
669           struct lua_state *s;
670           struct lua_softc *sc;
671           int error = 0;
672 
673           s = kmem_zalloc(sizeof(struct lua_state), KM_SLEEP);
674           sc = device_private(sc_self);
675           mutex_enter(&sc->sc_state_lock);
676           while (sc->sc_state == true) {
677                     error = cv_wait_sig(&sc->sc_state_cv, &sc->sc_state_lock);
678                     if (error)
679                               break;
680           }
681           if (!error)
682                     sc->sc_state = true;
683           mutex_exit(&sc->sc_state_lock);
684 
685           if (error) {
686                     kmem_free(s, sizeof(struct lua_state));
687                     return NULL;
688           }
689 
690           K = kmem_zalloc(sizeof(klua_State), KM_SLEEP);
691           K->L = lua_newstate(f, ud);
692           K->ks_user = false;
693           if (K->L == NULL) {
694                     kmem_free(K, sizeof(klua_State));
695                     K = NULL;
696                     goto finish;
697           }
698 
699           strlcpy(s->lua_name, name, MAX_LUA_NAME);
700           strlcpy(s->lua_desc, desc, MAX_LUA_DESC);
701           s->K = K;
702 
703           if (lua_require_on || lua_autoload_on) {
704                     lua_pushcfunction(K->L, lua_require);
705                     lua_setglobal(K->L, "require");
706           }
707           LIST_INSERT_HEAD(&lua_states, s, lua_next);
708 
709           mutex_init(&K->ks_lock, MUTEX_DEFAULT, ipl);
710 
711 finish:
712           mutex_enter(&sc->sc_state_lock);
713           sc->sc_state = false;
714           cv_signal(&sc->sc_state_cv);
715           mutex_exit(&sc->sc_state_lock);
716           return K;
717 }
718 
719 inline klua_State *
kluaL_newstate(const char * name,const char * desc,int ipl)720 kluaL_newstate(const char *name, const char *desc, int ipl)
721 {
722           return klua_newstate(lua_alloc, NULL, name, desc, ipl);
723 }
724 
725 void
klua_close(klua_State * K)726 klua_close(klua_State *K)
727 {
728           struct lua_state *s, *ns;
729           struct lua_softc *sc;
730           struct lua_module *m;
731           int error = 0;
732 
733           /* XXX consider registering a handler instead of a fixed name. */
734           lua_getglobal(K->L, "onClose");
735           if (lua_isfunction(K->L, -1))
736                     lua_pcall(K->L, -1, 0, 0);
737 
738           sc = device_private(sc_self);
739           mutex_enter(&sc->sc_state_lock);
740           while (sc->sc_state == true) {
741                     error = cv_wait_sig(&sc->sc_state_cv, &sc->sc_state_lock);
742                     if (error)
743                               break;
744           }
745           if (!error)
746                     sc->sc_state = true;
747           mutex_exit(&sc->sc_state_lock);
748 
749           if (error)
750                     return;             /* Nothing we can do... */
751 
752           LIST_FOREACH_SAFE(s, &lua_states, lua_next, ns)
753                     if (s->K == K) {
754                               LIST_REMOVE(s, lua_next);
755                               LIST_FOREACH(m, &s->lua_modules, mod_next)
756                                         m->refcount--;
757                               kmem_free(s, sizeof(struct lua_state));
758                     }
759 
760           lua_close(K->L);
761           mutex_destroy(&K->ks_lock);
762           kmem_free(K, sizeof(klua_State));
763 
764           mutex_enter(&sc->sc_state_lock);
765           sc->sc_state = false;
766           cv_signal(&sc->sc_state_cv);
767           mutex_exit(&sc->sc_state_lock);
768 }
769 
770 static klua_State *
klua_find(const char * name)771 klua_find(const char *name)
772 {
773           struct lua_state *s;
774           struct lua_softc *sc;
775           klua_State *K;
776           int error = 0;
777 
778           K = NULL;
779           sc = device_private(sc_self);
780           mutex_enter(&sc->sc_state_lock);
781           while (sc->sc_state == true) {
782                     error = cv_wait_sig(&sc->sc_state_cv, &sc->sc_state_lock);
783                     if (error)
784                               break;
785           }
786           if (!error)
787                     sc->sc_state = true;
788           mutex_exit(&sc->sc_state_lock);
789 
790           if (error)
791                     return NULL;
792 
793           LIST_FOREACH(s, &lua_states, lua_next)
794                     if (!strcmp(s->lua_name, name)) {
795                               K = s->K;
796                               break;
797                     }
798 
799           mutex_enter(&sc->sc_state_lock);
800           sc->sc_state = false;
801           cv_signal(&sc->sc_state_cv);
802           mutex_exit(&sc->sc_state_lock);
803           return K;
804 }
805 
806 inline void
klua_lock(klua_State * K)807 klua_lock(klua_State *K)
808 {
809           mutex_enter(&K->ks_lock);
810 }
811 
812 inline void
klua_unlock(klua_State * K)813 klua_unlock(klua_State *K)
814 {
815           mutex_exit(&K->ks_lock);
816 }
817 
818 MODULE(MODULE_CLASS_MISC, lua, NULL);
819 
820 #ifdef _MODULE
821 static const struct cfiattrdata luabus_iattrdata = {
822           "luabus", 0, { { NULL, NULL, 0 },}
823 };
824 
825 static const struct cfiattrdata *const lua_attrs[] = {
826           &luabus_iattrdata, NULL
827 };
828 
829 CFDRIVER_DECL(lua, DV_DULL, lua_attrs);
830 extern struct cfattach lua_ca;
831 static int lualoc[] = {
832           -1,
833           -1,
834           -1
835 };
836 
837 static struct cfdata lua_cfdata[] = {
838           {
839                     .cf_name = "lua",
840                     .cf_atname = "lua",
841                     .cf_unit = 0,
842                     .cf_fstate = FSTATE_STAR,
843                     .cf_loc = lualoc,
844                     .cf_flags = 0,
845                     .cf_pspec = NULL,
846           },
847           { NULL, NULL, 0, FSTATE_NOTFOUND, NULL, 0, NULL }
848 };
849 #endif
850 
851 static int
lua_modcmd(modcmd_t cmd,void * opaque)852 lua_modcmd(modcmd_t cmd, void *opaque)
853 {
854 #ifdef _MODULE
855           devmajor_t cmajor, bmajor;
856           int error = 0;
857 
858           cmajor = bmajor = NODEVMAJOR;
859 #endif
860           switch (cmd) {
861           case MODULE_CMD_INIT:
862 #ifdef _MODULE
863                     error = devsw_attach(lua_cd.cd_name, NULL, &bmajor,
864                         &lua_cdevsw, &cmajor);
865                     if (error) {
866                               aprint_error("%s: unable to register devsw\n",
867                                   lua_cd.cd_name);
868                               return error;
869                     }
870 
871                     error = config_cfdriver_attach(&lua_cd);
872                     if (error) {
873                               devsw_detach(NULL, &lua_cdevsw);
874                               return error;
875                     }
876 
877                     error = config_cfattach_attach(lua_cd.cd_name,
878                         &lua_ca);
879                     if (error) {
880                               config_cfdriver_detach(&lua_cd);
881                               devsw_detach(NULL, &lua_cdevsw);
882                               aprint_error("%s: unable to register cfattach\n",
883                                   lua_cd.cd_name);
884                               return error;
885                     }
886                     error = config_cfdata_attach(lua_cfdata, 1);
887                     if (error) {
888                               config_cfattach_detach(lua_cd.cd_name,
889                                   &lua_ca);
890                               config_cfdriver_detach(&lua_cd);
891                               devsw_detach(NULL, &lua_cdevsw);
892                               aprint_error("%s: unable to register cfdata\n",
893                                   lua_cd.cd_name);
894                               return error;
895                     }
896                     config_attach_pseudo(lua_cfdata);
897 #endif
898                     return 0;
899           case MODULE_CMD_FINI:
900 #ifdef _MODULE
901                     error = config_cfdata_detach(lua_cfdata);
902                     if (error)
903                               return error;
904 
905                     config_cfattach_detach(lua_cd.cd_name, &lua_ca);
906                     config_cfdriver_detach(&lua_cd);
907                     devsw_detach(NULL, &lua_cdevsw);
908 #endif
909                     return 0;
910           case MODULE_CMD_AUTOUNLOAD:
911                     /* no auto-unload */
912                     return EBUSY;
913           default:
914                     return ENOTTY;
915           }
916 }
917