experimental support for btrfs file system. (#3438 #3431 #3077 #2093)

This commit is contained in:
longpanda
2025-12-11 16:29:59 +08:00
parent 40fbc041ea
commit 06f164ef70
7 changed files with 2405 additions and 9 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -466,6 +466,37 @@ grub_err_t grub_disk_blocklist_read(void *chunklist, grub_uint64_t sector,
return 0;
}
grub_err_t grub_disk_blocklist_read2(grub_disk_t disk, grub_uint64_t sector,
grub_uint64_t size, char *buf)
{
ventoy_img_chunk_list *chunk_list = (ventoy_img_chunk_list *)(disk->read_hook_data);
if (buf < chunk_list->buf || buf >= chunk_list->buf + VTOY_CHUNK_BUF_SIZE)
{
return 2;
}
if ((chunk_list->buf + chunk_list->last_off) != buf)
{
chunk_list->err_code = VTOY_CHUNK_ERR_NOT_FLAT;
return 0;
}
if (chunk_list->last_off + size > VTOY_CHUNK_BUF_SIZE)
{
chunk_list->err_code = VTOY_CHUNK_ERR_OVER_FLOW;
return 0;
}
chunk_list->last_off += (grub_uint32_t)size;
if (chunk_list->last_off == VTOY_CHUNK_BUF_SIZE)
{
chunk_list->last_off = 0;
}
return grub_disk_blocklist_read(chunk_list, sector, size, disk->log_sector_size);
}
/* Read data from the disk. */
grub_err_t
grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
@@ -475,6 +506,14 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector,
{
return grub_disk_blocklist_read((ventoy_img_chunk_list *)disk->read_hook_data, sector, size, disk->log_sector_size);
}
else if (disk->read_hook == (grub_disk_read_hook_t)(void *)grub_disk_blocklist_read2)
{
grub_err_t rv = grub_disk_blocklist_read2(disk, sector, size, (char *)buf);
if (rv != 2)
{
return rv;
}
}
/* First of all, check if the region is within the disk. */
if (grub_disk_adjust_range (disk, &sector, &offset, size) != GRUB_ERR_NONE)

View File

@@ -202,6 +202,10 @@ int ventoy_get_fs_type(const char *fs)
{
return ventoy_fs_fat;
}
else if (grub_strncmp(fs, "btrfs", 5) == 0)
{
return ventoy_fs_btrfs;
}
return ventoy_fs_max;
}
@@ -1696,7 +1700,7 @@ static int ventoy_vlnk_probe_fs(ventoy_vlnk_part *cur)
{
const char *fs[ventoy_fs_max + 1] =
{
"exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
"exfat", "ntfs", "ext2", "xfs", "udf", "fat", "btrfs", NULL
};
if (!cur->dev)
@@ -3251,13 +3255,49 @@ void ventoy_fill_os_param(grub_file_t file, ventoy_os_param *param)
return;
}
int ventoy_check_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start)
static const char* g_chunk_err_msg[VTOY_CHUNK_ERR_MAX] =
{
"success",
"File system use more than 1 disks! (maybe RAID)",
"File system enable RAID feature, this is NOT supported!",
"File is compressed in disk, this is not supported!",
"File not flat in disk! (maybe compressed)",
"Read buffer overflow!",
};
static const char * ventoy_get_chunk_err_msg(grub_uint32_t err)
{
if (err < VTOY_CHUNK_ERR_MAX)
{
return g_chunk_err_msg[err];
}
return "XXXX";
}
int ventoy_check_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist,
grub_disk_addr_t start, char *err, grub_uint32_t len)
{
grub_uint32_t i = 0;
grub_uint64_t total = 0;
grub_uint64_t fileblk = 0;
ventoy_img_chunk *chunk = NULL;
if (chunklist->err_code)
{
if (err)
{
grub_snprintf(err, len, "%s", ventoy_get_chunk_err_msg(chunklist->err_code));
}
return 1;
}
if (err)
{
grub_snprintf(err, len, "Unsupported chunk list.");
}
for (i = 0; i < chunklist->cur_chunk; i++)
{
chunk = chunklist->chunk + i;
@@ -3307,6 +3347,10 @@ int ventoy_get_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, gr
{
grub_ext_get_file_chunk(start, file, chunklist);
}
else if (fs_type == ventoy_fs_btrfs)
{
grub_btrfs_get_file_chunk(start, file, chunklist);
}
else
{
file->read_hook = (grub_disk_read_hook_t)(void *)grub_disk_blocklist_read;
@@ -3368,6 +3412,7 @@ static grub_err_t ventoy_cmd_img_sector(grub_extcmd_context_t ctxt, int argc, ch
int rc;
grub_file_t file;
grub_disk_addr_t start;
char errmsg[128];
(void)ctxt;
(void)argc;
@@ -3408,12 +3453,14 @@ static grub_err_t ventoy_cmd_img_sector(grub_extcmd_context_t ctxt, int argc, ch
ventoy_get_block_list(file, &g_img_chunk_list, start);
rc = ventoy_check_block_list(file, &g_img_chunk_list, start);
rc = ventoy_check_block_list(file, &g_img_chunk_list, start, errmsg, sizeof(errmsg));
grub_file_close(file);
if (rc)
{
return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET, "Unsupported chunk list.\n");
vtoy_tip(10, "%s\n\nWill exit in 10 seconds...\n", errmsg);
grub_exit();
return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET, "%s\n", errmsg);
}
grub_memset(&g_grub_param->file_replace, 0, sizeof(g_grub_param->file_replace));
@@ -3950,6 +3997,7 @@ static grub_err_t ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt, int arg
grub_uint32_t i;
grub_file_t file;
ventoy_img_chunk_list chunklist;
char errmsg[128];
(void)ctxt;
(void)argc;
@@ -3973,8 +4021,9 @@ static grub_err_t ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt, int arg
ventoy_get_block_list(file, &chunklist, 0);
if (0 != ventoy_check_block_list(file, &chunklist, 0))
if (0 != ventoy_check_block_list(file, &chunklist, 0, errmsg, sizeof(errmsg)))
{
grub_printf("%s\n", errmsg);
grub_printf("########## UNSUPPORTED ###############\n");
}

View File

@@ -95,6 +95,12 @@
return (err);\
}
#define vtoy_tip(wait_seconds, fmt, ...) \
grub_printf(fmt, __VA_ARGS__); \
grub_refresh(); \
grub_sleep(wait_seconds)
#define VTOY_APPEND_NEWBUF(buf) \
{\
char *__c = buf;\
@@ -1150,7 +1156,7 @@ int ventoy_plugin_find_conf_replace(const char *iso, conf_replace *nodes[VTOY_MA
dud * ventoy_plugin_find_dud(const char *iso);
int ventoy_plugin_load_dud(dud *node, const char *isopart);
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);
int ventoy_check_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start, char *err, grub_uint32_t len);
void ventoy_plugin_dump_persistence(void);
grub_err_t ventoy_cmd_set_theme(grub_extcmd_context_t ctxt, int argc, char **args);
grub_err_t ventoy_cmd_set_theme_path(grub_extcmd_context_t ctxt, int argc, char **args);

View File

@@ -2765,7 +2765,7 @@ int ventoy_plugin_get_persistent_chunklist(const char *isopath, int index, vento
start = file->device->disk->partition->start;
ventoy_get_block_list(file, chunk_list, start);
if (0 != ventoy_check_block_list(file, chunk_list, start))
if (0 != ventoy_check_block_list(file, chunk_list, start, NULL, 0))
{
grub_free(chunk_list->chunk);
chunk_list->chunk = NULL;

View File

@@ -197,6 +197,8 @@ grub_disk_t EXPORT_FUNC(grub_disk_open) (const char *name);
void EXPORT_FUNC(grub_disk_close) (grub_disk_t disk);
grub_err_t EXPORT_FUNC(grub_disk_blocklist_read)(void *chunklist, grub_uint64_t sector,
grub_uint64_t size, grub_uint32_t log_sector_size);
grub_err_t EXPORT_FUNC(grub_disk_blocklist_read2)(grub_disk_t disk, grub_uint64_t sector,
grub_uint64_t size, char *buf);
grub_err_t EXPORT_FUNC(grub_disk_read) (grub_disk_t disk,
grub_disk_addr_t sector,

View File

@@ -36,6 +36,7 @@ typedef enum ventoy_fs_type
ventoy_fs_xfs, /* 3: XFS */
ventoy_fs_udf, /* 4: UDF */
ventoy_fs_fat, /* 5: FAT */
ventoy_fs_btrfs, /* 6: BTRFS */
ventoy_fs_max
}ventoy_fs_type;
@@ -252,12 +253,15 @@ typedef struct ventoy_virt_chunk
#define DEFAULT_CHUNK_NUM 1024
typedef struct ventoy_img_chunk_list
{
char *buf;
grub_uint32_t last_off;
grub_uint32_t err_code;
grub_uint32_t max_chunk;
grub_uint32_t cur_chunk;
ventoy_img_chunk *chunk;
}ventoy_img_chunk_list;
#pragma pack()
#define ventoy_filt_register grub_file_filter_register
@@ -291,7 +295,21 @@ typedef struct ventoy_grub_param
#pragma pack()
#define VTOY_CHUNK_BUF_SIZE (4 * 1024 * 1024)
typedef enum vtoy_chunk_err
{
VTOY_CHUNK_ERR_NONE = 0,
VTOY_CHUNK_ERR_MULTI_DEV,
VTOY_CHUNK_ERR_RAID,
VTOY_CHUNK_ERR_COMPRESS,
VTOY_CHUNK_ERR_NOT_FLAT,
VTOY_CHUNK_ERR_OVER_FLOW,
VTOY_CHUNK_ERR_MAX
}vtoy_chunk_err;
int grub_ext_get_file_chunk(grub_uint64_t part_start, grub_file_t file, ventoy_img_chunk_list *chunk_list);
int grub_btrfs_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);
void grub_iso9660_set_nojoliet(int nojoliet);
int grub_iso9660_is_joliet(void);