Add memtest support.
[syslinux-debian/hramrach.git] / com32 / lua / src / syslinux.c
blobafcdcaadab976055755798f1b65e8ab5b3220680
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 <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <syslinux/boot.h>
33 #define lnetlib_c /* Define the library */
35 #include "lua.h"
36 #include "lauxlib.h"
37 #include "lualib.h"
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 {
49 char *data;
50 char *name;
51 size_t size;
52 } 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);
64 char **arg;
65 char *ptr = NULL;
67 for (arg = argv; *arg; arg++) {
68 if (!memcmp(*arg, argument, la))
69 ptr = *arg + la;
72 return ptr;
75 /* Get a value with a potential suffix (k/m/g/t/p/e) */
76 static unsigned long long suffix_number(const char *str)
78 char *ep;
79 unsigned long long v;
80 int shift;
82 v = strtoull(str, &ep, 0);
83 switch (*ep | 0x20) {
84 case 'k':
85 shift = 10;
86 break;
87 case 'm':
88 shift = 20;
89 break;
90 case 'g':
91 shift = 30;
92 break;
93 case 't':
94 shift = 40;
95 break;
96 case 'p':
97 shift = 50;
98 break;
99 case 'e':
100 shift = 60;
101 break;
102 default:
103 shift = 0;
104 break;
106 v <<= shift;
108 return v;
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)
120 char **arg;
121 size_t bytes;
122 char *cmdline, *p;
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);
130 if (!cmdline)
131 return NULL;
133 for (arg = argv; *arg; arg++) {
134 int len = strlen(*arg);
135 memcpy(p, *arg, len);
136 p[len] = ' ';
137 p += len + 1;
140 if (p > cmdline)
141 p--; /* Remove the last space */
142 *p = '\0';
144 return cmdline;
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);
151 return 0;
154 /* do default boot */
155 static int sl_run_default(lua_State * L)
157 /* Preventing GCC to complain against unused L */
158 L=L;
159 syslinux_run_default();
160 return 0;
163 /* do local boot */
164 static int sl_local_boot(lua_State * L)
166 uint16_t flags = luaL_checkint(L, 1);
167 syslinux_local_boot(flags);
168 return 0;
171 static int sl_final_cleanup(lua_State * L)
173 uint16_t flags = luaL_checkint(L, 1);
174 syslinux_local_boot(flags);
175 return 0;
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, "");
183 char *initrd;
184 void *kernel_data, *file_data;
185 size_t kernel_len, file_len;
186 struct initramfs *initramfs;
187 char *newcmdline;
188 uint32_t mem_limit = luaL_optint(L, 3, 0);
189 uint16_t video_mode = luaL_optint(L, 4, 0);
190 // int ret, i;
191 int ret;
192 char **argv, **argp, *arg, *p;
194 (void)mem_limit;
195 (void)video_mode;
197 ret = __parse_argv(&argv, cmdline);
199 newcmdline = malloc(strlen(kernel) + 12);
200 if (!newcmdline)
201 printf("Mem alloc failed: cmdline\n");
203 strcpy(newcmdline, "BOOT_IMAGE=");
204 strcpy(newcmdline + strlen(newcmdline), kernel);
205 argv[0] = newcmdline;
206 argp = argv;
208 /* DEBUG
209 for (i=0; i<ret; i++)
210 printf("%d: %s\n", i, argv[i]);
213 newcmdline = make_cmdline(argp);
214 if (!newcmdline)
215 printf("Creating command line failed!\n");
217 /* DEBUG
218 printf("Command line: %s\n", newcmdline);
219 msleep(1000);
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" */
229 video_mode = 0xfffd;
230 break;
231 case 'e': /* "ext" */
232 video_mode = 0xfffe;
233 break;
234 case 'n': /* "normal" */
235 video_mode = 0xffff;
236 break;
237 default:
238 video_mode = strtoul(arg, NULL, 0);
239 break;
243 printf("Loading kernel %s...\n", kernel);
244 if (loadfile(kernel, &kernel_data, &kernel_len))
245 printf("failed!\n");
246 else
247 printf("ok\n");
249 initramfs = initramfs_init();
250 if (!initramfs)
251 printf("Initializing initrd failed!\n");
253 if ((arg = find_argument(argp, "initrd="))) {
254 do {
255 p = strchr(arg, ',');
256 if (p)
257 *p = '\0';
259 initrd = arg;
260 printf("Loading initrd %s... ", initrd);
261 if (initramfs_load_archive(initramfs, initrd)) {
262 printf("failed!\n");
264 printf("ok\n");
266 if (p)
267 *p++ = ',';
268 } while ((arg = p));
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");
275 } else
276 printf("Loading extra file failed\n");
278 /* DEBUG
279 msleep(10000);
282 ret = syslinux_boot_linux(kernel_data, kernel_len, initramfs, NULL, newcmdline);
284 printf("syslinux_boot_linux returned %d\n", ret);
286 return 0;
289 /* sleep for sec seconds */
290 static int sl_sleep(lua_State * L)
292 unsigned int sec = luaL_checkint(L, 1);
293 sleep(sec);
294 return 0;
297 /* sleep for msec milliseconds */
298 static int sl_msleep(lua_State * L)
300 unsigned int msec = luaL_checkint(L, 1);
301 msleep(msec);
302 return 0;
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);
313 return 0;
316 static int sl_loadfile(lua_State * L)
318 const char *filename = luaL_checkstring(L, 1);
319 syslinux_file *file;
321 void *file_data;
322 size_t file_len;
324 if (loadfile(filename, &file_data, &file_len)) {
325 lua_pushstring(L, "Could not load file");
326 lua_error(L);
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);
338 return 1;
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);
347 return 1;
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);
356 return 1;
359 static int sl_initramfs_init(lua_State * L)
361 struct initramfs *initramfs;
363 initramfs = initramfs_init();
364 if (!initramfs)
365 printf("Initializing initrd failed!\n");
367 lua_pushlightuserdata(L, initramfs);
368 luaL_getmetatable(L, SYSLINUX_FILE);
369 lua_setmetatable(L, -2);
371 return 1;
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)) {
380 printf("failed!\n");
383 return 0;
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;
392 size_t file_len = 0;
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 */
405 (void)video_mode;
406 (void)mem_limit;
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);
416 return 1;
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);
425 return 0;
428 static int sl_ipappend_strs(lua_State * L)
430 int i;
431 const struct syslinux_ipappend_strings *ip_strs = syslinux_ipappend_strings();
432 lua_newtable(L);
433 for (i = 0; i < ip_strs->count; i++) {
434 lua_pushinteger(L, i + 1);
435 lua_pushstring(L, ip_strs->ptr[i]);
436 lua_settable(L,-3);
438 return 1;
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");
450 break;
451 case SYSLINUX_FS_PXELINUX:
452 lua_pushstring(L, "PXELINUX");
453 break;
454 case SYSLINUX_FS_ISOLINUX:
455 lua_pushstring(L, "ISOLINUX");
456 break;
457 case SYSLINUX_FS_UNKNOWN:
458 default:
459 lua_pushstring(L, "Unknown Syslinux derivative");
460 break;
463 return 1;
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);
473 return 1;
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},
483 {"sleep", sl_sleep},
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},
497 {NULL, NULL}
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);
508 return 1;