1.0.11 release

This commit is contained in:
longpanda 2020-05-23 21:19:26 +08:00
parent f0d59949e5
commit ef40780f20
17 changed files with 844 additions and 19 deletions

View File

@ -46,6 +46,7 @@
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/fshelp.h>
#include <grub/ventoy.h>
GRUB_MOD_LICENSE ("GPLv3+");
@ -339,7 +340,7 @@ struct grub_ext2_data
static grub_dl_t my_mod;
static int g_ventoy_block_count;
/* Check is a = b^x for some x. */
static inline int
@ -499,6 +500,7 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
start = grub_le_to_cpu16 (ext[i].start_hi);
start = (start << 32) + grub_le_to_cpu32 (ext[i].start);
g_ventoy_block_count = (int)(grub_le_to_cpu16 (ext[i].len) - fileblock);
ret = fileblock + start;
}
}
@ -1069,8 +1071,46 @@ grub_ext2_mtime (grub_device_t device, grub_int32_t *tm)
}
int grub_ext_get_file_chunk(grub_uint64_t part_start, grub_file_t file, ventoy_img_chunk_list *chunk_list)
{
int blocksize;
int log2blocksize;
grub_disk_t disk;
grub_disk_addr_t i = 0;
grub_disk_addr_t blockcnt;
grub_disk_addr_t blknr;
grub_fshelp_node_t node = NULL;
disk = file->device->disk;
node = &(((struct grub_ext2_data *)file->data)->diropen);
log2blocksize = LOG2_EXT2_BLOCK_SIZE (node->data);
blocksize = 1 << (log2blocksize + GRUB_DISK_SECTOR_BITS);
blockcnt = (file->size + blocksize - 1) >> (log2blocksize + GRUB_DISK_SECTOR_BITS);
while (i < blockcnt)
{
g_ventoy_block_count = 1;
blknr = grub_ext2_read_block(node, i);
if (blknr == 0)
{
return 0;
}
i += g_ventoy_block_count;
blknr = blknr << log2blocksize;
grub_disk_blocklist_read(chunk_list, blknr, g_ventoy_block_count * blocksize, disk->log_sector_size);
}
for (i = 0; i < chunk_list->cur_chunk; i++)
{
chunk_list->chunk[i].disk_start_sector += part_start;
chunk_list->chunk[i].disk_end_sector += part_start;
}
return 0;
}
static struct grub_fs grub_ext2_fs =
{
.name = "ext2",

View File

@ -0,0 +1,429 @@
/* fshelp.c -- Filesystem helper functions */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2004,2005,2006,2007,2008 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/err.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/fshelp.h>
#include <grub/dl.h>
#include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv3+");
typedef int (*iterate_dir_func) (grub_fshelp_node_t dir,
grub_fshelp_iterate_dir_hook_t hook,
void *data);
typedef grub_err_t (*lookup_file_func) (grub_fshelp_node_t dir,
const char *name,
grub_fshelp_node_t *foundnode,
enum grub_fshelp_filetype *foundtype);
typedef char *(*read_symlink_func) (grub_fshelp_node_t node);
struct stack_element {
struct stack_element *parent;
grub_fshelp_node_t node;
enum grub_fshelp_filetype type;
};
/* Context for grub_fshelp_find_file. */
struct grub_fshelp_find_file_ctx
{
/* Inputs. */
const char *path;
grub_fshelp_node_t rootnode;
/* Global options. */
int symlinknest;
/* Current file being traversed and its parents. */
struct stack_element *currnode;
};
/* Helper for find_file_iter. */
static void
free_node (grub_fshelp_node_t node, struct grub_fshelp_find_file_ctx *ctx)
{
if (node != ctx->rootnode)
grub_free (node);
}
static void
pop_element (struct grub_fshelp_find_file_ctx *ctx)
{
struct stack_element *el;
el = ctx->currnode;
ctx->currnode = el->parent;
free_node (el->node, ctx);
grub_free (el);
}
static void
free_stack (struct grub_fshelp_find_file_ctx *ctx)
{
while (ctx->currnode)
pop_element (ctx);
}
static void
go_up_a_level (struct grub_fshelp_find_file_ctx *ctx)
{
if (!ctx->currnode->parent)
return;
pop_element (ctx);
}
static grub_err_t
push_node (struct grub_fshelp_find_file_ctx *ctx, grub_fshelp_node_t node, enum grub_fshelp_filetype filetype)
{
struct stack_element *nst;
nst = grub_malloc (sizeof (*nst));
if (!nst)
return grub_errno;
nst->node = node;
nst->type = filetype & ~GRUB_FSHELP_CASE_INSENSITIVE;
nst->parent = ctx->currnode;
ctx->currnode = nst;
return GRUB_ERR_NONE;
}
static grub_err_t
go_to_root (struct grub_fshelp_find_file_ctx *ctx)
{
free_stack (ctx);
return push_node (ctx, ctx->rootnode, GRUB_FSHELP_DIR);
}
struct grub_fshelp_find_file_iter_ctx
{
const char *name;
grub_fshelp_node_t *foundnode;
enum grub_fshelp_filetype *foundtype;
};
/* Helper for grub_fshelp_find_file. */
static int
find_file_iter (const char *filename, enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node, void *data)
{
struct grub_fshelp_find_file_iter_ctx *ctx = data;
if (filetype == GRUB_FSHELP_UNKNOWN ||
((filetype & GRUB_FSHELP_CASE_INSENSITIVE)
? grub_strcasecmp (ctx->name, filename)
: grub_strcmp (ctx->name, filename)))
{
grub_free (node);
return 0;
}
/* The node is found, stop iterating over the nodes. */
*ctx->foundnode = node;
*ctx->foundtype = filetype;
return 1;
}
static grub_err_t
directory_find_file (grub_fshelp_node_t node, const char *name, grub_fshelp_node_t *foundnode,
enum grub_fshelp_filetype *foundtype, iterate_dir_func iterate_dir)
{
int found;
struct grub_fshelp_find_file_iter_ctx ctx = {
.foundnode = foundnode,
.foundtype = foundtype,
.name = name
};
found = iterate_dir (node, find_file_iter, &ctx);
if (! found)
{
if (grub_errno)
return grub_errno;
}
return GRUB_ERR_NONE;
}
static grub_err_t
find_file (char *currpath,
iterate_dir_func iterate_dir, lookup_file_func lookup_file,
read_symlink_func read_symlink,
struct grub_fshelp_find_file_ctx *ctx)
{
char *name, *next;
grub_err_t err;
for (name = currpath; ; name = next)
{
char c;
grub_fshelp_node_t foundnode = NULL;
enum grub_fshelp_filetype foundtype = 0;
/* Remove all leading slashes. */
while (*name == '/')
name++;
/* Found the node! */
if (! *name)
return 0;
/* Extract the actual part from the pathname. */
for (next = name; *next && *next != '/'; next++);
/* At this point it is expected that the current node is a
directory, check if this is true. */
if (ctx->currnode->type != GRUB_FSHELP_DIR)
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
/* Don't rely on fs providing actual . in the listing. */
if (next - name == 1 && name[0] == '.')
continue;
/* Don't rely on fs providing actual .. in the listing. */
if (next - name == 2 && name[0] == '.' && name[1] == '.')
{
go_up_a_level (ctx);
continue;
}
/* Iterate over the directory. */
c = *next;
*next = '\0';
if (lookup_file)
err = lookup_file (ctx->currnode->node, name, &foundnode, &foundtype);
else
err = directory_find_file (ctx->currnode->node, name, &foundnode, &foundtype, iterate_dir);
*next = c;
if (err)
return err;
if (!foundnode)
break;
push_node (ctx, foundnode, foundtype);
/* Read in the symlink and follow it. */
if (ctx->currnode->type == GRUB_FSHELP_SYMLINK)
{
char *symlink;
/* Test if the symlink does not loop. */
if (++ctx->symlinknest == 8)
return grub_error (GRUB_ERR_SYMLINK_LOOP,
N_("too deep nesting of symlinks"));
symlink = read_symlink (ctx->currnode->node);
if (!symlink)
return grub_errno;
/* The symlink is an absolute path, go back to the root inode. */
if (symlink[0] == '/')
{
err = go_to_root (ctx);
if (err)
return err;
}
else
{
/* Get from symlink to containing directory. */
go_up_a_level (ctx);
}
/* Lookup the node the symlink points to. */
find_file (symlink, iterate_dir, lookup_file, read_symlink, ctx);
grub_free (symlink);
if (grub_errno)
return grub_errno;
}
}
return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"),
ctx->path);
}
static grub_err_t
grub_fshelp_find_file_real (const char *path, grub_fshelp_node_t rootnode,
grub_fshelp_node_t *foundnode,
iterate_dir_func iterate_dir,
lookup_file_func lookup_file,
read_symlink_func read_symlink,
enum grub_fshelp_filetype expecttype)
{
struct grub_fshelp_find_file_ctx ctx = {
.path = path,
.rootnode = rootnode,
.symlinknest = 0,
.currnode = 0
};
grub_err_t err;
enum grub_fshelp_filetype foundtype;
char *duppath;
if (!path || path[0] != '/')
{
return grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), path);
}
err = go_to_root (&ctx);
if (err)
return err;
duppath = grub_strdup (path);
if (!duppath)
return grub_errno;
err = find_file (duppath, iterate_dir, lookup_file, read_symlink, &ctx);
grub_free (duppath);
if (err)
{
free_stack (&ctx);
return err;
}
*foundnode = ctx.currnode->node;
foundtype = ctx.currnode->type;
/* Avoid the node being freed. */
ctx.currnode->node = 0;
free_stack (&ctx);
/* Check if the node that was found was of the expected type. */
if (expecttype == GRUB_FSHELP_REG && foundtype != expecttype)
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file"));
else if (expecttype == GRUB_FSHELP_DIR && foundtype != expecttype)
return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
return 0;
}
/* Lookup the node PATH. The node ROOTNODE describes the root of the
directory tree. The node found is returned in FOUNDNODE, which is
either a ROOTNODE or a new malloc'ed node. ITERATE_DIR is used to
iterate over all directory entries in the current node.
READ_SYMLINK is used to read the symlink if a node is a symlink.
EXPECTTYPE is the type node that is expected by the called, an
error is generated if the node is not of the expected type. */
grub_err_t
grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
grub_fshelp_node_t *foundnode,
iterate_dir_func iterate_dir,
read_symlink_func read_symlink,
enum grub_fshelp_filetype expecttype)
{
return grub_fshelp_find_file_real (path, rootnode, foundnode,
iterate_dir, NULL,
read_symlink, expecttype);
}
grub_err_t
grub_fshelp_find_file_lookup (const char *path, grub_fshelp_node_t rootnode,
grub_fshelp_node_t *foundnode,
lookup_file_func lookup_file,
read_symlink_func read_symlink,
enum grub_fshelp_filetype expecttype)
{
return grub_fshelp_find_file_real (path, rootnode, foundnode,
NULL, lookup_file,
read_symlink, expecttype);
}
/* Read LEN bytes from the file NODE on disk DISK into the buffer BUF,
beginning with the block POS. READ_HOOK should be set before
reading a block from the file. READ_HOOK_DATA is passed through as
the DATA argument to READ_HOOK. GET_BLOCK is used to translate
file blocks to disk blocks. The file is FILESIZE bytes big and the
blocks have a size of LOG2BLOCKSIZE (in log2). */
grub_ssize_t
grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node,
grub_disk_read_hook_t read_hook, void *read_hook_data,
grub_off_t pos, grub_size_t len, char *buf,
grub_disk_addr_t (*get_block) (grub_fshelp_node_t node,
grub_disk_addr_t block),
grub_off_t filesize, int log2blocksize,
grub_disk_addr_t blocks_start)
{
grub_disk_addr_t i, blockcnt;
int blocksize = 1 << (log2blocksize + GRUB_DISK_SECTOR_BITS);
if (pos > filesize)
{
grub_error (GRUB_ERR_OUT_OF_RANGE,
N_("attempt to read past the end of file"));
return -1;
}
/* Adjust LEN so it we can't read past the end of the file. */
if (pos + len > filesize)
len = filesize - pos;
blockcnt = ((len + pos) + blocksize - 1) >> (log2blocksize + GRUB_DISK_SECTOR_BITS);
for (i = pos >> (log2blocksize + GRUB_DISK_SECTOR_BITS); i < blockcnt; i++)
{
grub_disk_addr_t blknr;
int blockoff = pos & (blocksize - 1);
int blockend = blocksize;
int skipfirst = 0;
blknr = get_block (node, i);
if (grub_errno)
return -1;
blknr = blknr << log2blocksize;
/* Last block. */
if (i == blockcnt - 1)
{
blockend = (len + pos) & (blocksize - 1);
/* The last portion is exactly blocksize. */
if (! blockend)
blockend = blocksize;
}
/* First block. */
if (i == (pos >> (log2blocksize + GRUB_DISK_SECTOR_BITS)))
{
skipfirst = blockoff;
blockend -= skipfirst;
}
/* If the block number is 0 this block is not stored on disk but
is zero filled instead. */
if (blknr)
{
disk->read_hook = read_hook;
disk->read_hook_data = read_hook_data;
grub_disk_read (disk, blknr + blocks_start, skipfirst,
blockend, buf);
disk->read_hook = 0;
if (grub_errno)
return -1;
}
else if (read_hook != (grub_disk_read_hook_t)grub_disk_blocklist_read)
grub_memset (buf, 0, blockend);
buf += blocksize - skipfirst;
}
return len;
}

