+ /* ----------------------------------------------------------------------- *
+ *
+ * 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 <syslinux/boot.h>
--#define lnetlib_c /* Define the library */
++#define lnetlib_c /* Define the library */
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
-#include "../../../menu/libmenu/com32io.h"
+ #include "syslinux/boot.h"
+ #include "syslinux/loadfile.h"
+ #include "syslinux/linux.h"
- char *data;
- char *name;
- size_t size;
++#include "../../cmenu/libmenu/com32io.h"
+
+ int __parse_argv(char ***argv, const char *str);
+
+ #define SYSLINUX_FILE "syslinux_file"
+
+ typedef struct syslinux_file {
- int la = strlen(argument);
- char **arg;
- char *ptr = NULL;
++ 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;
- static int sl_run_command(lua_State *L)
- for (arg = argv; *arg; arg++) {
- if (!memcmp(*arg, argument, la))
- ptr = *arg + la;
- }
++ for (arg = argv; *arg; arg++) {
++ if (!memcmp(*arg, argument, la))
++ ptr = *arg + la;
++ }
+
- return ptr;
++ return ptr;
+ }
+
+ /* Get a value with a potential suffix (k/m/g/t/p/e) */
+ static unsigned long long suffix_number(const char *str)
{
- const char *cmd = luaL_checkstring(L, 1); /* Reads the string parameter */
- syslinux_run_command(cmd);
- return 0;
- 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;
++ 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;
}
- return (v > 0xffffffff) ? 0xffffffff : (uint32_t)v;
+ /* Truncate to 32 bits, with saturate */
+ static inline uint32_t saturate32(unsigned long long v)
+ {
- 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;
-}
++ return (v > 0xffffffff) ? 0xffffffff : (uint32_t) v;
+ }
+
+ /* Stitch together the command line from a set of argv's */
+ static char *make_cmdline(char **argv)
+ {
-static int sl_run_command(lua_State *L)
++ 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;
+
- const char *cmd = luaL_checkstring(L, 1); /* Reads the string parameter */
- syslinux_run_command(cmd);
- return 0;
++ 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)
+ {
-static int sl_run_default(lua_State *L)
++ const char *cmd = luaL_checkstring(L, 1); /* Reads the string parameter */
++ syslinux_run_command(cmd);
++ return 0;
+ }
+
+ /* do default boot */
- syslinux_run_default();
- return 0;
++static int sl_run_default(lua_State * L)
+ {
-static int sl_local_boot(lua_State *L)
++ syslinux_run_default();
++ return 0;
+ }
+
+ /* do local boot */
- uint16_t flags = luaL_checkint(L, 1);
- syslinux_local_boot(flags);
- return 0;
++static int sl_local_boot(lua_State * L)
+ {
-static int sl_final_cleanup(lua_State *L)
++ uint16_t flags = luaL_checkint(L, 1);
++ syslinux_local_boot(flags);
++ return 0;
+ }
+
- uint16_t flags = luaL_checkint(L, 1);
- syslinux_local_boot(flags);
- return 0;
++static int sl_final_cleanup(lua_State * L)
+ {
-static int sl_boot_linux(lua_State *L)
++ uint16_t flags = luaL_checkint(L, 1);
++ syslinux_local_boot(flags);
++ return 0;
+ }
+
+ /* boot linux kernel and initrd */
- 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;
- 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);
- sleep(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;
++static int sl_boot_linux(lua_State * L)
+ {
- }
-
-
- 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");
++ 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);
++ sleep(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;
++ }
+ }
- /* DEBUG
- sleep(10000);
- */
+
- ret = syslinux_boot_linux(kernel_data, kernel_len, initramfs, newcmdline,
- video_mode, mem_limit);
- printf("syslinux_boot_linux returned %d\n", ret);
++ 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));
++ }
+
- return 0;
-}
++ 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");
+
-static int sl_sleep(lua_State *L)
++ /* DEBUG
++ sleep(10000);
++ */
+
++ ret = syslinux_boot_linux(kernel_data, kernel_len, initramfs, newcmdline);
++
++ printf("syslinux_boot_linux returned %d\n", ret);
++
++ return 0;
++}
+
+ /* sleep for msec milliseconds */
- unsigned int msec = luaL_checkint(L, 1);
- sleep(msec);
- return 0;
++static int sl_sleep(lua_State * L)
+ {
-
-static int sl_run_kernel_image(lua_State *L)
++ unsigned int msec = luaL_checkint(L, 1);
++ sleep(msec);
++ return 0;
+ }
+
- 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);
++static int sl_run_kernel_image(lua_State * L)
+ {
- syslinux_run_kernel_image(filename, cmdline, ipappend_flags, type);
- return 0;
++ 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);
+
-static int sl_loadfile(lua_State *L)
++ syslinux_run_kernel_image(filename, cmdline, ipappend_flags, type);
++ return 0;
+ }
+
- const char *filename = luaL_checkstring(L, 1);
- syslinux_file *file;
++static int sl_loadfile(lua_State * L)
+ {
- void *file_data;
- size_t file_len;
++ const char *filename = luaL_checkstring(L, 1);
++ syslinux_file *file;
+
- if (loadfile(filename, &file_data, &file_len)) {
- lua_pushstring(L, "Could not load file");
- lua_error(L);
- }
++ void *file_data;
++ size_t file_len;
+
- file = malloc(sizeof(syslinux_file));
- file->name = filename;
- file->size = file_len;
- file->data = file_data;
++ if (loadfile(filename, &file_data, &file_len)) {
++ lua_pushstring(L, "Could not load file");
++ lua_error(L);
++ }
+
- lua_pushlightuserdata(L, file);
- luaL_getmetatable(L, SYSLINUX_FILE);
- lua_setmetatable(L, -2);
++ file = malloc(sizeof(syslinux_file));
++ file->name = filename;
++ file->size = file_len;
++ file->data = file_data;
+
- return 1;
++ lua_pushlightuserdata(L, file);
++ luaL_getmetatable(L, SYSLINUX_FILE);
++ lua_setmetatable(L, -2);
+
-
-static int sl_filesize(lua_State *L)
++ return 1;
+ }
+
- const syslinux_file *file = luaL_checkudata(L, 1, SYSLINUX_FILE);
++static int sl_filesize(lua_State * L)
+ {
- lua_pushinteger(L, file->size);
++ const syslinux_file *file = luaL_checkudata(L, 1, SYSLINUX_FILE);
+
- return 1;
++ lua_pushinteger(L, file->size);
+
-
-static int sl_filename(lua_State *L)
++ return 1;
+ }
+
- const syslinux_file *file = luaL_checkudata(L, 1, SYSLINUX_FILE);
++static int sl_filename(lua_State * L)
+ {
- lua_pushstring(L, file->name);
++ const syslinux_file *file = luaL_checkudata(L, 1, SYSLINUX_FILE);
+
- return 1;
++ lua_pushstring(L, file->name);
+
-
-static int sl_initramfs_init(lua_State *L)
++ return 1;
+ }
+
- struct initramfs *initramfs;
++static int sl_initramfs_init(lua_State * L)
+ {
- initramfs = initramfs_init();
- if (!initramfs)
- printf("Initializing initrd failed!\n");
++ struct initramfs *initramfs;
+
- lua_pushlightuserdata(L, initramfs);
- luaL_getmetatable(L, SYSLINUX_FILE);
- lua_setmetatable(L, -2);
++ initramfs = initramfs_init();
++ if (!initramfs)
++ printf("Initializing initrd failed!\n");
+
- return 1;
++ lua_pushlightuserdata(L, initramfs);
++ luaL_getmetatable(L, SYSLINUX_FILE);
++ lua_setmetatable(L, -2);
+
-
-static int sl_initramfs_load_archive(lua_State *L)
++ return 1;
+ }
+
- const struct initramfs *initramfs = luaL_checkudata(L, 1, SYSLINUX_FILE);
- const char *filename = luaL_checkstring(L, 2);
++static int sl_initramfs_load_archive(lua_State * L)
+ {
- if (initramfs_load_archive(initramfs, filename)) {
- printf("failed!\n");
- }
++ const struct initramfs *initramfs = luaL_checkudata(L, 1, SYSLINUX_FILE);
++ const char *filename = luaL_checkstring(L, 2);
+
- return 0;
++ if (initramfs_load_archive(initramfs, filename)) {
++ printf("failed!\n");
++ }
+
-static int sl_initramfs_add_file(lua_State *L)
++ return 0;
+ }
+
- 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;
++static int sl_initramfs_add_file(lua_State * L)
+ {
- if (initramfs_add_file(initramfs, file_data, file_len, file_len,
- "/testfile1", 0, 0755))
++ 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;
+
- return 0;
++ if (initramfs_add_file(initramfs, file_data, file_len, file_len,
++ "/testfile1", 0, 0755))
+
-static int sl_boot_it(lua_State *L)
++ return 0;
+ }
+
- 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;
++static int sl_boot_it(lua_State * L)
+ {
- ret = syslinux_boot_linux(kernel->data, kernel->size, initramfs, cmdline,
- video_mode, mem_limit);
++ 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;
+
- return 0;
++ ret = syslinux_boot_linux(kernel->data, kernel->size, initramfs, cmdline);
+
++ return 0;
+ }
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},
- {"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},
-- {NULL, NULL}
++ {"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},
++ {"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},
++ {NULL, NULL}
};
/* This defines a function that opens up your library. */
--LUALIB_API int luaopen_syslinux (lua_State *L) {
- luaL_openlib(L, LUA_SYSLINUXLIBNAME, syslinuxlib, 0);
- return 1;
- }
++LUALIB_API int luaopen_syslinux(lua_State * L)
++{
+
- luaL_newmetatable(L, SYSLINUX_FILE);
++ luaL_newmetatable(L, SYSLINUX_FILE);
- luaL_openlib(L, LUA_SYSLINUXLIBNAME, syslinuxlib, 0);
- return 1;
++ luaL_openlib(L, LUA_SYSLINUXLIBNAME, syslinuxlib, 0);
++ return 1;
+ }