diff options
Diffstat (limited to 'contrib/syslinux-4.02/com32/lua/src/syslinux.c')
-rw-r--r-- | contrib/syslinux-4.02/com32/lua/src/syslinux.c | 472 |
1 files changed, 472 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/com32/lua/src/syslinux.c b/contrib/syslinux-4.02/com32/lua/src/syslinux.c new file mode 100644 index 0000000..fa54d7f --- /dev/null +++ b/contrib/syslinux-4.02/com32/lua/src/syslinux.c @@ -0,0 +1,472 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <syslinux/boot.h> + +#define lnetlib_c /* Define the library */ + +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +#include "syslinux/boot.h" +#include "syslinux/loadfile.h" +#include "syslinux/linux.h" +#include "syslinux/config.h" + +int __parse_argv(char ***argv, const char *str); + +#define SYSLINUX_FILE "syslinux_file" + +typedef struct syslinux_file { + char *data; + char *name; + size_t size; +} syslinux_file; + +/* + * Most code taken from: + * com32/modules/linux.c + */ + +/* Find the last instance of a particular command line argument + (which should include the final =; do not use for boolean arguments) */ +static char *find_argument(char **argv, const char *argument) +{ + int la = strlen(argument); + char **arg; + char *ptr = NULL; + + for (arg = argv; *arg; arg++) { + if (!memcmp(*arg, argument, la)) + ptr = *arg + la; + } + + return ptr; +} + +/* Get a value with a potential suffix (k/m/g/t/p/e) */ +static unsigned long long suffix_number(const char *str) +{ + char *ep; + unsigned long long v; + int shift; + + v = strtoull(str, &ep, 0); + switch (*ep | 0x20) { + case 'k': + shift = 10; + break; + case 'm': + shift = 20; + break; + case 'g': + shift = 30; + break; + case 't': + shift = 40; + break; + case 'p': + shift = 50; + break; + case 'e': + shift = 60; + break; + default: + shift = 0; + break; + } + v <<= shift; + + return v; +} + +/* Truncate to 32 bits, with saturate */ +static inline uint32_t saturate32(unsigned long long v) +{ + return (v > 0xffffffff) ? 0xffffffff : (uint32_t) v; +} + +/* Stitch together the command line from a set of argv's */ +static char *make_cmdline(char **argv) +{ + char **arg; + size_t bytes; + char *cmdline, *p; + + bytes = 1; /* Just in case we have a zero-entry cmdline */ + for (arg = argv; *arg; arg++) { + bytes += strlen(*arg) + 1; + } + + p = cmdline = malloc(bytes); + if (!cmdline) + return NULL; + + for (arg = argv; *arg; arg++) { + int len = strlen(*arg); + memcpy(p, *arg, len); + p[len] = ' '; + p += len + 1; + } + + if (p > cmdline) + p--; /* Remove the last space */ + *p = '\0'; + + return cmdline; +} + +static int sl_run_command(lua_State * L) +{ + const char *cmd = luaL_checkstring(L, 1); /* Reads the string parameter */ + syslinux_run_command(cmd); + return 0; +} + +/* do default boot */ +static int sl_run_default(lua_State * L) +{ + syslinux_run_default(); + return 0; +} + +/* do local boot */ +static int sl_local_boot(lua_State * L) +{ + uint16_t flags = luaL_checkint(L, 1); + syslinux_local_boot(flags); + return 0; +} + +static int sl_final_cleanup(lua_State * L) +{ + uint16_t flags = luaL_checkint(L, 1); + syslinux_local_boot(flags); + return 0; +} + +/* boot linux kernel and initrd */ +static int sl_boot_linux(lua_State * L) +{ + const char *kernel = luaL_checkstring(L, 1); + const char *cmdline = luaL_optstring(L, 2, ""); + char *initrd; + void *kernel_data, *file_data; + size_t kernel_len, file_len; + struct initramfs *initramfs; + char *newcmdline; + uint32_t mem_limit = luaL_optint(L, 3, 0); + uint16_t video_mode = luaL_optint(L, 4, 0); +// int ret, i; + int ret; + char **argv, **argp, *arg, *p; + + ret = __parse_argv(&argv, cmdline); + + newcmdline = malloc(strlen(kernel) + 12); + if (!newcmdline) + printf("Mem alloc failed: cmdline\n"); + + strcpy(newcmdline, "BOOT_IMAGE="); + strcpy(newcmdline + strlen(newcmdline), kernel); + argv[0] = newcmdline; + argp = argv; + + /* DEBUG + for (i=0; i<ret; i++) + printf("%d: %s\n", i, argv[i]); + */ + + newcmdline = make_cmdline(argp); + if (!newcmdline) + printf("Creating command line failed!\n"); + + /* DEBUG + printf("Command line: %s\n", newcmdline); + msleep(1000); + */ + + /* Look for specific command-line arguments we care about */ + if ((arg = find_argument(argp, "mem="))) + mem_limit = saturate32(suffix_number(arg)); + + if ((arg = find_argument(argp, "vga="))) { + switch (arg[0] | 0x20) { + case 'a': /* "ask" */ + video_mode = 0xfffd; + break; + case 'e': /* "ext" */ + video_mode = 0xfffe; + break; + case 'n': /* "normal" */ + video_mode = 0xffff; + break; + default: + video_mode = strtoul(arg, NULL, 0); + break; + } + } + + printf("Loading kernel %s...\n", kernel); + if (loadfile(kernel, &kernel_data, &kernel_len)) + printf("failed!\n"); + else + printf("ok\n"); + + initramfs = initramfs_init(); + if (!initramfs) + printf("Initializing initrd failed!\n"); + + if ((arg = find_argument(argp, "initrd="))) { + do { + p = strchr(arg, ','); + if (p) + *p = '\0'; + + initrd = arg; + printf("Loading initrd %s... ", initrd); + if (initramfs_load_archive(initramfs, initrd)) { + printf("failed!\n"); + } + printf("ok\n"); + + if (p) + *p++ = ','; + } while ((arg = p)); + } + + if (!loadfile("/testfile1", &file_data, &file_len)) { + if (initramfs_add_file(initramfs, file_data, file_len, file_len, + "/testfile1", 0, 0755)) + printf("Adding extra file failed\n"); + } else + printf("Loading extra file failed\n"); + + /* DEBUG + msleep(10000); + */ + + ret = syslinux_boot_linux(kernel_data, kernel_len, initramfs, newcmdline); + + printf("syslinux_boot_linux returned %d\n", ret); + + return 0; +} + +/* sleep for sec seconds */ +static int sl_sleep(lua_State * L) +{ + unsigned int sec = luaL_checkint(L, 1); + sleep(sec); + return 0; +} + +/* sleep for msec milliseconds */ +static int sl_msleep(lua_State * L) +{ + unsigned int msec = luaL_checkint(L, 1); + msleep(msec); + return 0; +} + +static int sl_run_kernel_image(lua_State * L) +{ + const char *filename = luaL_checkstring(L, 1); + const char *cmdline = luaL_checkstring(L, 2); + uint32_t ipappend_flags = luaL_checkint(L, 3); + uint32_t type = luaL_checkint(L, 4); + + syslinux_run_kernel_image(filename, cmdline, ipappend_flags, type); + return 0; +} + +static int sl_loadfile(lua_State * L) +{ + const char *filename = luaL_checkstring(L, 1); + syslinux_file *file; + + void *file_data; + size_t file_len; + + if (loadfile(filename, &file_data, &file_len)) { + lua_pushstring(L, "Could not load file"); + lua_error(L); + } + + file = malloc(sizeof(syslinux_file)); + file->name = filename; + file->size = file_len; + file->data = file_data; + + lua_pushlightuserdata(L, file); + luaL_getmetatable(L, SYSLINUX_FILE); + lua_setmetatable(L, -2); + + return 1; +} + +static int sl_filesize(lua_State * L) +{ + const syslinux_file *file = luaL_checkudata(L, 1, SYSLINUX_FILE); + + lua_pushinteger(L, file->size); + + return 1; +} + +static int sl_filename(lua_State * L) +{ + const syslinux_file *file = luaL_checkudata(L, 1, SYSLINUX_FILE); + + lua_pushstring(L, file->name); + + return 1; +} + +static int sl_initramfs_init(lua_State * L) +{ + struct initramfs *initramfs; + + initramfs = initramfs_init(); + if (!initramfs) + printf("Initializing initrd failed!\n"); + + lua_pushlightuserdata(L, initramfs); + luaL_getmetatable(L, SYSLINUX_FILE); + lua_setmetatable(L, -2); + + return 1; +} + +static int sl_initramfs_load_archive(lua_State * L) +{ + const struct initramfs *initramfs = luaL_checkudata(L, 1, SYSLINUX_FILE); + const char *filename = luaL_checkstring(L, 2); + + if (initramfs_load_archive(initramfs, filename)) { + printf("failed!\n"); + } + + return 0; +} + +static int sl_initramfs_add_file(lua_State * L) +{ + const struct initramfs *initramfs = luaL_checkudata(L, 1, SYSLINUX_FILE); + const char *filename = luaL_checkstring(L, 2); + void *file_data; + size_t file_len = 0; + + if (initramfs_add_file(initramfs, file_data, file_len, file_len, + "/testfile1", 0, 0755)) + + return 0; +} + +static int sl_boot_it(lua_State * L) +{ + const syslinux_file *kernel = luaL_checkudata(L, 1, SYSLINUX_FILE); + const struct initramfs *initramfs = luaL_checkudata(L, 2, SYSLINUX_FILE); + const char *cmdline = luaL_optstring(L, 3, ""); + uint32_t mem_limit = luaL_optint(L, 4, 0); + uint16_t video_mode = luaL_optint(L, 5, 0); + int ret; + + ret = syslinux_boot_linux(kernel->data, kernel->size, initramfs, cmdline); + + return 0; +} + +static int sl_derivative(lua_State * L) +{ + const struct syslinux_version *sv; + + sv = syslinux_version(); + + switch (sv->filesystem) { + case SYSLINUX_FS_SYSLINUX: + lua_pushstring(L, "SYSLINUX"); + break; + case SYSLINUX_FS_PXELINUX: + lua_pushstring(L, "PXELINUX"); + break; + case SYSLINUX_FS_ISOLINUX: + lua_pushstring(L, "ISOLINUX"); + break; + case SYSLINUX_FS_UNKNOWN: + default: + lua_pushstring(L, "Unknown Syslinux derivative"); + break; + } + + return 1; +} + +static int sl_version(lua_State * L) +{ + const struct syslinux_version *sv; + + sv = syslinux_version(); + lua_pushstring(L, sv->version_string); + + return 1; +} + +static const luaL_reg syslinuxlib[] = { + {"run_command", sl_run_command}, + {"run_default", sl_run_default}, + {"local_boot", sl_local_boot}, + {"final_cleanup", sl_final_cleanup}, + {"boot_linux", sl_boot_linux}, + {"run_kernel_image", sl_run_kernel_image}, + {"sleep", sl_sleep}, + {"msleep", sl_msleep}, + {"loadfile", sl_loadfile}, + {"filesize", sl_filesize}, + {"filename", sl_filename}, + {"initramfs_init", sl_initramfs_init}, + {"initramfs_load_archive", sl_initramfs_load_archive}, + {"initramfs_add_file", sl_initramfs_add_file}, + {"boot_it", sl_boot_it}, + {"derivative", sl_derivative}, + {"version", sl_version}, + {NULL, NULL} +}; + +/* This defines a function that opens up your library. */ + +LUALIB_API int luaopen_syslinux(lua_State * L) +{ + + luaL_newmetatable(L, SYSLINUX_FILE); + + luaL_openlib(L, LUA_SYSLINUXLIBNAME, syslinuxlib, 0); + return 1; +} |