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 * ----------------------------------------------------------------------- */
31 #include <syslinux/boot.h>
33 #define lnetlib_c /* Define the library */
38 #include "syslinux/boot.h"
39 #include "syslinux/loadfile.h"
40 #include "syslinux/linux.h"
41 #include "syslinux/config.h"
42 #include "syslinux/reboot.h"
44 int __parse_argv(char ***argv
, const char *str
);
46 #define SYSLINUX_FILE "syslinux_file"
48 typedef struct syslinux_file
{
55 * Most code taken from:
56 * com32/modules/linux.c
59 /* Find the last instance of a particular command line argument
60 (which should include the final =; do not use for boolean arguments) */
61 static char *find_argument(char **argv
, const char *argument
)
63 int la
= strlen(argument
);
67 for (arg
= argv
; *arg
; arg
++) {
68 if (!memcmp(*arg
, argument
, la
))
75 /* Get a value with a potential suffix (k/m/g/t/p/e) */
76 static unsigned long long suffix_number(const char *str
)
82 v
= strtoull(str
, &ep
, 0);
111 /* Truncate to 32 bits, with saturate */
112 static inline uint32_t saturate32(unsigned long long v
)
114 return (v
> 0xffffffff) ? 0xffffffff : (uint32_t) v
;
117 /* Stitch together the command line from a set of argv's */
118 static char *make_cmdline(char **argv
)
124 bytes
= 1; /* Just in case we have a zero-entry cmdline */
125 for (arg
= argv
; *arg
; arg
++) {
126 bytes
+= strlen(*arg
) + 1;
129 p
= cmdline
= malloc(bytes
);
133 for (arg
= argv
; *arg
; arg
++) {
134 int len
= strlen(*arg
);
135 memcpy(p
, *arg
, len
);
141 p
--; /* Remove the last space */
147 static int sl_run_command(lua_State
* L
)
149 const char *cmd
= luaL_checkstring(L
, 1); /* Reads the string parameter */
150 syslinux_run_command(cmd
);
154 /* do default boot */
155 static int sl_run_default(lua_State
* L
)
157 /* Preventing GCC to complain against unused L */
159 syslinux_run_default();
164 static int sl_local_boot(lua_State
* L
)
166 uint16_t flags
= luaL_checkint(L
, 1);
167 syslinux_local_boot(flags
);
171 static int sl_final_cleanup(lua_State
* L
)
173 uint16_t flags
= luaL_checkint(L
, 1);
174 syslinux_local_boot(flags
);
178 /* boot linux kernel and initrd */
179 static int sl_boot_linux(lua_State
* L
)
181 const char *kernel
= luaL_checkstring(L
, 1);
182 const char *cmdline
= luaL_optstring(L
, 2, "");
184 void *kernel_data
, *file_data
;
185 size_t kernel_len
, file_len
;
186 struct initramfs
*initramfs
;
188 uint32_t mem_limit
= luaL_optint(L
, 3, 0);
189 uint16_t video_mode
= luaL_optint(L
, 4, 0);
192 char **argv
, **argp
, *arg
, *p
;
197 ret
= __parse_argv(&argv
, cmdline
);
199 newcmdline
= malloc(strlen(kernel
) + 12);
201 printf("Mem alloc failed: cmdline\n");
203 strcpy(newcmdline
, "BOOT_IMAGE=");
204 strcpy(newcmdline
+ strlen(newcmdline
), kernel
);
205 argv
[0] = newcmdline
;
209 for (i=0; i<ret; i++)
210 printf("%d: %s\n", i, argv[i]);
213 newcmdline
= make_cmdline(argp
);
215 printf("Creating command line failed!\n");
218 printf("Command line: %s\n", newcmdline);
222 /* Look for specific command-line arguments we care about */
223 if ((arg
= find_argument(argp
, "mem=")))
224 mem_limit
= saturate32(suffix_number(arg
));
226 if ((arg
= find_argument(argp
, "vga="))) {
227 switch (arg
[0] | 0x20) {
228 case 'a': /* "ask" */
231 case 'e': /* "ext" */
234 case 'n': /* "normal" */
238 video_mode
= strtoul(arg
, NULL
, 0);
243 printf("Loading kernel %s...\n", kernel
);
244 if (loadfile(kernel
, &kernel_data
, &kernel_len
))
249 initramfs
= initramfs_init();
251 printf("Initializing initrd failed!\n");
253 if ((arg
= find_argument(argp
, "initrd="))) {
255 p
= strchr(arg
, ',');
260 printf("Loading initrd %s... ", initrd
);
261 if (initramfs_load_archive(initramfs
, initrd
)) {
271 if (!loadfile("/testfile1", &file_data
, &file_len
)) {
272 if (initramfs_add_file(initramfs
, file_data
, file_len
, file_len
,
273 "/testfile1", 0, 0755))
274 printf("Adding extra file failed\n");
276 printf("Loading extra file failed\n");
282 ret
= syslinux_boot_linux(kernel_data
, kernel_len
, initramfs
, NULL
, newcmdline
);
284 printf("syslinux_boot_linux returned %d\n", ret
);
289 /* sleep for sec seconds */
290 static int sl_sleep(lua_State
* L
)
292 unsigned int sec
= luaL_checkint(L
, 1);
297 /* sleep for msec milliseconds */
298 static int sl_msleep(lua_State
* L
)
300 unsigned int msec
= luaL_checkint(L
, 1);
305 static int sl_run_kernel_image(lua_State
* L
)
307 const char *filename
= luaL_checkstring(L
, 1);
308 const char *cmdline
= luaL_checkstring(L
, 2);
309 uint32_t ipappend_flags
= luaL_checkint(L
, 3);
310 uint32_t type
= luaL_checkint(L
, 4);
312 syslinux_run_kernel_image(filename
, cmdline
, ipappend_flags
, type
);
316 static int sl_loadfile(lua_State
* L
)
318 const char *filename
= luaL_checkstring(L
, 1);
324 if (loadfile(filename
, &file_data
, &file_len
)) {
325 lua_pushstring(L
, "Could not load file");
329 file
= malloc(sizeof(syslinux_file
));
330 strlcpy(file
->name
,filename
,sizeof(syslinux_file
));
331 file
->size
= file_len
;
332 file
->data
= file_data
;
334 lua_pushlightuserdata(L
, file
);
335 luaL_getmetatable(L
, SYSLINUX_FILE
);
336 lua_setmetatable(L
, -2);
341 static int sl_filesize(lua_State
* L
)
343 const syslinux_file
*file
= luaL_checkudata(L
, 1, SYSLINUX_FILE
);
345 lua_pushinteger(L
, file
->size
);
350 static int sl_filename(lua_State
* L
)
352 const syslinux_file
*file
= luaL_checkudata(L
, 1, SYSLINUX_FILE
);
354 lua_pushstring(L
, file
->name
);
359 static int sl_initramfs_init(lua_State
* L
)
361 struct initramfs
*initramfs
;
363 initramfs
= initramfs_init();
365 printf("Initializing initrd failed!\n");
367 lua_pushlightuserdata(L
, initramfs
);
368 luaL_getmetatable(L
, SYSLINUX_FILE
);
369 lua_setmetatable(L
, -2);
374 static int sl_initramfs_load_archive(lua_State
* L
)
376 struct initramfs
*initramfs
= luaL_checkudata(L
, 1, SYSLINUX_FILE
);
377 const char *filename
= luaL_checkstring(L
, 2);
379 if (initramfs_load_archive(initramfs
, filename
)) {
386 static int sl_initramfs_add_file(lua_State
* L
)
388 struct initramfs
*initramfs
= luaL_checkudata(L
, 1, SYSLINUX_FILE
);
389 /* FIXME: This code is doing nothing */
390 //const char *filename = luaL_checkstring(L, 2);
391 void *file_data
= NULL
;
394 return initramfs_add_file(initramfs
, file_data
, file_len
, file_len
, "/testfile1", 0, 0755);
397 static int sl_boot_it(lua_State
* L
)
399 const syslinux_file
*kernel
= luaL_checkudata(L
, 1, SYSLINUX_FILE
);
400 struct initramfs
*initramfs
= luaL_checkudata(L
, 2, SYSLINUX_FILE
);
401 const char *cmdline
= luaL_optstring(L
, 3, "");
402 uint32_t mem_limit
= luaL_optint(L
, 4, 0);
403 uint16_t video_mode
= luaL_optint(L
, 5, 0);
404 /* Preventing gcc to complain about unused variables */
408 return syslinux_boot_linux(kernel
->data
, kernel
->size
,
409 initramfs
, NULL
, (char *)cmdline
);
412 static int sl_config_file(lua_State
* L
)
414 const char *config_file
= syslinux_config_file();
415 lua_pushstring(L
, config_file
);
419 static int sl_reboot(lua_State
* L
)
421 int warm_boot
= luaL_optint(L
, 1, 0);
422 /* explicitly convert it to 1 or 0 */
423 warm_boot
= warm_boot
? 1 : 0;
424 syslinux_reboot(warm_boot
);
428 static int sl_ipappend_strs(lua_State
* L
)
431 const struct syslinux_ipappend_strings
*ip_strs
= syslinux_ipappend_strings();
433 for (i
= 0; i
< ip_strs
->count
; i
++) {
434 lua_pushinteger(L
, i
+ 1);
435 lua_pushstring(L
, ip_strs
->ptr
[i
]);
441 static int sl_derivative(lua_State
* L
)
443 const struct syslinux_version
*sv
;
445 sv
= syslinux_version();
447 switch (sv
->filesystem
) {
448 case SYSLINUX_FS_SYSLINUX
:
449 lua_pushstring(L
, "SYSLINUX");
451 case SYSLINUX_FS_PXELINUX
:
452 lua_pushstring(L
, "PXELINUX");
454 case SYSLINUX_FS_ISOLINUX
:
455 lua_pushstring(L
, "ISOLINUX");
457 case SYSLINUX_FS_UNKNOWN
:
459 lua_pushstring(L
, "Unknown Syslinux derivative");
466 static int sl_version(lua_State
* L
)
468 const struct syslinux_version
*sv
;
470 sv
= syslinux_version();
471 lua_pushstring(L
, sv
->version_string
);
476 static const luaL_reg syslinuxlib
[] = {
477 {"run_command", sl_run_command
},
478 {"run_default", sl_run_default
},
479 {"local_boot", sl_local_boot
},
480 {"final_cleanup", sl_final_cleanup
},
481 {"boot_linux", sl_boot_linux
},
482 {"run_kernel_image", sl_run_kernel_image
},
484 {"msleep", sl_msleep
},
485 {"loadfile", sl_loadfile
},
486 {"filesize", sl_filesize
},
487 {"filename", sl_filename
},
488 {"initramfs_init", sl_initramfs_init
},
489 {"initramfs_load_archive", sl_initramfs_load_archive
},
490 {"initramfs_add_file", sl_initramfs_add_file
},
491 {"boot_it", sl_boot_it
},
492 {"config_file", sl_config_file
},
493 {"ipappend_strs", sl_ipappend_strs
},
494 {"reboot", sl_reboot
},
495 {"derivative", sl_derivative
},
496 {"version", sl_version
},
500 /* This defines a function that opens up your library. */
502 LUALIB_API
int luaopen_syslinux(lua_State
* L
)
505 luaL_newmetatable(L
, SYSLINUX_FILE
);
507 luaL_openlib(L
, LUA_SYSLINUXLIBNAME
, syslinuxlib
, 0);