1. Boot menu over serial supported

2. Optimization for booting Solus
3. Optimization for booting .efi file
4. support deepin-live iso
5. support Endless OS
6. framework for booting .img file
pull/383/head
longpanda 4 years ago
parent 433d854aab
commit be50ea69aa

@ -331,7 +331,7 @@ EFI_STATUS EFIAPI ventoy_save_ramdisk_param(VOID)
Status = gRT->SetVariable(L"VentoyRamDisk", &VarGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
sizeof(g_ramdisk_param), &(g_ramdisk_param));
debug("set efi variable %r", Status);
debug("set ramdisk variable %r", Status);
return Status;
}
@ -663,17 +663,22 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
size = StrDecimalToUintn(pPos + 5);
debug("memory addr:%p size:%lu", chain, size);
g_chain = AllocatePool(size);
CopyMem(g_chain, chain, size);
if (StrStr(pCmdLine, L"memdisk"))
{
g_iso_buf_size = size;
g_iso_data_buf = (UINT8 *)chain + sizeof(ventoy_chain_head);
g_iso_buf_size = size - sizeof(ventoy_chain_head);
debug("memdisk mode iso_buf_size:%u", g_iso_buf_size);
g_chain = chain;
gMemdiskMode = TRUE;
}
else
{
debug("This is normal mode");
g_chain = AllocatePool(size);
CopyMem(g_chain, chain, size);
g_chunk = (ventoy_img_chunk *)((char *)g_chain + g_chain->img_chunk_offset);
g_img_chunk_num = g_chain->img_chunk_num;
g_override_chunk = (ventoy_override_chunk *)((char *)g_chain + g_chain->override_chunk_offset);
@ -725,6 +730,8 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle)
}
}
ventoy_debug_pause();
FreePool(pCmdLine);
return EFI_SUCCESS;
}
@ -942,15 +949,29 @@ EFI_STATUS EFIAPI VentoyEfiMain
if (gMemdiskMode)
{
g_ramdisk_param.PhyAddr = (UINT64)(UINTN)g_chain;
g_ramdisk_param.PhyAddr = (UINT64)(UINTN)g_iso_data_buf;
g_ramdisk_param.DiskSize = (UINT64)g_iso_buf_size;
ventoy_save_ramdisk_param();
if (gLoadIsoEfi)
{
ventoy_find_iso_disk(ImageHandle);
ventoy_find_iso_disk_fs(ImageHandle);
ventoy_load_isoefi_driver(ImageHandle);
}
ventoy_install_blockio(ImageHandle, g_iso_buf_size);
ventoy_debug_pause();
Status = ventoy_boot(ImageHandle);
ventoy_delete_ramdisk_param();
if (gLoadIsoEfi && gBlockData.IsoDriverImage)
{
gBS->UnloadImage(gBlockData.IsoDriverImage);
}
}
else
{

@ -339,6 +339,7 @@ extern ventoy_sector_flag *g_sector_flag;
extern UINT32 g_sector_flag_num;
extern BOOLEAN gMemdiskMode;
extern UINTN g_iso_buf_size;
extern UINT8 *g_iso_data_buf;
extern ventoy_grub_param_file_replace *g_file_replace_list;
extern BOOLEAN g_fixup_iso9660_secover_enable;
extern EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *g_con_simple_input_ex;

@ -36,6 +36,7 @@
#include <Protocol/SimpleFileSystem.h>
#include <Ventoy.h>
UINT8 *g_iso_data_buf = NULL;
UINTN g_iso_buf_size = 0;
BOOLEAN gMemdiskMode = FALSE;
@ -254,7 +255,7 @@ EFI_STATUS EFIAPI ventoy_block_io_ramdisk_read
(VOID)This;
(VOID)MediaId;
CopyMem(Buffer, (char *)g_chain + (Lba * 2048), BufferSize);
CopyMem(Buffer, g_iso_data_buf + (Lba * 2048), BufferSize);
if (g_blockio_start_record_bcd && FALSE == g_blockio_bcd_read_done)
{

@ -809,6 +809,16 @@ module = {
common = commands/blocklist.c;
};
module = {
name = blscfg;
common = commands/blscfg.c;
common = commands/loadenv.h;
enable = powerpc_ieee1275;
enable = efi;
enable = i386_pc;
enable = emu;
};
module = {
name = boot;
common = commands/boot.c;
@ -986,6 +996,7 @@ module = {
module = {
name = loadenv;
common = commands/loadenv.c;
common = commands/loadenv.h;
common = lib/envblk.c;
};

File diff suppressed because it is too large Load Diff

@ -0,0 +1,894 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2000, 2001, 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/types.h>
#include <grub/misc.h>
#include <grub/command.h>
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/file.h>
#include <grub/normal.h>
#include <grub/script_sh.h>
#include <grub/i18n.h>
#include <grub/term.h>
#include <grub/legacy_parse.h>
#include <grub/crypto.h>
#include <grub/auth.h>
#include <grub/disk.h>
#include <grub/partition.h>
GRUB_MOD_LICENSE ("GPLv3+");
/* Helper for legacy_file. */
static grub_err_t
legacy_file_getline (char **line, int cont __attribute__ ((unused)),
void *data __attribute__ ((unused)))
{
*line = 0;
return GRUB_ERR_NONE;
}
static grub_err_t
legacy_file (const char *filename)
{
grub_file_t file;
char *entryname = NULL, *entrysrc = NULL;
grub_menu_t menu;
char *suffix = grub_strdup ("");
if (!suffix)
return grub_errno;
file = grub_file_open (filename, GRUB_FILE_TYPE_CONFIG);
if (! file)
{
grub_free (suffix);
return grub_errno;
}
menu = grub_env_get_menu ();
if (! menu)
{
menu = grub_zalloc (sizeof (*menu));
if (! menu)
{
grub_free (suffix);
return grub_errno;
}
grub_env_set_menu (menu);
}
while (1)
{
char *buf = grub_file_getline (file);
char *parsed = NULL;
if (!buf && grub_errno)
{
grub_file_close (file);
grub_free (suffix);
return grub_errno;
}
if (!buf)
break;
{
char *oldname = NULL;
char *newsuffix;
char *ptr;
for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++);
oldname = entryname;
parsed = grub_legacy_parse (ptr, &entryname, &newsuffix);
grub_free (buf);
buf = NULL;
if (newsuffix)
{
char *t;
t = suffix;
suffix = grub_realloc (suffix, grub_strlen (suffix)
+ grub_strlen (newsuffix) + 1);
if (!suffix)
{
grub_free (t);
grub_free (entrysrc);
grub_free (parsed);
grub_free (newsuffix);
grub_free (suffix);
return grub_errno;
}
grub_memcpy (suffix + grub_strlen (suffix), newsuffix,
grub_strlen (newsuffix) + 1);
grub_free (newsuffix);
newsuffix = NULL;
}
if (oldname != entryname && oldname)
{
const char **args = grub_malloc (sizeof (args[0]));
if (!args)
{
grub_file_close (file);
return grub_errno;
}
args[0] = oldname;
grub_normal_add_menu_entry (1, args, NULL, NULL, "legacy",
NULL, NULL,
entrysrc, 0, NULL, NULL);
grub_free (args);
entrysrc[0] = 0;
grub_free (oldname);
}
}
if (parsed && !entryname)
{
grub_normal_parse_line (parsed, legacy_file_getline, NULL);
grub_print_error ();
grub_free (parsed);
parsed = NULL;
}
else if (parsed)
{
if (!entrysrc)
entrysrc = parsed;
else
{
char *t;
t = entrysrc;
entrysrc = grub_realloc (entrysrc, grub_strlen (entrysrc)
+ grub_strlen (parsed) + 1);
if (!entrysrc)
{
grub_free (t);
grub_free (parsed);
grub_free (suffix);
return grub_errno;
}
grub_memcpy (entrysrc + grub_strlen (entrysrc), parsed,
grub_strlen (parsed) + 1);
grub_free (parsed);
parsed = NULL;
}
}
}
grub_file_close (file);
if (entryname)
{
const char **args = grub_malloc (sizeof (args[0]));
if (!args)
{
grub_file_close (file);
grub_free (suffix);
grub_free (entrysrc);
return grub_errno;
}
args[0] = entryname;
grub_normal_add_menu_entry (1, args, NULL, NULL, NULL,
NULL, NULL, entrysrc, 0, NULL,
NULL);
grub_free (args);
}
grub_normal_parse_line (suffix, legacy_file_getline, NULL);
grub_print_error ();
grub_free (suffix);
grub_free (entrysrc);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_cmd_legacy_source (struct grub_command *cmd,
int argc, char **args)
{
int new_env, extractor;
grub_err_t ret;
if (argc != 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
extractor = (cmd->name[0] == 'e');
new_env = (cmd->name[extractor ? (sizeof ("extract_legacy_entries_") - 1)
: (sizeof ("legacy_") - 1)] == 'c');
if (new_env)
grub_cls ();
if (new_env && !extractor)
grub_env_context_open ();
if (extractor)
grub_env_extractor_open (!new_env);
ret = legacy_file (args[0]);
if (new_env)
{
grub_menu_t menu;
menu = grub_env_get_menu ();
if (menu && menu->size)
grub_show_menu (menu, 1, 0);
if (!extractor)
grub_env_context_close ();
}
if (extractor)
grub_env_extractor_close (!new_env);
return ret;
}
static enum
{
GUESS_IT, LINUX, MULTIBOOT, KFREEBSD, KNETBSD, KOPENBSD
} kernel_type;
static grub_err_t
grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
int argc, char **args)
{
int i;
#ifdef TODO
int no_mem_option = 0;
#endif
struct grub_command *cmd;
char **cutargs;
int cutargc;
grub_err_t err = GRUB_ERR_NONE;
for (i = 0; i < 2; i++)
{
/* FIXME: really support this. */
if (argc >= 1 && grub_strcmp (args[0], "--no-mem-option") == 0)
{
#ifdef TODO
no_mem_option = 1;
#endif
argc--;
args++;
continue;
}
/* linux16 handles both zImages and bzImages. */
if (argc >= 1 && (grub_strcmp (args[0], "--type=linux") == 0
|| grub_strcmp (args[0], "--type=biglinux") == 0))
{
kernel_type = LINUX;
argc--;
args++;
continue;
}
if (argc >= 1 && grub_strcmp (args[0], "--type=multiboot") == 0)
{
kernel_type = MULTIBOOT;
argc--;
args++;
continue;
}
if (argc >= 1 && grub_strcmp (args[0], "--type=freebsd") == 0)
{
kernel_type = KFREEBSD;
argc--;
args++;
continue;
}
if (argc >= 1 && grub_strcmp (args[0], "--type=openbsd") == 0)
{
kernel_type = KOPENBSD;
argc--;
args++;
continue;
}
if (argc >= 1 && grub_strcmp (args[0], "--type=netbsd") == 0)
{
kernel_type = KNETBSD;
argc--;
args++;
continue;
}
}
if (argc < 2)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
cutargs = grub_malloc (sizeof (cutargs[0]) * (argc - 1));
if (!cutargs)
return grub_errno;
cutargc = argc - 1;
grub_memcpy (cutargs + 1, args + 2, sizeof (cutargs[0]) * (argc - 2));
cutargs[0] = args[0];
do
{
/* First try Linux. */
if (kernel_type == GUESS_IT || kernel_type == LINUX)
{
#ifdef GRUB_MACHINE_PCBIOS
cmd = grub_command_find ("linux16");
#else
cmd = grub_command_find ("linux");
#endif
if (cmd)
{
if (!(cmd->func) (cmd, cutargc, cutargs))
{
kernel_type = LINUX;
goto out;
}
}
grub_errno = GRUB_ERR_NONE;
}
/* Then multiboot. */
if (kernel_type == GUESS_IT || kernel_type == MULTIBOOT)
{
cmd = grub_command_find ("multiboot");
if (cmd)
{
if (!(cmd->func) (cmd, argc, args))
{
kernel_type = MULTIBOOT;
goto out;
}
}
grub_errno = GRUB_ERR_NONE;
}
{
int bsd_device = -1;
int bsd_slice = -1;
int bsd_part = -1;
{
grub_device_t dev;
const char *hdbiasstr;
int hdbias = 0;
hdbiasstr = grub_env_get ("legacy_hdbias");
if (hdbiasstr)
{
hdbias = grub_strtoul (hdbiasstr, 0, 0);
grub_errno = GRUB_ERR_NONE;
}
dev = grub_device_open (0);
if (dev && dev->disk
&& dev->disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID
&& dev->disk->id >= 0x80 && dev->disk->id <= 0x90)
{
struct grub_partition *part = dev->disk->partition;
bsd_device = dev->disk->id - 0x80 - hdbias;
if (part && (grub_strcmp (part->partmap->name, "netbsd") == 0
|| grub_strcmp (part->partmap->name, "openbsd") == 0
|| grub_strcmp (part->partmap->name, "bsd") == 0))
{
bsd_part = part->number;
part = part->parent;
}
if (part && grub_strcmp (part->partmap->name, "msdos") == 0)
bsd_slice = part->number;
}
if (dev)
grub_device_close (dev);
}
/* k*BSD didn't really work well with grub-legacy. */
if (kernel_type == GUESS_IT || kernel_type == KFREEBSD)
{
char buf[sizeof("adXXXXXXXXXXXXsXXXXXXXXXXXXYYY")];
if (bsd_device != -1)
{
if (bsd_slice != -1 && bsd_part != -1)
grub_snprintf(buf, sizeof(buf), "ad%ds%d%c", bsd_device,
bsd_slice, 'a' + bsd_part);
else if (bsd_slice != -1)
grub_snprintf(buf, sizeof(buf), "ad%ds%d", bsd_device,
bsd_slice);
else
grub_snprintf(buf, sizeof(buf), "ad%d", bsd_device);
grub_env_set ("kFreeBSD.vfs.root.mountfrom", buf);
}
else
grub_env_unset ("kFreeBSD.vfs.root.mountfrom");
cmd = grub_command_find ("kfreebsd");
if (cmd)
{
if (!(cmd->func) (cmd, cutargc, cutargs))
{
kernel_type = KFREEBSD;
goto out;
}
}
grub_errno = GRUB_ERR_NONE;
}
{
char **bsdargs;
int bsdargc;
char bsddevname[sizeof ("wdXXXXXXXXXXXXY")];
int found = 0;
if (bsd_device == -1)
{
bsdargs = cutargs;
bsdargc = cutargc;
}
else
{
char rbuf[3] = "-r";
bsdargc = cutargc + 2;
bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc);
if (!bsdargs)
{
err = grub_errno;
goto out;
}
grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0]));
bsdargs[argc] = rbuf;
bsdargs[argc + 1] = bsddevname;
grub_snprintf (bsddevname, sizeof (bsddevname),
"wd%d%c", bsd_device,
bsd_part != -1 ? bsd_part + 'a' : 'c');
}
if (kernel_type == GUESS_IT || kernel_type == KNETBSD)
{
cmd = grub_command_find ("knetbsd");
if (cmd)
{
if (!(cmd->func) (cmd, bsdargc, bsdargs))
{
kernel_type = KNETBSD;
found = 1;
goto free_bsdargs;
}
}
grub_errno = GRUB_ERR_NONE;
}
if (kernel_type == GUESS_IT || kernel_type == KOPENBSD)
{
cmd = grub_command_find ("kopenbsd");
if (cmd)
{
if (!(cmd->func) (cmd, bsdargc, bsdargs))
{
kernel_type = KOPENBSD;
found = 1;
goto free_bsdargs;
}
}
grub_errno = GRUB_ERR_NONE;
}
free_bsdargs:
if (bsdargs != cutargs)
grub_free (bsdargs);
if (found)
goto out;
}
}
}
while (0);
err = grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s",
args[0]);
out:
grub_free (cutargs);
return err;
}
static grub_err_t
grub_cmd_legacy_initrd (struct grub_command *mycmd __attribute__ ((unused)),
int argc, char **args)
{
struct grub_command *cmd;
if (kernel_type == LINUX)
{
#ifdef GRUB_MACHINE_PCBIOS
cmd = grub_command_find ("initrd16");
#else
cmd = grub_command_find ("initrd");
#endif
if (!cmd)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
#ifdef GRUB_MACHINE_PCBIOS
"initrd16"
#else
"initrd"
#endif
);
return cmd->func (cmd, argc ? 1 : 0, args);
}
if (kernel_type == MULTIBOOT)
{
cmd = grub_command_find ("module");
if (!cmd)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
"module");
return cmd->func (cmd, argc, args);
}
return grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("you need to load the kernel first"));
}
static grub_err_t
grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused)),
int argc, char **args)
{
struct grub_command *cmd;
if (kernel_type == LINUX)
{
cmd = grub_command_find ("initrd16");
if (!cmd)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
"initrd16");
return cmd->func (cmd, argc, args);
}
if (kernel_type == MULTIBOOT)
{
char **newargs;
grub_err_t err;
char nounzipbuf[10] = "--nounzip";
cmd = grub_command_find ("module");
if (!cmd)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
"module");
newargs = grub_malloc ((argc + 1) * sizeof (newargs[0]));
if (!newargs)
return grub_errno;
grub_memcpy (newargs + 1, args, argc * sizeof (newargs[0]));
newargs[0] = nounzipbuf;
err = cmd->func (cmd, argc + 1, newargs);
grub_free (newargs);
return err;
}
return grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("you need to load the kernel first"));
}
static grub_err_t
check_password_deny (const char *user __attribute__ ((unused)),
const char *entered __attribute__ ((unused)),
void *password __attribute__ ((unused)))
{
return GRUB_ACCESS_DENIED;
}
#define MD5_HASHLEN 16
struct legacy_md5_password
{
grub_uint8_t *salt;
int saltlen;
grub_uint8_t hash[MD5_HASHLEN];
};
static int
check_password_md5_real (const char *entered,
struct legacy_md5_password *pw)
{
grub_size_t enteredlen = grub_strlen (entered);
unsigned char alt_result[MD5_HASHLEN];
unsigned char *digest;
grub_uint8_t *ctx;
grub_size_t i;
int ret;
ctx = grub_zalloc (GRUB_MD_MD5->contextsize);
if (!ctx)
return 0;
GRUB_MD_MD5->init (ctx);
GRUB_MD_MD5->write (ctx, entered, enteredlen);
GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3);
GRUB_MD_MD5->write (ctx, entered, enteredlen);
digest = GRUB_MD_MD5->read (ctx);
GRUB_MD_MD5->final (ctx);
grub_memcpy (alt_result, digest, MD5_HASHLEN);
GRUB_MD_MD5->init (ctx);
GRUB_MD_MD5->write (ctx, entered, enteredlen);
GRUB_MD_MD5->write (ctx, pw->salt, pw->saltlen); /* include the $1$ header */
for (i = enteredlen; i > 16; i -= 16)
GRUB_MD_MD5->write (ctx, alt_result, 16);
GRUB_MD_MD5->write (ctx, alt_result, i);
for (i = enteredlen; i > 0; i >>= 1)
GRUB_MD_MD5->write (ctx, entered + ((i & 1) ? enteredlen : 0), 1);
digest = GRUB_MD_MD5->read (ctx);
GRUB_MD_MD5->final (ctx);
for (i = 0; i < 1000; i++)
{
grub_memcpy (alt_result, digest, 16);
GRUB_MD_MD5->init (ctx);
if ((i & 1) != 0)
GRUB_MD_MD5->write (ctx, entered, enteredlen);
else
GRUB_MD_MD5->write (ctx, alt_result, 16);
if (i % 3 != 0)
GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3);
if (i % 7 != 0)
GRUB_MD_MD5->write (ctx, entered, enteredlen);
if ((i & 1) != 0)
GRUB_MD_MD5->write (ctx, alt_result, 16);
else
GRUB_MD_MD5->write (ctx, entered, enteredlen);
digest = GRUB_MD_MD5->read (ctx);
GRUB_MD_MD5->final (ctx);
}
ret = (grub_crypto_memcmp (digest, pw->hash, MD5_HASHLEN) == 0);
grub_free (ctx);
return ret;
}
static grub_err_t
check_password_md5 (const char *user,
const char *entered,
void *password)
{
if (!check_password_md5_real (entered, password))
return GRUB_ACCESS_DENIED;
grub_auth_authenticate (user);
return GRUB_ERR_NONE;
}
static inline int
ib64t (char c)
{
if (c == '.')
return 0;
if (c == '/')
return 1;
if (c >= '0' && c <= '9')
return c - '0' + 2;
if (c >= 'A' && c <= 'Z')
return c - 'A' + 12;
if (c >= 'a' && c <= 'z')
return c - 'a' + 38;
return -1;
}
static struct legacy_md5_password *
parse_legacy_md5 (int argc, char **args)
{
const char *salt, *saltend;
struct legacy_md5_password *pw = NULL;
int i;
const char *p;
if (grub_memcmp (args[0], "--md5", sizeof ("--md5")) != 0)
goto fail;
if (argc == 1)
goto fail;
if (grub_strlen(args[1]) <= 3)
goto fail;
salt = args[1];
saltend = grub_strchr (salt + 3, '$');
if (!saltend)
goto fail;
pw = grub_malloc (sizeof (*pw));
if (!pw)
goto fail;
p = saltend + 1;
for (i = 0; i < 5; i++)
{
int n;
grub_uint32_t w = 0;
for (n = 0; n < 4; n++)
{
int ww = ib64t(*p++);
if (ww == -1)
goto fail;
w |= ww << (n * 6);
}
pw->hash[i == 4 ? 5 : 12+i] = w & 0xff;
pw->hash[6+i] = (w >> 8) & 0xff;
pw->hash[i] = (w >> 16) & 0xff;
}
{
int n;
grub_uint32_t w = 0;
for (n = 0; n < 2; n++)
{
int ww = ib64t(*p++);
if (ww == -1)
goto fail;
w |= ww << (6 * n);
}
if (w >= 0x100)
goto fail;
pw->hash[11] = w;
}
pw->saltlen = saltend - salt;
pw->salt = (grub_uint8_t *) grub_strndup (salt, pw->saltlen);
if (!pw->salt)
goto fail;
return pw;
fail:
grub_free (pw);
return NULL;
}
static grub_err_t
grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)),
int argc, char **args)
{
struct legacy_md5_password *pw = NULL;
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
if (args[0][0] != '-' || args[0][1] != '-')
return grub_normal_set_password ("legacy", args[0]);
pw = parse_legacy_md5 (argc, args);
if (pw)
return grub_auth_register_authentication ("legacy", check_password_md5, pw);
else
/* This is to imitate minor difference between grub-legacy in GRUB2.
If 2 password commands are executed in a row and second one fails
on GRUB2 the password of first one is used, whereas in grub-legacy
authenthication is denied. In case of no password command was executed
early both versions deny any access. */
return grub_auth_register_authentication ("legacy", check_password_deny,
NULL);
}
int
grub_legacy_check_md5_password (int argc, char **args,
char *entered)
{
struct legacy_md5_password *pw = NULL;
int ret;
if (args[0][0] != '-' || args[0][1] != '-')
{
char correct[GRUB_AUTH_MAX_PASSLEN];
grub_memset (correct, 0, sizeof (correct));
grub_strncpy (correct, args[0], sizeof (correct));
return grub_crypto_memcmp (entered, correct, GRUB_AUTH_MAX_PASSLEN) == 0;
}
pw = parse_legacy_md5 (argc, args);
if (!pw)
return 0;
ret = check_password_md5_real (entered, pw);
grub_free (pw);
return ret;
}
static grub_err_t
grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unused)),
int argc, char **args)
{
char entered[GRUB_AUTH_MAX_PASSLEN];
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
grub_puts_ (N_("Enter password: "));
if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN))
return GRUB_ACCESS_DENIED;
if (!grub_legacy_check_md5_password (argc, args,
entered))
return GRUB_ACCESS_DENIED;
return GRUB_ERR_NONE;
}
static grub_command_t cmd_source, cmd_configfile;
static grub_command_t cmd_source_extract, cmd_configfile_extract;
static grub_command_t cmd_kernel, cmd_initrd, cmd_initrdnounzip;
static grub_command_t cmd_password, cmd_check_password;
GRUB_MOD_INIT(legacycfg)
{
cmd_source
= grub_register_command ("legacy_source",
grub_cmd_legacy_source,
N_("FILE"),
/* TRANSLATORS: "legacy config" means
"config as used by grub-legacy". */
N_("Parse legacy config in same context"));
cmd_configfile
= grub_register_command ("legacy_configfile",
grub_cmd_legacy_source,
N_("FILE"),
N_("Parse legacy config in new context"));
cmd_source_extract
= grub_register_command ("extract_legacy_entries_source",
grub_cmd_legacy_source,
N_("FILE"),
N_("Parse legacy config in same context taking only menu entries"));
cmd_configfile_extract
= grub_register_command ("extract_legacy_entries_configfile",
grub_cmd_legacy_source,
N_("FILE"),
N_("Parse legacy config in new context taking only menu entries"));
cmd_kernel = grub_register_command ("legacy_kernel",
grub_cmd_legacy_kernel,
N_("[--no-mem-option] [--type=TYPE] FILE [ARG ...]"),
N_("Simulate grub-legacy `kernel' command"));
cmd_initrd = grub_register_command ("legacy_initrd",
grub_cmd_legacy_initrd,
N_("FILE [ARG ...]"),
N_("Simulate grub-legacy `initrd' command"));
cmd_initrdnounzip = grub_register_command ("legacy_initrd_nounzip",
grub_cmd_legacy_initrdnounzip,
N_("FILE [ARG ...]"),
N_("Simulate grub-legacy `modulenounzip' command"));
cmd_password = grub_register_command ("legacy_password",
grub_cmd_legacy_password,
N_("[--md5] PASSWD [FILE]"),
N_("Simulate grub-legacy `password' command"));
cmd_check_password = grub_register_command ("legacy_check_password",
grub_cmd_legacy_check_password,
N_("[--md5] PASSWD [FILE]"),
N_("Simulate grub-legacy `password' command in menu entry mode"));
}
GRUB_MOD_FINI(legacycfg)
{
grub_unregister_command (cmd_source);
grub_unregister_command (cmd_configfile);
grub_unregister_command (cmd_source_extract);
grub_unregister_command (cmd_configfile_extract);
grub_unregister_command (cmd_kernel);
grub_unregister_command (cmd_initrd);
grub_unregister_command (cmd_initrdnounzip);
grub_unregister_command (cmd_password);
grub_unregister_command (cmd_check_password);
}

