Experimental support for SteamOS recovery images. (#3712 #2875 #1815)
Ventoy CI / build (push) Canceled after 0s
Mirror GitHub to Gitee / Sync-GitHub-to-Gitee (push) Canceled after 0s

This commit is contained in:
longpanda
2026-09-30 19:20:12 +08:00
parent a67151f859
commit 029a0a9d16
17 changed files with 1194 additions and 2 deletions
@@ -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 <http://www.gnu.org/licenses/>.
*/
#include <grub/types.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
#include <grub/command.h>
#include <grub/i18n.h>
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);
}
@@ -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 <http://www.gnu.org/licenses/>.
*/
#include <grub/mm.h>
#include <grub/dl.h>
#include <grub/command.h>
#include <grub/term.h>
#include <grub/i18n.h>
#include <grub/misc.h>
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);
}
@@ -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 <http://www.gnu.org/licenses/>.
*/
#include <grub/font.h>
#include <grub/dl.h>
#include <grub/misc.h>
#include <grub/command.h>
#include <grub/i18n.h>
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);
}
@@ -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
@@ -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;
}
@@ -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)
@@ -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);
@@ -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}"
@@ -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
+32
View File
@@ -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
+110
View File
@@ -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
+119
View File
@@ -0,0 +1,119 @@
#!/ventoy/busybox/sh
#************************************************************************************
# Copyright (c) 2020, longpanda <admin@ventoy.net>
#
# 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 <http://www.gnu.org/licenses/>.
#
#************************************************************************************
. /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
@@ -0,0 +1,33 @@
#!/ventoy/busybox/sh
#************************************************************************************
# Copyright (c) 2020, longpanda <admin@ventoy.net>
#
# 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 <http://www.gnu.org/licenses/>.
#
#************************************************************************************
. $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
+16
View File
@@ -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:
+1 -1
View File
@@ -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
+50
View File
@@ -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
+195 -1
View File
@@ -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;