From 029a0a9d16553f514f9f71ccea1ead4eebde88b8 Mon Sep 17 00:00:00 2001 From: longpanda Date: Wed, 30 Sep 2026 19:20:12 +0800 Subject: [PATCH] Experimental support for SteamOS recovery images. (#3712 #2875 #1815) --- .../grub-core/commands/efi/efifwsetup.c | 98 ++++++ .../grub-2.04/grub-core/commands/terminal.c | 313 ++++++++++++++++++ .../grub-2.04/grub-core/font/font_cmd.c | 117 +++++++ .../grub-2.04/grub-core/kern/corecmd.c | 5 + .../grub-2.04/grub-core/ventoy/ventoy.c | 43 +++ .../grub-2.04/grub-core/ventoy/ventoy_cmd.c | 37 +++ .../grub-2.04/grub-core/ventoy/ventoy_def.h | 2 + .../ventoy/hook/default/12-dm-ventoy.rules | 1 + IMG/cpio/ventoy/hook/default/ventoy-udev.sh | 22 ++ IMG/cpio/ventoy/hook/gentoo/mats-hook.sh | 32 ++ IMG/cpio/ventoy/hook/ventoy-hook-lib.sh | 110 ++++++ IMG/cpio/ventoy/loop/steamos/ventoy-disk.sh | 119 +++++++ IMG/cpio/ventoy/loop/steamos/ventoy-hook.sh | 33 ++ IMG/cpio/ventoy/loop/steamos/ventoy.hook | 16 + IMG/cpio/ventoy/ventoy_loop.sh | 2 +- INSTALL/grub/grub.cfg | 50 +++ VtoyTool/vtoydm.c | 196 ++++++++++- 17 files changed, 1194 insertions(+), 2 deletions(-) create mode 100644 GRUB2/MOD_SRC/grub-2.04/grub-core/commands/efi/efifwsetup.c create mode 100644 GRUB2/MOD_SRC/grub-2.04/grub-core/commands/terminal.c create mode 100644 GRUB2/MOD_SRC/grub-2.04/grub-core/font/font_cmd.c create mode 100644 IMG/cpio/ventoy/hook/default/12-dm-ventoy.rules create mode 100644 IMG/cpio/ventoy/hook/default/ventoy-udev.sh create mode 100644 IMG/cpio/ventoy/hook/gentoo/mats-hook.sh create mode 100644 IMG/cpio/ventoy/loop/steamos/ventoy-disk.sh create mode 100644 IMG/cpio/ventoy/loop/steamos/ventoy-hook.sh create mode 100644 IMG/cpio/ventoy/loop/steamos/ventoy.hook diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/efi/efifwsetup.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/efi/efifwsetup.c new file mode 100644 index 00000000..86a8751a --- /dev/null +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/efi/efifwsetup.c @@ -0,0 +1,98 @@ +/* fwsetup.c - Reboot into firmware setup menu. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_efi_boolean_t efifwsetup_is_supported (void); + +static grub_err_t +grub_cmd_fwsetup (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + grub_efi_uint64_t *old_os_indications; + grub_efi_uint64_t os_indications = GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI; + grub_err_t status; + grub_size_t oi_size; + grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; + + if (argc >= 1 && grub_strcmp(args[0], "--is-supported") == 0) + return !efifwsetup_is_supported (); + + if (!efifwsetup_is_supported ()) + return grub_error (GRUB_ERR_INVALID_COMMAND, + N_("reboot to firmware setup is not supported by the current firmware")); + + old_os_indications = grub_efi_get_variable ("OsIndications", &global, + &oi_size); + + if (old_os_indications != NULL && oi_size == sizeof (os_indications)) + os_indications |= *old_os_indications; + + status = grub_efi_set_variable ("OsIndications", &global, &os_indications, + sizeof (os_indications)); + if (status != GRUB_ERR_NONE) + return status; + + grub_reboot (); + + return GRUB_ERR_BUG; +} + +static grub_command_t cmd = NULL; + +static grub_efi_boolean_t +efifwsetup_is_supported (void) +{ + grub_efi_uint64_t *os_indications_supported = NULL; + grub_size_t oi_size = 0; + grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; + + os_indications_supported = grub_efi_get_variable ("OsIndicationsSupported", + &global, &oi_size); + + if (!os_indications_supported) + return 0; + + if (*os_indications_supported & GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI) + return 1; + + return 0; +} + +GRUB_MOD_INIT (efifwsetup) +{ + cmd = grub_register_command ("fwsetup", grub_cmd_fwsetup, NULL, + N_("Reboot into firmware setup menu.")); + +} + +GRUB_MOD_FINI (efifwsetup) +{ + if (cmd) + grub_unregister_command (cmd); +} diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/terminal.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/terminal.c new file mode 100644 index 00000000..00a69add --- /dev/null +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/commands/terminal.c @@ -0,0 +1,313 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009,2010 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 . + */ + +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_uint8_t g_terminal_lock = 0; + +struct grub_term_autoload *grub_term_input_autoload = NULL; +struct grub_term_autoload *grub_term_output_autoload = NULL; + +struct abstract_terminal +{ + struct abstract_terminal *next; + struct abstract_terminal *prev; + const char *name; + grub_err_t (*init) (struct abstract_terminal *term); + grub_err_t (*fini) (struct abstract_terminal *term); +}; + +static grub_err_t +handle_command (int argc, char **args, struct abstract_terminal **enabled, + struct abstract_terminal **disabled, + struct grub_term_autoload *autoloads, + const char *active_str, + const char *available_str) +{ + int i; + struct abstract_terminal *term; + struct grub_term_autoload *aut; + + if (argc == 0) + { + grub_puts_ (active_str); + for (term = *enabled; term; term = term->next) + grub_printf ("%s ", term->name); + grub_printf ("\n"); + grub_puts_ (available_str); + for (term = *disabled; term; term = term->next) + grub_printf ("%s ", term->name); + /* This is quadratic but we don't expect mode than 30 terminal + modules ever. */ + for (aut = autoloads; aut; aut = aut->next) + { + for (term = *disabled; term; term = term->next) + if (grub_strcmp (term->name, aut->name) == 0 + || (aut->name[0] && aut->name[grub_strlen (aut->name) - 1] == '*' + && grub_memcmp (term->name, aut->name, + grub_strlen (aut->name) - 1) == 0)) + break; + if (!term) + for (term = *enabled; term; term = term->next) + if (grub_strcmp (term->name, aut->name) == 0 + || (aut->name[0] && aut->name[grub_strlen (aut->name) - 1] == '*' + && grub_memcmp (term->name, aut->name, + grub_strlen (aut->name) - 1) == 0)) + break; + if (!term) + grub_printf ("%s ", aut->name); + } + grub_printf ("\n"); + return GRUB_ERR_NONE; + } + i = 0; + + if (grub_strcmp (args[0], "--append") == 0 + || grub_strcmp (args[0], "--remove") == 0) + i++; + + if (i == argc) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("no terminal specified")); + + for (; i < argc; i++) + { + int again = 0; + while (1) + { + for (term = *disabled; term; term = term->next) + if (grub_strcmp (args[i], term->name) == 0 + || (grub_strcmp (args[i], "ofconsole") == 0 + && grub_strcmp ("console", term->name) == 0)) + break; + if (term == 0) + for (term = *enabled; term; term = term->next) + if (grub_strcmp (args[i], term->name) == 0 + || (grub_strcmp (args[i], "ofconsole") == 0 + && grub_strcmp ("console", term->name) == 0)) + break; + if (term) + break; + if (again) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("terminal `%s' isn't found"), + args[i]); + for (aut = autoloads; aut; aut = aut->next) + if (grub_strcmp (args[i], aut->name) == 0 + || (grub_strcmp (args[i], "ofconsole") == 0 + && grub_strcmp ("console", aut->name) == 0) + || (aut->name[0] && aut->name[grub_strlen (aut->name) - 1] == '*' + && grub_memcmp (args[i], aut->name, + grub_strlen (aut->name) - 1) == 0)) + { + grub_dl_t mod; + mod = grub_dl_load (aut->modname); + if (mod) + grub_dl_ref (mod); + grub_errno = GRUB_ERR_NONE; + break; + } + if (grub_memcmp (args[i], "serial_usb", + sizeof ("serial_usb") - 1) == 0 + && grub_term_poll_usb) + { + grub_term_poll_usb (1); + again = 1; + continue; + } + if (!aut) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("terminal `%s' isn't found"), + args[i]); + again = 1; + } + } + + if (grub_strcmp (args[0], "--append") == 0) + { + for (i = 1; i < argc; i++) + { + for (term = *disabled; term; term = term->next) + if (grub_strcmp (args[i], term->name) == 0 + || (grub_strcmp (args[i], "ofconsole") == 0 + && grub_strcmp ("console", term->name) == 0)) + break; + if (term) + { + if (term->init && term->init (term) != GRUB_ERR_NONE) + return grub_errno; + + grub_list_remove (GRUB_AS_LIST (term)); + grub_list_push (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term)); + } + } + return GRUB_ERR_NONE; + } + + if (grub_strcmp (args[0], "--remove") == 0) + { + for (i = 1; i < argc; i++) + { + for (term = *enabled; term; term = term->next) + if (grub_strcmp (args[i], term->name) == 0 + || (grub_strcmp (args[i], "ofconsole") == 0 + && grub_strcmp ("console", term->name) == 0)) + break; + if (term) + { + if (!term->next && term == *enabled) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "can't remove the last terminal"); + grub_list_remove (GRUB_AS_LIST (term)); + if (term->fini) + term->fini (term); + grub_list_push (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term)); + } + } + return GRUB_ERR_NONE; + } + for (i = 0; i < argc; i++) + { + for (term = *disabled; term; term = term->next) + if (grub_strcmp (args[i], term->name) == 0 + || (grub_strcmp (args[i], "ofconsole") == 0 + && grub_strcmp ("console", term->name) == 0)) + break; + if (term) + { + if (term->init && term->init (term) != GRUB_ERR_NONE) + return grub_errno; + + grub_list_remove (GRUB_AS_LIST (term)); + grub_list_push (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term)); + } + } + + { + struct abstract_terminal *next; + for (term = *enabled; term; term = next) + { + next = term->next; + for (i = 0; i < argc; i++) + if (grub_strcmp (args[i], term->name) == 0 + || (grub_strcmp (args[i], "ofconsole") == 0 + && grub_strcmp ("console", term->name) == 0)) + break; + if (i == argc) + { + if (!term->next && term == *enabled) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "can't remove the last terminal"); + grub_list_remove (GRUB_AS_LIST (term)); + if (term->fini) + term->fini (term); + grub_list_push (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term)); + } + } + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_terminal_lock (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + (void)argc; + (void)args; + + if (args[0] && args[0][0] == '1') + g_terminal_lock = 1; + else + g_terminal_lock = 0; + + return 0; +} + +static grub_err_t +grub_cmd_terminal_input (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + (void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, next); + (void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, prev); + (void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, name); + (void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, init); + (void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, fini); + + if (g_terminal_lock) return 0; + + return handle_command (argc, args, + (struct abstract_terminal **) (void *) &grub_term_inputs, + (struct abstract_terminal **) (void *) &grub_term_inputs_disabled, + grub_term_input_autoload, + N_ ("Active input terminals:"), + N_ ("Available input terminals:")); +} + +static grub_err_t +grub_cmd_terminal_output (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + (void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, next); + (void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, prev); + (void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, name); + (void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, init); + (void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, fini); + + if (g_terminal_lock) return 0; + + return handle_command (argc, args, + (struct abstract_terminal **) (void *) &grub_term_outputs, + (struct abstract_terminal **) (void *) &grub_term_outputs_disabled, + grub_term_output_autoload, + N_ ("Active output terminals:"), + N_ ("Available output terminals:")); +} + +static grub_command_t cmd_terminal_input, cmd_terminal_output, cmd_lock_terminal; + +GRUB_MOD_INIT(terminal) +{ + cmd_lock_terminal = + grub_register_command ("terminal_lock", grub_cmd_terminal_lock, + 0, N_("lock terminal.")); + + cmd_terminal_input = + grub_register_command ("terminal_input", grub_cmd_terminal_input, + N_("[--append|--remove] " + "[TERMINAL1] [TERMINAL2] ..."), + N_("List or select an input terminal.")); + cmd_terminal_output = + grub_register_command ("terminal_output", grub_cmd_terminal_output, + N_("[--append|--remove] " + "[TERMINAL1] [TERMINAL2] ..."), + N_("List or select an output terminal.")); +} + +GRUB_MOD_FINI(terminal) +{ + grub_unregister_command (cmd_lock_terminal); + grub_unregister_command (cmd_terminal_input); + grub_unregister_command (cmd_terminal_output); +} diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/font/font_cmd.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/font/font_cmd.c new file mode 100644 index 00000000..d573c1b6 --- /dev/null +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/font/font_cmd.c @@ -0,0 +1,117 @@ +/* font_cmd.c - Font command definition. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2005,2006,2007,2008,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 . + */ + +#include +#include +#include +#include +#include + +static grub_uint8_t g_font_lock = 0; + +static grub_err_t +loadfont_command (grub_command_t cmd __attribute__ ((unused)), + int argc, + char **args) +{ + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + + if (g_font_lock) return 0; + + while (argc--) + if (grub_font_load (*args++) == 0) + { + if (!grub_errno) + return grub_error (GRUB_ERR_BAD_FONT, "invalid font"); + return grub_errno; + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +lsfonts_command (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + struct grub_font_node *node; + + grub_puts_ (N_("Loaded fonts:")); + for (node = grub_font_list; node; node = node->next) + { + grub_font_t font = node->value; + grub_printf ("%s\n", grub_font_get_name (font)); + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +lockfont_command (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + if (args[0] && args[0][0] == '1') + { + g_font_lock = 1; + } + else + { + g_font_lock = 0; + } + + return GRUB_ERR_NONE; +} + +static grub_command_t cmd_loadfont, cmd_lsfonts, cmd_lockfont; + +#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_COREBOOT) +void grub_font_init (void) +#else +GRUB_MOD_INIT(font) +#endif +{ + grub_font_loader_init (); + + cmd_loadfont = + grub_register_command ("loadfont", loadfont_command, + N_("FILE..."), + N_("Specify one or more font files to load.")); + cmd_lsfonts = + grub_register_command ("lsfonts", lsfonts_command, + 0, N_("List the loaded fonts.")); + cmd_lockfont = + grub_register_command ("lockfont", lockfont_command, + 0, N_("Lock fonts.")); +} + +#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_COREBOOT) +void grub_font_fini (void) +#else +GRUB_MOD_FINI(font) +#endif +{ + /* TODO: Determine way to free allocated resources. + Warning: possible pointer references could be in use. */ + + grub_unregister_command (cmd_loadfont); + grub_unregister_command (cmd_lsfonts); + grub_unregister_command (cmd_lockfont); +} diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/corecmd.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/corecmd.c index 69c85d03..d3740bc9 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/corecmd.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/kern/corecmd.c @@ -84,6 +84,11 @@ grub_core_cmd_insmod (struct grub_command *cmd __attribute__ ((unused)), return grub_error (GRUB_ERR_BAD_SIGNATURE, "Cannot insmod when SecureBoot is enabled and Policy is check."); } + if (grub_strcmp(argv[0], "steamenv") == 0) { + grub_printf("Ventoy skip module steamenv ...\n"); + return 0; + } + if (argv[0][0] == '/' || argv[0][0] == '(' || argv[0][0] == '+') mod = grub_dl_load_file (argv[0]); else diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c index f48c68df..42050635 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c @@ -49,6 +49,10 @@ int g_ventoy_debug = 0; static int g_efi_os = 0xFF; grub_uint32_t g_ventoy_plat_data; +static grub_uint8_t g_timeout_lock = 0; +static grub_uint8_t g_theme_lock = 0; +static char *g_lock_theme = NULL; + #ifdef GRUB_MACHINE_EFI static VTOY_SHIM *g_vtoy_shim = NULL; #endif @@ -236,6 +240,29 @@ int ventoy_strncmp (const char *pattern, const char *str, grub_size_t n) return (int)(grub_uint8_t)*pattern - (int)(grub_uint8_t)*str; } +void ventoy_timeout_lock(int lock) +{ + g_timeout_lock = lock ? 1 : 0; +} + +void ventoy_theme_lock(int lock) +{ + const char *env = NULL; + + g_theme_lock = 0; + grub_check_free(g_lock_theme); + + if (lock) + { + env = grub_env_get("theme"); + if (env) + { + g_lock_theme = grub_strdup(env); + g_theme_lock = 1; + } + } +} + grub_err_t ventoy_env_int_set(const char *name, int value) { char buf[16]; @@ -553,6 +580,19 @@ static char * ventoy_global_var_write_hook(struct grub_env_var *var, const char return grub_strdup(val); } +static char * ventoy_timeout_write_hook(struct grub_env_var *var, const char *val) +{ + (void)var; + return grub_strdup(g_timeout_lock ? "-1" : val); +} + +static char * ventoy_theme_write_hook(struct grub_env_var *var, const char *val) +{ + (void)var; + return grub_strdup(g_theme_lock ? g_lock_theme : val); +} + + int ventoy_global_var_init(void) { int i; @@ -564,6 +604,9 @@ int ventoy_global_var_init(void) grub_register_variable_hook(g_global_vars[i].name, ventoy_global_var_read_hook, ventoy_global_var_write_hook); } + grub_register_variable_hook("timeout", NULL, ventoy_timeout_write_hook); + grub_register_variable_hook("theme", NULL, ventoy_theme_write_hook); + return 0; } diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c index 790ffb53..969171fe 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c @@ -6449,6 +6449,40 @@ static grub_err_t ventoy_cmd_update_sb_policy(grub_extcmd_context_t ctxt, int ar VENTOY_CMD_RETURN(0); } +static grub_err_t ventoy_cmd_timeout_lock(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + + if (args[0] && args[0][0] == '1') + { + ventoy_timeout_lock(1); + } + else + { + ventoy_timeout_lock(0); + } + + VENTOY_CMD_RETURN(0); +} + +static grub_err_t ventoy_cmd_theme_lock(grub_extcmd_context_t ctxt, int argc, char **args) +{ + (void)ctxt; + (void)argc; + + if (args[0] && args[0][0] == '1') + { + ventoy_theme_lock(1); + } + else + { + ventoy_theme_lock(0); + } + + VENTOY_CMD_RETURN(0); +} + static grub_err_t ventoy_cmd_sb_info(grub_extcmd_context_t ctxt, int argc, char **args) { (void)ctxt; @@ -7140,6 +7174,9 @@ static cmd_para ventoy_cmds[] = { "vt_sbinfo", ventoy_cmd_sb_info, 0, NULL, "", "", NULL }, { "vt_update_sb_policy", ventoy_cmd_update_sb_policy, 0, NULL, "", "", NULL }, + { "vt_timeout_lock", ventoy_cmd_timeout_lock, 0, NULL, "", "", NULL }, + { "vt_theme_lock", ventoy_cmd_theme_lock, 0, NULL, "", "", NULL }, + }; int ventoy_register_all_cmd(void) diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h index 22ece47a..bd08797e 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h @@ -661,6 +661,8 @@ int ventoy_str_all_digit(const char *str); int ventoy_str_all_alnum(const char *str); int ventoy_str_len_alnum(const char *str, int len); char * ventoy_str_basename(char *path); +void ventoy_timeout_lock(int lock); +void ventoy_theme_lock(int lock); grub_err_t ventoy_env_int_set(const char *name, int value); int ventoy_str_chrcnt(const char *str, char c); int ventoy_strcmp(const char *pattern, const char *str); diff --git a/IMG/cpio/ventoy/hook/default/12-dm-ventoy.rules b/IMG/cpio/ventoy/hook/default/12-dm-ventoy.rules new file mode 100644 index 00000000..01c97883 --- /dev/null +++ b/IMG/cpio/ventoy/hook/default/12-dm-ventoy.rules @@ -0,0 +1 @@ +ACTION=="add|change", KERNEL=="dm-[0-9]*", ENV{DM_NAME}=="ventoy[0-9]*", ENV{DM_UDEV_DISABLE_SYBSYSTEM_RULES_FLAG}="", ENV{DM_UDEV_DISABLE_DISK_RULES_FLAG}="", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="", IMPORT{program}="/ventoy/hook/default/ventoy-udev.sh $env{DM_NAME}" diff --git a/IMG/cpio/ventoy/hook/default/ventoy-udev.sh b/IMG/cpio/ventoy/hook/default/ventoy-udev.sh new file mode 100644 index 00000000..009ab9c9 --- /dev/null +++ b/IMG/cpio/ventoy/hook/default/ventoy-udev.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +PATH=$PATH:/ventoy/busybox:/ventoy/tool + +echo "$@" >> /ventoy/log + +VT_DMNAME=$1 +VT_PART_NUM="${VT_DMNAME#*ventoy}" +VT_PARENT_DEV="/dev/mapper/ventoy" +VT_PARTUUID= + +[ -b "$VT_PARENT_DEV" ] || exit 0 + +VT_PARTUUID=$(/ventoy/tool/vtoygpt $VT_PARENT_DEV $VT_PART_NUM | awk '{print $2}') + +echo "$VT_DMNAME PARTUUID=$VT_PARTUUID" >> /ventoy/log + +if [ -n "$VT_PARTUUID" ]; then + echo "ID_PART_ENTRY_UUID=$VT_PARTUUID" + echo "ID_PART_ENTRY_NUMBER=$VT_PART_NUM" + echo "ID_PART_ENTRY_SCHEME=gpt" +fi diff --git a/IMG/cpio/ventoy/hook/gentoo/mats-hook.sh b/IMG/cpio/ventoy/hook/gentoo/mats-hook.sh new file mode 100644 index 00000000..209a6ada --- /dev/null +++ b/IMG/cpio/ventoy/hook/gentoo/mats-hook.sh @@ -0,0 +1,32 @@ +#!/ventoy/busybox/sh + +. /ventoy/hook/ventoy-hook-lib.sh + +VTPATH_OLD=$PATH; PATH=$BUSYBOX_PATH:$VTOY_PATH/tool:$PATH + +for i in 0 1 2 3 4 5 6 7 8 9; do + vtdiskname=$(get_ventoy_disk_name) + if [ "$vtdiskname" = "unknown" ]; then + vtlog "wait for disk ..." + $SLEEP 2 + else + break + fi +done + +echo '############ Copy ISO file to memory ... ###############' + +vtoydm -C -f $VTOY_PATH/ventoy_image_map -d $vtdiskname -o $VTOY_PATH/dump.iso + +[ -d /ventoy/tmpmnt ] || mkdir /ventoy/tmpmnt + +mount /ventoy/dump.iso /ventoy/tmpmnt +cp -a /ventoy/tmpmnt/* $1/ + +umount /ventoy/tmpmnt +rm -f /ventoy/dump.iso + +echo '############ Copy ISO file to memory finished OK ###############' +sleep 2 + +PATH=$VTPATH_OLD diff --git a/IMG/cpio/ventoy/hook/ventoy-hook-lib.sh b/IMG/cpio/ventoy/hook/ventoy-hook-lib.sh index b31f8528..e7708c40 100644 --- a/IMG/cpio/ventoy/hook/ventoy-hook-lib.sh +++ b/IMG/cpio/ventoy/hook/ventoy-hook-lib.sh @@ -280,6 +280,37 @@ create_ventoy_device_mapper() { #echo "$VT_DM_BIN ls" >> /ventoy/ventoy_iso_part_dm_cmd } +create_ventoy_wrapper_device_mapper() { + vtlog "create_ventoy_wrapper_device_mapper $*" + + VT_DM_BIN=$(ventoy_find_bin_path dmsetup) + if [ -z "$VT_DM_BIN" ]; then + vtlog "no dmsetup avaliable, lastly try inbox dmsetup" + VT_DM_BIN=$VTOY_PATH/tool/dmsetup + fi + + vtlog "dmsetup avaliable in system $VT_DM_BIN" + + if ventoy_check_dm_module "$1"; then + vtlog "device-mapper module check success" + else + vterr "Error: no dm module avaliable" + fi + + $VTOY_PATH/tool/vtoydm -w -f $VTOY_PATH/ventoy_image_map -d $1 > $VTOY_PATH/ventoy_dm_table + + VT_LOOP_DEV=$(losetup -f) + losetup $VT_LOOP_DEV /ventoy/dmwrapper.bin + $SED "s#/dev/loop0#$VT_LOOP_DEV#" -i $VTOY_PATH/ventoy_dm_table + + + if [ -z "$2" ]; then + $VT_DM_BIN create ventoy $VTOY_PATH/ventoy_dm_table >>$VTLOG 2>&1 + else + $VT_DM_BIN "$2" create ventoy $VTOY_PATH/ventoy_dm_table >>$VTLOG 2>&1 + fi +} + create_persistent_device_mapper() { vtlog "create_persistent_device_mapper $*" @@ -597,6 +628,57 @@ ventoy_udev_disk_common_hook() { fi } +ventoy_create_wrapper_dm() { + if echo $1 | $EGREP -q "nvme.*p[0-9]$|mmc.*p[0-9]$|nbd.*p[0-9]$"; then + VTDISK="${1:0:-2}" + else + VTDISK="${1:0:-1}" + fi + + if [ -e /vtoy/vtoy ]; then + VTRWMOD="" + else + VTRWMOD="--readonly" + fi + + # create device mapper for iso image file + if create_ventoy_wrapper_device_mapper "/dev/$VTDISK" $VTRWMOD; then + vtlog "==== create wrapper ventoy device mapper success ====" + else + vtlog "==== create wrapper ventoy device mapper failed ====" + + $SLEEP 3 + + if $GREP -q "/dev/$VTDISK" /proc/mounts; then + $GREP "/dev/$VTDISK" /proc/mounts | while read vtLine; do + vtPart=$(echo $vtLine | $AWK '{print $1}') + vtMnt=$(echo $vtLine | $AWK '{print $2}') + vtlog "$vtPart is mounted on $vtMnt now umount it ..." + $BUSYBOX_PATH/umount $vtMnt + done + fi + + if create_ventoy_wrapper_device_mapper "/dev/$VTDISK" $VTRWMOD; then + vtlog "==== create wrapper ventoy device mapper success after retry ====" + else + vtlog "==== create wrapper ventoy device mapper failed after retry ====" + return + fi + fi + + if [ "$2" = "noreplace" ]; then + vtlog "no need to replace block device" + else + ventoy_copy_device_mapper "/dev/$1" + fi + + if [ -f $VTOY_PATH/ventoy_persistent_map ]; then + create_persistent_device_mapper "/dev/$VTDISK" + ventoy_create_persistent_link + fi +} + + ventoy_create_dev_ventoy_part() { blkdev_num=$($VTOY_PATH/tool/dmsetup ls | $GREP ventoy | $SED 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1 \2/') $BUSYBOX_PATH/mknod -m 0666 /dev/ventoy b $blkdev_num @@ -616,6 +698,34 @@ ventoy_create_dev_ventoy_part() { } +ventoy_remove_all_dm() { + if [ -e /vtoy_dm_table ]; then + vtPartid=1 + $CAT /vtoy_dm_table | while read vtline; do + vtlog "dmsetup remove ventoy${vtPartid}" + $VTOY_PATH/tool/dmsetup remove ventoy${vtPartid} + vtPartid=$(expr $vtPartid + 1) + done + fi + + vtlog "dmsetup remove ventoy" + $VTOY_PATH/tool/dmsetup remove ventoy + rm -f /dev/ventoy* + + if [ -e $VTOY_PATH/ventoy_raw_table ]; then + RAWDISKNAME=$($HEAD -n1 $VTOY_PATH/ventoy_raw_table | $AWK '{print $4}') + vtlog "dmsetup remove ${RAWDISKNAME#/dev/}" + $VTOY_PATH/tool/dmsetup remove ${RAWDISKNAME#/dev/} + rm -f $VTOY_PATH/ventoy_iso_part_dm_cmd + fi + + if [ -e $VTOY_PATH/persistent_dm_table ]; then + vtlog "dmsetup remove vtoy_persistent" + $VTOY_PATH/tool/dmsetup remove vtoy_persistent + fi +} + + ventoy_create_chromeos_ventoy_part() { blkdev_num=$($VTOY_PATH/tool/dmsetup ls | $GREP ventoy | $SED 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1 \2/') $BUSYBOX_PATH/mknod -m 0666 /dev/ventoy b $blkdev_num diff --git a/IMG/cpio/ventoy/loop/steamos/ventoy-disk.sh b/IMG/cpio/ventoy/loop/steamos/ventoy-disk.sh new file mode 100644 index 00000000..3f9cb965 --- /dev/null +++ b/IMG/cpio/ventoy/loop/steamos/ventoy-disk.sh @@ -0,0 +1,119 @@ +#!/ventoy/busybox/sh +#************************************************************************************ +# Copyright (c) 2020, longpanda +# +# This program 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. +# +# This program 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 this program; if not, see . +# +#************************************************************************************ + +. /ventoy/hook/ventoy-hook-lib.sh + +if is_ventoy_hook_finished; then + exit 0 +fi + +vtlog "####### $0 $* ########" + +VTPATH_OLD=$PATH; PATH=$BUSYBOX_PATH:$VTOY_PATH/tool:$PATH + +wait_for_usb_disk_ready + +vtdiskname=$(get_ventoy_disk_name) +if [ "$vtdiskname" = "unknown" ]; then + vtlog "ventoy disk not found" + exit 0 +fi + +/usr/bin/insmod $VTOY_PATH/modules/dm-mod.ko* + +ventoy_udev_disk_common_hook "${vtdiskname#/dev/}2" "noreplace" +ventoy_create_dev_ventoy_part + + +mkdir -p /ventoy/tmpmnt +mount /dev/ventoy3 /ventoy/tmpmnt +mount --bind /ventoy/tmpmnt/lib/modules /lib/modules + +for mod in loop iso9660 ntfs ntfs3 exfat ext2 ext3 ext4 xfs btrfs; do + vtlog "modprobe $mod" + /usr/bin/modprobe $mod >> $VTLOG 2>&1 +done + +umount /lib/modules +umount /ventoy/tmpmnt + +ventoy_remove_all_dm + + +vtimgname=$(get_ventoy_iso_name) +if [ "$vtimgname" = "unknown" -o -z "$vtimgname" ]; then + vterr "image file path not found" + exit 0 +fi + +if echo "$vtdiskname" | $EGREP -q "nvme|mmc|nbd"; then + vtdatapart=${vtdiskname}p1 +else + vtdatapart=${vtdiskname}1 +fi + +# rw: the holo hook mounts the image rootfs rw +mkdir -p /run/ventoy-media + +if mount "$vtdatapart" /run/ventoy-media >>$VTLOG 2>&1; then + vtlog "mounted $vtdatapart at /run/ventoy-media OK" + mount | grep ventoy >>$VTLOG 2>&1 +else + vtlog "mounted $vtdatapart at /run/ventoy-media failed" + exit 0 +fi + + +vtimgfile="/run/ventoy-media${vtimgname}" +if ! [ -f "$vtimgfile" ]; then + vterr "$vtimgfile not found on data partition" + umount /run/ventoy-media >>$VTLOG 2>&1 + exit 0 +fi + + +vtloopdev=$(losetup -f) +if [ -z "$vtloopdev" ]; then + vterr "no free loop device" + exit 0 +fi + +if ! losetup -P "$vtloopdev" "$vtimgfile" >>$VTLOG 2>&1; then + vterr "losetup $vtloopdev $vtimgfile failed" + exit 0 +fi +vtlog "attached $vtimgfile to $vtloopdev" + +vtloop=0 +while ! [ -e "${vtloopdev}p2" ]; do + let vtloop=vtloop+1 + if [ $vtloop -gt 10 ]; then + break + fi + $SLEEP 0.3 +done + +# exact /dev path avoids PARTLABEL/LABEL/UUID collisions with an installed SteamOS +if [ -e "${vtloopdev}p2" ]; then + ln -s "${vtloopdev}p2" /dev/steamos-media-efi + vtlog "/dev/steamos-media-efi -> ${vtloopdev}p2" +else + vterr "${vtloopdev}p2 not created, partition scan failed" +fi + diff --git a/IMG/cpio/ventoy/loop/steamos/ventoy-hook.sh b/IMG/cpio/ventoy/loop/steamos/ventoy-hook.sh new file mode 100644 index 00000000..764cdf5a --- /dev/null +++ b/IMG/cpio/ventoy/loop/steamos/ventoy-hook.sh @@ -0,0 +1,33 @@ +#!/ventoy/busybox/sh +#************************************************************************************ +# Copyright (c) 2020, longpanda +# +# This program 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. +# +# This program 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 this program; if not, see . +# +#************************************************************************************ + +. $VTOY_PATH/hook/ventoy-os-lib.sh + +# inject the disk hook before the run_hook phase of the stock mkinitcpio /init +# if $GREP -q "run_hookfunctions 'run_hook' 'hook'" /init; then + # echo "insert ventoy-disk.sh before run_hook" >> $VTLOG + # $SED "/run_hookfunctions 'run_hook' 'hook'/i\\$BUSYBOX_PATH/sh $VTOY_PATH/loop/steamos/ventoy-disk-new.sh" -i /init +# else + # echo "run_hook anchor not found in /init" >> $VTLOG +# fi + + +$SED "s/udev /udev ventoy /g" -i /config + +cp -a $VTOY_PATH/loop/steamos/ventoy.hook /hooks/ventoy diff --git a/IMG/cpio/ventoy/loop/steamos/ventoy.hook b/IMG/cpio/ventoy/loop/steamos/ventoy.hook new file mode 100644 index 00000000..d0b695c3 --- /dev/null +++ b/IMG/cpio/ventoy/loop/steamos/ventoy.hook @@ -0,0 +1,16 @@ +#!/usr/bin/ash + +run_earlyhook() { + : +} + +run_hook() { + msg ":: Ventoy hook..." + /ventoy/busybox/sh /ventoy/loop/steamos/ventoy-disk.sh +} + +run_cleanuphook() { + : +} + +# vim: set ft=sh ts=4 sw=4 et: diff --git a/IMG/cpio/ventoy/ventoy_loop.sh b/IMG/cpio/ventoy/ventoy_loop.sh index 532faaaf..62527cbc 100644 --- a/IMG/cpio/ventoy/ventoy_loop.sh +++ b/IMG/cpio/ventoy/ventoy_loop.sh @@ -43,7 +43,7 @@ done # # #################################################################### $BUSYBOX_PATH/mkdir -p /ventoy/modules -$BUSYBOX_PATH/ls -1a / | $EGREP '\.ko$|\.ko.[gx]z$' | while read vtline; do +$BUSYBOX_PATH/ls -1a / | $EGREP '\.ko$|\.ko.[gx]z$|\.ko.zst$' | while read vtline; do if [ "${vtline:0:1}" = "." ]; then $BUSYBOX_PATH/mv /${vtline} /ventoy/modules/${vtline:1} else diff --git a/INSTALL/grub/grub.cfg b/INSTALL/grub/grub.cfg index f66cce8c..590d85a8 100644 --- a/INSTALL/grub/grub.cfg +++ b/INSTALL/grub/grub.cfg @@ -50,6 +50,13 @@ function ventoy_gui_console { fi } +function ventoy_cfg_theme_lock { + vt_timeout_lock $1 + vt_theme_lock $1 + terminal_lock $1 + lockfont $1 +} + function ventoy_acpi_param { if [ "$VTOY_PARAM_NO_ACPI" != "1" ]; then vt_acpi_param "$1" "$2" @@ -1997,6 +2004,47 @@ function ventoy_img_freedombox { vt_unset_boot_opt } +function steamenv_init { + echo "dummy steamenv_boot" +} + +function steamenv_boot { + if [ -n "${vtdebug_flag}" ]; then + $1 $2 loglevel=7 + else + $@ + fi +} + + +function ventoy_img_steamos { + vt_load_cpio $vtoy_path "${vt_chosen_path}" ${vtoy_iso_part} "busybox=$ventoy_busybox_ver" + vt_trailer_cpio ${vtoy_iso_part} "${vt_chosen_path}" noinit + + vt_get_lib_module_ver (vtimghd,3) /lib/modules/ vt_module_ver + if [ -n "$vt_module_ver" ]; then + vt_img_extra_initrd_append (vtimghd,3)/lib/modules/$vt_module_ver/kernel/drivers/md/dm-mod + fi + + ventoy_debug_pause + + #boot image file + vt_set_boot_opt rdinit=/vtoy/vtoy ventoyos=steamos steamos.efi=/dev/steamos-media-efi + vt_img_hook_root + + set theme=$vtback_theme + ventoy_gui_console + ventoy_cfg_theme_lock 1 + + configfile (vtimghd,2)/EFI/steamos/grub.cfg + + ventoy_cfg_theme_lock 0 + + vt_img_unhook_root + vt_unset_boot_opt +} + + function ventoy_img_paldo { vt_load_cpio $vtoy_path "${vt_chosen_path}" ${vtoy_iso_part} "busybox=$ventoy_busybox_ver" vt_trailer_cpio ${vtoy_iso_part} "${vt_chosen_path}" noinit @@ -2376,6 +2424,8 @@ function img_common_menuentry { ventoy_img_recalbox elif [ "$vtImgHd1Label" = "ESYSRESCUE" ]; then ventoy_img_esysrescue + elif [ -e (vtimghd,1)/SteamOS ]; then + ventoy_img_steamos elif [ -e (vtimghd,1)/easy.sfs ]; then ventoy_img_easyos elif [ -d (vtimghd,2)/easyos ]; then diff --git a/VtoyTool/vtoydm.c b/VtoyTool/vtoydm.c index 6da6896a..10f9e9f3 100644 --- a/VtoyTool/vtoydm.c +++ b/VtoyTool/vtoydm.c @@ -70,6 +70,7 @@ static int verbose = 0; #define CMD_PRINT_EXTRACT_ISO_FILE 5 #define CMD_PRINT_RAW_TABLE 6 #define CMD_COPY_ISO 7 +#define CMD_PRINT_WRAP_TABLE 8 static uint64_t g_iso_file_size; static char g_disk_name[128]; @@ -789,6 +790,191 @@ static int vtoydm_print_raw_linear_table(const char *img_map_file, const char *d return 0; } +static int vtoydm_print_wrap_linear_table(const char *img_map_file, const char *diskname, int part, uint64_t offset) +{ + int i; + int len; + int cnt; + uint64_t sector_num = 0; + uint64_t iso_file_size = 0; + uint32_t dir_rec_secs = 0; + uint32_t curr_offset = 0; + uint32_t dir_entry_cnt = 0; + uint32_t head_sector_num = 0; + uint32_t uiCurrExtent = 0; + uint32_t iso_sector_num = 0; + uint32_t disk_sector_num; + uint32_t sector_start; + ventoy_img_chunk *chunk = NULL; + uint8_t *pucBuf = NULL; + FILE *pstFile = NULL; + BISO_PVD_S *pstPVD = NULL; + BISO_VD_S *pstEVD = NULL; + BISO_DIR_RECORD_S *pstRecord = NULL; + + chunk = vtoydm_get_img_map_data(img_map_file, &len); + if (NULL == chunk) + { + return 1; + } + + cnt = len / sizeof(ventoy_img_chunk); + for (i = 0; i < cnt; i++) + { + sector_num = chunk[i].img_end_sector - chunk[i].img_start_sector + 1; + iso_file_size += sector_num * 2048; + } + + + iso_sector_num = (uint32_t)(iso_file_size / 2048); + dir_entry_cnt = (uint32_t)((iso_file_size + (0xFFFFF800 - 1)) / 0xFFFFF800); + head_sector_num = 16 + 2 + dir_entry_cnt / (2048 / 46) + 2; + + debug("Total iso file size: %llu iso sectors:%u dir record cnt:%u, header sectors:%u\n", + (_ULL)iso_file_size, iso_sector_num, dir_entry_cnt, head_sector_num); + + pucBuf = (uint8_t *)malloc(head_sector_num * 2048); + if (!pucBuf) + { + free(chunk); + return 1; + } + memset(pucBuf, 0, head_sector_num * 2048); + + /* Fill PVD */ + pstPVD = (BISO_PVD_S *)(pucBuf + 0x8000); + pstPVD->ucType = BISO_VD_TYPE_PVD; + memcpy(pstPVD->szId, BISO_VD_ID, 5); + pstPVD->ucVersion = 1; + memset(pstPVD->szSystemId, ' ', sizeof(pstPVD->szSystemId)); + memset(pstPVD->szVolumeSetId, ' ', sizeof(pstPVD->szVolumeSetId)); + memset(pstPVD->szPublisherId, ' ', sizeof(pstPVD->szPublisherId)); + memset(pstPVD->szPreparerId, ' ', sizeof(pstPVD->szPreparerId)); + memset(pstPVD->szApplicationId, ' ', sizeof(pstPVD->szApplicationId)); + memset(pstPVD->szCopyrightFileId, ' ', sizeof(pstPVD->szCopyrightFileId)); + memset(pstPVD->szAbstractFileId, ' ', sizeof(pstPVD->szAbstractFileId)); + memset(pstPVD->szBibliographicFileId, ' ', sizeof(pstPVD->szBibliographicFileId)); + memset(pstPVD->szCreationDate, '0', sizeof(pstPVD->szCreationDate)); + memset(pstPVD->szModifyDate, '0', sizeof(pstPVD->szModifyDate)); + memset(pstPVD->szExpirationDate, '0', sizeof(pstPVD->szExpirationDate)); + memset(pstPVD->szEffectiveDate, '0', sizeof(pstPVD->szEffectiveDate)); + + memset(pstPVD->szVolumeId, ' ', sizeof(pstPVD->szVolumeId)); + memcpy(pstPVD->szVolumeId, "Ventoy", 6); + memcpy(pstPVD->szPublisherId, "VENTOY", 6); + memcpy(pstPVD->szPreparerId, "https://www.ventoy.net", 22); + + BISO_FILL_733(pstPVD->uiVolumeSpace, head_sector_num + iso_sector_num); + BISO_FILL_723(pstPVD->usVolumeSet, 1); + BISO_FILL_723(pstPVD->usVolumeSeq, 1); + BISO_FILL_723(pstPVD->usBlockSize, 2048); + + pstPVD->stRootDirRecord.ucLength = 34; + pstPVD->stRootDirRecord.ucExtAttrLen = 0; + + BISO_FILL_733(pstPVD->stRootDirRecord.uiExtent, 0x12); + pstPVD->stRootDirRecord.ucFlags = 2; + BISO_FILL_723(pstPVD->stRootDirRecord.uiVolumeSeqNum, 1); + pstPVD->stRootDirRecord.ucNameLen = 1; + + /* End VD */ + pstEVD = (BISO_VD_S *)(pucBuf + 0x8800); + pstEVD->ucType = BISO_VD_TYPE_END; + memcpy(pstEVD->szId, BISO_VD_ID, 5); + pstEVD->ucVersion = 1; + + + /* Fill Dir Record */ + pstRecord = (BISO_DIR_RECORD_S *)(pucBuf + 0x9000 + 2 * sizeof(BISO_DIR_RECORD_S)); + uiCurrExtent = head_sector_num; + curr_offset = sizeof(BISO_DIR_RECORD_S) * 2; + dir_rec_secs = 1; + + while (iso_file_size > 0) + { + pstRecord->ucLength = 46; + BISO_FILL_733(pstRecord->uiExtent, uiCurrExtent); + BISO_FILL_723(pstRecord->uiVolumeSeqNum, 1); + pstRecord->ucNameLen = 12; + memcpy(pstRecord->szName, "ventoy.raw;1", 12); + + if (iso_file_size > 0xFFFFF800) + { + pstRecord->ucFlags = 0x80; + BISO_FILL_733(pstRecord->uiSize, 0xFFFFF800); + uiCurrExtent += 0xFFFFF800 / 2048; + iso_file_size -= 0xFFFFF800; + + + pstRecord = (BISO_DIR_RECORD_S *)((char *)pstRecord + 46); + curr_offset += 46; + + if (curr_offset > (2048 - 46)) + { + pstRecord = (BISO_DIR_RECORD_S *)((char *)pstRecord + (2048 - curr_offset)); + curr_offset = 0; + dir_rec_secs++; + } + } + else + { + pstRecord->ucFlags = 0x00; + BISO_FILL_733(pstRecord->uiSize, iso_file_size); + break; + } + } + + + BISO_FILL_733(pstPVD->stRootDirRecord.uiSize, dir_rec_secs * 2048); + pstRecord = (BISO_DIR_RECORD_S *)(pucBuf + 0x9000); + memcpy(pstRecord, &pstPVD->stRootDirRecord, sizeof(BISO_DIR_RECORD_S)); + + pstRecord++; + memcpy(pstRecord, &pstPVD->stRootDirRecord, sizeof(BISO_DIR_RECORD_S)); + pstRecord->szName[0] = 0x01; + + + pstFile = fopen("/ventoy/dmwrapper.bin", "wb+"); + if (pstFile) + { + fwrite(pucBuf, 2048, head_sector_num, pstFile); + fclose(pstFile); + } + + printf("0 %u linear /dev/loop0 0\n", head_sector_num * 4); + + for (i = 0; i < len / sizeof(ventoy_img_chunk); i++) + { + sector_start = chunk[i].img_start_sector + head_sector_num; + disk_sector_num = (uint32_t)(chunk[i].disk_end_sector + 1 - chunk[i].disk_start_sector); + + /* TBD: to be more flexible */ + #if 0 + printf("%u %u linear %s %llu\n", + (sector_start << 2), disk_sector_num, + diskname, (unsigned long long)chunk[i].disk_start_sector); + #else + if (strstr(diskname, "nvme") || strstr(diskname, "mmc") || strstr(diskname, "nbd")) + { + printf("%u %u linear %sp%d %llu\n", + (sector_start << 2), disk_sector_num, + diskname, part, (unsigned long long)chunk[i].disk_start_sector - offset); + } + else + { + printf("%u %u linear %s%d %llu\n", + (sector_start << 2), disk_sector_num, + diskname, part, (unsigned long long)chunk[i].disk_start_sector - offset); + } + #endif + } + + free(chunk); + free(pucBuf); + return 0; +} + + int vtoydm_main(int argc, char **argv) { int ch; @@ -801,7 +987,7 @@ int vtoydm_main(int argc, char **argv) char filepath[300] = {0}; char outfile[300] = {0}; - while ((ch = getopt(argc, argv, "s:l:o:d:f:v::i::p::r::c::h::e::E::C::")) != -1) + while ((ch = getopt(argc, argv, "s:l:o:d:f:v::i::p::r::c::h::e::E::C::w::")) != -1) { if (ch == 'd') { @@ -819,6 +1005,10 @@ int vtoydm_main(int argc, char **argv) { cmd = CMD_PRINT_RAW_TABLE; } + else if (ch == 'w') + { + cmd = CMD_PRINT_WRAP_TABLE; + } else if (ch == 'c') { cmd = CMD_CREATE_DM; @@ -887,6 +1077,10 @@ int vtoydm_main(int argc, char **argv) { return vtoydm_print_raw_linear_table(filepath, diskname, part); } + case CMD_PRINT_WRAP_TABLE: + { + return vtoydm_print_wrap_linear_table(filepath, diskname, part, offset); + } case CMD_CREATE_DM: { break;