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
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 * ----------------------------------------------------------------------- */
32 #include <syslinux/boot.h>
34 #define lnetlib_c /* Define the library */
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
{
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
);
69 for (arg
= argv
; *arg
; arg
++) {
70 if (!memcmp(*arg
, argument
, la
))
77 /* Stitch together the command line from a set of argv's */
78 static char *make_cmdline(char **argv
)
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
);
93 for (arg
= argv
; *arg
; arg
++) {
94 int len
= strlen(*arg
);
101 p
--; /* Remove the last space */
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
);
114 /* do default boot */
115 static int sl_run_default(lua_State
* L
)
117 /* Preventing GCC to complain against unused L */
119 syslinux_run_default();
124 static int sl_local_boot(lua_State
* L
)
126 uint16_t flags
= luaL_checkint(L
, 1);
127 syslinux_local_boot(flags
);
131 static int sl_final_cleanup(lua_State
* L
)
133 syslinux_final_cleanup (luaL_checkint (L
, 1));
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, "");
145 struct initramfs
*initramfs
;
148 char **argv
, **argp
, *arg
, *p
;
150 ret
= __parse_argv(&argv
, cmdline
);
152 newcmdline
= malloc(strlen(kernel
) + 12);
154 printf("Mem alloc failed: cmdline\n");
156 strcpy(newcmdline
, "BOOT_IMAGE=");
157 strcpy(newcmdline
+ strlen(newcmdline
), kernel
);
158 argv
[0] = newcmdline
;
162 for (i=0; i<ret; i++)
163 printf("%d: %s\n", i, argv[i]);
166 newcmdline
= make_cmdline(argp
);
168 printf("Creating command line failed!\n");
171 printf("Command line: %s\n", newcmdline);
175 printf("Loading kernel %s... ", kernel
);
176 if (loadfile(kernel
, &kernel_data
, &kernel_len
))
181 initramfs
= initramfs_init();
183 printf("Initializing initrd failed!\n");
185 if ((arg
= find_argument(argp
, "initrd="))) {
187 p
= strchr(arg
, ',');
192 printf("Loading initrd %s... ", initrd
);
193 if (initramfs_load_archive(initramfs
, initrd
))
203 ret
= syslinux_boot_linux(kernel_data
, kernel_len
, initramfs
, NULL
, newcmdline
);
205 printf("syslinux_boot_linux returned %d\n", ret
);
210 /* sleep for sec seconds */
211 static int sl_sleep(lua_State
* L
)
213 unsigned int sec
= luaL_checkint(L
, 1);
218 /* sleep for msec milliseconds */
219 static int sl_msleep(lua_State
* L
)
221 unsigned int msec
= luaL_checkint(L
, 1);
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
);
237 static int sl_loadfile(lua_State
* L
)
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
)) {
248 return luaL_error (L
, "Could not load file");
250 luaL_setmetatable (L
, SYSLINUX_FILE
);
254 static int sl_unloadfile (lua_State
*L
)
256 syslinux_file
*file
= luaL_checkudata (L
, 1, SYSLINUX_FILE
);
260 /* the __gc method may also be (repeatedly) called before garbage collection, so: */
261 file
->name
= file
->data
= NULL
;
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
);
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
);
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
);
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
);
303 static int sl_initramfs_add_file(lua_State
* L
)
305 const char *filename
= luaL_checkstring(L
, 2);
307 const char *file_data
= luaL_optlstring (L
, 3, NULL
, &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
);
323 static int sl_initramfs_size (lua_State
*L
)
325 lua_pushinteger (L
, initramfs_size (luaL_checkudata(L
, 1, SYSLINUX_INITRAMFS
)));
329 static int sl_initramfs_purge (lua_State
*L
)
331 struct initramfs
*ir
= luaL_checkudata(L
, 1, SYSLINUX_INITRAMFS
);
335 free ((void *)ir
->data
);
339 /* the __gc method may also be (repeatedly) called before garbage collection, so: */
340 ir
->next
= ir
->prev
= ir
;
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
);
349 const char *cmdline_param
= luaL_optlstring(L
, 3, "", &len
);
350 char *cmdline
= malloc (len
+1); /* syslinux_boot_linux needs non-const cmdline */
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
);
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
);
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
);
377 static int sl_ipappend_strs(lua_State
* L
)
380 const struct syslinux_ipappend_strings
*ip_strs
= syslinux_ipappend_strings();
382 for (i
= 0; i
< ip_strs
->count
; i
++) {
383 lua_pushinteger(L
, i
+ 1);
384 lua_pushstring(L
, ip_strs
->ptr
[i
]);
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");
400 case SYSLINUX_FS_PXELINUX
:
401 lua_pushstring(L
, "PXELINUX");
403 case SYSLINUX_FS_ISOLINUX
:
404 lua_pushstring(L
, "ISOLINUX");
406 case SYSLINUX_FS_UNKNOWN
:
408 lua_pushstring(L
, "Unknown Syslinux derivative");
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
);
425 static int sl_get_key (lua_State
* L
)
427 int timeout
= luaL_checkint (L
, 1);
428 lua_pushinteger (L
, get_key (stdin
, timeout
));
432 static int sl_KEY_CTRL (lua_State
* L
)
434 lua_pushinteger (L
, KEY_CTRL (luaL_checkint (L
, 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
},
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
},
460 static const luaL_Reg file_methods
[] = {
461 {"__gc", sl_unloadfile
},
462 {"name", sl_filename
},
463 {"size", sl_filesize
},
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
},
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);
498 export (KEY
, BACKSPACE
);
523 export (KEY
, INSERT
);
524 export (KEY
, DELETE
);
525 lua_setfield (L
, -2, "KEY");
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");