@ -0,0 +1,397 @@
/* loadenv.c - command to load/save environment variable. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008,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/dl.h>
#include <grub/mm.h>
#include <grub/file.h>
#include <grub/disk.h>
#include <grub/misc.h>
#include <grub/env.h>
#include <grub/partition.h>
#include <grub/lib/envblk.h>
#include <grub/extcmd.h>
#include <grub/i18n.h>
#include "loadenv.h"
GRUB_MOD_LICENSE ("GPLv3+");
static const struct grub_arg_option options[] =
{
/* TRANSLATORS: This option is used to override default filename
for loading and storing environment. */
{"file", 'f', 0, N_("Specify filename."), 0, ARG_TYPE_PATHNAME},
{"skip-sig", 's', 0,
N_("Skip signature-checking of the environment file."), 0, ARG_TYPE_NONE},
{0, 0, 0, 0, 0, 0}
};
/* Opens 'filename' with compression filters disabled. Optionally disables the
PUBKEY filter (that insists upon properly signed files) as well. PUBKEY
filter is restored before the function returns. */
static grub_file_t
open_envblk_file (char *filename,
enum grub_file_type type)
{
grub_file_t file;
char *buf = 0;
if (! filename)
{
const char *prefix;
int len;
prefix = grub_env_get ("prefix");
if (! prefix)
{
grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix");
return 0;
}
len = grub_strlen (prefix);
buf = grub_malloc (len + 1 + sizeof (GRUB_ENVBLK_DEFCFG));
if (! buf)
return 0;
filename = buf;
grub_strcpy (filename, prefix);
filename[len] = '/';
grub_strcpy (filename + len + 1, GRUB_ENVBLK_DEFCFG);
}
file = grub_file_open (filename, type);
grub_free (buf);
return file;
}
static grub_err_t
grub_cmd_load_env (grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_arg_list *state = ctxt->state;
grub_file_t file;
grub_envblk_t envblk;
grub_env_whitelist_t whitelist;
whitelist.len = argc;
whitelist.list = args;
/* state[0] is the -f flag; state[1] is the --skip-sig flag */
file = open_envblk_file ((state[0].set) ? state[0].arg : 0,
GRUB_FILE_TYPE_LOADENV
| (state[1].set
? GRUB_FILE_TYPE_SKIP_SIGNATURE : GRUB_FILE_TYPE_NONE));
if (! file)
return grub_errno;
envblk = read_envblk_file (file);
if (! envblk)
goto fail;
/* argc > 0 indicates caller provided a whitelist of variables to read. */
grub_envblk_iterate (envblk, argc > 0 ? &whitelist : 0, set_var);
grub_envblk_close (envblk);
fail:
grub_file_close (file);
return grub_errno;
}
/* Print all variables in current context. */
static int
print_var (const char *name, const char *value,
void *hook_data __attribute__ ((unused)))
{
grub_printf ("%s=%s\n", name, value);
return 0;
}
static grub_err_t
grub_cmd_list_env (grub_extcmd_context_t ctxt,
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
struct grub_arg_list *state = ctxt->state;
grub_file_t file;
grub_envblk_t envblk;
file = open_envblk_file ((state[0].set) ? state[0].arg : 0,
GRUB_FILE_TYPE_LOADENV
| (state[1].set
? GRUB_FILE_TYPE_SKIP_SIGNATURE : GRUB_FILE_TYPE_NONE));
if (! file)
return grub_errno;
envblk = read_envblk_file (file);
if (! envblk)
goto fail;
grub_envblk_iterate (envblk, NULL, print_var);
grub_envblk_close (envblk);
fail:
grub_file_close (file);
return grub_errno;
}
/* Used to maintain a variable length of blocklists internally. */
struct blocklist
{
grub_disk_addr_t sector;
unsigned offset;
unsigned length;
struct blocklist *next;
};
static void
free_blocklists (struct blocklist *p)
{
struct blocklist *q;
for (; p; p = q)
{
q = p->next;
grub_free (p);
}
}
static grub_err_t
check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
grub_file_t file)
{
grub_size_t total_length;
grub_size_t index;
grub_disk_t disk;
grub_disk_addr_t part_start;
struct blocklist *p;
char *buf;
/* Sanity checks. */
total_length = 0;
for (p = blocklists; p; p = p->next)
{
struct blocklist *q;
/* Check if any pair of blocks overlap. */
for (q = p->next; q; q = q->next)
{
grub_disk_addr_t s1, s2;
grub_disk_addr_t e1, e2;
s1 = p->sector;
e1 = s1 + ((p->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
s2 = q->sector;
e2 = s2 + ((q->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS);
if (s1 < e2 && s2 < e1)
{
/* This might be actually valid, but it is unbelievable that
any filesystem makes such a silly allocation. */
return grub_error (GRUB_ERR_BAD_FS, "malformed file");
}
}
total_length += p->length;
}
if (total_length != grub_file_size (file))
{
/* Maybe sparse, unallocated sectors. No way in GRUB. */
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "sparse file not allowed");
}
/* One more sanity check. Re-read all sectors by blocklists, and compare
those with the data read via a file. */
disk = file->device->disk;
part_start = grub_partition_get_start (disk->partition);
buf = grub_envblk_buffer (envblk);
char *blockbuf = NULL;
grub_size_t blockbuf_len = 0;
for (p = blocklists, index = 0; p; index += p->length, p = p->next)
{
if (p->length > blockbuf_len)
{
grub_free (blockbuf);
blockbuf_len = 2 * p->length;
blockbuf = grub_malloc (blockbuf_len);
if (!blockbuf)
return grub_errno;
}
if (grub_disk_read (disk, p->sector - part_start,
p->offset, p->length, blockbuf))
return grub_errno;
if (grub_memcmp (buf + index, blockbuf, p->length) != 0)
return grub_error (GRUB_ERR_FILE_READ_ERROR, "invalid blocklist");
}
return GRUB_ERR_NONE;
}
static int
write_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
grub_file_t file)
{
char *buf;
grub_disk_t disk;
grub_disk_addr_t part_start;
struct blocklist *p;
grub_size_t index;
buf = grub_envblk_buffer (envblk);
disk = file->device->disk;
part_start = grub_partition_get_start (disk->partition);
index = 0;
for (p = blocklists; p; index += p->length, p = p->next)
{
if (grub_disk_write (disk, p->sector - part_start,
p->offset, p->length, buf + index))
return 0;
}
return 1;
}
/* Context for grub_cmd_save_env. */
struct grub_cmd_save_env_ctx
{
struct blocklist *head, *tail;
};
/* Store blocklists in a linked list. */
static void
save_env_read_hook (grub_disk_addr_t sector, unsigned offset, unsigned length,
void *data)
{
struct grub_cmd_save_env_ctx *ctx = data;
struct blocklist *block;
block = grub_malloc (sizeof (*block));
if (! block)
return;
block->sector = sector;
block->offset = offset;
block->length = length;
/* Slightly complicated, because the list should be FIFO. */
block->next = 0;
if (ctx->tail)
ctx->tail->next = block;
ctx->tail = block;
if (! ctx->head)
ctx->head = block;
}
static grub_err_t
grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_arg_list *state = ctxt->state;
grub_file_t file;
grub_envblk_t envblk;
struct grub_cmd_save_env_ctx ctx = {
.head = 0,
.tail = 0
};
if (! argc)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no variable is specified");
file = open_envblk_file ((state[0].set) ? state[0].arg : 0,
GRUB_FILE_TYPE_SAVEENV
| GRUB_FILE_TYPE_SKIP_SIGNATURE);
if (! file)
return grub_errno;
if (! file->device->disk)
{
grub_file_close (file);
return grub_error (GRUB_ERR_BAD_DEVICE, "disk device required");
}
file->read_hook = save_env_read_hook;
file->read_hook_data = &ctx;
envblk = read_envblk_file (file);
file->read_hook = 0;
if (! envblk)
goto fail;
if (check_blocklists (envblk, ctx.head, file))
goto fail;
while (argc)
{
const char *value;
value = grub_env_get (args[0]);
if (value)
{
if (! grub_envblk_set (envblk, args[0], value))
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "environment block too small");
goto fail;
}
}
else
grub_envblk_delete (envblk, args[0]);
argc--;
args++;
}
write_blocklists (envblk, ctx.head, file);
fail:
if (envblk)
grub_envblk_close (envblk);
free_blocklists (ctx.head);
grub_file_close (file);
return grub_errno;
}
static grub_extcmd_t cmd_load, cmd_list, cmd_save;
GRUB_MOD_INIT(loadenv)
{
cmd_load =
grub_register_extcmd ("load_env", grub_cmd_load_env, 0,
N_("[-f FILE] [-s|--skip-sig] [variable_name_to_whitelist] [...]"),
N_("Load variables from environment block file."),
options);
cmd_list =
grub_register_extcmd ("list_env", grub_cmd_list_env, 0, N_("[-f FILE]"),
N_("List variables from environment block file."),
options);
cmd_save =
grub_register_extcmd ("save_env", grub_cmd_save_env, 0,
N_("[-f FILE] variable_name [...]"),
N_("Save variables to environment block file."),
options);
}
GRUB_MOD_FINI(loadenv)
{
grub_unregister_extcmd (cmd_load);
grub_unregister_extcmd (cmd_list);
grub_unregister_extcmd (cmd_save);
}

@ -0,0 +1,93 @@
/* loadenv.c - command to load/save environment variable. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008,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/>.
*/
static grub_envblk_t UNUSED
read_envblk_file (grub_file_t file)
{
grub_off_t offset = 0;
char *buf;
grub_size_t size = grub_file_size (file);
grub_envblk_t envblk;
buf = grub_malloc (size);
if (! buf)
return 0;
while (size > 0)
{
grub_ssize_t ret;
ret = grub_file_read (file, buf + offset, size);
if (ret <= 0)
{
grub_free (buf);
return 0;
}
size -= ret;
offset += ret;
}
envblk = grub_envblk_open (buf, offset);
if (! envblk)
{
grub_free (buf);
grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid environment block");
return 0;
}
return envblk;
}
struct grub_env_whitelist
{
grub_size_t len;
char **list;
};
typedef struct grub_env_whitelist grub_env_whitelist_t;
static int UNUSED
test_whitelist_membership (const char* name,
const grub_env_whitelist_t* whitelist)
{
grub_size_t i;
for (i = 0; i < whitelist->len; i++)
if (grub_strcmp (name, whitelist->list[i]) == 0)
return 1; /* found it */
return 0; /* not found */
}
/* Helper for grub_cmd_load_env. */
static int UNUSED
set_var (const char *name, const char *value, void *whitelist)
{
if (! whitelist)
{
grub_env_set (name, value);
return 0;
}
if (test_whitelist_membership (name,
(const grub_env_whitelist_t *) whitelist))
grub_env_set (name, value);
return 0;
}