View File

@ -127,6 +127,10 @@ static int ventoy_get_fs_type(const char *fs)
{
return ventoy_fs_udf;
}
else if (grub_strncmp(fs, "fat", 3) == 0)
{
return ventoy_fs_fat;
}
return ventoy_fs_max;
}
@ -1288,7 +1292,35 @@ void ventoy_fill_os_param(grub_file_t file, ventoy_os_param *param)
return;
}
static int ventoy_get_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start)
int ventoy_check_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start)
{
grub_uint32_t i = 0;
grub_uint64_t total = 0;
ventoy_img_chunk *chunk = NULL;
for (i = 0; i < chunklist->cur_chunk; i++)
{
chunk = chunklist->chunk + i;
if (chunk->disk_start_sector <= start)
{
debug("%u disk start invalid %lu\n", i, (ulong)start);
return 1;
}
total += chunk->disk_end_sector + 1 - chunk->disk_start_sector;
}
if (total != (file->size / 512))
{
debug("Invalid total: %llu %llu\n", (ulonglong)total, (ulonglong)(file->size / 512));
return 1;
}
return 0;
}
int ventoy_get_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start)
{
int fs_type;
grub_uint32_t i = 0;
@ -1302,6 +1334,10 @@ static int ventoy_get_block_list(grub_file_t file, ventoy_img_chunk_list *chunkl
{
grub_fat_get_file_chunk(start, file, chunklist);
}
else if (fs_type == ventoy_fs_ext)
{
grub_ext_get_file_chunk(start, file, chunklist);
}
else
{
file->read_hook = (grub_disk_read_hook_t)grub_disk_blocklist_read;
@ -1336,7 +1372,9 @@ static int ventoy_get_block_list(grub_file_t file, ventoy_img_chunk_list *chunkl
static grub_err_t ventoy_cmd_img_sector(grub_extcmd_context_t ctxt, int argc, char **args)
{
int rc;
grub_file_t file;
grub_disk_addr_t start;
(void)ctxt;
(void)argc;
@ -1363,12 +1401,19 @@ static grub_err_t ventoy_cmd_img_sector(grub_extcmd_context_t ctxt, int argc, ch
g_img_chunk_list.max_chunk = DEFAULT_CHUNK_NUM;
g_img_chunk_list.cur_chunk = 0;
ventoy_get_block_list(file, &g_img_chunk_list, file->device->disk->partition->start);
start = file->device->disk->partition->start;
ventoy_get_block_list(file, &g_img_chunk_list, start);
rc = ventoy_check_block_list(file, &g_img_chunk_list, start);
grub_file_close(file);
if (rc)
{
return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET, "Unsupported chunk list.\n");
}
grub_memset(&g_grub_param->file_replace, 0, sizeof(g_grub_param->file_replace));
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
@ -1481,8 +1526,11 @@ static grub_err_t ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt, int arg
chunklist.cur_chunk = 0;
ventoy_get_block_list(file, &chunklist, 0);
grub_file_close(file);
if (0 != ventoy_check_block_list(file, &chunklist, 0))
{
grub_printf("########## UNSUPPORTED ###############\n");
}
grub_printf("filesystem: <%s> entry number:<%u>\n", file->fs->name, chunklist.cur_chunk);
@ -1493,6 +1541,7 @@ static grub_err_t ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt, int arg
}
grub_printf("\n==================================\n");
for (i = 0; i < chunklist.cur_chunk; i++)
{
grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i,
@ -1504,6 +1553,7 @@ static grub_err_t ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt, int arg
}
grub_free(chunklist.chunk);
grub_file_close(file);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
@ -1566,6 +1616,17 @@ static grub_err_t ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt, int a
return 0;
}
static grub_err_t ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
ventoy_plugin_dump_persistence();
return 0;
}
static grub_err_t ventoy_cmd_check_mode(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
@ -1812,6 +1873,7 @@ static cmd_para ventoy_cmds[] =
{ "vt_dynamic_menu", ventoy_cmd_dynamic_menu, 0, NULL, "", "", NULL },
{ "vt_check_mode", ventoy_cmd_check_mode, 0, NULL, "", "", NULL },
{ "vt_dump_auto_install", ventoy_cmd_dump_auto_install, 0, NULL, "", "", NULL },
{ "vt_dump_persistence", ventoy_cmd_dump_persistence, 0, NULL, "", "", NULL },
{ "vt_is_udf", ventoy_cmd_is_udf, 0, NULL, "", "", NULL },
{ "vt_file_size", ventoy_cmd_file_size, 0, NULL, "", "", NULL },

View File

@ -561,6 +561,14 @@ typedef struct install_template
struct install_template *next;
}install_template;
typedef struct persistence_config
{
char isopath[256];
char filepath[256];
struct persistence_config *next;
}persistence_config;
extern int g_ventoy_last_entry;
extern int g_ventoy_memdisk_mode;
extern int g_ventoy_iso_raw;
@ -571,7 +579,10 @@ void ventoy_swap_img(img_info *img1, img_info *img2);
char * ventoy_plugin_get_install_template(const char *isopath);
void ventoy_plugin_dump_auto_install(void);
int ventoy_fill_windows_rtdata(void *buf, char *isopath);
int ventoy_plugin_get_persistent_chunklist(const char *isopath, ventoy_img_chunk_list *chunk_list);
int ventoy_get_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start);
int ventoy_check_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start);
void ventoy_plugin_dump_persistence(void);
#endif /* __VENTOY_DEF_H__ */

