source: bootcd/isolinux/syslinux-6.03/com32/lua/src/syslinux.c @ e16e8f2

Last change on this file since e16e8f2 was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 12.1 KB
Line 
1/* ----------------------------------------------------------------------- *
2 *
3 *   Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
4 *
5 *   Permission is hereby granted, free of charge, to any person
6 *   obtaining a copy of this software and associated documentation
7 *   files (the "Software"), to deal in the Software without
8 *   restriction, including without limitation the rights to use,
9 *   copy, modify, merge, publish, distribute, sublicense, and/or
10 *   sell copies of the Software, and to permit persons to whom
11 *   the Software is furnished to do so, subject to the following
12 *   conditions:
13 *
14 *   The above copyright notice and this permission notice shall
15 *   be included in all copies or substantial portions of the Software.
16 *
17 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 *   OTHER DEALINGS IN THE SOFTWARE.
25 *
26 * ----------------------------------------------------------------------- */
27
28#include <getkey.h>
29#include <stdlib.h>
30#include <string.h>
31#include <unistd.h>
32#include <syslinux/boot.h>
33
34#define lnetlib_c               /* Define the library */
35
36#include "lua.h"
37#include "lauxlib.h"
38#include "lualib.h"
39#include "syslinux/boot.h"
40#include "syslinux/loadfile.h"
41#include "syslinux/linux.h"
42#include "syslinux/config.h"
43#include "syslinux/reboot.h"
44
45int __parse_argv(char ***argv, const char *str);
46
47#define SYSLINUX_FILE "syslinux_file"
48
49typedef struct syslinux_file {
50    char *data;
51    char *name;
52    size_t size;
53} syslinux_file;
54
55/*
56 * Most code taken from:
57 *      com32/modules/linux.c
58 */
59
60/* Find the last instance of a particular command line argument
61   (which should include the final =; do not use for boolean arguments) */
62static char *find_argument(char **argv, const char *argument)
63{
64    int la = strlen(argument);
65    char **arg;
66    char *ptr = NULL;
67
68    for (arg = argv; *arg; arg++) {
69        if (!memcmp(*arg, argument, la))
70            ptr = *arg + la;
71    }
72
73    return ptr;
74}
75
76/* Get a value with a potential suffix (k/m/g/t/p/e) */
77static unsigned long long suffix_number(const char *str)
78{
79    char *ep;
80    unsigned long long v;
81    int shift;
82
83    v = strtoull(str, &ep, 0);
84    switch (*ep | 0x20) {
85    case 'k':
86        shift = 10;
87        break;
88    case 'm':
89        shift = 20;
90        break;
91    case 'g':
92        shift = 30;
93        break;
94    case 't':
95        shift = 40;
96        break;
97    case 'p':
98        shift = 50;
99        break;
100    case 'e':
101        shift = 60;
102        break;
103    default:
104        shift = 0;
105        break;
106    }
107    v <<= shift;
108
109    return v;
110}
111
112/* Truncate to 32 bits, with saturate */
113static inline uint32_t saturate32(unsigned long long v)
114{
115    return (v > 0xffffffff) ? 0xffffffff : (uint32_t) v;
116}
117
118/* Stitch together the command line from a set of argv's */
119static char *make_cmdline(char **argv)
120{
121    char **arg;
122    size_t bytes;
123    char *cmdline, *p;
124
125    bytes = 1;                  /* Just in case we have a zero-entry cmdline */
126    for (arg = argv; *arg; arg++) {
127        bytes += strlen(*arg) + 1;
128    }
129
130    p = cmdline = malloc(bytes);
131    if (!cmdline)
132        return NULL;
133
134    for (arg = argv; *arg; arg++) {
135        int len = strlen(*arg);
136        memcpy(p, *arg, len);
137        p[len] = ' ';
138        p += len + 1;
139    }
140
141    if (p > cmdline)
142        p--;                    /* Remove the last space */
143    *p = '\0';
144
145    return cmdline;
146}
147
148static int sl_run_command(lua_State * L)
149{
150    const char *cmd = luaL_checkstring(L, 1);   /* Reads the string parameter */
151    syslinux_run_command(cmd);
152    return 0;
153}
154
155/* do default boot */
156static int sl_run_default(lua_State * L)
157{
158    /* Preventing GCC to complain against unused L */
159    L=L;
160    syslinux_run_default();
161    return 0;
162}
163
164/* do local boot */
165static int sl_local_boot(lua_State * L)
166{
167    uint16_t flags = luaL_checkint(L, 1);
168    syslinux_local_boot(flags);
169    return 0;
170}
171
172static int sl_final_cleanup(lua_State * L)
173{
174    uint16_t flags = luaL_checkint(L, 1);
175    syslinux_local_boot(flags);
176    return 0;
177}
178
179/* boot linux kernel and initrd */
180static int sl_boot_linux(lua_State * L)
181{
182    const char *kernel = luaL_checkstring(L, 1);
183    const char *cmdline = luaL_optstring(L, 2, "");
184    char *initrd;
185    void *kernel_data, *file_data;
186    size_t kernel_len, file_len;
187    struct initramfs *initramfs;
188    char *newcmdline;
189    uint32_t mem_limit = luaL_optint(L, 3, 0);
190    uint16_t video_mode = luaL_optint(L, 4, 0);
191    int ret;
192    char **argv, **argp, *arg, *p;
193
194    (void)mem_limit;
195    (void)video_mode;
196
197    ret = __parse_argv(&argv, cmdline);
198
199    newcmdline = malloc(strlen(kernel) + 12);
200    if (!newcmdline)
201        printf("Mem alloc failed: cmdline\n");
202
203    strcpy(newcmdline, "BOOT_IMAGE=");
204    strcpy(newcmdline + strlen(newcmdline), kernel);
205    argv[0] = newcmdline;
206    argp = argv;
207
208    /* DEBUG
209       for (i=0; i<ret; i++)
210       printf("%d: %s\n", i, argv[i]);
211     */
212
213    newcmdline = make_cmdline(argp);
214    if (!newcmdline)
215        printf("Creating command line failed!\n");
216
217    /* DEBUG
218       printf("Command line: %s\n", newcmdline);
219       msleep(1000);
220     */
221
222    printf("Loading kernel %s...\n", kernel);
223    if (loadfile(kernel, &kernel_data, &kernel_len))
224        printf("failed!\n");
225    else
226        printf("ok\n");
227
228    initramfs = initramfs_init();
229    if (!initramfs)
230        printf("Initializing initrd failed!\n");
231
232    if ((arg = find_argument(argp, "initrd="))) {
233        do {
234            p = strchr(arg, ',');
235            if (p)
236                *p = '\0';
237
238            initrd = arg;
239            printf("Loading initrd %s... ", initrd);
240            if (initramfs_load_archive(initramfs, initrd)) {
241                printf("failed!\n");
242            }
243            printf("ok\n");
244
245            if (p)
246                *p++ = ',';
247        } while ((arg = p));
248    }
249
250    ret = syslinux_boot_linux(kernel_data, kernel_len, initramfs, NULL, newcmdline);
251
252    printf("syslinux_boot_linux returned %d\n", ret);
253
254    return 0;
255}
256
257/* sleep for sec seconds */
258static int sl_sleep(lua_State * L)
259{
260    unsigned int sec = luaL_checkint(L, 1);
261    sleep(sec);
262    return 0;
263}
264
265/* sleep for msec milliseconds */
266static int sl_msleep(lua_State * L)
267{
268    unsigned int msec = luaL_checkint(L, 1);
269    msleep(msec);
270    return 0;
271}
272
273static int sl_run_kernel_image(lua_State * L)
274{
275    const char *filename = luaL_checkstring(L, 1);
276    const char *cmdline = luaL_checkstring(L, 2);
277    uint32_t ipappend_flags = luaL_checkint(L, 3);
278    uint32_t type = luaL_checkint(L, 4);
279
280    syslinux_run_kernel_image(filename, cmdline, ipappend_flags, type);
281    return 0;
282}
283
284static int sl_loadfile(lua_State * L)
285{
286    const char *filename = luaL_checkstring(L, 1);
287    syslinux_file *file;
288
289    void *file_data;
290    size_t file_len;
291
292    if (loadfile(filename, &file_data, &file_len)) {
293        lua_pushstring(L, "Could not load file");
294        lua_error(L);
295    }
296
297    file = malloc(sizeof(syslinux_file));
298    strlcpy(file->name,filename,sizeof(syslinux_file));
299    file->size = file_len;
300    file->data = file_data;
301
302    lua_pushlightuserdata(L, file);
303    luaL_getmetatable(L, SYSLINUX_FILE);
304    lua_setmetatable(L, -2);
305
306    return 1;
307}
308
309static int sl_filesize(lua_State * L)
310{
311    const syslinux_file *file = luaL_checkudata(L, 1, SYSLINUX_FILE);
312
313    lua_pushinteger(L, file->size);
314
315    return 1;
316}
317
318static int sl_filename(lua_State * L)
319{
320    const syslinux_file *file = luaL_checkudata(L, 1, SYSLINUX_FILE);
321
322    lua_pushstring(L, file->name);
323
324    return 1;
325}
326
327static int sl_initramfs_init(lua_State * L)
328{
329    struct initramfs *initramfs;
330
331    initramfs = initramfs_init();
332    if (!initramfs)
333        printf("Initializing initrd failed!\n");
334
335    lua_pushlightuserdata(L, initramfs);
336    luaL_getmetatable(L, SYSLINUX_FILE);
337    lua_setmetatable(L, -2);
338
339    return 1;
340}
341
342static int sl_initramfs_load_archive(lua_State * L)
343{
344    struct initramfs *initramfs = luaL_checkudata(L, 1, SYSLINUX_FILE);
345    const char *filename = luaL_checkstring(L, 2);
346
347    if (initramfs_load_archive(initramfs, filename)) {
348        printf("failed!\n");
349    }
350
351    return 0;
352}
353
354static int sl_initramfs_add_file(lua_State * L)
355{
356    struct initramfs *initramfs = luaL_checkudata(L, 1, SYSLINUX_FILE);
357    const char *filename = luaL_checkstring(L, 2);
358    void *file_data = NULL;
359    size_t file_len = 0;
360
361    return initramfs_add_file(initramfs, file_data, file_len, file_len,
362                              filename, 0, 0755);
363}
364
365static int sl_boot_it(lua_State * L)
366{
367    const syslinux_file *kernel = luaL_checkudata(L, 1, SYSLINUX_FILE);
368    struct initramfs *initramfs = luaL_checkudata(L, 2, SYSLINUX_FILE);
369    const char *cmdline = luaL_optstring(L, 3, "");
370    uint32_t mem_limit = luaL_optint(L, 4, 0);
371    uint16_t video_mode = luaL_optint(L, 5, 0);
372    /* Preventing gcc to complain about unused variables */
373    (void)video_mode;
374    (void)mem_limit;
375
376    return syslinux_boot_linux(kernel->data, kernel->size,
377                               initramfs, NULL, (char *)cmdline);
378}
379
380static int sl_config_file(lua_State * L)
381{
382    const char *config_file = syslinux_config_file();
383    lua_pushstring(L, config_file);
384    return 1;
385}
386
387static int sl_reboot(lua_State * L)
388{
389    int warm_boot = luaL_optint(L, 1, 0);
390    /* explicitly convert it to 1 or 0 */
391    warm_boot = warm_boot? 1 : 0;
392    syslinux_reboot(warm_boot);
393    return 0;
394}
395
396static int sl_ipappend_strs(lua_State * L)
397{
398    int i;
399    const struct syslinux_ipappend_strings *ip_strs = syslinux_ipappend_strings();
400    lua_newtable(L);
401    for (i = 0; i < ip_strs->count; i++) {
402        lua_pushinteger(L, i + 1);
403        lua_pushstring(L, ip_strs->ptr[i]);
404        lua_settable(L,-3);
405    }
406    return 1;
407}
408
409static int sl_derivative(lua_State * L)
410{
411    const struct syslinux_version *sv;
412
413    sv = syslinux_version();
414
415    switch (sv->filesystem) {
416    case SYSLINUX_FS_SYSLINUX:
417        lua_pushstring(L, "SYSLINUX");
418        break;
419    case SYSLINUX_FS_PXELINUX:
420        lua_pushstring(L, "PXELINUX");
421        break;
422    case SYSLINUX_FS_ISOLINUX:
423        lua_pushstring(L, "ISOLINUX");
424        break;
425    case SYSLINUX_FS_UNKNOWN:
426    default:
427        lua_pushstring(L, "Unknown Syslinux derivative");
428        break;
429    }
430
431    return 1;
432}
433
434static int sl_version(lua_State * L)
435{
436    const struct syslinux_version *sv;
437
438    sv = syslinux_version();
439    lua_pushstring(L, sv->version_string);
440
441    return 1;
442}
443
444static int sl_get_key (lua_State * L)
445{
446    int timeout = luaL_checkint (L, 1);
447    lua_pushinteger (L, get_key (stdin, timeout));
448    return 1;
449}
450
451static int sl_KEY_CTRL (lua_State * L)
452{
453    lua_pushinteger (L, KEY_CTRL (luaL_checkint (L, 1)));
454    return 1;
455}
456
457static const luaL_Reg syslinuxlib[] = {
458    {"run_command", sl_run_command},
459    {"run_default", sl_run_default},
460    {"local_boot", sl_local_boot},
461    {"final_cleanup", sl_final_cleanup},
462    {"boot_linux", sl_boot_linux},
463    {"run_kernel_image", sl_run_kernel_image},
464    {"sleep", sl_sleep},
465    {"msleep", sl_msleep},
466    {"loadfile", sl_loadfile},
467    {"filesize", sl_filesize},
468    {"filename", sl_filename},
469    {"initramfs_init", sl_initramfs_init},
470    {"initramfs_load_archive", sl_initramfs_load_archive},
471    {"initramfs_add_file", sl_initramfs_add_file},
472    {"boot_it", sl_boot_it},
473    {"config_file", sl_config_file},
474    {"ipappend_strs", sl_ipappend_strs},
475    {"reboot", sl_reboot},
476    {"derivative", sl_derivative},
477    {"version", sl_version},
478    {"get_key", sl_get_key},
479    {"KEY_CTRL", sl_KEY_CTRL},
480    {NULL, NULL}
481};
482
483/* This defines a function that opens up your library. */
484
485LUALIB_API int luaopen_syslinux(lua_State * L)
486{
487
488    luaL_newmetatable(L, SYSLINUX_FILE);
489
490    luaL_newlib(L, syslinuxlib);
491
492    lua_newtable (L);
493#define export_key(x) lua_pushinteger (L, KEY_##x); lua_setfield (L, -2, #x);
494    export_key (NONE);
495    export_key (BACKSPACE);
496    export_key (TAB);
497    export_key (ENTER);
498    export_key (ESC);
499    export_key (DEL);
500    export_key (F1);
501    export_key (F2);
502    export_key (F3);
503    export_key (F4);
504    export_key (F5);
505    export_key (F6);
506    export_key (F7);
507    export_key (F8);
508    export_key (F9);
509    export_key (F10);
510    export_key (F11);
511    export_key (F12);
512    export_key (UP);
513    export_key (DOWN);
514    export_key (LEFT);
515    export_key (RIGHT);
516    export_key (PGUP);
517    export_key (PGDN);
518    export_key (HOME);
519    export_key (END);
520    export_key (INSERT);
521    export_key (DELETE);
522    lua_setfield (L, -2, "KEY");
523
524    return 1;
525}
Note: See TracBrowser for help on using the repository browser.