@ -0,0 +1,349 @@
/* menuentry.c - menuentry command */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 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/types.h>
#include <grub/misc.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/extcmd.h>
#include <grub/i18n.h>
#include <grub/normal.h>
static const struct grub_arg_option options[] =
{
{"class", 1, GRUB_ARG_OPTION_REPEATABLE,
N_("Menu entry type."), N_("STRING"), ARG_TYPE_STRING},
{"users", 2, 0,
N_("List of users allowed to boot this entry."), N_("USERNAME[,USERNAME]"),
ARG_TYPE_STRING},
{"hotkey", 3, 0,
N_("Keyboard key to quickly boot this entry."), N_("KEYBOARD_KEY"), ARG_TYPE_STRING},
{"source", 4, 0,
N_("Use STRING as menu entry body."), N_("STRING"), ARG_TYPE_STRING},
{"id", 0, 0, N_("Menu entry identifier."), N_("STRING"), ARG_TYPE_STRING},
/* TRANSLATORS: menu entry can either be bootable by anyone or only by
handful of users. By default when security is active only superusers can
boot a given menu entry. With --unrestricted (this option)
anyone can boot it. */
{"unrestricted", 0, 0, N_("This entry can be booted by any user."),
0, ARG_TYPE_NONE},
{0, 0, 0, 0, 0, 0}
};
static struct
{
const char *name;
int key;
} hotkey_aliases[] =
{
{"backspace", GRUB_TERM_BACKSPACE},
{"tab", GRUB_TERM_TAB},
{"delete", GRUB_TERM_KEY_DC},
{"insert", GRUB_TERM_KEY_INSERT},
{"f1", GRUB_TERM_KEY_F1},
{"f2", GRUB_TERM_KEY_F2},
{"f3", GRUB_TERM_KEY_F3},
{"f4", GRUB_TERM_KEY_F4},
{"f5", GRUB_TERM_KEY_F5},
{"f6", GRUB_TERM_KEY_F6},
{"f7", GRUB_TERM_KEY_F7},
{"f8", GRUB_TERM_KEY_F8},
{"f9", GRUB_TERM_KEY_F9},
{"f10", GRUB_TERM_KEY_F10},
{"f11", GRUB_TERM_KEY_F11},
{"f12", GRUB_TERM_KEY_F12},
};
/* Add a menu entry to the current menu context (as given by the environment
variable data slot `menu'). As the configuration file is read, the script
parser calls this when a menu entry is to be created. */
grub_err_t
grub_normal_add_menu_entry (int argc, const char **args,
char **classes, const char *id,
const char *users, const char *hotkey,
const char *prefix, const char *sourcecode,
int submenu, int *index, struct bls_entry *bls)
{
int menu_hotkey = 0;
char **menu_args = NULL;
char *menu_users = NULL;
char *menu_title = NULL;
char *menu_sourcecode = NULL;
char *menu_id = NULL;
struct grub_menu_entry_class *menu_classes = NULL;
grub_menu_t menu;
grub_menu_entry_t *last;
menu = grub_env_get_menu ();
if (! menu)
return grub_error (GRUB_ERR_MENU, "no menu context");
last = &menu->entry_list;
menu_sourcecode = grub_xasprintf ("%s%s", prefix ?: "", sourcecode);
if (! menu_sourcecode)
return grub_errno;
if (classes && classes[0])
{
int i;
for (i = 0; classes[i]; i++); /* count # of menuentry classes */
menu_classes = grub_zalloc (sizeof (struct grub_menu_entry_class)
* (i + 1));
if (! menu_classes)
goto fail;
for (i = 0; classes[i]; i++)
{
menu_classes[i].name = grub_strdup (classes[i]);
if (! menu_classes[i].name)
goto fail;
menu_classes[i].next = classes[i + 1] ? &menu_classes[i + 1] : NULL;
}
}
if (users)
{
menu_users = grub_strdup (users);
if (! menu_users)
goto fail;
}
if (hotkey)
{
unsigned i;
for (i = 0; i < ARRAY_SIZE (hotkey_aliases); i++)
if (grub_strcmp (hotkey, hotkey_aliases[i].name) == 0)
{
menu_hotkey = hotkey_aliases[i].key;
break;
}
if (i == ARRAY_SIZE (hotkey_aliases))
menu_hotkey = hotkey[0];
}
if (! argc)
{
grub_error (GRUB_ERR_MENU, "menuentry is missing title");
goto fail;
}
menu_title = grub_strdup (args[0]);
if (! menu_title)
goto fail;
grub_dprintf ("menu", "id:\"%s\"\n", id);
grub_dprintf ("menu", "title:\"%s\"\n", menu_title);
menu_id = grub_strdup (id ? : menu_title);
if (! menu_id)
goto fail;
grub_dprintf ("menu", "menu_id:\"%s\"\n", menu_id);
/* Save argc, args to pass as parameters to block arg later. */
menu_args = grub_malloc (sizeof (char*) * (argc + 1));
if (! menu_args)
goto fail;
{
int i;
for (i = 0; i < argc; i++)
{
menu_args[i] = grub_strdup (args[i]);
if (! menu_args[i])
goto fail;
}
menu_args[argc] = NULL;
}
/* Add the menu entry at the end of the list. */
int ind=0;
while (*last)
{
ind++;
last = &(*last)->next;
}
*last = grub_zalloc (sizeof (**last));
if (! *last)
goto fail;
(*last)->title = menu_title;
(*last)->id = menu_id;
(*last)->hotkey = menu_hotkey;
(*last)->classes = menu_classes;
if (menu_users)
(*last)->restricted = 1;
(*last)->users = menu_users;
(*last)->argc = argc;
(*last)->args = menu_args;
(*last)->sourcecode = menu_sourcecode;
(*last)->submenu = submenu;
(*last)->bls = bls;
menu->size++;
if (index)
*index = ind;
return GRUB_ERR_NONE;
fail:
grub_free (menu_sourcecode);
{
int i;
for (i = 0; menu_classes && menu_classes[i].name; i++)
grub_free (menu_classes[i].name);
grub_free (menu_classes);
}
{
int i;
for (i = 0; menu_args && menu_args[i]; i++)
grub_free (menu_args[i]);
grub_free (menu_args);
}
grub_free (menu_users);
grub_free (menu_title);
grub_free (menu_id);
return grub_errno;
}
static char *
setparams_prefix (int argc, char **args)
{
int i;
int j;
char *p;
char *result;
grub_size_t len = 10;
/* Count resulting string length */
for (i = 0; i < argc; i++)
{
len += 3; /* 3 = 1 space + 2 quotes */
p = args[i];
while (*p)
len += (*p++ == '\'' ? 3 : 1);
}
result = grub_malloc (len + 2);
if (! result)
return 0;
grub_strcpy (result, "setparams");
p = result + 9;
for (j = 0; j < argc; j++)
{
*p++ = ' ';
*p++ = '\'';
p = grub_strchrsub (p, args[j], '\'', "'\\''");
*p++ = '\'';
}
*p++ = '\n';
*p = '\0';
return result;
}
static grub_err_t
grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
{
char ch;
char *src;
char *prefix;
unsigned len;
grub_err_t r;
const char *users;
if (! argc)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing arguments");
if (ctxt->state[3].set && ctxt->script)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "multiple menuentry definitions");
if (! ctxt->state[3].set && ! ctxt->script)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no menuentry definition");
if (ctxt->state[1].set)
users = ctxt->state[1].arg;
else if (ctxt->state[5].set)
users = NULL;
else
users = "";
if (! ctxt->script)
return grub_normal_add_menu_entry (argc, (const char **) args,
(ctxt->state[0].set ? ctxt->state[0].args
: NULL),
ctxt->state[4].arg,
users,
ctxt->state[2].arg, 0,
ctxt->state[3].arg,
ctxt->extcmd->cmd->name[0] == 's',
NULL, NULL);
src = args[argc - 1];
args[argc - 1] = NULL;
len = grub_strlen(src);
ch = src[len - 1];
src[len - 1] = '\0';
prefix = setparams_prefix (argc - 1, args);
if (! prefix)
return grub_errno;
r = grub_normal_add_menu_entry (argc - 1, (const char **) args,
ctxt->state[0].args, ctxt->state[4].arg,
users,
ctxt->state[2].arg, prefix, src + 1,
ctxt->extcmd->cmd->name[0] == 's', NULL,
NULL);
src[len - 1] = ch;
args[argc - 1] = src;
grub_free (prefix);
return r;
}
static grub_extcmd_t cmd, cmd_sub;
void
grub_menu_init (void)
{
cmd = grub_register_extcmd ("menuentry", grub_cmd_menuentry,
GRUB_COMMAND_FLAG_BLOCKS
| GRUB_COMMAND_ACCEPT_DASH
| GRUB_COMMAND_FLAG_EXTRACTOR,
N_("BLOCK"), N_("Define a menu entry."), options);
cmd_sub = grub_register_extcmd ("submenu", grub_cmd_menuentry,
GRUB_COMMAND_FLAG_BLOCKS
| GRUB_COMMAND_ACCEPT_DASH
| GRUB_COMMAND_FLAG_EXTRACTOR,
N_("BLOCK"), N_("Define a submenu."),
options);
}
void
grub_menu_fini (void)
{
grub_unregister_extcmd (cmd);
grub_unregister_extcmd (cmd_sub);
}

@ -109,6 +109,52 @@ grub_env_write_root (struct grub_env_var *var __attribute__ ((unused)),
return grub_strdup (val);
}
static int g_ventoy_hook_root = 0;
void ventoy_env_hook_root(int hook)
{
g_ventoy_hook_root = hook;
}
static char *
ventoy_env_write_root (struct grub_env_var *var __attribute__ ((unused)),
const char *val)
{
const char *pos = val;
char buf[256];
if (g_ventoy_hook_root == 0)
{
return grub_env_write_root(var, val);
}
if (pos[0] == '(')
{
pos++;
}
if (grub_strncmp(pos, "vtimghd", 7) == 0)
{
return grub_env_write_root(var, val);
}
pos = grub_strchr(val, ',');
if (!pos)
{
return grub_env_write_root(var, val);
}
if (val[0] == '(')
{
grub_snprintf(buf, sizeof(buf), "(vtimghd%s", pos);
}
else
{
grub_snprintf(buf, sizeof(buf), "vtimghd%s", pos);
}
return grub_env_write_root(var, buf);
}
static void
grub_set_prefix_and_root (void)
{
@ -123,7 +169,7 @@ grub_set_prefix_and_root (void)
if (header->type == OBJ_TYPE_PREFIX)
prefix = (char *) header + sizeof (struct grub_module_header);
grub_register_variable_hook ("root", 0, grub_env_write_root);
grub_register_variable_hook ("root", 0, ventoy_env_write_root);
grub_machine_get_bootlocation (&fwdevice, &fwpath);

File diff suppressed because it is too large Load Diff

@ -0,0 +1,575 @@
/* main.c - the normal mode main routine */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2000,2001,2002,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/kernel.h>
#include <grub/normal.h>
#include <grub/dl.h>
#include <grub/menu.h>
#include <grub/misc.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/term.h>
#include <grub/env.h>
#include <grub/parser.h>
#include <grub/reader.h>
#include <grub/menu_viewer.h>
#include <grub/auth.h>
#include <grub/i18n.h>
#include <grub/charset.h>
#include <grub/script_sh.h>
#include <grub/bufio.h>
GRUB_MOD_LICENSE ("GPLv3+");
#define GRUB_DEFAULT_HISTORY_SIZE 50
static int nested_level = 0;
int grub_normal_exit_level = 0;
void
grub_normal_free_menu (grub_menu_t menu)
{
grub_menu_entry_t entry = menu->entry_list;
while (entry)
{
grub_menu_entry_t next_entry = entry->next;
grub_size_t i;
if (entry->classes)
{
struct grub_menu_entry_class *class;
for (class = entry->classes; class; class = class->next)
grub_free (class->name);
grub_free (entry->classes);
}
if (entry->args)
{
for (i = 0; entry->args[i]; i++)
grub_free (entry->args[i]);
grub_free (entry->args);
}
if (entry->bls)
{
entry->bls->visible = 0;
}
grub_free ((void *) entry->id);
grub_free ((void *) entry->users);
grub_free ((void *) entry->title);
grub_free ((void *) entry->sourcecode);
grub_free (entry);
entry = next_entry;
}
grub_free (menu);
grub_env_unset_menu ();
}
/* Helper for read_config_file. */
static grub_err_t
read_config_file_getline (char **line, int cont __attribute__ ((unused)),
void *data)
{
grub_file_t file = data;
while (1)
{
char *buf;
*line = buf = grub_file_getline (file);
if (! buf)
return grub_errno;
if (buf[0] == '#')
grub_free (*line);
else
break;
}
return GRUB_ERR_NONE;
}
static grub_menu_t
read_config_file (const char *config)
{
grub_file_t rawfile, file;
char *old_file = 0, *old_dir = 0;
char *config_dir, *ptr = 0;
const char *ctmp;
grub_menu_t newmenu;
newmenu = grub_env_get_menu ();
if (! newmenu)
{
newmenu = grub_zalloc (sizeof (*newmenu));
if (! newmenu)
return 0;
grub_env_set_menu (newmenu);
}
/* Try to open the config file. */
rawfile = grub_file_open (config, GRUB_FILE_TYPE_CONFIG);
if (! rawfile)
return 0;
file = grub_bufio_open (rawfile, 0);
if (! file)
{
grub_file_close (rawfile);
return 0;
}
ctmp = grub_env_get ("config_file");
if (ctmp)
old_file = grub_strdup (ctmp);
ctmp = grub_env_get ("config_directory");
if (ctmp)
old_dir = grub_strdup (ctmp);
if (*config == '(')
{
grub_env_set ("config_file", config);
config_dir = grub_strdup (config);
}
else
{
/* $root is guranteed to be defined, otherwise open above would fail */
config_dir = grub_xasprintf ("(%s)%s", grub_env_get ("root"), config);
if (config_dir)
grub_env_set ("config_file", config_dir);
}
if (config_dir)
{
ptr = grub_strrchr (config_dir, '/');
if (ptr)
*ptr = 0;
grub_env_set ("config_directory", config_dir);
grub_free (config_dir);
}
grub_env_export ("config_file");
grub_env_export ("config_directory");
while (1)
{
char *line;
/* Print an error, if any. */
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
if ((read_config_file_getline (&line, 0, file)) || (! line))
break;
grub_normal_parse_line (line, read_config_file_getline, file);
grub_free (line);
}
if (old_file)
grub_env_set ("config_file", old_file);
else
grub_env_unset ("config_file");
if (old_dir)
grub_env_set ("config_directory", old_dir);
else
grub_env_unset ("config_directory");
grub_free (old_file);
grub_free (old_dir);
grub_file_close (file);
return newmenu;
}
/* Initialize the screen. */
void
grub_normal_init_page (struct grub_term_output *term,
int y)
{
grub_ssize_t msg_len;
int posx;
char *msg_formatted;
grub_uint32_t *unicode_msg;
grub_uint32_t *last_position;
grub_term_cls (term);
msg_formatted = grub_xasprintf (_("GNU GRUB version %s"), PACKAGE_VERSION);
if (!msg_formatted)
return;
msg_len = grub_utf8_to_ucs4_alloc (msg_formatted,
&unicode_msg, &last_position);
grub_free (msg_formatted);
if (msg_len < 0)
{
return;
}
posx = grub_getstringwidth (unicode_msg, last_position, term);
posx = ((int) grub_term_width (term) - posx) / 2;
if (posx < 0)
posx = 0;
grub_term_gotoxy (term, (struct grub_term_coordinate) { posx, y });
grub_print_ucs4 (unicode_msg, last_position, 0, 0, term);
grub_putcode ('\n', term);
grub_putcode ('\n', term);
grub_free (unicode_msg);
}
static void
read_lists (const char *val)
{
if (! grub_no_modules)
{
read_command_list (val);
read_fs_list (val);
read_crypto_list (val);
read_terminal_list (val);
}
grub_gettext_reread_prefix (val);
}
static char *
read_lists_hook (struct grub_env_var *var __attribute__ ((unused)),
const char *val)
{
read_lists (val);
return val ? grub_strdup (val) : NULL;
}
/* Read the config file CONFIG and execute the menu interface or
the command line interface if BATCH is false. */
void
grub_normal_execute (const char *config, int nested, int batch)
{
grub_menu_t menu = 0;
const char *prefix;
if (! nested)
{
prefix = grub_env_get ("prefix");
read_lists (prefix);
grub_register_variable_hook ("prefix", NULL, read_lists_hook);
}
grub_boot_time ("Executing config file");
if (config)
{
menu = read_config_file (config);
/* Ignore any error. */
grub_errno = GRUB_ERR_NONE;
}
grub_boot_time ("Executed config file");
if (! batch)
{
if (menu && menu->size)
{
grub_boot_time ("Entering menu");
grub_show_menu (menu, nested, 0);
if (nested)
grub_normal_free_menu (menu);
}
}
}
/* This starts the normal mode. */
void
grub_enter_normal_mode (const char *config)
{
grub_boot_time ("Entering normal mode");
nested_level++;
grub_normal_execute (config, 0, 0);
grub_boot_time ("Entering shell");
grub_cmdline_run (0, 1);
nested_level--;
if (grub_normal_exit_level)
grub_normal_exit_level--;
grub_boot_time ("Exiting normal mode");
}
/* Enter normal mode from rescue mode. */
static grub_err_t
grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
int argc, char *argv[])
{
if (argc == 0)
{
/* Guess the config filename. It is necessary to make CONFIG static,
so that it won't get broken by longjmp. */
char *config;
const char *prefix;
prefix = grub_env_get ("prefix");
if (prefix)
{
config = grub_xasprintf ("%s/grub.cfg", prefix);
if (! config)
goto quit;
grub_enter_normal_mode (config);
grub_free (config);
}
else
grub_enter_normal_mode (0);
}
else
grub_enter_normal_mode (argv[0]);
quit:
return 0;
}
/* Exit from normal mode to rescue mode. */
static grub_err_t
grub_cmd_normal_exit (struct grub_command *cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char *argv[] __attribute__ ((unused)))
{
if (nested_level <= grub_normal_exit_level)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "not in normal environment");
grub_normal_exit_level++;
return GRUB_ERR_NONE;
}
static grub_err_t
grub_normal_reader_init (int nested)
{
struct grub_term_output *term;
const char *msg_esc = _("ESC at any time exits.");
char *msg_formatted;
msg_formatted = grub_xasprintf (_("Minimal BASH-like line editing is supported. For "
"the first word, TAB lists possible command completions. Anywhere "
"else TAB lists possible device or file completions. %s"),
nested ? msg_esc : "");
if (!msg_formatted)
return grub_errno;
FOR_ACTIVE_TERM_OUTPUTS(term)
{
grub_normal_init_page (term, 1);
grub_term_setcursor (term, 1);
if (grub_term_width (term) > 3 + STANDARD_MARGIN + 20)
grub_print_message_indented (msg_formatted, 3, STANDARD_MARGIN, term);
else
grub_print_message_indented (msg_formatted, 0, 0, term);
grub_putcode ('\n', term);
grub_putcode ('\n', term);
grub_putcode ('\n', term);
}
grub_free (msg_formatted);
return 0;
}
static grub_err_t
grub_normal_read_line_real (char **line, int cont, int nested)
{
const char *prompt;
if (cont)
/* TRANSLATORS: it's command line prompt. */
prompt = _(">");
else
/* TRANSLATORS: it's command line prompt. */
prompt = _("grub>");
if (!prompt)
return grub_errno;
while (1)
{
*line = grub_cmdline_get (prompt);
if (*line)
return 0;
if (cont || nested)
{
grub_free (*line);
*line = 0;
return grub_errno;
}
}
}
static grub_err_t
grub_normal_read_line (char **line, int cont,
void *data __attribute__ ((unused)))
{
return grub_normal_read_line_real (line, cont, 0);
}
void
grub_cmdline_run (int nested, int force_auth)
{
grub_err_t err = GRUB_ERR_NONE;
do
{
err = grub_auth_check_authentication (NULL);
}
while (err && force_auth);
if (err)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
return;
}
grub_normal_reader_init (nested);
while (1)
{
char *line = NULL;
if (grub_normal_exit_level)
break;
/* Print an error, if any. */
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
grub_normal_read_line_real (&line, 0, nested);
if (! line)
break;
grub_normal_parse_line (line, grub_normal_read_line, NULL);
grub_free (line);
}
}
static char *
grub_env_write_pager (struct grub_env_var *var __attribute__ ((unused)),
const char *val)
{
grub_set_more ((*val == '1'));
return grub_strdup (val);
}
/* clear */
static grub_err_t
grub_mini_cmd_clear (struct grub_command *cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char *argv[] __attribute__ ((unused)))
{
grub_cls ();
return 0;
}
static grub_command_t cmd_clear;
static void (*grub_xputs_saved) (const char *str);
static const char *features[] = {
"feature_chainloader_bpb", "feature_ntldr", "feature_platform_search_hint",
"feature_default_font_path", "feature_all_video_module",
"feature_menuentry_id", "feature_menuentry_options", "feature_200_final",
"feature_nativedisk_cmd", "feature_timeout_style"
};
GRUB_MOD_INIT(normal)
{
unsigned i;
grub_boot_time ("Preparing normal module");
/* Previously many modules depended on gzio. Be nice to user and load it. */
grub_dl_load ("gzio");
grub_errno = 0;
grub_normal_auth_init ();
grub_context_init ();
grub_script_init ();
grub_menu_init ();
grub_xputs_saved = grub_xputs;
grub_xputs = grub_xputs_normal;
/* Normal mode shouldn't be unloaded. */
if (mod)
grub_dl_ref (mod);
cmd_clear =
grub_register_command ("clear", grub_mini_cmd_clear,
0, N_("Clear the screen."));
grub_set_history (GRUB_DEFAULT_HISTORY_SIZE);
grub_register_variable_hook ("pager", 0, grub_env_write_pager);
grub_env_export ("pager");
/* Register a command "normal" for the rescue mode. */
grub_register_command ("normal", grub_cmd_normal,
0, N_("Enter normal mode."));
grub_register_command ("normal_exit", grub_cmd_normal_exit,
0, N_("Exit from normal mode."));
/* Reload terminal colors when these variables are written to. */
grub_register_variable_hook ("color_normal", NULL, grub_env_write_color_normal);
grub_register_variable_hook ("color_highlight", NULL, grub_env_write_color_highlight);
/* Preserve hooks after context changes. */
grub_env_export ("color_normal");
grub_env_export ("color_highlight");
/* Set default color names. */
grub_env_set ("color_normal", "light-gray/black");
grub_env_set ("color_highlight", "black/light-gray");
for (i = 0; i < ARRAY_SIZE (features); i++)
{
grub_env_set (features[i], "y");
grub_env_export (features[i]);
}
grub_env_set ("grub_cpu", GRUB_TARGET_CPU);
grub_env_export ("grub_cpu");
grub_env_set ("grub_platform", GRUB_PLATFORM);
grub_env_export ("grub_platform");
grub_boot_time ("Normal module prepared");
}
GRUB_MOD_FINI(normal)
{
grub_context_fini ();
grub_script_fini ();
grub_menu_fini ();
grub_normal_auth_fini ();
grub_xputs = grub_xputs_saved;
grub_set_history (0);
grub_register_variable_hook ("pager", 0, 0);
grub_fs_autoload_hook = 0;
grub_unregister_command (cmd_clear);
}