View File

@ -852,8 +852,10 @@ grub_err_t ventoy_cmd_linux_locate_initrd(grub_extcmd_context_t ctxt, int argc,
grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **args)
{
int rc;
char *template_file = NULL;
char *template_buf = NULL;
char *persistent_buf = NULL;
grub_uint8_t *buf = NULL;
grub_uint32_t mod;
grub_uint32_t headlen;
@ -861,9 +863,11 @@ grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **arg
grub_uint32_t padlen;
grub_uint32_t img_chunk_size;
grub_uint32_t template_size = 0;
grub_uint32_t persistent_size = 0;
grub_file_t file;
grub_file_t scriptfile;
ventoy_img_chunk_list chunk_list;
(void)ctxt;
(void)argc;
@ -892,6 +896,13 @@ grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **arg
g_ventoy_cpio_size = 0;
}
rc = ventoy_plugin_get_persistent_chunklist(args[1], &chunk_list);
if (rc == 0 && chunk_list.cur_chunk > 0 && chunk_list.chunk)
{
persistent_size = chunk_list.cur_chunk * sizeof(ventoy_img_chunk);
persistent_buf = (char *)(chunk_list.chunk);
}
template_file = ventoy_plugin_get_install_template(args[1]);
if (template_file)
{
@ -915,7 +926,7 @@ grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **arg
}
}
g_ventoy_cpio_buf = grub_malloc(file->size + 4096 + template_size + img_chunk_size);
g_ventoy_cpio_buf = grub_malloc(file->size + 4096 + template_size + persistent_size + img_chunk_size);
if (NULL == g_ventoy_cpio_buf)
{
grub_file_close(file);
@ -943,6 +954,15 @@ grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **arg
buf += headlen + ventoy_align(template_size, 4);
}
if (persistent_size > 0 && persistent_buf)
{
headlen = ventoy_cpio_newc_fill_head(buf, persistent_size, persistent_buf, "ventoy/ventoy_persistent_map");
buf += headlen + ventoy_align(persistent_size, 4);
grub_free(persistent_buf);
persistent_buf = NULL;
}
/* step2: insert os param to cpio */
headlen = ventoy_cpio_newc_fill_head(buf, 0, NULL, "ventoy/ventoy_os_param");
padlen = sizeof(ventoy_os_param);

