ldlinux: Fix return pointer to local data
[syslinux.git] / com32 / lua / src / syslinux.c
blob9a2998b95706af85e4eff42459957ee4c493475b
1 /* ----------------------------------------------------------------------- *
3 * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
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:
14 * The above copyright notice and this permission notice shall
15 * be included in all copies or substantial portions of the Software.
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.
26 * ----------------------------------------------------------------------- */
28 #include <getkey.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <syslinux/boot.h>
34 #define lnetlib_c /* Define the library */
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"
45 int __parse_argv(char ***argv, const char *str);
47 static const char SYSLINUX_FILE[] = "syslinux_file";
48 static const char SYSLINUX_INITRAMFS[] = "syslinux_initramfs";
50 typedef struct syslinux_file {
51 void *data;
52 char *name;
53 size_t size;
54 } syslinux_file;
57 * Most code taken from:
58 * com32/modules/linux.c
61 /* Find the last instance of a particular command line argument
62 (which should include the final =; do not use for boolean arguments) */
63 static char *find_argument(char **argv, const char *argument)
65 int la = strlen(argument);
66 char **arg;
67 char *ptr = NULL;
69 for (arg = argv; *arg; arg++) {
70 if (!memcmp(*arg, argument, la))
71 ptr = *arg + la;
74 return ptr;
77 /* Stitch together the command line from a set of argv's */
78 static char *make_cmdline(char **argv)
80 char **arg;
81 size_t bytes;
82 char *cmdline, *p;
84 bytes = 1; /* Just in case we have a zero-entry cmdline */
85 for (arg = argv; *arg; arg++) {
86 bytes += strlen(*arg) + 1;
89 p = cmdline = malloc(bytes);
90 if (!cmdline)
91 return NULL;
93 for (arg = argv; *arg; arg++) {
94 int len = strlen(*arg);
95 memcpy(p, *arg, len);
96 p[len] = ' ';
97 p += len + 1;
100 if (p > cmdline)
101 p--; /* Remove the last space */
102 *p = '\0';
104 return cmdline;
107 static int sl_run_command(lua_State * L)
109 const char *cmd = luaL_checkstring(L, 1); /* Reads the string parameter */
110 syslinux_run_command(cmd);
111 return 0;
114 /* do default boot */
115 static int sl_run_default(lua_State * L)
117 /* Preventing GCC to complain against unused L */
118 L=L;
119 syslinux_run_default();
120 return 0;
123 /* do local boot */
124 static int sl_local_boot(lua_State * L)
126 uint16_t flags = luaL_checkint(L, 1);
127 syslinux_local_boot(flags);
128 return 0;
131 static int sl_final_cleanup(lua_State * L)
133 syslinux_final_cleanup (luaL_checkint (L, 1));
134 return 0;
137 /* boot linux kernel and initrd */
138 static int sl_boot_linux(lua_State * L)
140 const char *kernel = luaL_checkstring(L, 1);
141 const char *cmdline = luaL_optstring(L, 2, "");
142 char *initrd;
143 void *kernel_data;
144 size_t kernel_len;
145 struct initramfs *initramfs;
146 char *newcmdline;
147 int ret;
148 char **argv, **argp, *arg, *p;
150 ret = __parse_argv(&argv, cmdline);
152 newcmdline = malloc(strlen(kernel) + 12);
153 if (!newcmdline)
154 printf("Mem alloc failed: cmdline\n");
156 strcpy(newcmdline, "BOOT_IMAGE=");
157 strcpy(newcmdline + strlen(newcmdline), kernel);
158 argv[0] = newcmdline;
159 argp = argv;
161 /* DEBUG
162 for (i=0; i<ret; i++)
163 printf("%d: %s\n", i, argv[i]);
166 newcmdline = make_cmdline(argp);
167 if (!newcmdline)
168 printf("Creating command line failed!\n");
170 /* DEBUG
171 printf("Command line: %s\n", newcmdline);
172 msleep(1000);
175 printf("Loading kernel %s... ", kernel);
176 if (loadfile(kernel, &kernel_data, &kernel_len))
177 printf("failed!\n");
178 else
179 printf("ok\n");
181 initramfs = initramfs_init();
182 if (!initramfs)
183 printf("Initializing initrd failed!\n");
185 if ((arg = find_argument(argp, "initrd="))) {
186 do {
187 p = strchr(arg, ',');
188 if (p)
189 *p = '\0';
191 initrd = arg;
192 printf("Loading initrd %s... ", initrd);
193 if (initramfs_load_archive(initramfs, initrd))
194 printf("failed!\n");
195 else
196 printf("ok\n");
198 if (p)
199 *p++ = ',';
200 } while ((arg = p));
203 ret = syslinux_boot_linux(kernel_data, kernel_len, initramfs, NULL, newcmdline);
205 printf("syslinux_boot_linux returned %d\n", ret);
207 return 0;
210 /* sleep for sec seconds */
211 static int sl_sleep(lua_State * L)
213 unsigned int sec = luaL_checkint(L, 1);
214 sleep(sec);
215 return 0;
218 /* sleep for msec milliseconds */
219 static int sl_msleep(lua_State * L)
221 unsigned int msec = luaL_checkint(L, 1);
222 msleep(msec);
223 return 0;
226 static int sl_run_kernel_image(lua_State * L)
228 const char *filename = luaL_checkstring(L, 1);
229 const char *cmdline = luaL_checkstring(L, 2);
230 uint32_t ipappend_flags = luaL_checkint(L, 3);
231 uint32_t type = luaL_checkint(L, 4);
233 syslinux_run_kernel_image(filename, cmdline, ipappend_flags, type);
234 return 0;
237 static int sl_loadfile(lua_State * L)
239 size_t name_len;
240 const char *filename = luaL_checklstring (L, 1, &name_len);
241 syslinux_file *file = lua_newuserdata (L, sizeof (syslinux_file));
243 file->name = malloc (name_len+1);
244 if (!file->name) return luaL_error (L, "Out of memory");
245 memcpy (file->name, filename, name_len+1);
246 if (loadfile (file->name, &file->data, &file->size)) {
247 free (file->name);
248 return luaL_error (L, "Could not load file");
250 luaL_setmetatable (L, SYSLINUX_FILE);
251 return 1;
254 static int sl_unloadfile (lua_State *L)
256 syslinux_file *file = luaL_checkudata (L, 1, SYSLINUX_FILE);
258 free (file->name);
259 free (file->data);
260 /* the __gc method may also be (repeatedly) called before garbage collection, so: */
261 file->name = file->data = NULL;
262 return 0;
265 static int sl_filesize(lua_State * L)
267 const syslinux_file *file = luaL_checkudata(L, 1, SYSLINUX_FILE);
269 lua_pushinteger(L, file->size);
271 return 1;
274 static int sl_filename(lua_State * L)
276 const syslinux_file *file = luaL_checkudata(L, 1, SYSLINUX_FILE);
278 lua_pushstring(L, file->name);
280 return 1;
283 static int sl_initramfs_init(lua_State * L)
285 struct initramfs *ir = lua_newuserdata (L, sizeof (*ir));
287 memset (ir, 0, sizeof (*ir)); /* adapted from initramfs_init() */
288 ir->prev = ir->next = ir;
289 luaL_setmetatable (L, SYSLINUX_INITRAMFS);
290 return 1;
293 static int sl_initramfs_load_archive(lua_State * L)
295 const char *filename = luaL_checkstring(L, 2);
297 if (initramfs_load_archive (luaL_checkudata(L, 1, SYSLINUX_INITRAMFS), filename))
298 return luaL_error (L, "Loading initramfs %s failed", filename);
299 lua_settop (L, 1);
300 return 1;
303 static int sl_initramfs_add_file(lua_State * L)
305 const char *filename = luaL_checkstring(L, 2);
306 size_t file_len;
307 const char *file_data = luaL_optlstring (L, 3, NULL, &file_len);
308 void *data = NULL;
310 if (file_len) {
311 data = malloc (file_len);
312 if (!data) return luaL_error (L, "Out of memory");
313 memcpy (data, file_data, file_len);
315 if (initramfs_add_file(luaL_checkudata(L, 1, SYSLINUX_INITRAMFS),
316 data, file_len, file_len, filename,
317 luaL_optint (L, 4, 0), luaL_optint (L, 5, 0755)))
318 return luaL_error (L, "Adding file %s to initramfs failed", filename);
319 lua_settop (L, 1);
320 return 1;
323 static int sl_initramfs_size (lua_State *L)
325 lua_pushinteger (L, initramfs_size (luaL_checkudata(L, 1, SYSLINUX_INITRAMFS)));
326 return 1;
329 static int sl_initramfs_purge (lua_State *L)
331 struct initramfs *ir = luaL_checkudata(L, 1, SYSLINUX_INITRAMFS);
333 ir = ir->next;
334 while (ir->len) {
335 free ((void *)ir->data);
336 ir = ir->next;
337 free (ir->prev);
339 /* the __gc method may also be (repeatedly) called before garbage collection, so: */
340 ir->next = ir->prev = ir;
341 return 0;
344 static int sl_boot_it(lua_State * L)
346 const syslinux_file *kernel = luaL_checkudata(L, 1, SYSLINUX_FILE);
347 struct initramfs *ir = luaL_testudata(L, 2, SYSLINUX_INITRAMFS);
348 size_t len;
349 const char *cmdline_param = luaL_optlstring(L, 3, "", &len);
350 char *cmdline = malloc (len+1); /* syslinux_boot_linux needs non-const cmdline */
351 int err;
353 if (!cmdline) return luaL_error (L, "Out of memory");
354 memcpy (cmdline, cmdline_param, len+1);
355 err = syslinux_boot_linux (kernel->data, kernel->size, ir, NULL, cmdline);
356 free (cmdline);
357 if (err) return luaL_error (L, "Booting failed");
358 return 0; /* unexpected */
361 static int sl_config_file(lua_State * L)
363 const char *config_file = syslinux_config_file();
364 lua_pushstring(L, config_file);
365 return 1;
368 static int sl_reboot(lua_State * L)
370 int warm_boot = luaL_optint(L, 1, 0);
371 /* explicitly convert it to 1 or 0 */
372 warm_boot = warm_boot? 1 : 0;
373 syslinux_reboot(warm_boot);
374 return 0;
377 static int sl_ipappend_strs(lua_State * L)
379 int i;
380 const struct syslinux_ipappend_strings *ip_strs = syslinux_ipappend_strings();
381 lua_newtable(L);
382 for (i = 0; i < ip_strs->count; i++) {
383 lua_pushinteger(L, i + 1);
384 lua_pushstring(L, ip_strs->ptr[i]);
385 lua_settable(L,-3);
387 return 1;
390 static int sl_derivative(lua_State * L)
392 const struct syslinux_version *sv;
394 sv = syslinux_version();
396 switch (sv->filesystem) {
397 case SYSLINUX_FS_SYSLINUX:
398 lua_pushstring(L, "SYSLINUX");
399 break;
400 case SYSLINUX_FS_PXELINUX:
401 lua_pushstring(L, "PXELINUX");
402 break;
403 case SYSLINUX_FS_ISOLINUX:
404 lua_pushstring(L, "ISOLINUX");
405 break;
406 case SYSLINUX_FS_UNKNOWN:
407 default:
408 lua_pushstring(L, "Unknown Syslinux derivative");
409 break;
412 return 1;
415 static int sl_version(lua_State * L)
417 const struct syslinux_version *sv;
419 sv = syslinux_version();
420 lua_pushstring(L, sv->version_string);
422 return 1;
425 static int sl_get_key (lua_State * L)
427 int timeout = luaL_checkint (L, 1);
428 lua_pushinteger (L, get_key (stdin, timeout));
429 return 1;
432 static int sl_KEY_CTRL (lua_State * L)
434 lua_pushinteger (L, KEY_CTRL (luaL_checkint (L, 1)));
435 return 1;
438 static const luaL_Reg syslinuxlib[] = {
439 {"run_command", sl_run_command},
440 {"run_default", sl_run_default},
441 {"local_boot", sl_local_boot},
442 {"final_cleanup", sl_final_cleanup},
443 {"boot_linux", sl_boot_linux},
444 {"run_kernel_image", sl_run_kernel_image},
445 {"sleep", sl_sleep},
446 {"msleep", sl_msleep},
447 {"loadfile", sl_loadfile},
448 {"initramfs", sl_initramfs_init},
449 {"boot_it", sl_boot_it},
450 {"config_file", sl_config_file},
451 {"ipappend_strs", sl_ipappend_strs},
452 {"reboot", sl_reboot},
453 {"derivative", sl_derivative},
454 {"version", sl_version},
455 {"get_key", sl_get_key},
456 {"KEY_CTRL", sl_KEY_CTRL},
457 {NULL, NULL}
460 static const luaL_Reg file_methods[] = {
461 {"__gc", sl_unloadfile},
462 {"name", sl_filename},
463 {"size", sl_filesize},
464 {NULL, NULL}
467 static const luaL_Reg initramfs_methods[] = {
468 {"__gc", sl_initramfs_purge},
469 {"load", sl_initramfs_load_archive},
470 {"add_file", sl_initramfs_add_file},
471 {"size", sl_initramfs_size},
472 {NULL, NULL}
475 /* This defines a function that opens up your library. */
477 LUALIB_API int luaopen_syslinux(lua_State * L)
480 luaL_newmetatable(L, SYSLINUX_FILE);
481 lua_pushstring (L, "__index");
482 lua_pushvalue (L, -2);
483 lua_settable (L, -3);
484 luaL_setfuncs (L, file_methods, 0);
486 luaL_newmetatable (L, SYSLINUX_INITRAMFS);
487 lua_pushstring (L, "__index");
488 lua_pushvalue (L, -2);
489 lua_settable (L, -3);
490 luaL_setfuncs (L, initramfs_methods, 0);
492 luaL_newlib(L, syslinuxlib);
494 #define export(c,x) lua_pushinteger (L,c##_##x); lua_setfield (L, -2, #x);
496 lua_newtable (L);
497 export (KEY, NONE);
498 export (KEY, BACKSPACE);
499 export (KEY, TAB);
500 export (KEY, ENTER);
501 export (KEY, ESC);
502 export (KEY, DEL);
503 export (KEY, F1);
504 export (KEY, F2);
505 export (KEY, F3);
506 export (KEY, F4);
507 export (KEY, F5);
508 export (KEY, F6);
509 export (KEY, F7);
510 export (KEY, F8);
511 export (KEY, F9);
512 export (KEY, F10);
513 export (KEY, F11);
514 export (KEY, F12);
515 export (KEY, UP);
516 export (KEY, DOWN);
517 export (KEY, LEFT);
518 export (KEY, RIGHT);
519 export (KEY, PGUP);
520 export (KEY, PGDN);
521 export (KEY, HOME);
522 export (KEY, END);
523 export (KEY, INSERT);
524 export (KEY, DELETE);
525 lua_setfield (L, -2, "KEY");
527 lua_newtable (L);
528 export (IMAGE_TYPE, KERNEL);
529 export (IMAGE_TYPE, LINUX);
530 export (IMAGE_TYPE, BOOT);
531 export (IMAGE_TYPE, BSS);
532 export (IMAGE_TYPE, PXE);
533 export (IMAGE_TYPE, FDIMAGE);
534 export (IMAGE_TYPE, COM32);
535 export (IMAGE_TYPE, CONFIG);
536 export (IMAGE_TYPE, LOCALBOOT);
537 lua_setfield (L, -2, "IMAGE_TYPE");
539 return 1;