diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/fs/ext2.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/fs/ext2.c
index eb0dae5e..8e5b38b0 100644
--- a/GRUB2/MOD_SRC/grub-2.04/grub-core/fs/ext2.c
+++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/fs/ext2.c
@@ -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",
diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/fs/fshelp.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/fs/fshelp.c
new file mode 100644
index 00000000..5901fac4
--- /dev/null
+++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/fs/fshelp.c
@@ -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;
+}
diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c
index ce77a8c8..883ca097 100644
--- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c
+++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c
@@ -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 },
diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h
index c0456236..0202045f 100644
--- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h
+++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_def.h
@@ -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__ */
 
diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_linux.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_linux.c
index 06cd046e..403bf30b 100644
--- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_linux.c
+++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_linux.c
@@ -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);
diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c
index 82de5130..16a31cc3 100644
--- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c
+++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c
@@ -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;
+}
+
diff --git a/GRUB2/MOD_SRC/grub-2.04/include/grub/ventoy.h b/GRUB2/MOD_SRC/grub-2.04/include/grub/ventoy.h
index 205ba1d1..799bfb4e 100644
--- a/GRUB2/MOD_SRC/grub-2.04/include/grub/ventoy.h
+++ b/GRUB2/MOD_SRC/grub-2.04/include/grub/ventoy.h
@@ -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);
diff --git a/IMG/cpio/ventoy/hook/debian/antix-hook.sh b/IMG/cpio/ventoy/hook/debian/antix-hook.sh
index 66615047..fa9d0834 100644
--- a/IMG/cpio/ventoy/hook/debian/antix-hook.sh
+++ b/IMG/cpio/ventoy/hook/debian/antix-hook.sh
@@ -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
diff --git a/IMG/cpio/ventoy/hook/debian/default-hook.sh b/IMG/cpio/ventoy/hook/debian/default-hook.sh
index 706173b2..bd2dd1ea 100644
--- a/IMG/cpio/ventoy/hook/debian/default-hook.sh
+++ b/IMG/cpio/ventoy/hook/debian/default-hook.sh
@@ -50,6 +50,3 @@ if [ -f $VTOY_PATH/autoinstall ]; then
     fi
 fi
 
-
-
-
diff --git a/IMG/cpio/ventoy/hook/debian/udev_disk_hook.sh b/IMG/cpio/ventoy/hook/debian/udev_disk_hook.sh
index 6bc7077d..007d2fa3 100644
--- a/IMG/cpio/ventoy/hook/debian/udev_disk_hook.sh
+++ b/IMG/cpio/ventoy/hook/debian/udev_disk_hook.sh
@@ -118,5 +118,6 @@ else
     fi
 fi
 
+
 # OK finish
 set_ventoy_hook_finish
diff --git a/IMG/cpio/ventoy/hook/ventoy-hook-lib.sh b/IMG/cpio/ventoy/hook/ventoy-hook-lib.sh
index f70d5574..c656c6fe 100644
--- a/IMG/cpio/ventoy/hook/ventoy-hook-lib.sh
+++ b/IMG/cpio/ventoy/hook/ventoy-hook-lib.sh
@@ -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
diff --git a/IMG/cpio/ventoy/ventoy.sh b/IMG/cpio/ventoy/ventoy.sh
index 5beb46df..e64a4a76 100644
--- a/IMG/cpio/ventoy/ventoy.sh
+++ b/IMG/cpio/ventoy/ventoy.sh
@@ -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
 
diff --git a/INSTALL/Ventoy2Disk.sh b/INSTALL/Ventoy2Disk.sh
index 64322178..01a5ab4c 100644
--- a/INSTALL/Ventoy2Disk.sh
+++ b/INSTALL/Ventoy2Disk.sh
@@ -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
diff --git a/INSTALL/grub/grub.cfg b/INSTALL/grub/grub.cfg
index ab18f8d8..0c51f5c1 100644
--- a/INSTALL/grub/grub.cfg
+++ b/INSTALL/grub/grub.cfg
@@ -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   
diff --git a/License/license-logo.txt b/License/license-logo.txt
new file mode 100644
index 00000000..cfaa8772
--- /dev/null
+++ b/License/license-logo.txt
@@ -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)
diff --git a/VtoyTool/vtoydm.c b/VtoyTool/vtoydm.c
index d45050c1..aa460af0 100644
--- a/VtoyTool/vtoydm.c
+++ b/VtoyTool/vtoydm.c
@@ -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);
diff --git a/VtoyTool/vtoydump.c b/VtoyTool/vtoydump.c
index e494598a..1c620d3c 100644
--- a/VtoyTool/vtoydump.c
+++ b/VtoyTool/vtoydump.c
@@ -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)