View File

@ -38,7 +38,9 @@
GRUB_MOD_LICENSE ("GPLv3+");
static char g_iso_disk_name[128];
static install_template *g_install_template_head = NULL;
static persistence_config *g_persistence_head = NULL;
static int ventoy_plugin_control_entry(VTOY_JSON *json, const char *isodisk)
{
@ -101,6 +103,24 @@ static int ventoy_plugin_theme_entry(VTOY_JSON *json, const char *isodisk)
debug("vtoy_gfxmode %s\n", value);
grub_env_set("vtoy_gfxmode", value);
}
value = vtoy_json_get_string_ex(json->pstChild, "ventoy_left");
if (value)
{
grub_env_set("VTLE_LFT", value);
}
value = vtoy_json_get_string_ex(json->pstChild, "ventoy_top");
if (value)
{
grub_env_set("VTLE_TOP", value);
}
value = vtoy_json_get_string_ex(json->pstChild, "ventoy_color");
if (value)
{
grub_env_set("VTLE_CLR", value);
}
return 0;
}
@ -162,11 +182,68 @@ static int ventoy_plugin_auto_install_entry(VTOY_JSON *json, const char *isodisk
}
static int ventoy_plugin_persistence_entry(VTOY_JSON *json, const char *isodisk)
{
const char *iso = NULL;
const char *persist = NULL;
VTOY_JSON *pNode = NULL;
persistence_config *node = NULL;
persistence_config *next = NULL;
(void)isodisk;
if (json->enDataType != JSON_TYPE_ARRAY)
{
debug("Not array %d\n", json->enDataType);
return 0;
}
if (g_persistence_head)
{
for (node = g_persistence_head; node; node = next)
{
next = node->next;
grub_free(node);
}
g_persistence_head = NULL;
}
for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
{
iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
if (iso && iso[0] == '/')
{
persist = vtoy_json_get_string_ex(pNode->pstChild, "backend");
if (persist && persist[0] == '/')
{
node = grub_zalloc(sizeof(persistence_config));
if (node)
{
grub_snprintf(node->isopath, sizeof(node->isopath), "%s", iso);
grub_snprintf(node->filepath, sizeof(node->filepath), "%s", persist);
if (g_persistence_head)
{
node->next = g_persistence_head;
}
g_persistence_head = node;
}
}
}
}
return 0;
}
static plugin_entry g_plugin_entries[] =
{
{ "control", ventoy_plugin_control_entry },
{ "theme", ventoy_plugin_theme_entry },
{ "auto_install", ventoy_plugin_auto_install_entry },
{ "persistence", ventoy_plugin_persistence_entry },
};
static int ventoy_parse_plugin_config(VTOY_JSON *json, const char *isodisk)
@ -174,6 +251,8 @@ static int ventoy_parse_plugin_config(VTOY_JSON *json, const char *isodisk)
int i;
VTOY_JSON *cur = json;
grub_snprintf(g_iso_disk_name, sizeof(g_iso_disk_name), "%s", isodisk);
while (cur)
{
for (i = 0; i < (int)ARRAY_SIZE(g_plugin_entries); i++)
@ -260,6 +339,32 @@ void ventoy_plugin_dump_auto_install(void)
return;
}
void ventoy_plugin_dump_persistence(void)
{
int rc;
persistence_config *node = NULL;
ventoy_img_chunk_list chunk_list;
for (node = g_persistence_head; node; node = node->next)
{
grub_printf("IMAGE:<%s>\n", node->isopath);
grub_printf("PERSIST:<%s>", node->filepath);
rc = ventoy_plugin_get_persistent_chunklist(node->isopath, &chunk_list);
if (rc == 0)
{
grub_printf(" [ SUCCESS ]\n\n");
grub_free(chunk_list.chunk);
}
else
{
grub_printf(" [ FAILED ]\n\n");
}
}
return;
}
char * ventoy_plugin_get_install_template(const char *isopath)
{
@ -276,3 +381,59 @@ char * ventoy_plugin_get_install_template(const char *isopath)
return NULL;
}
int ventoy_plugin_get_persistent_chunklist(const char *isopath, ventoy_img_chunk_list *chunk_list)
{
int rc = 1;
grub_uint64_t start = 0;
grub_file_t file = NULL;
persistence_config *node = NULL;
for (node = g_persistence_head; node; node = node->next)
{
if (grub_strcmp(node->isopath, isopath) == 0)
{
break;
}
}
if (NULL == node)
{
goto end;
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", g_iso_disk_name, node->filepath);
if (!file)
{
debug("Failed to open file %s%s\n", g_iso_disk_name, node->filepath);
goto end;
}
grub_memset(chunk_list, 0, sizeof(ventoy_img_chunk_list));
chunk_list->chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
if (NULL == chunk_list->chunk)
{
goto end;
}
chunk_list->max_chunk = DEFAULT_CHUNK_NUM;
chunk_list->cur_chunk = 0;
start = file->device->disk->partition->start;
ventoy_get_block_list(file, chunk_list, start);
if (0 != ventoy_check_block_list(file, chunk_list, start))
{
grub_free(chunk_list->chunk);
chunk_list->chunk = NULL;
goto end;
}
rc = 0;
end:
if (file)
grub_file_close(file);
return rc;
}

View File

@ -35,6 +35,7 @@ typedef enum ventoy_fs_type
ventoy_fs_ext, /* 2: ext2/ext3/ext4 */
ventoy_fs_xfs, /* 3: XFS */
ventoy_fs_udf, /* 4: UDF */
ventoy_fs_fat, /* 5: FAT */
ventoy_fs_max
}ventoy_fs_type;
@ -224,7 +225,7 @@ typedef struct ventoy_grub_param
#pragma pack()
int grub_ext_get_file_chunk(grub_uint64_t part_start, grub_file_t file, ventoy_img_chunk_list *chunk_list);
int grub_fat_get_file_chunk(grub_uint64_t part_start, grub_file_t file, ventoy_img_chunk_list *chunk_list);
grub_uint64_t grub_iso9660_get_last_read_pos(grub_file_t file);
grub_uint64_t grub_iso9660_get_last_file_dirent_pos(grub_file_t file);

