1 /******************************************************************************
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <grub/types.h>
21 #include <grub/misc.h>
25 #include <grub/disk.h>
26 #include <grub/device.h>
27 #include <grub/term.h>
28 #include <grub/partition.h>
29 #include <grub/file.h>
30 #include <grub/normal.h>
31 #include <grub/extcmd.h>
32 #include <grub/datetime.h>
33 #include <grub/i18n.h>
35 #include <grub/time.h>
37 #include <grub/elfload.h>
38 #include <grub/ventoy.h>
39 #include "ventoy_def.h"
41 GRUB_MOD_LICENSE ("GPLv3+");
43 char g_ko_mod_path
[256];
44 int g_conf_new_len
= 0;
45 char *g_conf_new_data
= NULL
;
47 int g_mod_new_len
= 0;
48 char *g_mod_new_data
= NULL
;
50 grub_uint64_t g_mod_override_offset
= 0;
51 grub_uint64_t g_conf_override_offset
= 0;
53 static int ventoy_get_file_override(const char *filename
, grub_uint64_t
*offset
)
59 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", filename
);
65 *offset
= grub_iso9660_get_last_file_dirent_pos(file
) + 2;
67 grub_file_close(file
);
72 static grub_uint32_t
ventoy_unix_get_override_chunk_count(void)
74 grub_uint32_t count
= 0;
76 if (g_conf_new_len
> 0)
81 if (g_mod_new_len
> 0)
89 static grub_uint32_t
ventoy_unix_get_virt_chunk_count(void)
91 grub_uint32_t count
= 0;
93 if (g_conf_new_len
> 0)
98 if (g_mod_new_len
> 0)
105 static grub_uint32_t
ventoy_unix_get_virt_chunk_size(void)
109 size
= sizeof(ventoy_virt_chunk
) * ventoy_unix_get_virt_chunk_count();
111 if (g_conf_new_len
> 0)
113 size
+= ventoy_align_2k(g_conf_new_len
);
116 if (g_mod_new_len
> 0)
118 size
+= ventoy_align_2k(g_mod_new_len
);
124 static void ventoy_unix_fill_override_data( grub_uint64_t isosize
, void *override
)
126 grub_uint64_t sector
;
127 ventoy_override_chunk
*cur
;
128 ventoy_iso9660_override
*dirent
;
130 sector
= (isosize
+ 2047) / 2048;
132 cur
= (ventoy_override_chunk
*)override
;
134 if (g_conf_new_len
> 0)
137 cur
->img_offset
= g_conf_override_offset
;
138 cur
->override_size
= sizeof(ventoy_iso9660_override
);
139 dirent
= (ventoy_iso9660_override
*)cur
->override_data
;
140 dirent
->first_sector
= (grub_uint32_t
)sector
;
141 dirent
->size
= (grub_uint32_t
)g_conf_new_len
;
142 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
143 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
144 sector
+= (dirent
->size
+ 2047) / 2048;
147 if (g_mod_new_len
> 0)
151 cur
->img_offset
= g_mod_override_offset
;
152 cur
->override_size
= sizeof(ventoy_iso9660_override
);
153 dirent
= (ventoy_iso9660_override
*)cur
->override_data
;
154 dirent
->first_sector
= (grub_uint32_t
)sector
;
155 dirent
->size
= (grub_uint32_t
)g_mod_new_len
;
156 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
157 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
158 sector
+= (dirent
->size
+ 2047) / 2048;
164 static void ventoy_unix_fill_virt_data( grub_uint64_t isosize
, ventoy_chain_head
*chain
)
166 grub_uint64_t sector
;
167 grub_uint32_t offset
;
168 grub_uint32_t data_secs
;
170 ventoy_virt_chunk
*cur
;
172 override
= (char *)chain
+ chain
->virt_chunk_offset
;
173 cur
= (ventoy_virt_chunk
*)override
;
175 sector
= (isosize
+ 2047) / 2048;
176 offset
= 2 * sizeof(ventoy_virt_chunk
);
178 if (g_conf_new_len
> 0)
180 ventoy_unix_fill_virt(g_conf_new_data
, g_conf_new_len
);
183 if (g_mod_new_len
> 0)
185 ventoy_unix_fill_virt(g_mod_new_data
, g_mod_new_len
);
191 static int ventoy_freebsd_append_conf(char *buf
, const char *isopath
)
198 ventoy_img_chunk
*chunk
;
199 grub_uint8_t disk_sig
[4];
200 grub_uint8_t disk_guid
[16];
202 debug("ventoy_freebsd_append_conf %s\n", isopath
);
204 isofile
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", isopath
);
210 vtoy_ssprintf(buf
, pos
, "ventoy_load=\"%s\"\n", "YES");
211 vtoy_ssprintf(buf
, pos
, "ventoy_name=\"%s\"\n", g_ko_mod_path
);
213 disk
= isofile
->device
->disk
;
215 ventoy_get_disk_guid(isofile
->name
, disk_guid
, disk_sig
);
217 for (i
= 0; i
< 16; i
++)
219 grub_snprintf(uuid
+ i
* 2, sizeof(uuid
), "%02x", disk_guid
[i
]);
222 vtoy_ssprintf(buf
, pos
, "hint.ventoy.0.disksize=%llu\n", (ulonglong
)(disk
->total_sectors
* (1 << disk
->log_sector_size
)));
223 vtoy_ssprintf(buf
, pos
, "hint.ventoy.0.diskuuid=\"%s\"\n", uuid
);
224 vtoy_ssprintf(buf
, pos
, "hint.ventoy.0.disksignature=%02x%02x%02x%02x\n", disk_sig
[0], disk_sig
[1], disk_sig
[2], disk_sig
[3]);
225 vtoy_ssprintf(buf
, pos
, "hint.ventoy.0.segnum=%u\n", g_img_chunk_list
.cur_chunk
);
227 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
229 chunk
= g_img_chunk_list
.chunk
+ i
;
230 vtoy_ssprintf(buf
, pos
, "hint.ventoy.%u.seg=\"0x%llx@0x%llx\"\n",
231 i
, (ulonglong
)(chunk
->disk_start_sector
* 512),
232 (ulonglong
)((chunk
->disk_end_sector
+ 1) * 512));
235 grub_file_close(isofile
);
240 static int ventoy_dragonfly_append_conf(char *buf
, const char *isopath
)
244 debug("ventoy_dragonfly_append_conf %s\n", isopath
);
246 vtoy_ssprintf(buf
, pos
, "tmpfs_load=\"%s\"\n", "YES");
247 vtoy_ssprintf(buf
, pos
, "dm_target_linear_load=\"%s\"\n", "YES");
248 vtoy_ssprintf(buf
, pos
, "initrd.img_load=\"%s\"\n", "YES");
249 vtoy_ssprintf(buf
, pos
, "initrd.img_type=\"%s\"\n", "md_image");
250 vtoy_ssprintf(buf
, pos
, "vfs.root.mountfrom=\"%s\"\n", "ufs:md0s0");
255 grub_err_t
ventoy_cmd_unix_reset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
263 g_mod_override_offset
= 0;
264 g_conf_override_offset
= 0;
266 check_free(g_mod_new_data
, grub_free
);
267 check_free(g_conf_new_data
, grub_free
);
269 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
272 grub_err_t
ventoy_cmd_parse_freenas_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
275 const char *ver
= NULL
;
277 VTOY_JSON
*json
= NULL
;
282 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
285 debug("Failed to open file %s\n", args
[0]);
289 buf
= grub_malloc(file
->size
+ 2);
292 grub_file_close(file
);
295 grub_file_read(file
, buf
, file
->size
);
298 json
= vtoy_json_create();
304 if (vtoy_json_parse(json
, buf
))
309 ver
= vtoy_json_get_string_ex(json
->pstChild
, "Version");
312 debug("freenas version:<%s>\n", ver
);
313 ventoy_set_env(args
[1], ver
);
317 debug("freenas version:<%s>\n", "NOT FOUND");
318 grub_env_unset(args
[1]);
322 grub_check_free(buf
);
323 check_free(json
, vtoy_json_destroy
);
324 grub_file_close(file
);
326 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
329 grub_err_t
ventoy_cmd_unix_freebsd_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
334 char *nextline
= NULL
;
340 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
343 debug("Failed to open file %s\n", args
[0]);
347 buf
= grub_zalloc(file
->size
+ 2);
350 grub_file_close(file
);
353 grub_file_read(file
, buf
, file
->size
);
355 for (start
= buf
; start
; start
= nextline
)
357 if (grub_strncmp(start
, "USERLAND_VERSION", 16) == 0)
360 while (*nextline
&& *nextline
!= '\r' && *nextline
!= '\n')
368 nextline
= ventoy_get_line(start
);
373 debug("freebsd version:<%s>\n", start
);
374 ventoy_set_env(args
[1], start
);
378 debug("freebsd version:<%s>\n", "NOT FOUND");
379 grub_env_unset(args
[1]);
383 grub_file_close(file
);
385 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
388 grub_err_t
ventoy_cmd_unix_freebsd_ver_elf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
392 grub_elf_t elf
= NULL
;
393 grub_off_t offset
= 0;
394 grub_uint32_t len
= 0;
406 debug("Invalid argc %d\n", argc
);
410 data
= grub_zalloc(8192);
416 elf
= grub_elf_open(args
[0], GRUB_FILE_TYPE_LINUX_INITRD
);
419 debug("Failed to open file %s\n", args
[0]);
423 if (args
[1][0] == '6')
425 Elf64_Ehdr
*e
= &(elf
->ehdr
.ehdr64
);
431 h
= hdr
= grub_zalloc(e
->e_shnum
* e
->e_shentsize
);
437 debug("read section header %u %u %u\n", e
->e_shnum
, e
->e_shentsize
, e
->e_shstrndx
);
438 grub_file_seek(elf
->file
, e
->e_shoff
);
439 grub_file_read(elf
->file
, h
, e
->e_shnum
* e
->e_shentsize
);
441 s
= (Elf64_Shdr
*)((char *)h
+ e
->e_shstrndx
* e
->e_shentsize
);
442 str
= grub_malloc(s
->sh_size
+ 1);
449 debug("read string table %u %u\n", (grub_uint32_t
)s
->sh_offset
, (grub_uint32_t
)s
->sh_size
);
450 grub_file_seek(elf
->file
, s
->sh_offset
);
451 grub_file_read(elf
->file
, str
, s
->sh_size
);
453 for (t
= h
, i
= 0; i
< e
->e_shnum
; i
++)
455 if (grub_strcmp(str
+ t
->sh_name
, ".data") == 0)
457 offset
= t
->sh_offset
;
459 debug("find .data section at %u %u\n", (grub_uint32_t
)offset
, len
);
462 t
= (Elf64_Shdr
*)((char *)t
+ e
->e_shentsize
);
467 Elf32_Ehdr
*e
= &(elf
->ehdr
.ehdr32
);
473 h
= hdr
= grub_zalloc(e
->e_shnum
* e
->e_shentsize
);
479 debug("read section header %u %u %u\n", e
->e_shnum
, e
->e_shentsize
, e
->e_shstrndx
);
480 grub_file_seek(elf
->file
, e
->e_shoff
);
481 grub_file_read(elf
->file
, h
, e
->e_shnum
* e
->e_shentsize
);
483 s
= (Elf32_Shdr
*)((char *)h
+ e
->e_shstrndx
* e
->e_shentsize
);
484 str
= grub_malloc(s
->sh_size
+ 1);
491 debug("read string table %u %u\n", (grub_uint32_t
)s
->sh_offset
, (grub_uint32_t
)s
->sh_size
);
492 grub_file_seek(elf
->file
, s
->sh_offset
);
493 grub_file_read(elf
->file
, str
, s
->sh_size
);
495 for (t
= h
, i
= 0; i
< e
->e_shnum
; i
++)
497 if (grub_strcmp(str
+ t
->sh_name
, ".data") == 0)
499 offset
= t
->sh_offset
;
501 debug("find .data section at %u %u\n", (grub_uint32_t
)offset
, len
);
504 t
= (Elf32_Shdr
*)((char *)t
+ e
->e_shentsize
);
508 if (offset
== 0 || len
== 0)
510 debug(".data section not found %s\n", args
[0]);
514 grub_file_seek(elf
->file
, offset
+ len
- 8192);
515 grub_file_read(elf
->file
, data
, 8192);
517 for (j
= 0; j
< 8192 - 12; j
++)
519 if (grub_strncmp(data
+ j
, "@(#)FreeBSD ", 12) == 0)
521 for (k
= j
+ 12; k
< 8192; k
++)
523 if (0 == grub_isdigit(data
[k
]) && data
[k
] != '.')
530 grub_snprintf(ver
, sizeof(ver
), "%s", data
+ j
+ 12);
537 k
= (int)grub_strtoul(ver
, NULL
, 10);
538 debug("freebsd version:<%s> <%d.x>\n", ver
, k
);
539 grub_snprintf(ver
, sizeof(ver
), "%d.x", k
);
540 ventoy_set_env(args
[2], ver
);
544 debug("freebsd version:<%s>\n", "NOT FOUND");
548 grub_check_free(str
);
549 grub_check_free(hdr
);
550 grub_check_free(data
);
551 check_free(elf
, grub_elf_close
);
553 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
556 grub_err_t
ventoy_cmd_unix_replace_conf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
560 grub_uint64_t offset
;
562 const char *confile
= NULL
;
563 const char * loader_conf
[] =
566 "/boot/defaults/loader.conf",
573 debug("Replace conf invalid argc %d\n", argc
);
577 for (i
= 0; i
< sizeof(loader_conf
) / sizeof(loader_conf
[0]); i
++)
579 if (ventoy_get_file_override(loader_conf
[i
], &offset
) == 0)
581 confile
= loader_conf
[i
];
582 g_conf_override_offset
= offset
;
589 debug("Can't find loader.conf file from %u locations\n", i
);
593 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "(loop)/%s", confile
);
596 debug("Failed to open %s \n", confile
);
600 debug("old conf file size:%d\n", (int)file
->size
);
602 data
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
605 grub_file_close(file
);
609 grub_file_read(file
, data
, file
->size
);
610 grub_file_close(file
);
612 g_conf_new_data
= data
;
613 g_conf_new_len
= (int)file
->size
;
615 if (grub_strcmp(args
[0], "FreeBSD") == 0)
617 g_conf_new_len
+= ventoy_freebsd_append_conf(data
+ file
->size
, args
[1]);
619 else if (grub_strcmp(args
[0], "DragonFly") == 0)
621 g_conf_new_len
+= ventoy_dragonfly_append_conf(data
+ file
->size
, args
[1]);
624 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
627 grub_err_t
ventoy_cmd_unix_replace_ko(grub_extcmd_context_t ctxt
, int argc
, char **args
)
630 grub_uint64_t offset
;
637 debug("Replace ko invalid argc %d\n", argc
);
641 debug("replace ko %s\n", args
[0]);
643 if (ventoy_get_file_override(args
[0], &offset
) == 0)
645 grub_snprintf(g_ko_mod_path
, sizeof(g_ko_mod_path
), "%s", args
[0]);
646 g_mod_override_offset
= offset
;
650 debug("Can't find replace ko file from %s\n", args
[0]);
654 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[1]);
657 debug("Failed to open %s \n", args
[1]);
661 debug("new ko file size:%d\n", (int)file
->size
);
663 data
= grub_malloc(file
->size
);
666 debug("Failed to alloc memory for new ko %d\n", (int)file
->size
);
667 grub_file_close(file
);
671 grub_file_read(file
, data
, file
->size
);
672 grub_file_close(file
);
674 g_mod_new_data
= data
;
675 g_mod_new_len
= (int)file
->size
;
677 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
680 grub_err_t
ventoy_cmd_unix_fill_image_desc(grub_extcmd_context_t ctxt
, int argc
, char **args
)
684 grub_uint32_t memsize
;
685 ventoy_image_desc
*desc
;
686 grub_uint8_t flag
[32] = {
687 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00,
688 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
695 debug("ventoy_cmd_unix_fill_image_desc %p\n", g_mod_new_data
);
702 byte
= (grub_uint8_t
*)g_mod_new_data
;
703 for (i
= 0; i
< g_mod_new_len
- 32; i
+= 16)
705 if (byte
[i
] == 0xFF && byte
[i
+ 1] == 0xEE)
707 if (grub_memcmp(flag
, byte
+ i
, 32) == 0)
709 debug("Find position flag at %d(0x%x)\n", i
, i
);
715 if (i
>= g_mod_new_len
- 32)
717 debug("Failed to find position flag %d\n", i
);
721 desc
= (ventoy_image_desc
*)(byte
+ i
);
722 desc
->disk_size
= g_ventoy_disk_size
;
723 desc
->part1_size
= g_ventoy_disk_part_size
[0];
724 grub_memcpy(desc
->disk_uuid
, g_ventoy_part_info
->MBR
.BootCode
+ 0x180, 16);
725 grub_memcpy(desc
->disk_signature
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1B8, 4);
727 desc
->img_chunk_count
= g_img_chunk_list
.cur_chunk
;
728 memsize
= g_img_chunk_list
.cur_chunk
* sizeof(ventoy_img_chunk
);
730 debug("image chunk count:%u memsize:%u\n", desc
->img_chunk_count
, memsize
);
732 if (memsize
>= VTOY_SIZE_1MB
* 8)
734 grub_printf("image chunk count:%u memsize:%u too big\n", desc
->img_chunk_count
, memsize
);
738 grub_memcpy(desc
+ 1, g_img_chunk_list
.chunk
, memsize
);
741 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
744 grub_err_t
ventoy_cmd_unix_gzip_newko(grub_extcmd_context_t ctxt
, int argc
, char **args
)
753 debug("ventoy_cmd_unix_gzip_newko %p\n", g_mod_new_data
);
760 buf
= grub_malloc(g_mod_new_len
);
766 newlen
= ventoy_gzip_compress(g_mod_new_data
, g_mod_new_len
, buf
, g_mod_new_len
);
768 grub_free(g_mod_new_data
);
770 debug("gzip org len:%d newlen:%d\n", g_mod_new_len
, newlen
);
772 g_mod_new_data
= (char *)buf
;
773 g_mod_new_len
= newlen
;
776 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
779 grub_err_t
ventoy_cmd_unix_chain_data(grub_extcmd_context_t ctxt
, int argc
, char **args
)
781 int ventoy_compatible
= 0;
782 grub_uint32_t size
= 0;
783 grub_uint64_t isosize
= 0;
784 grub_uint32_t boot_catlog
= 0;
785 grub_uint32_t img_chunk_size
= 0;
786 grub_uint32_t override_count
= 0;
787 grub_uint32_t override_size
= 0;
788 grub_uint32_t virt_chunk_size
= 0;
791 const char *pLastChain
= NULL
;
792 const char *compatible
;
793 ventoy_chain_head
*chain
;
799 compatible
= grub_env_get("ventoy_compatible");
800 if (compatible
&& compatible
[0] == 'Y')
802 ventoy_compatible
= 1;
805 if (NULL
== g_img_chunk_list
.chunk
)
807 grub_printf("ventoy not ready\n");
811 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
817 isosize
= file
->size
;
819 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
822 if (ventoy_is_efi_os() && (!ventoy_has_efi_eltorito(file
, boot_catlog
)))
824 grub_env_set("LoadIsoEfiDriver", "on");
829 if (ventoy_is_efi_os())
831 grub_env_set("LoadIsoEfiDriver", "on");
835 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "File %s is not bootable", args
[0]);
839 img_chunk_size
= g_img_chunk_list
.cur_chunk
* sizeof(ventoy_img_chunk
);
841 if (ventoy_compatible
)
843 size
= sizeof(ventoy_chain_head
) + img_chunk_size
;
847 override_count
= ventoy_unix_get_override_chunk_count();
848 override_size
= override_count
* sizeof(ventoy_override_chunk
);
850 virt_chunk_size
= ventoy_unix_get_virt_chunk_size();
851 size
= sizeof(ventoy_chain_head
) + img_chunk_size
+ override_size
+ virt_chunk_size
;
854 pLastChain
= grub_env_get("vtoy_chain_mem_addr");
857 chain
= (ventoy_chain_head
*)grub_strtoul(pLastChain
, NULL
, 16);
860 debug("free last chain memory %p\n", chain
);
865 chain
= grub_malloc(size
);
868 grub_printf("Failed to alloc chain memory size %u\n", size
);
869 grub_file_close(file
);
873 grub_snprintf(envbuf
, sizeof(envbuf
), "0x%lx", (unsigned long)chain
);
874 grub_env_set("vtoy_chain_mem_addr", envbuf
);
875 grub_snprintf(envbuf
, sizeof(envbuf
), "%u", size
);
876 grub_env_set("vtoy_chain_mem_size", envbuf
);
878 grub_memset(chain
, 0, sizeof(ventoy_chain_head
));
880 /* part 1: os parameter */
881 g_ventoy_chain_type
= ventoy_chain_linux
;
882 ventoy_fill_os_param(file
, &(chain
->os_param
));
884 /* part 2: chain head */
885 disk
= file
->device
->disk
;
886 chain
->disk_drive
= disk
->id
;
887 chain
->disk_sector_size
= (1 << disk
->log_sector_size
);
888 chain
->real_img_size_in_bytes
= file
->size
;
889 chain
->virt_img_size_in_bytes
= (file
->size
+ 2047) / 2048 * 2048;
890 chain
->boot_catalog
= boot_catlog
;
892 if (!ventoy_is_efi_os())
894 grub_file_seek(file
, boot_catlog
* 2048);
895 grub_file_read(file
, chain
->boot_catalog_sector
, sizeof(chain
->boot_catalog_sector
));
898 /* part 3: image chunk */
899 chain
->img_chunk_offset
= sizeof(ventoy_chain_head
);
900 chain
->img_chunk_num
= g_img_chunk_list
.cur_chunk
;
901 grub_memcpy((char *)chain
+ chain
->img_chunk_offset
, g_img_chunk_list
.chunk
, img_chunk_size
);
903 if (ventoy_compatible
)
908 /* part 4: override chunk */
909 chain
->override_chunk_offset
= chain
->img_chunk_offset
+ img_chunk_size
;
910 chain
->override_chunk_num
= override_count
;
911 ventoy_unix_fill_override_data(isosize
, (char *)chain
+ chain
->override_chunk_offset
);
913 /* part 5: virt chunk */
914 chain
->virt_chunk_offset
= chain
->override_chunk_offset
+ override_size
;
915 chain
->virt_chunk_num
= ventoy_unix_get_virt_chunk_count();
916 ventoy_unix_fill_virt_data(isosize
, chain
);
918 grub_file_close(file
);
920 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);