@ -803,6 +803,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
goto refresh;
case GRUB_TERM_KEY_F2:
case '2':
if (0 == g_ventoy_fn_mutex) {
cmdstr = grub_env_get("VTOY_F2_CMD");
if (cmdstr)
@ -816,6 +817,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
}
break;
case GRUB_TERM_KEY_F3:
case '3':
if (0 == g_ventoy_fn_mutex) {
cmdstr = grub_env_get("VTOY_F3_CMD");
if (cmdstr)
@ -827,6 +829,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
}
break;
case GRUB_TERM_KEY_F4:
case '4':
if (0 == g_ventoy_fn_mutex) {
cmdstr = grub_env_get("VTOY_F4_CMD");
if (cmdstr)
@ -840,6 +843,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
}
break;
case GRUB_TERM_KEY_F5:
case '5':
if (0 == g_ventoy_fn_mutex) {
cmdstr = grub_env_get("VTOY_F5_CMD");
if (cmdstr)
@ -853,6 +857,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
}
break;
case GRUB_TERM_KEY_F6:
case '6':
if (0 == g_ventoy_fn_mutex) {
cmdstr = grub_env_get("VTOY_F6_CMD");
if (cmdstr)
@ -866,6 +871,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
}
break;
case GRUB_TERM_KEY_F7:
case '7':
cmdstr = grub_env_get("VTOY_F7_CMD");
if (cmdstr)
{
@ -875,6 +881,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
}
break;
case GRUB_TERM_KEY_F1:
case '1':
menu_fini ();
g_ventoy_memdisk_mode = 1 - g_ventoy_memdisk_mode;
g_ventoy_menu_refresh = 1;