View File

@ -25,5 +25,9 @@ fi
$SED -i "/_search_for_boot_device_/a\ $BUSYBOX_PATH/sh $VTOY_PATH/hook/debian/antix-disk.sh" /init
if [ -f $VTOY_PATH/ventoy_persistent_map ]; then
$SED 's#for param in $cmdline#for param in persist_all $cmdline#g' -i /init
fi
# for debug
#$SED -i "/^linuxfs_error/a\exec $VTOY_PATH/busybox/sh" /init

View File

@ -50,6 +50,3 @@ if [ -f $VTOY_PATH/autoinstall ]; then
fi
fi

View File

@ -118,5 +118,6 @@ else
fi
fi
# OK finish
set_ventoy_hook_finish

View File

@ -215,6 +215,29 @@ create_ventoy_device_mapper() {
fi
}
create_persistent_device_mapper() {
vtlog "create_persistent_device_mapper $*"
VT_DM_BIN=$(ventoy_find_bin_path dmsetup)
if [ -z "$VT_DM_BIN" ]; then
vtlog "no dmsetup avaliable, lastly try inbox dmsetup"
VT_DM_BIN=$VTOY_PATH/tool/dmsetup
fi
vtlog "dmsetup avaliable in system $VT_DM_BIN"
if ventoy_check_dm_module "$1"; then
vtlog "device-mapper module check success"
else
vterr "Error: no dm module avaliable"
fi
$VTOY_PATH/tool/vtoydm -p -f $VTOY_PATH/ventoy_persistent_map -d $1 > $VTOY_PATH/persistent_dm_table
$VT_DM_BIN create vtoy_persistent $VTOY_PATH/persistent_dm_table >>$VTLOG 2>&1
}
wait_for_ventoy_dm_disk_label() {
DM=$($BUSYBOX_PATH/readlink $VTOY_DM_PATH)
vtlog "wait_for_ventoy_dm_disk_label $DM ..."
@ -385,6 +408,30 @@ ventoy_copy_device_mapper() {
fi
}
# create link for device-mapper
ventoy_create_persistent_link() {
blkdev_num=$($VTOY_PATH/tool/dmsetup ls | grep vtoy_persistent | sed 's/.*(\([0-9][0-9]*\),.*\([0-9][0-9]*\).*/\1:\2/')
vtDM=$(ventoy_find_dm_id ${blkdev_num})
if ! [ -d /dev/disk/by-label ]; then
mkdir -p /dev/disk/by-label
fi
VTLABEL=$($BUSYBOX_PATH/blkid /dev/$vtDM | $SED 's/.*LABEL="\([^"]*\)".*/\1/')
if [ -z "$VTLABEL" ]; then
VTLABEL=casper-rw
fi
vtlog "Persistent Label: ##${VTLABEL}##"
if ! [ -e /dev/disk/by-label/$VTLABEL ]; then
vtOldDir=$PWD
cd /dev/disk/by-label
ln -s ../../$vtDM $VTLABEL
cd $vtOldDir
fi
}
ventoy_udev_disk_common_hook() {
VTDISK="${1:0:-1}"
@ -419,8 +466,14 @@ ventoy_udev_disk_common_hook() {
else
ventoy_copy_device_mapper "/dev/$1"
fi
if [ -f $VTOY_PATH/ventoy_persistent_map ]; then
create_persistent_device_mapper "/dev/$VTDISK"
ventoy_create_persistent_link
fi
}
is_inotify_ventoy_part() {
if echo $1 | grep -q "2$"; then
if ! [ -e /sys/block/$1 ]; then

View File

@ -222,6 +222,11 @@ if [ "$rmproc" = "Y" ]; then
$BUSYBOX_PATH/rm -rf /proc
fi
if [ -f $VTOY_PATH/ventoy_persistent_map ]; then
export PERSISTENT='YES'
export PERSISTENCE='true'
fi
cd /
unset VTOY_PATH VTLOG FIND GREP EGREP CAT AWK SED SLEEP HEAD

View File

@ -111,17 +111,31 @@ if ! check_tool_work_ok; then
fi
grep "^$DISK" /proc/mounts | while read mtline; do
mtpnt=$(echo $mtline | awk '{print $DISK}')
mtpnt=$(echo $mtline | awk '{print $2}')
vtdebug "Trying to umount $mtpnt ..."
umount $mtpnt >/dev/null 2>&1
done
if swapon -s | grep -q "^${DISK}[0-9]"; then
swapon -s | grep "^${DISK}[0-9]" | awk '{print $1}' | while read line; do
vtdebug "Trying to swapoff $line ..."
swapoff $line
done
fi
if grep "$DISK" /proc/mounts; then
vterr "$DISK is already mounted, please umount it first!"
cd $OLDDIR
exit 1
fi
if swapon -s | grep -q "^${DISK}[0-9]"; then
vterr "$DISK is used as swap, please swapoff it first!"
cd $OLDDIR
exit 1
fi
if [ "$MODE" = "install" ]; then
vtdebug "install ventoy ..."
@ -230,6 +244,12 @@ if [ "$MODE" = "install" ]; then
vtinfo "esp partition processing ..."
sleep 1
mtpnt=$(grep "^${DISK}2" /proc/mounts | awk '{print $2}')
if [ -n "$mtpnt" ]; then
umount $mtpnt >/dev/null 2>&1
fi
if [ "$SECUREBOOT" != "YES" ]; then
mkdir ./tmp_mnt
@ -239,9 +259,14 @@ if [ "$MODE" = "install" ]; then
vtdebug "mounting part2 success"
break
fi
mtpnt=$(grep "^${DISK}2" /proc/mounts | awk '{print $2}')
if [ -n "$mtpnt" ]; then
umount $mtpnt >/dev/null 2>&1
fi
sleep 2
done
rm -f ./tmp_mnt/EFI/BOOT/BOOTX64.EFI
rm -f ./tmp_mnt/EFI/BOOT/grubx64.efi
rm -f ./tmp_mnt/EFI/BOOT/MokManager.efi

View File

@ -121,6 +121,7 @@ function distro_specify_initrd_file {
fi
}
function distro_specify_initrd_file_phase2 {
if [ -f (loop)/boot/initrd.img ]; then
vt_linux_specify_initrd_file /boot/initrd.img
@ -132,6 +133,8 @@ function distro_specify_initrd_file_phase2 {
vt_linux_specify_initrd_file /boot/iniramfs.igz
elif [ -f (loop)/initrd-x86_64 ]; then
vt_linux_specify_initrd_file /initrd-x86_64
elif [ -f (loop)/live/initrd.img ]; then
vt_linux_specify_initrd_file /live/initrd.img
fi
}
@ -453,7 +456,7 @@ function common_menuentry {
#############################################################
#############################################################
set VENTOY_VERSION="1.0.10"
set VENTOY_VERSION="1.0.11"
# Default menu display mode, you can change it as you want.
# 0: List mode

5
License/license-logo.txt Normal file
View File

@ -0,0 +1,5 @@
Ventoy Logo was downloaded from https://www.easyicon.net/29165-usb_icon.html
As descripted in the website:
Author: Ahmad Hania
License: Creative Commons (Attribution-Noncommercial-Share Alike 3.0 Unported)

View File

@ -500,10 +500,17 @@ static int vtoydm_print_linear_table(const char *img_map_file, const char *diskn
{
sector_start = chunk[i].img_start_sector;
sector_num = chunk[i].img_end_sector - chunk[i].img_start_sector + 1;
/* TBD: to be more flexible */
#if 0
printf("%u %u linear %s %llu\n",
(sector_start << 2), (sector_num << 2),
diskname, (unsigned long long)chunk[i].disk_start_sector);
#else
printf("%u %u linear %s1 %llu\n",
(sector_start << 2), (sector_num << 2),
diskname, (unsigned long long)chunk[i].disk_start_sector - 2048);
#endif
}
free(chunk);

View File

@ -50,6 +50,7 @@ typedef enum ventoy_fs_type
ventoy_fs_ext, /* 2: ext2/ext3/ext4 */
ventoy_fs_xfs, /* 3: XFS */
ventoy_fs_udf, /* 4: UDF */
ventoy_fs_fat, /* 5: FAT */
ventoy_fs_max
}ventoy_fs_type;
@ -143,7 +144,7 @@ static ventoy_guid vtoy_guid = VENTOY_GUID;
static const char *g_ventoy_fs[ventoy_fs_max] =
{
"exfat", "ntfs", "ext*", "xfs", "udf"
"exfat", "ntfs", "ext*", "xfs", "udf", "fat"
};
static int vtoy_check_os_param(ventoy_os_param *param)