diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:29:52 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:29:52 +0000 |
commit | ca67b09c015d4af3ae3cce12aa72e60941dbb8b5 (patch) | |
tree | b7316d7b06c373e08dabb79a2c866c568e08f49e /debian/grub-extras/lua/grub_lib.c | |
parent | Adding upstream version 2.06. (diff) | |
download | grub2-ca67b09c015d4af3ae3cce12aa72e60941dbb8b5.tar.xz grub2-ca67b09c015d4af3ae3cce12aa72e60941dbb8b5.zip |
Adding debian version 2.06-13+deb12u1.debian/2.06-13+deb12u1debian
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | debian/grub-extras/lua/grub_lib.c | 537 |
1 files changed, 537 insertions, 0 deletions
diff --git a/debian/grub-extras/lua/grub_lib.c b/debian/grub-extras/lua/grub_lib.c new file mode 100644 index 0000000..3d25d02 --- /dev/null +++ b/debian/grub-extras/lua/grub_lib.c @@ -0,0 +1,537 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +#include "grub_lib.h" + +#include <grub/env.h> +#include <grub/parser.h> +#include <grub/command.h> +#include <grub/normal.h> +#include <grub/file.h> +#include <grub/device.h> + +#ifdef ENABLE_LUA_PCI +#include <grub/pci.h> +#endif + +/* Updates the globals grub_errno and grub_msg, leaving their values on the + top of the stack, and clears grub_errno. When grub_errno is zero, grub_msg + is not left on the stack. The value returned is the number of values left on + the stack. */ +static int +push_result (lua_State *state) +{ + int saved_errno; + int num_results; + + saved_errno = grub_errno; + grub_errno = 0; + + /* Push once for setfield, and again to leave on the stack */ + lua_pushinteger (state, saved_errno); + lua_pushinteger (state, saved_errno); + lua_setfield (state, LUA_GLOBALSINDEX, "grub_errno"); + + if (saved_errno) + { + /* Push once for setfield, and again to leave on the stack */ + lua_pushstring (state, grub_errmsg); + lua_pushstring (state, grub_errmsg); + num_results = 2; + } + else + { + lua_pushnil (state); + num_results = 1; + } + + lua_setfield (state, LUA_GLOBALSINDEX, "grub_errmsg"); + + return num_results; +} + +/* Updates the globals grub_errno and grub_msg ( without leaving them on the + stack ), clears grub_errno, and returns the value of grub_errno before it + was cleared. */ +static int +save_errno (lua_State *state) +{ + int saved_errno; + + saved_errno = grub_errno; + lua_pop(state, push_result(state)); + + return saved_errno; +} + +static int +grub_lua_run (lua_State *state) +{ + int n; + char **args; + const char *s; + + s = luaL_checkstring (state, 1); + if ((! grub_parser_split_cmdline (s, 0, 0, &n, &args)) + && (n >= 0)) + { + grub_command_t cmd; + + cmd = grub_command_find (args[0]); + if (cmd) + (cmd->func) (cmd, n-1, &args[1]); + else + grub_error (GRUB_ERR_FILE_NOT_FOUND, "command not found"); + + grub_free (args[0]); + grub_free (args); + } + + return push_result (state); +} + +static int +grub_lua_getenv (lua_State *state) +{ + int n, i; + + n = lua_gettop (state); + for (i = 1; i <= n; i++) + { + const char *name, *value; + + name = luaL_checkstring (state, i); + value = grub_env_get (name); + if (value) + lua_pushstring (state, value); + else + lua_pushnil (state); + } + + return n; +} + +static int +grub_lua_setenv (lua_State *state) +{ + const char *name, *value; + + name = luaL_checkstring (state, 1); + value = luaL_checkstring (state, 2); + + if (name[0]) + grub_env_set (name, value); + + return 0; +} + +/* Helper for grub_lua_enum_device. */ +static int +grub_lua_enum_device_iter (const char *name, void *data) +{ + lua_State *state = data; + int result; + grub_device_t dev; + + result = 0; + dev = grub_device_open (name); + if (dev) + { + grub_fs_t fs; + + fs = grub_fs_probe (dev); + if (fs) + { + lua_pushvalue (state, 1); + lua_pushstring (state, name); + lua_pushstring (state, fs->name); + if (! fs->uuid) + lua_pushnil (state); + else + { + int err; + char *uuid; + + err = fs->uuid (dev, &uuid); + if (err) + { + grub_errno = 0; + lua_pushnil (state); + } + else + { + lua_pushstring (state, uuid); + grub_free (uuid); + } + } + + if (! fs->label) + lua_pushnil (state); + else + { + int err; + char *label = NULL; + + err = fs->label (dev, &label); + if (err) + { + grub_errno = 0; + lua_pushnil (state); + } + else + { + if (label == NULL) + { + lua_pushnil (state); + } + else + { + lua_pushstring (state, label); + } + grub_free (label); + } + } + + lua_call (state, 4, 1); + result = lua_tointeger (state, -1); + lua_pop (state, 1); + } + else + grub_errno = 0; + grub_device_close (dev); + } + else + grub_errno = 0; + + return result; +} + +static int +grub_lua_enum_device (lua_State *state) +{ + luaL_checktype (state, 1, LUA_TFUNCTION); + grub_device_iterate (grub_lua_enum_device_iter, state); + return push_result (state); +} + +static int +enum_file (const char *name, const struct grub_dirhook_info *info, + void *data) +{ + int result; + lua_State *state = data; + + lua_pushvalue (state, 1); + lua_pushstring (state, name); + lua_pushinteger (state, info->dir != 0); + lua_call (state, 2, 1); + result = lua_tointeger (state, -1); + lua_pop (state, 1); + + return result; +} + +static int +grub_lua_enum_file (lua_State *state) +{ + char *device_name; + const char *arg; + grub_device_t dev; + + luaL_checktype (state, 1, LUA_TFUNCTION); + arg = luaL_checkstring (state, 2); + device_name = grub_file_get_device_name (arg); + dev = grub_device_open (device_name); + if (dev) + { + grub_fs_t fs; + const char *path; + + fs = grub_fs_probe (dev); + path = grub_strchr (arg, ')'); + if (! path) + path = arg; + else + path++; + + if (fs) + { + (fs->dir) (dev, path, enum_file, state); + } + + grub_device_close (dev); + } + + grub_free (device_name); + + return push_result (state); +} + +#ifdef ENABLE_LUA_PCI +/* Helper for grub_lua_enum_pci. */ +static int +grub_lua_enum_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, void *data) +{ + lua_State *state = data; + int result; + grub_pci_address_t addr; + grub_uint32_t class; + + lua_pushvalue (state, 1); + lua_pushinteger (state, grub_pci_get_bus (dev)); + lua_pushinteger (state, grub_pci_get_device (dev)); + lua_pushinteger (state, grub_pci_get_function (dev)); + lua_pushinteger (state, pciid); + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class = grub_pci_read (addr); + lua_pushinteger (state, class); + + lua_call (state, 5, 1); + result = lua_tointeger (state, -1); + lua_pop (state, 1); + + return result; +} + +static int +grub_lua_enum_pci (lua_State *state) +{ + luaL_checktype (state, 1, LUA_TFUNCTION); + grub_pci_iterate (grub_lua_enum_pci_iter, state); + return push_result (state); +} +#endif + +static int +grub_lua_file_open (lua_State *state) +{ + grub_file_t file; + const char *name; + + name = luaL_checkstring (state, 1); + file = grub_file_open (name); + save_errno (state); + + if (! file) + return 0; + + lua_pushlightuserdata (state, file); + return 1; +} + +static int +grub_lua_file_close (lua_State *state) +{ + grub_file_t file; + + luaL_checktype (state, 1, LUA_TLIGHTUSERDATA); + file = lua_touserdata (state, 1); + grub_file_close (file); + + return push_result (state); +} + +static int +grub_lua_file_seek (lua_State *state) +{ + grub_file_t file; + grub_off_t offset; + + luaL_checktype (state, 1, LUA_TLIGHTUSERDATA); + file = lua_touserdata (state, 1); + offset = luaL_checkinteger (state, 2); + + offset = grub_file_seek (file, offset); + save_errno (state); + + lua_pushinteger (state, offset); + return 1; +} + +static int +grub_lua_file_read (lua_State *state) +{ + grub_file_t file; + luaL_Buffer b; + int n; + + luaL_checktype (state, 1, LUA_TLIGHTUSERDATA); + file = lua_touserdata (state, 1); + n = luaL_checkinteger (state, 2); + + luaL_buffinit (state, &b); + while (n) + { + char *p; + int nr; + + nr = (n > LUAL_BUFFERSIZE) ? LUAL_BUFFERSIZE : n; + p = luaL_prepbuffer (&b); + + nr = grub_file_read (file, p, nr); + if (nr <= 0) + break; + + luaL_addsize (&b, nr); + n -= nr; + } + + save_errno (state); + luaL_pushresult (&b); + return 1; +} + +static int +grub_lua_file_getline (lua_State *state) +{ + grub_file_t file; + char *line; + + luaL_checktype (state, 1, LUA_TLIGHTUSERDATA); + file = lua_touserdata (state, 1); + + line = grub_file_getline (file); + save_errno (state); + + if (! line) + return 0; + + lua_pushstring (state, line); + grub_free (line); + return 1; +} + +static int +grub_lua_file_getsize (lua_State *state) +{ + grub_file_t file; + + luaL_checktype (state, 1, LUA_TLIGHTUSERDATA); + file = lua_touserdata (state, 1); + + lua_pushinteger (state, file->size); + return 1; +} + +static int +grub_lua_file_getpos (lua_State *state) +{ + grub_file_t file; + + luaL_checktype (state, 1, LUA_TLIGHTUSERDATA); + file = lua_touserdata (state, 1); + + lua_pushinteger (state, file->offset); + return 1; +} + +static int +grub_lua_file_eof (lua_State *state) +{ + grub_file_t file; + + luaL_checktype (state, 1, LUA_TLIGHTUSERDATA); + file = lua_touserdata (state, 1); + + lua_pushboolean (state, file->offset >= file->size); + return 1; +} + +static int +grub_lua_file_exist (lua_State *state) +{ + grub_file_t file; + const char *name; + int result; + + result = 0; + name = luaL_checkstring (state, 1); + file = grub_file_open (name); + if (file) + { + result++; + grub_file_close (file); + } + else + grub_errno = 0; + + lua_pushboolean (state, result); + return 1; +} + +static int +grub_lua_add_menu (lua_State *state) +{ + int n; + const char *source; + + source = luaL_checklstring (state, 1, 0); + n = lua_gettop (state) - 1; + if (n > 0) + { + const char **args; + char *p; + int i; + + args = grub_malloc (n * sizeof (args[0])); + if (!args) + return push_result (state); + for (i = 0; i < n; i++) + args[i] = luaL_checkstring (state, 2 + i); + + p = grub_strdup (source); + if (! p) + return push_result (state); + + grub_normal_add_menu_entry (n, args, NULL, NULL, NULL, NULL, NULL, p, 0); + } + else + { + lua_pushstring (state, "not enough parameter"); + lua_error (state); + } + + return push_result (state); +} + +luaL_Reg grub_lua_lib[] = + { + {"run", grub_lua_run}, + {"getenv", grub_lua_getenv}, + {"setenv", grub_lua_setenv}, + {"enum_device", grub_lua_enum_device}, + {"enum_file", grub_lua_enum_file}, +#ifdef ENABLE_LUA_PCI + {"enum_pci", grub_lua_enum_pci}, +#endif + {"file_open", grub_lua_file_open}, + {"file_close", grub_lua_file_close}, + {"file_seek", grub_lua_file_seek}, + {"file_read", grub_lua_file_read}, + {"file_getline", grub_lua_file_getline}, + {"file_getsize", grub_lua_file_getsize}, + {"file_getpos", grub_lua_file_getpos}, + {"file_eof", grub_lua_file_eof}, + {"file_exist", grub_lua_file_exist}, + {"add_menu", grub_lua_add_menu}, + {0, 0} + }; |