@ -180,11 +180,13 @@ command-line or ESC to discard edits and return to the GRUB menu."),
if (nested)
{
#if 0
ret += grub_print_message_indented_real
(_("Press enter to boot the selected OS, "
"`e' to edit the commands before booting "
"or `c' for a command-line. ESC to return previous menu."),
STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
#endif
}
else
{
@ -195,7 +197,7 @@ command-line or ESC to discard edits and return to the GRUB menu."),
ret += grub_print_message_indented_real("\n", STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
ret += grub_print_message_indented_real(grub_env_get("VTOY_HOTKEY_TIP"),
STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
3, 6, term, dry_run);
}
}
return ret;

@ -34,6 +34,7 @@
#include <grub/i18n.h>
#include <grub/net.h>
#include <grub/misc.h>
#include <grub/kernel.h>
#ifdef GRUB_MACHINE_EFI
#include <grub/efi/efi.h>
#endif
@ -317,6 +318,38 @@ static grub_err_t ventoy_cmd_strstr(grub_extcmd_context_t ctxt, int argc, char *
return (grub_strstr(args[0], args[1])) ? 0 : 1;
}
static grub_err_t ventoy_cmd_strbegin(grub_extcmd_context_t ctxt, int argc, char **args)
{
char *c0, *c1;
(void)ctxt;
if (argc != 2)
{
return 1;
}
c0 = args[0];
c1 = args[1];
while (*c0 && *c1)
{
if (*c0 != *c1)
{
return 1;
}
c0++;
c1++;
}
if (*c1)
{
return 1;
}
return 0;
}
static grub_err_t ventoy_cmd_incr(grub_extcmd_context_t ctxt, int argc, char **args)
{
long value_long = 0;
@ -410,7 +443,122 @@ static grub_err_t ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt, int argc,
return 0;
}
static grub_err_t ventoy_cmd_load_iso_to_mem(grub_extcmd_context_t ctxt, int argc, char **args)
static int ventoy_load_efiboot_template(char **buf, int *datalen, int *direntoff)
{
int len;
grub_file_t file;
char exec[128];
char *data = NULL;
grub_uint32_t offset;
file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
if (file == NULL)
{
debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
return 1;
}
len = (int)file->size;
data = (char *)grub_malloc(file->size);
if (!data)
{
return 1;
}
grub_file_read(file, data, file->size);
grub_file_close(file);
grub_snprintf(exec, sizeof(exec), "loopback efiboot mem:0x%llx:size:%d", (ulonglong)(ulong)data, len);
grub_script_execute_sourcecode(exec);
file = grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD);
offset = (grub_uint32_t)grub_iso9660_get_last_file_dirent_pos(file);
grub_file_close(file);
grub_script_execute_sourcecode("loopback -d efiboot");
*buf = data;
*datalen = len;
*direntoff = offset + 2;
return 0;
}
static grub_err_t ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt, int argc, char **args)
{
int len = 0;
int totlen = 0;
int offset = 0;
grub_file_t file;
char name[32];
char value[32];
char *buf = NULL;
char *data = NULL;
ventoy_iso9660_override *dirent;
(void)ctxt;
if (argc != 2)
{
return 1;
}
totlen = sizeof(ventoy_chain_head);
if (ventoy_load_efiboot_template(&buf, &len, &offset))
{
debug("failed to load efiboot template %d\n", len);
return 1;
}
totlen += len;
debug("efiboot template len:%d offset:%d\n", len, offset);
file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s", args[0]);
if (file == NULL)
{
debug("failed to open file <%s>\n", args[0]);
return 1;
}
totlen += ventoy_align_2k(file->size);
dirent = (ventoy_iso9660_override *)(buf + offset);
dirent->first_sector = len / 2048;
dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
dirent->size = (grub_uint32_t)file->size;
dirent->size_be = grub_swap_bytes32(dirent->size);
debug("rawiso len:%d efilen:%d total:%d\n", len, (int)file->size, totlen);
#ifdef GRUB_MACHINE_EFI
data = (char *)grub_efi_allocate_iso_buf(totlen);
#else
data = (char *)grub_malloc(totlen);
#endif
ventoy_fill_os_param(file, (ventoy_os_param *)data);
grub_memcpy(data + sizeof(ventoy_chain_head), buf, len);
grub_check_free(buf);
grub_file_read(file, data + sizeof(ventoy_chain_head) + len, file->size);
grub_file_close(file);
grub_snprintf(name, sizeof(name), "%s_addr", args[1]);
grub_snprintf(value, sizeof(value), "0x%llx", (ulonglong)(ulong)data);
grub_env_set(name, value);
grub_snprintf(name, sizeof(name), "%s_size", args[1]);
grub_snprintf(value, sizeof(value), "%d", (int)(totlen));
grub_env_set(name, value);
return 0;
}
static grub_err_t ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt, int argc, char **args)
{
int rc = 1;
char name[32];
@ -430,7 +578,7 @@ static grub_err_t ventoy_cmd_load_iso_to_mem(grub_extcmd_context_t ctxt, int arg
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (file == NULL)
{
debug("failed to open file <%s> for udf check\n", args[0]);
debug("failed to open file <%s>\n", args[0]);
return 1;
}
@ -456,6 +604,57 @@ static grub_err_t ventoy_cmd_load_iso_to_mem(grub_extcmd_context_t ctxt, int arg
return rc;
}
static grub_err_t ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt, int argc, char **args)
{
int rc = 1;
int headlen;
char name[32];
char value[32];
char *buf = NULL;
grub_file_t file;
(void)ctxt;
(void)argc;
(void)args;
if (argc != 2)
{
return rc;
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (file == NULL)
{
debug("failed to open file <%s> for udf check\n", args[0]);
return 1;
}
headlen = sizeof(ventoy_chain_head);
#ifdef GRUB_MACHINE_EFI
buf = (char *)grub_efi_allocate_iso_buf(headlen + file->size);
#else
buf = (char *)grub_malloc(headlen + file->size);
#endif
ventoy_fill_os_param(file, (ventoy_os_param *)buf);
grub_file_read(file, buf + headlen, file->size);
grub_snprintf(name, sizeof(name), "%s_addr", args[1]);
grub_snprintf(value, sizeof(value), "0x%llx", (unsigned long long)(unsigned long)buf);
grub_env_set(name, value);
grub_snprintf(name, sizeof(name), "%s_size", args[1]);
grub_snprintf(value, sizeof(value), "%llu", (unsigned long long)file->size);
grub_env_set(name, value);
grub_file_close(file);
rc = 0;
return rc;
}
static grub_err_t ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
@ -834,6 +1033,14 @@ static int ventoy_colect_img_files(const char *filename, const struct grub_dirho
type = img_type_efi;
}
#endif
else if (0 == grub_strcasecmp(filename + len - 4, ".img"))
{
if (len == 18 && grub_strncmp(filename, "ventoy_wimboot", 14) == 0)
{
return 0;
}
type = img_type_img;
}
else
{
return 0;
@ -1359,13 +1566,14 @@ static grub_err_t ventoy_cmd_img_name(grub_extcmd_context_t ctxt, int argc, char
static grub_err_t ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt, int argc, char **args)
{
int img_id = 0;
char value[32];
char *pos = NULL;
const char *id = NULL;
img_info *cur = g_ventoy_img_list;
(void)ctxt;
if (argc != 1)
if (argc < 1 || argc > 2)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {var}", cmd_raw_name);
}
@ -1398,6 +1606,12 @@ static grub_err_t ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt, int arg
grub_env_set(args[0], cur->path);
if (argc > 1)
{
grub_snprintf(value, sizeof(value), "%llu", (ulonglong)(cur->size));
grub_env_set(args[1], value);
}
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
@ -2366,6 +2580,28 @@ end:
return 0;
}
static grub_err_t ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
ventoy_env_hook_root(1);
return 0;
}
static grub_err_t ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
ventoy_env_hook_root(0);
return 0;
}
grub_uint64_t ventoy_grub_get_file_size(const char *fmt, ...)
{
grub_uint64_t size = 0;
@ -2489,6 +2725,7 @@ static cmd_para ventoy_cmds[] =
{
{ "vt_incr", ventoy_cmd_incr, 0, NULL, "{Var} {INT}", "Increase integer variable", NULL },
{ "vt_strstr", ventoy_cmd_strstr, 0, NULL, "", "", NULL },
{ "vt_str_begin", ventoy_cmd_strbegin, 0, NULL, "", "", NULL },
{ "vt_debug", ventoy_cmd_debug, 0, NULL, "{on|off}", "turn debug on/off", NULL },
{ "vtdebug", ventoy_cmd_debug, 0, NULL, "{on|off}", "turn debug on/off", NULL },
{ "vtbreak", ventoy_cmd_break, 0, NULL, "{level}", "set debug break", NULL },
@ -2502,7 +2739,10 @@ static cmd_para ventoy_cmds[] =
{ "vt_img_sector", ventoy_cmd_img_sector, 0, NULL, "{imageName}", "", NULL },
{ "vt_dump_img_sector", ventoy_cmd_dump_img_sector, 0, NULL, "", "", NULL },
{ "vt_load_wimboot", ventoy_cmd_load_wimboot, 0, NULL, "", "", NULL },
{ "vt_load_cpio", ventoy_cmd_load_cpio, 0, NULL, "", "", NULL },
{ "vt_trailer_cpio", ventoy_cmd_trailer_cpio, 0, NULL, "", "", NULL },
{ "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd, 0, NULL, "", "", NULL },
{ "vt_dump_menu", ventoy_cmd_dump_menu, 0, NULL, "", "", NULL },
{ "vt_dynamic_menu", ventoy_cmd_dynamic_menu, 0, NULL, "", "", NULL },
@ -2517,7 +2757,9 @@ static cmd_para ventoy_cmds[] =
{ "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet, 0, NULL, "", "", NULL },
{ "vt_is_udf", ventoy_cmd_is_udf, 0, NULL, "", "", NULL },
{ "vt_file_size", ventoy_cmd_file_size, 0, NULL, "", "", NULL },
{ "vt_load_iso_to_mem", ventoy_cmd_load_iso_to_mem, 0, NULL, "", "", NULL },
{ "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem, 0, NULL, "", "", NULL },
{ "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk, 0, NULL, "", "", NULL },
{ "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso, 0, NULL, "", "", NULL },
{ "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect, 0, NULL, "{cfgfile}", "", NULL },
{ "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect, 0, NULL, "{cfgfile}", "", NULL },
@ -2557,6 +2799,9 @@ static cmd_para ventoy_cmds[] =
{ "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko, 0, NULL, "", "", NULL },
{ "vt_unix_chain_data", ventoy_cmd_unix_chain_data, 0, NULL, "", "", NULL },
{ "vt_img_hook_root", ventoy_cmd_img_hook_root, 0, NULL, "", "", NULL },
{ "vt_img_unhook_root", ventoy_cmd_img_unhook_root, 0, NULL, "", "", NULL },
};

@ -467,6 +467,7 @@ grub_err_t ventoy_cmd_linux_locate_initrd(grub_extcmd_context_t ctxt, int argc,
grub_err_t ventoy_cmd_initrd_count(grub_extcmd_context_t ctxt, int argc, char **args);
grub_err_t ventoy_cmd_valid_initrd_count(grub_extcmd_context_t ctxt, int argc, char **args);
grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **args);
grub_err_t ventoy_cmd_trailer_cpio(grub_extcmd_context_t ctxt, int argc, char **args);
int ventoy_cpio_newc_fill_head(void *buf, int filesize, const void *filedata, const char *name);
grub_file_t ventoy_grub_file_open(enum grub_file_type type, const char *fmt, ...);
grub_uint64_t ventoy_grub_get_file_size(const char *fmt, ...);

@ -564,6 +564,14 @@ grub_err_t ventoy_cmd_specify_initrd_file(grub_extcmd_context_t ctxt, int argc,
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static int ventoy_cpio_newc_get_int(char *value)
{
char buf[16] = {0};
grub_memcpy(buf, value, 8);
return (int)grub_strtoul(buf, NULL, 16);
}
static void ventoy_cpio_newc_fill_int(grub_uint32_t value, char *buf, int buflen)
{
int i;
@ -1082,6 +1090,96 @@ grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **arg
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
grub_err_t ventoy_cmd_trailer_cpio(grub_extcmd_context_t ctxt, int argc, char **args)
{
int mod;
int bufsize;
int namelen;
int offset;
char *name;
grub_uint8_t *bufend;
cpio_newc_header *head;
grub_file_t file;
char value[64];
const grub_uint8_t trailler[124] = {
0x30, 0x37, 0x30, 0x37, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x42, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x54, 0x52,
0x41, 0x49, 0x4C, 0x45, 0x52, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00
};
(void)ctxt;
(void)argc;
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", args[0], args[1]);
if (!file)
{
return 1;
}
grub_memset(g_ventoy_runtime_buf, 0, sizeof(ventoy_os_param));
ventoy_fill_os_param(file, (ventoy_os_param *)g_ventoy_runtime_buf);
grub_file_close(file);
grub_memcpy(g_ventoy_initrd_head, trailler, sizeof(trailler));
bufend = (grub_uint8_t *)g_ventoy_initrd_head + sizeof(trailler);
bufsize = (int)(bufend - g_ventoy_cpio_buf);
mod = bufsize % 512;
if (mod)
{
grub_memset(bufend, 0, 512 - mod);
bufsize += 512 - mod;
}
if (argc > 1 && grub_strcmp(args[2], "noinit") == 0)
{
head = (cpio_newc_header *)g_ventoy_cpio_buf;
name = (char *)(head + 1);
while (grub_strcmp(name, "TRAILER!!!"))
{
if (grub_strcmp(name, "init") == 0)
{
grub_memcpy(name, "xxxx", 4);
}
else if (grub_strcmp(name, "linuxrc") == 0)
{
grub_memcpy(name, "vtoyxrc", 7);
}
else if (grub_strcmp(name, "sbin") == 0)
{
grub_memcpy(name, "vtoy", 4);
}
else if (grub_strcmp(name, "sbin/init") == 0)
{
grub_memcpy(name, "vtoy/vtoy", 9);
}
namelen = ventoy_cpio_newc_get_int(head->c_namesize);
offset = sizeof(cpio_newc_header) + namelen;
offset = ventoy_align(offset, 4);
offset += ventoy_cpio_newc_get_int(head->c_filesize);
offset = ventoy_align(offset, 4);
head = (cpio_newc_header *)((char *)head + offset);
name = (char *)(head + 1);
}
}
grub_snprintf(value, sizeof(value), "0x%llx", (ulonglong)(ulong)g_ventoy_cpio_buf);
ventoy_set_env("ventoy_cpio_addr", value);
grub_snprintf(value, sizeof(value), "%d", bufsize);
ventoy_set_env("ventoy_cpio_size", value);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
grub_err_t ventoy_cmd_linux_chain_data(grub_extcmd_context_t ctxt, int argc, char **args)
{

@ -151,6 +151,12 @@ static int ventoy_plugin_theme_check(VTOY_JSON *json, const char *isodisk)
grub_printf("display_mode: %s\n", value);
}
value = vtoy_json_get_string_ex(json->pstChild, "serial_param");
if (value)
{
grub_printf("serial_param %s\n", value);
}
value = vtoy_json_get_string_ex(json->pstChild, "ventoy_left");
if (value)
{
@ -236,6 +242,13 @@ static int ventoy_plugin_theme_entry(VTOY_JSON *json, const char *isodisk)
debug("display_mode %s\n", value);
grub_env_set("vtoy_display_mode", value);
}
value = vtoy_json_get_string_ex(json->pstChild, "serial_param");
if (value)
{
debug("serial_param %s\n", value);
grub_env_set("vtoy_serial_param", value);
}
value = vtoy_json_get_string_ex(json->pstChild, "ventoy_left");
if (value)

@ -0,0 +1,631 @@
/******************************************************************************
* ventoy_unix.c
*
* 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/>.
*
*/
#include <grub/types.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/disk.h>
#include <grub/device.h>
#include <grub/term.h>
#include <grub/partition.h>
#include <grub/file.h>
#include <grub/normal.h>
#include <grub/extcmd.h>
#include <grub/datetime.h>
#include <grub/i18n.h>
#include <grub/net.h>
#include <grub/time.h>
#include <grub/ventoy.h>
#include "ventoy_def.h"
GRUB_MOD_LICENSE ("GPLv3+");
char g_ko_mod_path[256];
int g_conf_new_len = 0;
char *g_conf_new_data = NULL;
int g_mod_new_len = 0;
char *g_mod_new_data = NULL;
grub_uint64_t g_mod_override_offset = 0;
grub_uint64_t g_conf_override_offset = 0;
static int ventoy_get_file_override(const char *filename, grub_uint64_t *offset)
{
grub_file_t file;
*offset = 0;
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(loop)%s", filename);
if (!file)
{
return 1;
}
*offset = grub_iso9660_get_last_file_dirent_pos(file) + 2;
grub_file_close(file);
return 0;
}
static grub_uint32_t ventoy_unix_get_override_chunk_count(void)
{
grub_uint32_t count = 0;
if (g_conf_new_len > 0)
{
count++;
}
if (g_mod_new_len > 0)
{
count++;
}
return count;
}
static grub_uint32_t ventoy_unix_get_virt_chunk_count(void)
{
grub_uint32_t count = 0;
if (g_conf_new_len > 0)
{
count++;
}
if (g_mod_new_len > 0)
{
count++;
}
return count;
}
static grub_uint32_t ventoy_unix_get_virt_chunk_size(void)
{
grub_uint32_t size;
size = sizeof(ventoy_virt_chunk) * ventoy_unix_get_virt_chunk_count();
if (g_conf_new_len > 0)
{
size += ventoy_align_2k(g_conf_new_len);
}
if (g_mod_new_len > 0)
{
size += ventoy_align_2k(g_mod_new_len);
}
return size;
}
static void ventoy_unix_fill_override_data( grub_uint64_t isosize, void *override)
{
grub_uint64_t sector;
ventoy_override_chunk *cur;
ventoy_iso9660_override *dirent;
sector = (isosize + 2047) / 2048;
cur = (ventoy_override_chunk *)override;
if (g_conf_new_len > 0)
{
/* loader.conf */
cur->img_offset = g_conf_override_offset;
cur->override_size = sizeof(ventoy_iso9660_override);
dirent = (ventoy_iso9660_override *)cur->override_data;
dirent->first_sector = (grub_uint32_t)sector;
dirent->size = (grub_uint32_t)g_conf_new_len;
dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
dirent->size_be = grub_swap_bytes32(dirent->size);
sector += (dirent->size + 2047) / 2048;
}
if (g_mod_new_len > 0)
{
/* mod.ko */
cur++;
cur->img_offset = g_mod_override_offset;
cur->override_size = sizeof(ventoy_iso9660_override);
dirent = (ventoy_iso9660_override *)cur->override_data;
dirent->first_sector = (grub_uint32_t)sector;
dirent->size = (grub_uint32_t)g_mod_new_len;
dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
dirent->size_be = grub_swap_bytes32(dirent->size);
sector += (dirent->size + 2047) / 2048;
}
return;
}
static void ventoy_unix_fill_virt_data( grub_uint64_t isosize, ventoy_chain_head *chain)
{
grub_uint64_t sector;
grub_uint32_t offset;
grub_uint32_t data_secs;
char *override;
ventoy_virt_chunk *cur;
override = (char *)chain + chain->virt_chunk_offset;
cur = (ventoy_virt_chunk *)override;
sector = (isosize + 2047) / 2048;
offset = 2 * sizeof(ventoy_virt_chunk);
if (g_conf_new_len > 0)
{
ventoy_unix_fill_virt(g_conf_new_data, g_conf_new_len);
}
if (g_mod_new_len > 0)
{
ventoy_unix_fill_virt(g_mod_new_data, g_mod_new_len);
}
return;
}
static int ventoy_freebsd_append_conf(char *buf, const char *isopath)
{
int pos = 0;
grub_uint32_t i;
grub_disk_t disk;
grub_file_t isofile;
char uuid[64] = {0};
ventoy_img_chunk *chunk;
grub_uint8_t disk_guid[16];
debug("ventoy_freebsd_append_conf %s\n", isopath);
isofile = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", isopath);
if (!isofile)
{
return 1;
}
vtoy_ssprintf(buf, pos, "ventoy_load=\"%s\"\n", "YES");
vtoy_ssprintf(buf, pos, "ventoy_name=\"%s\"\n", g_ko_mod_path);
disk = isofile->device->disk;
ventoy_get_disk_guid(isofile->name, disk_guid);
for (i = 0; i < 16; i++)
{
grub_snprintf(uuid + i * 2, sizeof(uuid), "%02x", disk_guid[i]);
}
vtoy_ssprintf(buf, pos, "hint.ventoy.0.disksize=%llu\n", (ulonglong)(disk->total_sectors * (1 << disk->log_sector_size)));
vtoy_ssprintf(buf, pos, "hint.ventoy.0.diskuuid=\"%s\"\n", uuid);
vtoy_ssprintf(buf, pos, "hint.ventoy.0.segnum=%u\n", g_img_chunk_list.cur_chunk);
for (i = 0; i < g_img_chunk_list.cur_chunk; i++)
{
chunk = g_img_chunk_list.chunk + i;
vtoy_ssprintf(buf, pos, "hint.ventoy.%u.seg=\"0x%llx@0x%llx\"\n",
i, (ulonglong)(chunk->disk_start_sector * 512),
(ulonglong)((chunk->disk_end_sector + 1) * 512));
}
grub_file_close(isofile);
return pos;
}
grub_err_t ventoy_cmd_unix_reset(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
g_conf_new_len = 0;
g_mod_new_len = 0;
g_mod_override_offset = 0;
g_conf_override_offset = 0;
check_free(g_mod_new_data, grub_free);
check_free(g_conf_new_data, grub_free);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
grub_err_t ventoy_cmd_parse_freenas_ver(grub_extcmd_context_t ctxt, int argc, char **args)
{
grub_file_t file;
const char *ver = NULL;
char *buf = NULL;
VTOY_JSON *json = NULL;
(void)ctxt;
(void)argc;
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (!file)
{
debug("Failed to open file %s\n", args[0]);
return 1;
}
buf = grub_malloc(file->size + 2);
if (!buf)
{
grub_file_close(file);
return 0;
}
grub_file_read(file, buf, file->size);
buf[file->size] = 0;
json = vtoy_json_create();
if (!json)
{
goto end;
}
if (vtoy_json_parse(json, buf))
{
goto end;
}
ver = vtoy_json_get_string_ex(json->pstChild, "Version");
if (ver)
{
debug("freenas version:<%s>\n", ver);
ventoy_set_env(args[1], ver);
}
else
{
debug("freenas version:<%s>\n", "NOT FOUND");
grub_env_unset(args[1]);
}
end:
grub_check_free(buf);
check_free(json, vtoy_json_destroy);
grub_file_close(file);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
grub_err_t ventoy_cmd_unix_freebsd_ver(grub_extcmd_context_t ctxt, int argc, char **args)
{
grub_file_t file;
char *buf;
char *start = NULL;
char *nextline = NULL;
(void)ctxt;
(void)argc;
(void)args;
file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s", args[0]);
if (!file)
{
debug("Failed to open file %s\n", args[0]);
return 1;
}
buf = grub_zalloc(file->size + 2);
if (!buf)
{
grub_file_close(file);
return 0;
}
grub_file_read(file, buf, file->size);
for (start = buf; start; start = nextline)
{
if (grub_strncmp(start, "USERLAND_VERSION", 16) == 0)
{
nextline = start;
while (*nextline && *nextline != '\r' && *nextline != '\n')
{
nextline++;
}
*nextline = 0;
break;
}
nextline = ventoy_get_line(start);
}
if (start)
{
debug("freebsd version:<%s>\n", start);
ventoy_set_env(args[1], start);
}
else
{
debug("freebsd version:<%s>\n", "NOT FOUND");
grub_env_unset(args[1]);
}
grub_free(buf);
grub_file_close(file);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
grub_err_t ventoy_cmd_unix_replace_conf(grub_extcmd_context_t ctxt, int argc, char **args)
{
grub_uint32_t i;
char *data;
grub_uint64_t offset;
grub_file_t file;
const char *confile = NULL;
const char * loader_conf[] =
{
"/boot/loader.conf",
"/boot/defaults/loader.conf",
};
(void)ctxt;
if (argc != 2)
{
debug("Replace conf invalid argc %d\n", argc);
return 1;
}
for (i = 0; i < sizeof(loader_conf) / sizeof(loader_conf[0]); i++)
{
if (ventoy_get_file_override(loader_conf[i], &offset) == 0)
{
confile = loader_conf[i];
g_conf_override_offset = offset;
break;
}
}
if (confile == NULL)
{
debug("Can't find loader.conf file from %u locations\n", i);
return 1;
}
file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "(loop)/%s", confile);
if (!file)
{
debug("Failed to open %s \n", confile);
return 1;
}
debug("old conf file size:%d\n", (int)file->size);
data = grub_malloc(VTOY_MAX_SCRIPT_BUF);
if (!data)
{
grub_file_close(file);
return 1;
}
grub_file_read(file, data, file->size);
grub_file_close(file);
g_conf_new_data = data;
g_conf_new_len = (int)file->size;
if (grub_strcmp(args[0], "FreeBSD") == 0)
{
g_conf_new_len += ventoy_freebsd_append_conf(data + file->size, args[1]);
}
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
grub_err_t ventoy_cmd_unix_replace_ko(grub_extcmd_context_t ctxt, int argc, char **args)
{
char *data;
grub_uint64_t offset;
grub_file_t file;
(void)ctxt;
if (argc != 2)
{
debug("Replace ko invalid argc %d\n", argc);
return 1;
}
debug("replace ko %s\n", args[0]);
if (ventoy_get_file_override(args[0], &offset) == 0)
{
grub_snprintf(g_ko_mod_path, sizeof(g_ko_mod_path), "%s", args[0]);
g_mod_override_offset = offset;
}
else
{
debug("Can't find replace ko file from %s\n", args[0]);
return 1;
}
file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s", args[1]);
if (!file)
{
debug("Failed to open %s \n", args[1]);
return 1;
}
debug("new ko file size:%d\n", (int)file->size);
data = grub_malloc(file->size);
if (!data)
{
grub_file_close(file);
return 1;
}
grub_file_read(file, data, file->size);
grub_file_close(file);
g_mod_new_data = data;
g_mod_new_len = (int)file->size;
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
grub_err_t ventoy_cmd_unix_chain_data(grub_extcmd_context_t ctxt, int argc, char **args)
{
int ventoy_compatible = 0;
grub_uint32_t size = 0;
grub_uint64_t isosize = 0;
grub_uint32_t boot_catlog = 0;
grub_uint32_t img_chunk_size = 0;
grub_uint32_t override_count = 0;
grub_uint32_t override_size = 0;
grub_uint32_t virt_chunk_size = 0;
grub_file_t file;
grub_disk_t disk;
const char *pLastChain = NULL;
const char *compatible;
ventoy_chain_head *chain;
char envbuf[64];
(void)ctxt;
(void)argc;
compatible = grub_env_get("ventoy_compatible");
if (compatible && compatible[0] == 'Y')
{
ventoy_compatible = 1;
}
if (NULL == g_img_chunk_list.chunk)
{
grub_printf("ventoy not ready\n");
return 1;
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (!file)
{
return 1;
}
isosize = file->size;
boot_catlog = ventoy_get_iso_boot_catlog(file);
if (boot_catlog)
{
if (ventoy_is_efi_os() && (!ventoy_has_efi_eltorito(file, boot_catlog)))
{
grub_env_set("LoadIsoEfiDriver", "on");
}
}
else
{
if (ventoy_is_efi_os())
{
grub_env_set("LoadIsoEfiDriver", "on");
}
else
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "File %s is not bootable", args[0]);
}
}
img_chunk_size = g_img_chunk_list.cur_chunk * sizeof(ventoy_img_chunk);
if (ventoy_compatible)
{
size = sizeof(ventoy_chain_head) + img_chunk_size;
}
else
{
override_count = ventoy_unix_get_override_chunk_count();
override_size = override_count * sizeof(ventoy_override_chunk);
virt_chunk_size = ventoy_unix_get_virt_chunk_size();
size = sizeof(ventoy_chain_head) + img_chunk_size + override_size + virt_chunk_size;
}
pLastChain = grub_env_get("vtoy_chain_mem_addr");
if (pLastChain)
{
chain = (ventoy_chain_head *)grub_strtoul(pLastChain, NULL, 16);
if (chain)
{
debug("free last chain memory %p\n", chain);
grub_free(chain);
}
}
chain = grub_malloc(size);
if (!chain)
{
grub_printf("Failed to alloc chain memory size %u\n", size);
grub_file_close(file);
return 1;
}
grub_snprintf(envbuf, sizeof(envbuf), "0x%lx", (unsigned long)chain);
grub_env_set("vtoy_chain_mem_addr", envbuf);
grub_snprintf(envbuf, sizeof(envbuf), "%u", size);
grub_env_set("vtoy_chain_mem_size", envbuf);
grub_memset(chain, 0, sizeof(ventoy_chain_head));
/* part 1: os parameter */
g_ventoy_chain_type = ventoy_chain_linux;
ventoy_fill_os_param(file, &(chain->os_param));
/* part 2: chain head */
disk = file->device->disk;
chain->disk_drive = disk->id;
chain->disk_sector_size = (1 << disk->log_sector_size);
chain->real_img_size_in_bytes = file->size;
chain->virt_img_size_in_bytes = (file->size + 2047) / 2048 * 2048;
chain->boot_catalog = boot_catlog;
if (!ventoy_is_efi_os())
{
grub_file_seek(file, boot_catlog * 2048);
grub_file_read(file, chain->boot_catalog_sector, sizeof(chain->boot_catalog_sector));
}
/* part 3: image chunk */
chain->img_chunk_offset = sizeof(ventoy_chain_head);
chain->img_chunk_num = g_img_chunk_list.cur_chunk;
grub_memcpy((char *)chain + chain->img_chunk_offset, g_img_chunk_list.chunk, img_chunk_size);
if (ventoy_compatible)
{
return 0;
}
/* part 4: override chunk */
chain->override_chunk_offset = chain->img_chunk_offset + img_chunk_size;
chain->override_chunk_num = override_count;
ventoy_unix_fill_override_data(isosize, (char *)chain + chain->override_chunk_offset);
/* part 5: virt chunk */
chain->virt_chunk_offset = chain->override_chunk_offset + override_size;
chain->virt_chunk_num = ventoy_unix_get_virt_chunk_count();
ventoy_unix_fill_virt_data(isosize, chain);
grub_file_close(file);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}

@ -0,0 +1,53 @@
/* compiler.h - macros for various compiler features */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2005,2006,2007,2008,2009,2010,2014 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/>.
*/
#ifndef GRUB_COMPILER_HEADER
#define GRUB_COMPILER_HEADER 1
/* GCC version checking borrowed from glibc. */
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
# define GNUC_PREREQ(maj,min) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
#else
# define GNUC_PREREQ(maj,min) 0
#endif
/* Does this compiler support compile-time error attributes? */
#if GNUC_PREREQ(4,3)
# define ATTRIBUTE_ERROR(msg) \
__attribute__ ((__error__ (msg)))
#else
# define ATTRIBUTE_ERROR(msg) __attribute__ ((noreturn))
#endif
#if GNUC_PREREQ(4,4)
# define GNU_PRINTF gnu_printf
#else
# define GNU_PRINTF printf
#endif
#if GNUC_PREREQ(3,4)
# define WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
#else
# define WARN_UNUSED_RESULT
#endif
#define UNUSED __attribute__((__unused__))
#endif /* ! GRUB_COMPILER_HEADER */

@ -0,0 +1,133 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,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/>.
*/
#ifndef GRUB_KERNEL_HEADER
#define GRUB_KERNEL_HEADER 1
#include <grub/types.h>
#include <grub/symbol.h>
enum
{
OBJ_TYPE_ELF,
OBJ_TYPE_MEMDISK,
OBJ_TYPE_CONFIG,
OBJ_TYPE_PREFIX,
OBJ_TYPE_PUBKEY,
OBJ_TYPE_DTB
};
/* The module header. */
struct grub_module_header
{
/* The type of object. */
grub_uint32_t type;
/* The size of object (including this header). */
grub_uint32_t size;
};
/* "gmim" (GRUB Module Info Magic). */
#define GRUB_MODULE_MAGIC 0x676d696d
struct grub_module_info32
{
/* Magic number so we know we have modules present. */
grub_uint32_t magic;
/* The offset of the modules. */
grub_uint32_t offset;
/* The size of all modules plus this header. */
grub_uint32_t size;
};
struct grub_module_info64
{
/* Magic number so we know we have modules present. */
grub_uint32_t magic;
grub_uint32_t padding;
/* The offset of the modules. */
grub_uint64_t offset;
/* The size of all modules plus this header. */
grub_uint64_t size;
};
#ifndef GRUB_UTIL
/* Space isn't reusable on some platforms. */
/* On Qemu the preload space is readonly. */
/* On emu there is no preload space. */
/* On ieee1275 our code assumes that heap is p=v which isn't guaranteed for module space. */
#if defined (GRUB_MACHINE_QEMU) || defined (GRUB_MACHINE_EMU) \
|| defined (GRUB_MACHINE_EFI) \
|| (defined (GRUB_MACHINE_IEEE1275) && !defined (__sparc__))
#define GRUB_KERNEL_PRELOAD_SPACE_REUSABLE 0
#endif
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) \
|| defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) \
|| defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_ARC) \
|| (defined (__sparc__) && defined (GRUB_MACHINE_IEEE1275)) \
|| defined (GRUB_MACHINE_UBOOT) || defined (GRUB_MACHINE_XEN) \
|| defined(GRUB_MACHINE_XEN_PVH)
/* FIXME: stack is between 2 heap regions. Move it. */
#define GRUB_KERNEL_PRELOAD_SPACE_REUSABLE 1
#endif
#ifndef GRUB_KERNEL_PRELOAD_SPACE_REUSABLE
#error "Please check if preload space is reusable on this platform!"
#endif
#if GRUB_TARGET_SIZEOF_VOID_P == 8
#define grub_module_info grub_module_info64
#else
#define grub_module_info grub_module_info32
#endif
extern grub_addr_t EXPORT_VAR (grub_modbase);
void EXPORT_FUNC(ventoy_env_hook_root)(int hook);
#define FOR_MODULES(var) for (\
var = (grub_modbase && ((((struct grub_module_info *) grub_modbase)->magic) == GRUB_MODULE_MAGIC)) ? (struct grub_module_header *) \
(grub_modbase + (((struct grub_module_info *) grub_modbase)->offset)) : 0;\
var && (grub_addr_t) var \
< (grub_modbase + (((struct grub_module_info *) grub_modbase)->size)); \
var = (struct grub_module_header *) \
(((grub_uint32_t *) var) + ((((struct grub_module_header *) var)->size + sizeof (grub_addr_t) - 1) / sizeof (grub_addr_t)) * (sizeof (grub_addr_t) / sizeof (grub_uint32_t))))
grub_addr_t grub_modules_get_end (void);
#endif
/* The start point of the C code. */
void grub_main (void) __attribute__ ((noreturn));
/* The machine-specific initialization. This must initialize memory. */
void grub_machine_init (void);
/* The machine-specific finalization. */
void EXPORT_FUNC(grub_machine_fini) (int flags);
/* The machine-specific prefix initialization. */
void
grub_machine_get_bootlocation (char **device, char **path);
/* Register all the exported symbols. This is automatically generated. */
void grub_register_exported_symbols (void);
extern void (*EXPORT_VAR(grub_net_poll_cards_idle)) (void);
#endif /* ! GRUB_KERNEL_HEADER */

@ -0,0 +1,119 @@
/* menu.h - Menu model function prototypes and data structures. */
/*
* 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/>.
*/
#ifndef GRUB_MENU_HEADER
#define GRUB_MENU_HEADER 1
struct bls_entry
{
struct bls_entry *next;
struct bls_entry *prev;
struct keyval **keyvals;
int nkeyvals;
char *filename;
int visible;
};
struct grub_menu_entry_class
{
char *name;
struct grub_menu_entry_class *next;
};
/* The menu entry. */
struct grub_menu_entry
{
/* The title name. */
const char *title;
/* The identifier. */
const char *id;
/* If set means not everybody is allowed to boot this entry. */
int restricted;
/* Allowed users. */
const char *users;
/* The classes associated with the menu entry:
used to choose an icon or other style attributes.
This is a dummy head node for the linked list, so for an entry E,
E.classes->next is the first class if it is not NULL. */
struct grub_menu_entry_class *classes;
/* The sourcecode of the menu entry, used by the editor. */
const char *sourcecode;
/* Parameters to be passed to menu definition. */
int argc;
char **args;
int hotkey;
int submenu;
/* The next element. */
struct grub_menu_entry *next;
/* BLS used to populate the entry */
struct bls_entry *bls;
};
typedef struct grub_menu_entry *grub_menu_entry_t;
/* The menu. */
struct grub_menu
{
/* The size of a menu. */
int size;
/* The list of menu entries. */
grub_menu_entry_t entry_list;
};
typedef struct grub_menu *grub_menu_t;
/* Callback structure menu viewers can use to provide user feedback when
default entries are executed, possibly including fallback entries. */
typedef struct grub_menu_execute_callback
{
/* Called immediately before ENTRY is booted. */
void (*notify_booting) (grub_menu_entry_t entry, void *userdata);
/* Called when executing one entry has failed, and another entry, ENTRY, will
be executed as a fallback. The implementation of this function should
delay for a period of at least 2 seconds before returning in order to
allow the user time to read the information before it can be lost by
executing ENTRY. */
void (*notify_fallback) (grub_menu_entry_t entry, void *userdata);
/* Called when an entry has failed to execute and there is no remaining
fallback entry to attempt. */
void (*notify_failure) (void *userdata);
}
*grub_menu_execute_callback_t;
grub_menu_entry_t grub_menu_get_entry (grub_menu_t menu, int no);
int grub_menu_get_timeout (void);
void grub_menu_set_timeout (int timeout);
void grub_menu_entry_run (grub_menu_entry_t entry);
int grub_menu_get_default_entry_index (grub_menu_t menu);
void grub_menu_init (void);
void grub_menu_fini (void);
#endif /* GRUB_MENU_HEADER */

@ -0,0 +1,177 @@
/* normal.h - prototypes for the normal mode */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,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/>.
*/
#ifndef GRUB_NORMAL_HEADER
#define GRUB_NORMAL_HEADER 1
#include <grub/term.h>
#include <grub/symbol.h>
#include <grub/err.h>
#include <grub/env.h>
#include <grub/menu.h>
#include <grub/command.h>
#include <grub/file.h>
/* The standard left and right margin for some messages. */
#define STANDARD_MARGIN 6
/* The type of a completion item. */
enum grub_completion_type
{
GRUB_COMPLETION_TYPE_COMMAND,
GRUB_COMPLETION_TYPE_DEVICE,
GRUB_COMPLETION_TYPE_PARTITION,
GRUB_COMPLETION_TYPE_FILE,
GRUB_COMPLETION_TYPE_ARGUMENT
};
typedef enum grub_completion_type grub_completion_type_t;
extern struct grub_menu_viewer grub_normal_text_menu_viewer;
extern int grub_normal_exit_level;
/* Defined in `main.c'. */
void grub_enter_normal_mode (const char *config);
void grub_normal_execute (const char *config, int nested, int batch);
struct grub_term_screen_geometry
{
/* The number of entries shown at a time. */
int num_entries;
int first_entry_y;
int first_entry_x;
int entry_width;
int timeout_y;
int timeout_lines;
int border;
int right_margin;
};
void grub_menu_init_page (int nested, int edit,
struct grub_term_screen_geometry *geo,
struct grub_term_output *term);
void grub_normal_init_page (struct grub_term_output *term, int y);
char *grub_file_getline (grub_file_t file);
void grub_cmdline_run (int nested, int force_auth);
/* Defined in `cmdline.c'. */
char *grub_cmdline_get (const char *prompt);
grub_err_t grub_set_history (int newsize);
/* Defined in `completion.c'. */
char *grub_normal_do_completion (char *buf, int *restore,
void (*hook) (const char *item, grub_completion_type_t type, int count));
/* Defined in `misc.c'. */
grub_err_t grub_normal_print_device_info (const char *name);
/* Defined in `color.c'. */
char *grub_env_write_color_normal (struct grub_env_var *var, const char *val);
char *grub_env_write_color_highlight (struct grub_env_var *var, const char *val);
int grub_parse_color_name_pair (grub_uint8_t *ret, const char *name);
/* Defined in `menu_text.c'. */
void grub_wait_after_message (void);
void
grub_print_ucs4 (const grub_uint32_t * str,
const grub_uint32_t * last_position,
int margin_left, int margin_right,
struct grub_term_output *term);
void
grub_print_ucs4_menu (const grub_uint32_t * str,
const grub_uint32_t * last_position,
int margin_left, int margin_right,
struct grub_term_output *term,
int skip_lines, int max_lines, grub_uint32_t contchar,
struct grub_term_pos *pos);
int
grub_ucs4_count_lines (const grub_uint32_t * str,
const grub_uint32_t * last_position,
int margin_left, int margin_right,
struct grub_term_output *term);
grub_size_t grub_getstringwidth (grub_uint32_t * str,
const grub_uint32_t * last_position,
struct grub_term_output *term);
void grub_print_message_indented (const char *msg, int margin_left,
int margin_right,
struct grub_term_output *term);
void
grub_menu_text_register_instances (int entry, grub_menu_t menu, int nested);
grub_err_t
grub_show_menu (grub_menu_t menu, int nested, int autobooted);
/* Defined in `handler.c'. */
void read_handler_list (void);
void free_handler_list (void);
/* Defined in `dyncmd.c'. */
void read_command_list (const char *prefix);
/* Defined in `autofs.c'. */
void read_fs_list (const char *prefix);
void grub_context_init (void);
void grub_context_fini (void);
void read_crypto_list (const char *prefix);
void read_terminal_list (const char *prefix);
void grub_set_more (int onoff);
void grub_normal_reset_more (void);
void grub_xputs_normal (const char *str);
extern int grub_extractor_level;
grub_err_t
grub_normal_add_menu_entry (int argc, const char **args, char **classes,
const char *id,
const char *users, const char *hotkey,
const char *prefix, const char *sourcecode,
int submenu, int *index, struct bls_entry *bls);
grub_err_t
grub_normal_set_password (const char *user, const char *password);
void grub_normal_free_menu (grub_menu_t menu);
void grub_normal_auth_init (void);
void grub_normal_auth_fini (void);
void
grub_xnputs (const char *str, grub_size_t msg_len);
grub_command_t
grub_dyncmd_get_cmd (grub_command_t cmd);
void
grub_gettext_reread_prefix (const char *val);
enum grub_human_size_type
{
GRUB_HUMAN_SIZE_NORMAL,
GRUB_HUMAN_SIZE_SHORT,
GRUB_HUMAN_SIZE_SPEED,
};
const char *
grub_get_human_size (grub_uint64_t size, enum grub_human_size_type type);
#endif /* ! GRUB_NORMAL_HEADER */

@ -54,7 +54,8 @@ if [ -z "$VTOY_REDT_BUG" ]; then
fi
cd $VTOY_PATH
xz -d ventoy.sh.xz
xz -d ventoy_chain.sh.xz
xz -d ventoy_loop.sh.xz
if [ -n "$VTOY_REDT_BUG" ]; then
xz -d -c hook.cpio.xz | cpio -idm

@ -0,0 +1,150 @@
# Copyright (C) 2009 Red Hat, Inc. All rights reserved.
#
# This file is part of LVM2.
# Udev rules for device-mapper devices.
#
# These rules create a DM control node in /dev/mapper directory.
# The rules also create nodes named dm-x (x is a number) in /dev
# directory and symlinks to these nodes with names given by
# the actual DM names. Some udev environment variables are set
# for use in later rules:
# DM_NAME - actual DM device's name
# DM_UUID - UUID set for DM device (blank if not specified)
# DM_SUSPENDED - suspended state of DM device (0 or 1)
# DM_UDEV_RULES_VSN - DM udev rules version
#
# These rules cover only basic device-mapper functionality in udev.
#
# Various DM subsystems may contain further subsystem-specific rules
# in 11-dm-<subsystem_name>.rules which should be installed together
# with the DM subsystem and which extend these basic rules.
# For example:
# 11-dm-lvm.rules for LVM subsystem
# 11-dm-mpath.rules for multipath subsystem (since version 0.6.0, recommended!)
#
# Even more specific rules may be required by subsystems so always
# check subsystem's upstream repository for recent set of rules.
# Also, keep in mind that recent rules may also require recent
# subsystem-specific binaries.
KERNEL=="device-mapper", NAME="mapper/control"
SUBSYSTEM!="block", GOTO="dm_end"
KERNEL!="dm-[0-9]*", GOTO="dm_end"
# Device created, major and minor number assigned - "add" event generated.
# Table loaded - no event generated.
# Device resumed (or renamed) - "change" event generated.
# Device removed - "remove" event generated.
#
# The dm-X nodes are always created, even on "add" event, we can't suppress
# that (the node is created even earlier with devtmpfs). All the symlinks
# (e.g. /dev/mapper) are created in right time after a device has its table
# loaded and is properly resumed. For this reason, direct use of dm-X nodes
# is not recommended.
ACTION!="add|change", GOTO="dm_end"
# Decode udev control flags and set environment variables appropriately.
# These flags are encoded in DM_COOKIE variable that was introduced in
# kernel version 2.6.31. Therefore, we can use this feature with
# kernels >= 2.6.31 only. Cookie is not decoded for remove event.
ENV{DM_COOKIE}=="?*", IMPORT{program}="/usr/sbin/dmsetup udevflags $env{DM_COOKIE}"
# Rule out easy-to-detect inappropriate events first.
ENV{DISK_RO}=="1", GOTO="dm_disable"
# There is no cookie set nor any flags encoded in events not originating
# in libdevmapper so we need to detect this and try to behave correctly.
# For such spurious events, regenerate all flags from current udev database content
# (this information would normally be inaccessible for spurious ADD and CHANGE events).
ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}=="1", ENV{DM_ACTIVATION}="1", GOTO="dm_flags_done"
IMPORT{db}="DM_UDEV_DISABLE_DM_RULES_FLAG"
IMPORT{db}="DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG"
IMPORT{db}="DM_UDEV_DISABLE_DISK_RULES_FLAG"
IMPORT{db}="DM_UDEV_DISABLE_OTHER_RULES_FLAG"
IMPORT{db}="DM_UDEV_LOW_PRIORITY_FLAG"
IMPORT{db}="DM_UDEV_DISABLE_LIBRARY_FALLBACK_FLAG"
IMPORT{db}="DM_UDEV_PRIMARY_SOURCE_FLAG"
IMPORT{db}="DM_UDEV_FLAG7"
IMPORT{db}="DM_UDEV_RULES_VSN"
LABEL="dm_flags_done"
# Normally, we operate on "change" events. But when coldplugging, there's an
# "add" event present. We have to recognize this and do our actions in this
# particular situation, too. Also, we don't want the nodes to be created
# prematurely on "add" events while not coldplugging. We check
# DM_UDEV_PRIMARY_SOURCE_FLAG to see if the device was activated correctly
# before and if not, we ignore the "add" event totally. This way we can support
# udev triggers generating "add" events (e.g. "udevadm trigger --action=add" or
# "echo add > /sys/block/<dm_device>/uevent"). The trigger with "add" event is
# also used at boot to reevaluate udev rules for all existing devices activated
# before (e.g. in initrd). If udev is used in initrd, we require the udev init
# script to not remove the existing udev database so we can reuse the information
# stored at the time of device activation in the initrd.
ACTION!="add", GOTO="dm_no_coldplug"
ENV{DM_UDEV_RULES_VSN}!="1", ENV{DM_UDEV_PRIMARY_SOURCE_FLAG}!="1", GOTO="dm_disable"
ENV{DM_ACTIVATION}="1"
LABEL="dm_no_coldplug"
# Putting it together, following table is used to recognize genuine and spurious events.
# N.B. Spurious events are generated based on use of the WATCH udev
# rule or by triggering an event manually by "udevadm trigger" call
# or by "echo <event_name> > /sys/block/dm-X/uevent".
#
# EVENT DM_UDEV_PRIMARY_SOURCE_FLAG DM_ACTIVATION
# ======================================================================
# add event (genuine) 0 0
# change event (genuine) 1 1
# add event (spurious)
# |_ dev still not active 0 0
# \_ dev already active 1 1
# change event (spurious)
# |_ dev still not active 0 0
# \_ dev already active 1 0
# "dm" sysfs subdirectory is available in newer versions of DM
# only (kernels >= 2.6.29). We have to check for its existence
# and use dmsetup tool instead to get the DM name, uuid and
# suspended state if the "dm" subdirectory is not present.
# The "suspended" item was added even later (kernels >= 2.6.31),
# so we also have to call dmsetup if the kernel version used
# is in between these releases.
TEST=="dm", ENV{DM_NAME}="$attr{dm/name}", ENV{DM_UUID}="$attr{dm/uuid}", ENV{DM_SUSPENDED}="$attr{dm/suspended}"
TEST!="dm", IMPORT{program}="/usr/sbin/dmsetup info -j %M -m %m -c --nameprefixes --noheadings --rows -o name,uuid,suspended"
ENV{DM_SUSPENDED}!="?*", IMPORT{program}="/usr/sbin/dmsetup info -j %M -m %m -c --nameprefixes --noheadings --rows -o suspended"
# dmsetup tool provides suspended state information in textual
# form with values "Suspended"/"Active". We translate it to
# 0/1 respectively to be consistent with sysfs values.
ENV{DM_SUSPENDED}=="Active", ENV{DM_SUSPENDED}="0"
ENV{DM_SUSPENDED}=="Suspended", ENV{DM_SUSPENDED}="1"
# This variable provides a reliable way to check that device-mapper
# rules were installed. It means that all needed variables are set
# by these rules directly so there's no need to acquire them again
# later. Other rules can alternate the functionality based on this
# fact (e.g. fallback to rules that behave correctly even without
# these rules installed). It also provides versioning for any
# possible future changes.
# VSN 1 - original rules
# VSN 2 - add support for synthesized events
ENV{DM_UDEV_RULES_VSN}="2"
ENV{DM_UDEV_DISABLE_DM_RULES_FLAG}!="1", ENV{DM_NAME}=="?*", SYMLINK+="mapper/$env{DM_NAME}"
# Avoid processing and scanning a DM device in the other (foreign)
# rules if it is in suspended state. However, we still keep 'disk'
# and 'DM subsystem' related rules enabled in this case.
ENV{DM_SUSPENDED}=="1", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
GOTO="dm_end"
LABEL="dm_disable"
ENV{DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG}="1"
ENV{DM_UDEV_DISABLE_DISK_RULES_FLAG}="1"
ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}="1"
OPTIONS:="nowatch"
LABEL="dm_end"

@ -475,7 +475,7 @@ ventoy_udev_disk_common_hook() {
is_inotify_ventoy_part() {
if echo $1 | grep -q "2$"; then
if echo $1 | $GREP -q "2$"; then
if ! [ -e /sys/block/$1 ]; then
if [ -e /sys/class/block/$1 ]; then
if [ -e /dev/${1:0:-1} ]; then

@ -105,3 +105,9 @@ ventoy_print_yum_repo() {
ventoy_set_inotify_script() {
echo $VTOY_PATH/hook/$1 > $VTOY_PATH/inotifyd-hook-script.txt
}
ventoy_set_loop_inotify_script() {
echo $VTOY_PATH/loop/$1 > $VTOY_PATH/inotifyd-loop-script.txt
}

@ -24,203 +24,14 @@
# #
####################################################################
[ -d /proc ] || mkdir /proc; mount -t proc proc /proc
vtcmdline=$(cat /proc/cmdline)
vtkerver=$(cat /proc/version)
vtoy_cmdline=$(cat /proc/cmdline)
umount /proc; rm -rf /proc
echo "kenel version=$vtkerver" >>$VTLOG
echo "kenel cmdline=$vtcmdline" >>$VTLOG
#break here for debug
if [ "$VTOY_BREAK_LEVEL" = "01" ] || [ "$VTOY_BREAK_LEVEL" = "11" ]; then
sleep 5
echo -e "\n\n\033[32m ################################################# \033[0m"
echo -e "\033[32m ################ VENTOY DEBUG ################### \033[0m"
echo -e "\033[32m ################################################# \033[0m \n"
if [ "$VTOY_BREAK_LEVEL" = "11" ]; then
cat $VTLOG
fi
exec $BUSYBOX_PATH/sh
fi
####################################################################
# #
# Step 2 : extract real initramfs to / #
# #
####################################################################
cd /
rm -rf /init /linuxrc /dev/ /root
vtSbinFileNum=$(ls -1 /sbin | wc -l)
if [ $vtSbinFileNum -eq 1 ]; then
echo "remove whole sbin directory" >> $VTLOG
rm -rf /sbin
if echo $vtoy_cmdline | grep -q 'rdinit=/vtoy/vtoy'; then
echo "handover to init_loop" >>$VTLOG
rm -f /xxxx /vtoyxrc
exec $BUSYBOX_PATH/sh $VTOY_PATH/init_loop
else
echo "remove only sbin/init file" >> $VTLOG
ls -l /sbin >> $VTLOG
rm -f /sbin/init
fi
ventoy_is_initrd_ramdisk() {
#As I known, PCLinuxOS use ramdisk
if echo $vtkerver | grep -i -q 'PCLinuxOS'; then
true
else
false
fi
}
ventoy_mount_squashfs() {
mkdir /dev
mount -t devtmpfs devtmpfs /dev
dd if=$1 of=/dev/ram0 status=none
umount /dev && rm -rf /dev
}
# param: file skip magic tmp
ventoy_unpack_initramfs() {
vtfile=$1; vtskip=$2; vtmagic=$3; vttmp=$4
echo "=====ventoy_unpack_initramfs: #$*#" >> $VTLOG
#special process
#if [ "${vtmagic:0:4}" = '5678' ]; then
# echo -en '\x1F\x8B' | dd status=none of=$vtfile bs=1 count=2 conv=notrunc
# vtmagic='1F8B'
#fi
if [ "${vtmagic:0:4}" = '6873' ]; then
ventoy_mount_squashfs $vtfile
return
fi
for vtx in '1F8B zcat' '1F9E zcat' '425A bzcat' '5D00 lzcat' 'FD37 xzcat' '894C lzopcat' '0221 lz4cat' '28B5 zstdcat' '3037 cat'; do
if [ "${vtx:0:4}" = "${vtmagic:0:4}" ]; then
echo "vtx=$vtx" >> $VTLOG
if [ $vtskip -eq 0 ]; then
if [ "${vtx:5}" = "xzcat" ]; then
rm -f $VTOY_PATH/xzlog
${vtx:5} $vtfile 2> $VTOY_PATH/xzlog | (cpio -idmu 2>>$VTLOG; cat > $vttmp)
if grep -q 'corrupted data' $VTOY_PATH/xzlog; then
echo 'xzcat failed, now try xzminidec...' >> $VTLOG
cat $vtfile | xzminidec | (cpio -idmu 2>>$VTLOG; cat > $vttmp)
fi
else
${vtx:5} $vtfile | (cpio -idmu 2>>$VTLOG; cat > $vttmp)
fi
else
dd if=$vtfile skip=$vtskip iflag=skip_bytes status=none | ${vtx:5} | (cpio -idmu 2>>$VTLOG; cat > $vttmp)
fi
break
fi
done
}
# param: file magic tmp
ventoy_unpack_initrd() {
vtfile=$1; vtmagic=$2; vttmp=$3
echo "=====ventoy_unpack_initrd: #$*#" >> $VTLOG
for vtx in '1F8B zcat' '1F9E zcat' '425A bzcat' '5D00 lzcat' 'FD37 xzcat' '894C lzopcat' '0221 lz4cat' '28B5 zstdcat' '3037 cat'; do
if [ "${vtx:0:4}" = "${vtmagic:0:4}" ]; then
echo "vtx=$vtx" >> $VTLOG
${vtx:5} $vtfile > $vttmp
break
fi
done
}
# This export is for busybox cpio command
export EXTRACT_UNSAFE_SYMLINKS=1
for vtfile in $(ls /initrd*); do
#decompress first initrd
vtmagic=$(hexdump -n 2 -e '2/1 "%02X"' $vtfile)
if ventoy_is_initrd_ramdisk; then
ventoy_unpack_initrd $vtfile $vtmagic ${vtfile}_tmp
mv ${vtfile}_tmp $vtfile
break
else
ventoy_unpack_initramfs $vtfile 0 $vtmagic ${vtfile}_tmp
fi
#only for cpio,cpio,...,initrd sequence, initrd,cpio or initrd,initrd sequence is not supported
while [ -e ${vtfile}_tmp ] && [ $(stat -c '%s' ${vtfile}_tmp) -gt 512 ]; do
mv ${vtfile}_tmp $vtfile
vtdump=$(hexdump -n 512 -e '512/1 "%02X"' $vtfile)
vtmagic=$(echo $vtdump | sed 's/^\(00\)*//')
let vtoffset="(${#vtdump}-${#vtmagic})/2"
if [ -z "$vtmagic" ]; then
echo "terminate with all zero data file" >> $VTLOG
break
fi
ventoy_unpack_initramfs $vtfile $vtoffset ${vtmagic:0:4} ${vtfile}_tmp
done
rm -f $vtfile ${vtfile}_tmp
done
#break here for debug
if [ "$VTOY_BREAK_LEVEL" = "02" ] || [ "$VTOY_BREAK_LEVEL" = "12" ]; then
sleep 5
echo -e "\n\n\033[32m ################################################# \033[0m"
echo -e "\033[32m ################ VENTOY DEBUG ################### \033[0m"
echo -e "\033[32m ################################################# \033[0m \n"
if [ "$VTOY_BREAK_LEVEL" = "12" ]; then
cat $VTOY_PATH/log
fi
exec $BUSYBOX_PATH/sh
fi
####################################################################
# #
# Step 3 : Extract injection archive #
# #
####################################################################
ventoy_unpack_injection() {
vtmagic=$(hexdump -n 2 -e '2/1 "%02X"' $VTOY_PATH/ventoy_injection)
echo "ventoy_unpack_injection vtmagic=$vtmagic ..."
if [ "1F8B" = "$vtmagic" ] || [ "1F9E" = "$vtmagic" ]; then
echo "tar.gz tar -xzvf"
tar -xzvf $VTOY_PATH/ventoy_injection -C /
elif [ "425A" = "$vtmagic" ]; then
echo "tar.bz2 tar -xjvf"
tar -xjvf $VTOY_PATH/ventoy_injection -C /
elif [ "FD37" = "$vtmagic" ]; then
echo "tar.xz tar -xJvf"
tar -xJvf $VTOY_PATH/ventoy_injection -C /
elif [ "5D00" = "$vtmagic" ]; then
echo "tar.lzma tar -xavf"
tar -xavf $VTOY_PATH/ventoy_injection -C /
else
echo "unzip -o"
unzip -o $VTOY_PATH/ventoy_injection -d /
fi
}
if [ -e $VTOY_PATH/ventoy_injection ]; then
echo "### decompress injection ... ###" >>$VTLOG
ventoy_unpack_injection > $VTOY_PATH/injection.log 2>&1
echo "handover to init_chain" >>$VTLOG
exec $BUSYBOX_PATH/sh $VTOY_PATH/init_chain
fi
####################################################################
# #
# Step 4 : Hand over to ventoy.sh #
# #
####################################################################
echo "Now hand over to ventoy.sh" >>$VTLOG
. $VTOY_PATH/tool/vtoytool_install.sh
export PATH=$VTOY_ORG_PATH
exec $BUSYBOX_PATH/sh $VTOY_PATH/ventoy.sh

@ -0,0 +1,226 @@
#!/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/>.
#
#************************************************************************************
###################################################################
# #
# Step 1 : parse kernel debug parameter #
# #
####################################################################
[ -d /proc ] || mkdir /proc; mount -t proc proc /proc
vtcmdline=$(cat /proc/cmdline)
vtkerver=$(cat /proc/version)
umount /proc; rm -rf /proc
echo "kenel version=$vtkerver" >>$VTLOG
echo "kenel cmdline=$vtcmdline" >>$VTLOG
#break here for debug
if [ "$VTOY_BREAK_LEVEL" = "01" ] || [ "$VTOY_BREAK_LEVEL" = "11" ]; then
sleep 5
echo -e "\n\n\033[32m ################################################# \033[0m"
echo -e "\033[32m ################ VENTOY DEBUG ################### \033[0m"
echo -e "\033[32m ################################################# \033[0m \n"
if [ "$VTOY_BREAK_LEVEL" = "11" ]; then
cat $VTLOG
fi
exec $BUSYBOX_PATH/sh
fi
####################################################################
# #
# Step 2 : extract real initramfs to / #
# #
####################################################################
cd /
rm -rf /init /linuxrc /dev/ /root
vtSbinFileNum=$(ls -1 /sbin | wc -l)
if [ $vtSbinFileNum -eq 1 ]; then
echo "remove whole sbin directory" >> $VTLOG
rm -rf /sbin
else
echo "remove only sbin/init file" >> $VTLOG
ls -l /sbin >> $VTLOG
rm -f /sbin/init
fi
ventoy_is_initrd_ramdisk() {
#As I known, PCLinuxOS use ramdisk
if echo $vtkerver | grep -i -q 'PCLinuxOS'; then
true
else
false
fi
}
ventoy_mount_squashfs() {
mkdir /dev
mount -t devtmpfs devtmpfs /dev
dd if=$1 of=/dev/ram0 status=none
umount /dev && rm -rf /dev
}
# param: file skip magic tmp
ventoy_unpack_initramfs() {
vtfile=$1; vtskip=$2; vtmagic=$3; vttmp=$4
echo "=====ventoy_unpack_initramfs: #$*#" >> $VTLOG
#special process
#if [ "${vtmagic:0:4}" = '5678' ]; then
# echo -en '\x1F\x8B' | dd status=none of=$vtfile bs=1 count=2 conv=notrunc
# vtmagic='1F8B'
#fi
if [ "${vtmagic:0:4}" = '6873' ]; then
ventoy_mount_squashfs $vtfile
return
fi
for vtx in '1F8B zcat' '1F9E zcat' '425A bzcat' '5D00 lzcat' 'FD37 xzcat' '894C lzopcat' '0221 lz4cat' '28B5 zstdcat' '3037 cat'; do
if [ "${vtx:0:4}" = "${vtmagic:0:4}" ]; then
echo "vtx=$vtx" >> $VTLOG
if [ $vtskip -eq 0 ]; then
if [ "${vtx:5}" = "xzcat" ]; then
rm -f $VTOY_PATH/xzlog
${vtx:5} $vtfile 2> $VTOY_PATH/xzlog | (cpio -idmu 2>>$VTLOG; cat > $vttmp)
if grep -q 'corrupted data' $VTOY_PATH/xzlog; then
echo 'xzcat failed, now try xzminidec...' >> $VTLOG
cat $vtfile | xzminidec | (cpio -idmu 2>>$VTLOG; cat > $vttmp)
fi
else
${vtx:5} $vtfile | (cpio -idmu 2>>$VTLOG; cat > $vttmp)
fi
else
dd if=$vtfile skip=$vtskip iflag=skip_bytes status=none | ${vtx:5} | (cpio -idmu 2>>$VTLOG; cat > $vttmp)
fi
break
fi
done
}
# param: file magic tmp
ventoy_unpack_initrd() {
vtfile=$1; vtmagic=$2; vttmp=$3
echo "=====ventoy_unpack_initrd: #$*#" >> $VTLOG
for vtx in '1F8B zcat' '1F9E zcat' '425A bzcat' '5D00 lzcat' 'FD37 xzcat' '894C lzopcat' '0221 lz4cat' '28B5 zstdcat' '3037 cat'; do
if [ "${vtx:0:4}" = "${vtmagic:0:4}" ]; then
echo "vtx=$vtx" >> $VTLOG
${vtx:5} $vtfile > $vttmp
break
fi
done
}
# This export is for busybox cpio command
export EXTRACT_UNSAFE_SYMLINKS=1
for vtfile in $(ls /initrd*); do
#decompress first initrd
vtmagic=$(hexdump -n 2 -e '2/1 "%02X"' $vtfile)
if ventoy_is_initrd_ramdisk; then
ventoy_unpack_initrd $vtfile $vtmagic ${vtfile}_tmp
mv ${vtfile}_tmp $vtfile
break
else
ventoy_unpack_initramfs $vtfile 0 $vtmagic ${vtfile}_tmp
fi
#only for cpio,cpio,...,initrd sequence, initrd,cpio or initrd,initrd sequence is not supported
while [ -e ${vtfile}_tmp ] && [ $(stat -c '%s' ${vtfile}_tmp) -gt 512 ]; do
mv ${vtfile}_tmp $vtfile
vtdump=$(hexdump -n 512 -e '512/1 "%02X"' $vtfile)
vtmagic=$(echo $vtdump | sed 's/^\(00\)*//')
let vtoffset="(${#vtdump}-${#vtmagic})/2"
if [ -z "$vtmagic" ]; then
echo "terminate with all zero data file" >> $VTLOG
break
fi
ventoy_unpack_initramfs $vtfile $vtoffset ${vtmagic:0:4} ${vtfile}_tmp
done
rm -f $vtfile ${vtfile}_tmp
done
#break here for debug
if [ "$VTOY_BREAK_LEVEL" = "02" ] || [ "$VTOY_BREAK_LEVEL" = "12" ]; then
sleep 5
echo -e "\n\n\033[32m ################################################# \033[0m"
echo -e "\033[32m ################ VENTOY DEBUG ################### \033[0m"
echo -e "\033[32m ################################################# \033[0m \n"
if [ "$VTOY_BREAK_LEVEL" = "12" ]; then
cat $VTOY_PATH/log
fi
exec $BUSYBOX_PATH/sh
fi
####################################################################
# #
# Step 3 : Extract injection archive #
# #
####################################################################
ventoy_unpack_injection() {
vtmagic=$(hexdump -n 2 -e '2/1 "%02X"' $VTOY_PATH/ventoy_injection)
echo "ventoy_unpack_injection vtmagic=$vtmagic ..."
if [ "1F8B" = "$vtmagic" ] || [ "1F9E" = "$vtmagic" ]; then
echo "tar.gz tar -xzvf"
tar -xzvf $VTOY_PATH/ventoy_injection -C /
elif [ "425A" = "$vtmagic" ]; then
echo "tar.bz2 tar -xjvf"
tar -xjvf $VTOY_PATH/ventoy_injection -C /
elif [ "FD37" = "$vtmagic" ]; then
echo "tar.xz tar -xJvf"
tar -xJvf $VTOY_PATH/ventoy_injection -C /
elif [ "5D00" = "$vtmagic" ]; then
echo "tar.lzma tar -xavf"
tar -xavf $VTOY_PATH/ventoy_injection -C /
else
echo "unzip -o"
unzip -o $VTOY_PATH/ventoy_injection -d /
fi
}
if [ -e $VTOY_PATH/ventoy_injection ]; then
echo "### decompress injection ... ###" >>$VTLOG
ventoy_unpack_injection > $VTOY_PATH/injection.log 2>&1
fi
####################################################################
# #
# Step 4 : Hand over to ventoy_chain.sh #
# #
####################################################################
echo "Now hand over to ventoy.sh" >>$VTLOG
. $VTOY_PATH/tool/vtoytool_install.sh
export PATH=$VTOY_ORG_PATH
exec $BUSYBOX_PATH/sh $VTOY_PATH/ventoy_chain.sh

@ -0,0 +1,90 @@
#!/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/>.
#
#************************************************************************************
###################################################################
# #
# Step 1 : parse kernel debug parameter #
# #
####################################################################
[ -d /proc ] || mkdir /proc; mount -t proc proc /proc
vtcmdline=$(cat /proc/cmdline)
vtkerver=$(cat /proc/version)
umount /proc; rm -rf /proc
echo "kenel version=$vtkerver" >>$VTLOG
echo "kenel cmdline=$vtcmdline" >>$VTLOG
#break here for debug
if [ "$VTOY_BREAK_LEVEL" = "01" ] || [ "$VTOY_BREAK_LEVEL" = "11" ]; then
sleep 5
echo -e "\n\n\033[32m ################################################# \033[0m"
echo -e "\033[32m ################ VENTOY DEBUG ################### \033[0m"
echo -e "\033[32m ################################################# \033[0m \n"
if [ "$VTOY_BREAK_LEVEL" = "11" ]; then
cat $VTLOG
fi
exec $BUSYBOX_PATH/sh
fi
####################################################################
# #
# Step 2 : Extract injection archive #
# #
####################################################################
ventoy_unpack_injection() {
vtmagic=$(hexdump -n 2 -e '2/1 "%02X"' $VTOY_PATH/ventoy_injection)
echo "ventoy_unpack_injection vtmagic=$vtmagic ..."
if [ "1F8B" = "$vtmagic" ] || [ "1F9E" = "$vtmagic" ]; then
echo "tar.gz tar -xzvf"
tar -xzvf $VTOY_PATH/ventoy_injection -C /
elif [ "425A" = "$vtmagic" ]; then
echo "tar.bz2 tar -xjvf"
tar -xjvf $VTOY_PATH/ventoy_injection -C /
elif [ "FD37" = "$vtmagic" ]; then
echo "tar.xz tar -xJvf"
tar -xJvf $VTOY_PATH/ventoy_injection -C /
elif [ "5D00" = "$vtmagic" ]; then
echo "tar.lzma tar -xavf"
tar -xavf $VTOY_PATH/ventoy_injection -C /
else
echo "unzip -o"
unzip -o $VTOY_PATH/ventoy_injection -d /
fi
}
if [ -e $VTOY_PATH/ventoy_injection ]; then
echo "### decompress injection ... ###" >>$VTLOG
ventoy_unpack_injection > $VTOY_PATH/injection.log 2>&1
fi
####################################################################
# #
# Step 3 : Hand over to ventoy_loop.sh #
# #
####################################################################
echo "Now hand over to ventoy.sh" >>$VTLOG
. $VTOY_PATH/tool/vtoytool_install.sh
export PATH=$VTOY_ORG_PATH
exec $BUSYBOX_PATH/sh $VTOY_PATH/ventoy_loop.sh

@ -0,0 +1,36 @@
#!/bin/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/>.
#
#************************************************************************************
cd /ventoy
xzcat tool.cpio.xz | cpio -idmu
/ventoy/tool/vtoytool/00/vtoytool_64 --install
while [ -n "Y" ]; do
line=$(/ventoy/tool/vtoydump -f /ventoy/ventoy_os_param)
if [ $? -eq 0 ]; then
vtdiskname=${line%%#*}
break
else
sleep 1
fi
done
echo "ventoy disk is $vtdiskname" >> /ventoy/log
/ventoy/tool/vtoydm -p -f /ventoy/ventoy_image_map -d $vtdiskname > /ventoy/ventoy_dm_table
dmsetup create ventoy /ventoy/ventoy_dm_table --readonly

@ -0,0 +1,21 @@
#!/bin/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/>.
#
#************************************************************************************
sed "/^mountroot$/i\\sh /ventoy/loop/deepin/ventoy-disk.sh" -i /init
exec /init

@ -0,0 +1,36 @@
#!/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
END_UDEV_DIR=$(ventoy_get_udev_conf_dir)
if ! [ -e "$END_UDEV_DIR/10-dm.rules" ]; then
echo 'Copy dm rule file' >> $VTLOG
$CAT $VTOY_PATH/hook/default/10-dm.rules > "$END_UDEV_DIR/10-dm.rules"
fi
if ! [ -e "$END_UDEV_DIR/13-dm-disk.rules" ]; then
echo 'Copy dm-disk rule file' >> $VTLOG
$CAT $VTOY_PATH/hook/default/13-dm-disk.rules > "$END_UDEV_DIR/13-dm-disk.rules"
fi
ventoy_set_loop_inotify_script endless/ventoy-inotifyd-hook.sh
$BUSYBOX_PATH/cp -a $VTOY_PATH/loop/endless/ventoy-inotifyd-start.sh /lib/dracut/hooks/pre-udev/01-ventoy-inotifyd-start.sh

@ -0,0 +1,37 @@
#!/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
VTPATH_OLD=$PATH; PATH=$PATH:$BUSYBOX_PATH:$VTOY_PATH/tool
if is_inotify_ventoy_part $3; then
vtlog "##### INOTIFYD: $2/$3 is created (YES) ..."
ventoy_udev_disk_common_hook "$3" "noreplace"
set_ventoy_hook_finish
else
vtlog "##### INOTIFYD: $2/$3 is created (NO) ..."
fi
PATH=$VTPATH_OLD

@ -0,0 +1,31 @@
#!/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
vtHook=$($CAT $VTOY_PATH/inotifyd-loop-script.txt)
vtdisk=$(get_ventoy_disk_name)
if [ "$vtdisk" = "unknown" ]; then
vtlog "... start inotifyd listen $vtHook ..."
$BUSYBOX_PATH/nohup $VTOY_PATH/tool/inotifyd $vtHook /dev:n 2>&- &
else
vtlog "... $vtdisk already exist ..."
$BUSYBOX_PATH/sh $vtHook n /dev "${vtdisk#/dev/}2"
fi

@ -136,6 +136,8 @@ ventoy_get_os_type() {
echo 'suse'; return
elif $GREP -q 'uruk' /etc/os-release; then
echo 'debian'; return
elif $GREP -q 'Solus' /etc/os-release; then
echo 'rhel7'; return
fi
fi

@ -0,0 +1,116 @@
#!/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/>.
#
#************************************************************************************
####################################################################
# #
# Step 1 : Parse kernel parameter #
# #
####################################################################
if ! [ -e /proc ]; then
$BUSYBOX_PATH/mkdir /proc
rmproc='Y'
fi
$BUSYBOX_PATH/mount -t proc proc /proc
# vtinit=xxx to replace rdinit=xxx
vtcmdline=$($CAT /proc/cmdline)
for i in $vtcmdline; do
if echo $i | $GREP -q vtinit; then
user_rdinit=${i#vtinit=}
echo "user set user_rdinit=${user_rdinit}" >>$VTLOG
fi
done
####################################################################
# #
# Step 2 : Do OS specific hook #
# #
####################################################################
ventoy_get_os_type() {
echo "kernel version" >> $VTLOG
$CAT /proc/version >> $VTLOG
# deepin-live
if $GREP -q 'deepin' /proc/version; then
echo 'deepin'; return
fi
if $GREP -q 'endless' /proc/version; then
echo 'endless'; return
fi
echo "default"
}
VTOS=$(ventoy_get_os_type)
echo "OS=###${VTOS}###" >>$VTLOG
if [ -e "$VTOY_PATH/loop/$VTOS/ventoy-hook.sh" ]; then
$BUSYBOX_PATH/sh "$VTOY_PATH/loop/$VTOS/ventoy-hook.sh"
fi
####################################################################
# #
# Step 3 : Check for debug break #
# #
####################################################################
if [ "$VTOY_BREAK_LEVEL" = "03" ] || [ "$VTOY_BREAK_LEVEL" = "13" ]; then
$SLEEP 5
echo -e "\n\n\033[32m ################################################# \033[0m"
echo -e "\033[32m ################ VENTOY DEBUG ################### \033[0m"
echo -e "\033[32m ################################################# \033[0m \n"
if [ "$VTOY_BREAK_LEVEL" = "13" ]; then
$CAT $VTOY_PATH/log
fi
exec $BUSYBOX_PATH/sh
fi
####################################################################
# #
# Step 3 : Hand over to real init #
# #
####################################################################
$BUSYBOX_PATH/umount /proc
if [ "$rmproc" = "Y" ]; then
$BUSYBOX_PATH/rm -rf /proc
fi
cd /
unset VTLOG FIND GREP EGREP CAT AWK SED SLEEP HEAD
for vtinit in $user_rdinit /sbin/init /init /linuxrc; do
if [ -d /ventoy_rdroot ]; then
if [ -e "/ventoy_rdroot$vtinit" ]; then
# switch_root will check /init file, this is a cheat code
echo 'switch_root' > /init
exec $BUSYBOX_PATH/switch_root /ventoy_rdroot "$vtinit"
fi
else
if [ -e "$vtinit" ];then
exec "$vtinit"
fi
fi
done
# Should never reach here
echo -e "\n\n\033[31m ############ INIT NOT FOUND ############### \033[0m \n"
exec $BUSYBOX_PATH/sh

@ -28,7 +28,8 @@ find ./tool | cpio -o -H newc>tool.cpio
xz tool.cpio
rm -rf tool
xz ventoy.sh
xz ventoy_chain.sh
xz ventoy_loop.sh
find ./hook | cpio -o -H newc>hook.cpio
xz hook.cpio

@ -62,12 +62,12 @@ else
fi
# 00->ff avoid sparse file
dd if=/dev/zero bs=1M count=$size | tr '\000' '\377' > persistence.img
dd if=/dev/zero bs=1M count=$size | tr '\000' '\377' > persistence.dat
sync
freeloop=$(losetup -f)
losetup $freeloop persistence.img
losetup $freeloop persistence.dat
mkfs -t $fstype $fsopt -L $label $freeloop

Binary file not shown.

@ -17,10 +17,8 @@
#************************************************************************************
function ventoy_pause {
if [ -n "${vtdebug_flag}" ]; then
echo "press Enter to continue ......"
read vtTmpPause
fi
echo "press Enter to continue ......"
read vtTmpPause
}
function ventoy_debug_pause {
@ -30,29 +28,20 @@ function ventoy_debug_pause {
fi
}
function ventoy_cli_console {
if [ "$grub_platform" = "pc" ]; then
#terminal_output vga_text
function ventoy_cli_console {
if [ -z "$vtoy_display_mode" ]; then
terminal_output console
elif [ "$vtoy_display_mode" = "GUI" ]; then
terminal_output console
else
if [ "$vtoy_display_mode" != "CLI" ]; then
terminal_output console
fi
fi
}
function ventoy_gui_console {
if [ "$grub_platform" = "pc" ]; then
if [ "$vtoy_display_mode" = "CLI" ]; then
terminal_output console
else
terminal_output gfxterm
fi
else
if [ "$vtoy_display_mode" != "CLI" ]; then
terminal_output gfxterm
fi
fi
if [ -z "$vtoy_display_mode" ]; then
terminal_output gfxterm
elif [ "$vtoy_display_mode" = "GUI" ]; then
terminal_output gfxterm
fi
}
function ventoy_power {
@ -401,7 +390,7 @@ function uefi_linux_menu_func {
fi
vt_load_cpio ${vtoy_path}/ventoy.cpio $2 $1
vt_linux_clear_initrd
if [ -d (loop)/pmagic ]; then
@ -501,7 +490,7 @@ function uefi_iso_menu_func {
unset LoadIsoEfiDriver
fi
vt_chosen_img_path chosen_path
set chosen_path=$2
vt_select_auto_install ${chosen_path}
vt_select_persistence ${chosen_path}
@ -512,8 +501,7 @@ function uefi_iso_menu_func {
vt_iso9660_nojoliet 0
fi
loopback loop ${1}${chosen_path}
vt_parse_iso_volume ${1}${chosen_path} vt_system_id vt_volume_id
loopback loop ${1}${chosen_path}
get_os_type (loop)
if [ -d (loop)/EFI ]; then
@ -548,10 +536,8 @@ function uefi_iso_menu_func {
}
function uefi_iso_memdisk {
vt_chosen_img_path chosen_path
echo 'Loading ISO file to memory ...'
vt_load_iso_to_mem ${1}${chosen_path} vtoy_iso_buf
vt_load_img_memdisk ${1}${2} vtoy_iso_buf
ventoy_cli_console
chainloader ${vtoy_path}/ventoy_x64.efi memdisk env_param=${env_param} isoefi=${LoadIsoEfiDriver} ${vtdebug_flag} mem:${vtoy_iso_buf_addr}:size:${vtoy_iso_buf_size}
@ -679,7 +665,7 @@ function legacy_iso_menu_func {
loopback -d loop
fi
vt_chosen_img_path chosen_path
set chosen_path=$2
vt_select_auto_install ${chosen_path}
vt_select_persistence ${chosen_path}
@ -691,7 +677,7 @@ function legacy_iso_menu_func {
fi
loopback loop ${1}${chosen_path}
vt_parse_iso_volume ${1}${chosen_path} vt_system_id vt_volume_id
get_os_type (loop)
if [ -n "$vtcompat" ]; then
@ -716,29 +702,99 @@ function legacy_iso_menu_func {
}
function legacy_iso_memdisk {
vt_chosen_img_path chosen_path
linux16 $vtoy_path/memdisk iso raw
echo "Loading ISO file to memory ..."
initrd16 ${1}${chosen_path}
initrd16 ${1}${2}
boot
}
function iso_deepin_live_proc {
if [ -d (loop)/ ]; then
loopback -d loop
fi
loopback loop ${1}${2}
vt_img_sector ${1}${2}
vt_load_cpio $vtoy_path/ventoy.cpio $2 $1
vt_trailer_cpio $1 $2 noinit
ventoy_debug_pause
vt_set_boot_opt rdinit=/ventoy/loop/deepin/ventoy-init.sh live-media=/dev/mapper/ventoy
set ventoy_loading_tip="Loading files ......"
linux (loop)/live/vmlinuz boot=live components locales=zh_CN.UTF-8 splash quiet
initrd (loop)/live/initrd.img
boot
unset ventoy_loading_tip
vt_unset_boot_opt
}
function iso_endless_os_proc {
if [ -d (loop)/ ]; then
loopback -d loop
fi
loopback loop ${1}${2}
vt_img_sector ${1}${2}
vt_load_cpio $vtoy_path/ventoy.cpio $2 $1
vt_trailer_cpio $1 $2 noinit
ventoy_debug_pause
vt_set_boot_opt '@kparams' rdinit=/vtoy/vtoy
set eosimage=loop
set ventoy_bls_bootdev=/boot
set ventoy_loading_tip="Loading files ......"
export eosimage
configfile (loop)/endless/grub/grub.cfg
unset eosimage
unset ventoy_bls_bootdev
unset ventoy_loading_tip
vt_unset_boot_opt
}
function iso_common_menuentry {
unset vt_system_id
unset vt_volume_id
vt_chosen_img_path vt_chosen_path vt_chosen_size
vt_parse_iso_volume ${vtoy_iso_part}${vt_chosen_path} vt_system_id vt_volume_id
#special process for deepin-live iso
if [ "$vt_chosen_size" = "403701760" ]; then
if vt_str_begin $vt_chosen_path "/deepin-live"; then
iso_deepin_live_proc $vtoy_iso_part $vt_chosen_path
fi
fi
#special process for Endless OS
if vt_str_begin $vt_volume_id "Endless-OS"; then
iso_endless_os_proc $vtoy_iso_part $vt_chosen_path
fi
if [ "$grub_platform" = "pc" ]; then
if vt_check_mode 0; then
legacy_iso_memdisk $vtoy_iso_part
legacy_iso_memdisk $vtoy_iso_part $vt_chosen_path
else
legacy_iso_menu_func $vtoy_iso_part
legacy_iso_menu_func $vtoy_iso_part $vt_chosen_path
fi
else
if vt_check_mode 0; then
uefi_iso_memdisk $vtoy_iso_part
uefi_iso_memdisk $vtoy_iso_part $vt_chosen_path
else
uefi_iso_menu_func $vtoy_iso_part
uefi_iso_menu_func $vtoy_iso_part $vt_chosen_path
fi
fi
}
@ -755,8 +811,8 @@ function iso_unsupport_menuentry {
}
function wim_common_menuentry {
vt_chosen_img_path chosen_path
vt_wim_chain_data ${vtoy_iso_part}${chosen_path}
vt_chosen_img_path vt_chosen_path vt_chosen_size
vt_wim_chain_data ${vtoy_iso_part}${vt_chosen_path}
ventoy_debug_pause
@ -780,10 +836,14 @@ function wim_unsupport_menuentry {
}
function efi_common_menuentry {
vt_chosen_img_path chosen_path
vt_chosen_img_path vt_chosen_path vt_chosen_size
vt_concat_efi_iso ${vtoy_iso_part}${vt_chosen_path} vtoy_iso_buf
ventoy_debug_pause
ventoy_cli_console
chainloader ${vtoy_iso_part}${chosen_path}
chainloader ${vtoy_path}/ventoy_x64.efi memdisk env_param=${env_param} isoefi=on ${vtdebug_flag} mem:${vtoy_iso_buf_addr}:size:${vtoy_iso_buf_size}
boot
ventoy_gui_console
}
@ -794,6 +854,17 @@ function efi_unsupport_menuentry {
function img_common_menuentry {
echo "To be implement"
}
function img_unsupport_menuentry {
common_unsupport_menuentry
}
#############################################################
#############################################################
#############################################################
@ -892,6 +963,18 @@ fi
if [ "$vtoy_display_mode" = "CLI" ]; then
terminal_output console
elif [ "$vtoy_display_mode" = "serial" ]; then
if [ -n "$vtoy_serial_param" ]; then
serial $vtoy_serial_param
fi
terminal_input serial
terminal_output serial
elif [ "$vtoy_display_mode" = "serial_console" ]; then
if [ -n "$vtoy_serial_param" ]; then
serial $vtoy_serial_param
fi
terminal_input serial console
terminal_output serial console
else
if [ -n "$vtoy_theme" ]; then
set theme=$vtoy_theme

Binary file not shown.

@ -1,6 +1,8 @@
*acpi: acpi
*all_functional_test: functional_test
*background_image: gfxterm_background
*bls_import: blscfg
*blscfg: blscfg
*cat: cat
*cpuid: cpuid
*crc: hashsum
@ -106,6 +108,7 @@ help: minicmd
hexdump_random: random
initrd16: linux16
initrd: linux
initrdefi: linux
keymap: keylayouts
kfreebsd_loadenv: bsd
kfreebsd_module: bsd
@ -122,6 +125,7 @@ legacy_password: legacycfg
legacy_source: legacycfg
linux16: linux16
linux: linux
linuxefi: linux
list_trusted: pgp
loadfont: font
lsapm: lsapm
@ -184,6 +188,8 @@ vbeinfo: videoinfo
vbetest: videotest
videoinfo: videoinfo
videotest: videotest
vt_set_boot_opt: linux
vt_unset_boot_opt: linux
write_byte: memrw
write_dword: memrw
write_word: memrw

Binary file not shown.

@ -96,6 +96,7 @@ bufio:
usbserial_ftdi: serial usb usbserial_common
legacy_password_test: functional_test legacycfg
cpuid: extcmd
blscfg: extcmd normal
hdparm: extcmd hexdump
bfs: fshelp
gcry_blowfish: crypto

@ -1,6 +1,8 @@
*acpi: acpi
*all_functional_test: functional_test
*background_image: gfxterm_background
*bls_import: blscfg
*blscfg: blscfg
*cat: cat
*cpuid: cpuid
*crc: hashsum
@ -96,6 +98,7 @@ help: minicmd
hexdump_random: random
initrd16: linux16
initrd: linux
initrdefi: linux
keymap: keylayouts
kfreebsd_loadenv: bsd
kfreebsd_module: bsd
@ -112,6 +115,7 @@ legacy_password: legacycfg
legacy_source: legacycfg
linux16: linux16
linux: linux
linuxefi: linux
list_trusted: pgp
loadbios: loadbios
loadfont: font
@ -173,6 +177,8 @@ true: true
usb: usbtest
videoinfo: videoinfo
videotest: videotest
vt_set_boot_opt: linux
vt_unset_boot_opt: linux
write_byte: memrw
write_dword: memrw
write_word: memrw

@ -93,6 +93,7 @@ bufio:
usbserial_ftdi: serial usb usbserial_common
legacy_password_test: functional_test legacycfg
cpuid: extcmd
blscfg: extcmd normal
hdparm: extcmd hexdump
bfs: fshelp
gcry_blowfish: crypto

Binary file not shown.

Binary file not shown.
Loading…
Cancel
Save