]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_unix.c
626517a036e29171f5bf8431010c35c652164189
[Ventoy.git] / GRUB2 / MOD_SRC / grub-2.04 / grub-core / ventoy / ventoy_unix.c
1 /******************************************************************************
2 * ventoy_unix.c
3 *
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
5 *
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.
10 *
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.
15 *
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/>.
18 *
19 */
20 #include <grub/types.h>
21 #include <grub/misc.h>
22 #include <grub/mm.h>
23 #include <grub/err.h>
24 #include <grub/dl.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>
34 #include <grub/net.h>
35 #include <grub/time.h>
36 #include <grub/ventoy.h>
37 #include "ventoy_def.h"
38
39 GRUB_MOD_LICENSE ("GPLv3+");
40
41 char g_ko_mod_path[256];
42 int g_conf_new_len = 0;
43 char *g_conf_new_data = NULL;
44
45 int g_mod_new_len = 0;
46 char *g_mod_new_data = NULL;
47
48 grub_uint64_t g_mod_override_offset = 0;
49 grub_uint64_t g_conf_override_offset = 0;
50
51 static int ventoy_get_file_override(const char *filename, grub_uint64_t *offset)
52 {
53 grub_file_t file;
54
55 *offset = 0;
56
57 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(loop)%s", filename);
58 if (!file)
59 {
60 return 1;
61 }
62
63 *offset = grub_iso9660_get_last_file_dirent_pos(file) + 2;
64
65 grub_file_close(file);
66
67 return 0;
68 }
69
70 static grub_uint32_t ventoy_unix_get_override_chunk_count(void)
71 {
72 grub_uint32_t count = 0;
73
74 if (g_conf_new_len > 0)
75 {
76 count++;
77 }
78
79 if (g_mod_new_len > 0)
80 {
81 count++;
82 }
83
84 return count;
85 }
86
87 static grub_uint32_t ventoy_unix_get_virt_chunk_count(void)
88 {
89 grub_uint32_t count = 0;
90
91 if (g_conf_new_len > 0)
92 {
93 count++;
94 }
95
96 if (g_mod_new_len > 0)
97 {
98 count++;
99 }
100
101 return count;
102 }
103 static grub_uint32_t ventoy_unix_get_virt_chunk_size(void)
104 {
105 grub_uint32_t size;
106
107 size = sizeof(ventoy_virt_chunk) * ventoy_unix_get_virt_chunk_count();
108
109 if (g_conf_new_len > 0)
110 {
111 size += ventoy_align_2k(g_conf_new_len);
112 }
113
114 if (g_mod_new_len > 0)
115 {
116 size += ventoy_align_2k(g_mod_new_len);
117 }
118
119 return size;
120 }
121
122 static void ventoy_unix_fill_override_data( grub_uint64_t isosize, void *override)
123 {
124 grub_uint64_t sector;
125 ventoy_override_chunk *cur;
126 ventoy_iso9660_override *dirent;
127
128 sector = (isosize + 2047) / 2048;
129
130 cur = (ventoy_override_chunk *)override;
131
132 if (g_conf_new_len > 0)
133 {
134 /* loader.conf */
135 cur->img_offset = g_conf_override_offset;
136 cur->override_size = sizeof(ventoy_iso9660_override);
137 dirent = (ventoy_iso9660_override *)cur->override_data;
138 dirent->first_sector = (grub_uint32_t)sector;
139 dirent->size = (grub_uint32_t)g_conf_new_len;
140 dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
141 dirent->size_be = grub_swap_bytes32(dirent->size);
142 sector += (dirent->size + 2047) / 2048;
143 }
144
145 if (g_mod_new_len > 0)
146 {
147 /* mod.ko */
148 cur++;
149 cur->img_offset = g_mod_override_offset;
150 cur->override_size = sizeof(ventoy_iso9660_override);
151 dirent = (ventoy_iso9660_override *)cur->override_data;
152 dirent->first_sector = (grub_uint32_t)sector;
153 dirent->size = (grub_uint32_t)g_mod_new_len;
154 dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
155 dirent->size_be = grub_swap_bytes32(dirent->size);
156 sector += (dirent->size + 2047) / 2048;
157 }
158
159 return;
160 }
161
162 static void ventoy_unix_fill_virt_data( grub_uint64_t isosize, ventoy_chain_head *chain)
163 {
164 grub_uint64_t sector;
165 grub_uint32_t offset;
166 grub_uint32_t data_secs;
167 char *override;
168 ventoy_virt_chunk *cur;
169
170 override = (char *)chain + chain->virt_chunk_offset;
171 cur = (ventoy_virt_chunk *)override;
172
173 sector = (isosize + 2047) / 2048;
174 offset = 2 * sizeof(ventoy_virt_chunk);
175
176 if (g_conf_new_len > 0)
177 {
178 ventoy_unix_fill_virt(g_conf_new_data, g_conf_new_len);
179 }
180
181 if (g_mod_new_len > 0)
182 {
183 ventoy_unix_fill_virt(g_mod_new_data, g_mod_new_len);
184 }
185
186 return;
187 }
188
189 static int ventoy_freebsd_append_conf(char *buf, const char *isopath)
190 {
191 int pos = 0;
192 grub_uint32_t i;
193 grub_disk_t disk;
194 grub_file_t isofile;
195 char uuid[64] = {0};
196 ventoy_img_chunk *chunk;
197 grub_uint8_t disk_sig[4];
198 grub_uint8_t disk_guid[16];
199
200 debug("ventoy_freebsd_append_conf %s\n", isopath);
201
202 isofile = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", isopath);
203 if (!isofile)
204 {
205 return 1;
206 }
207
208 vtoy_ssprintf(buf, pos, "ventoy_load=\"%s\"\n", "YES");
209 vtoy_ssprintf(buf, pos, "ventoy_name=\"%s\"\n", g_ko_mod_path);
210
211 disk = isofile->device->disk;
212
213 ventoy_get_disk_guid(isofile->name, disk_guid, disk_sig);
214
215 for (i = 0; i < 16; i++)
216 {
217 grub_snprintf(uuid + i * 2, sizeof(uuid), "%02x", disk_guid[i]);
218 }
219
220 vtoy_ssprintf(buf, pos, "hint.ventoy.0.disksize=%llu\n", (ulonglong)(disk->total_sectors * (1 << disk->log_sector_size)));
221 vtoy_ssprintf(buf, pos, "hint.ventoy.0.diskuuid=\"%s\"\n", uuid);
222 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]);
223 vtoy_ssprintf(buf, pos, "hint.ventoy.0.segnum=%u\n", g_img_chunk_list.cur_chunk);
224
225 for (i = 0; i < g_img_chunk_list.cur_chunk; i++)
226 {
227 chunk = g_img_chunk_list.chunk + i;
228 vtoy_ssprintf(buf, pos, "hint.ventoy.%u.seg=\"0x%llx@0x%llx\"\n",
229 i, (ulonglong)(chunk->disk_start_sector * 512),
230 (ulonglong)((chunk->disk_end_sector + 1) * 512));
231 }
232
233 grub_file_close(isofile);
234
235 return pos;
236 }
237
238 static int ventoy_dragonfly_append_conf(char *buf, const char *isopath)
239 {
240 int pos = 0;
241
242 debug("ventoy_dragonfly_append_conf %s\n", isopath);
243
244 vtoy_ssprintf(buf, pos, "tmpfs_load=\"%s\"\n", "YES");
245 vtoy_ssprintf(buf, pos, "dm_target_linear_load=\"%s\"\n", "YES");
246 vtoy_ssprintf(buf, pos, "initrd.img_load=\"%s\"\n", "YES");
247 vtoy_ssprintf(buf, pos, "initrd.img_type=\"%s\"\n", "md_image");
248 vtoy_ssprintf(buf, pos, "vfs.root.mountfrom=\"%s\"\n", "ufs:md0s0");
249
250 return pos;
251 }
252
253 grub_err_t ventoy_cmd_unix_reset(grub_extcmd_context_t ctxt, int argc, char **args)
254 {
255 (void)ctxt;
256 (void)argc;
257 (void)args;
258
259 g_conf_new_len = 0;
260 g_mod_new_len = 0;
261 g_mod_override_offset = 0;
262 g_conf_override_offset = 0;
263
264 check_free(g_mod_new_data, grub_free);
265 check_free(g_conf_new_data, grub_free);
266
267 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
268 }
269
270 grub_err_t ventoy_cmd_parse_freenas_ver(grub_extcmd_context_t ctxt, int argc, char **args)
271 {
272 grub_file_t file;
273 const char *ver = NULL;
274 char *buf = NULL;
275 VTOY_JSON *json = NULL;
276
277 (void)ctxt;
278 (void)argc;
279
280 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
281 if (!file)
282 {
283 debug("Failed to open file %s\n", args[0]);
284 return 1;
285 }
286
287 buf = grub_malloc(file->size + 2);
288 if (!buf)
289 {
290 grub_file_close(file);
291 return 0;
292 }
293 grub_file_read(file, buf, file->size);
294 buf[file->size] = 0;
295
296 json = vtoy_json_create();
297 if (!json)
298 {
299 goto end;
300 }
301
302 if (vtoy_json_parse(json, buf))
303 {
304 goto end;
305 }
306
307 ver = vtoy_json_get_string_ex(json->pstChild, "Version");
308 if (ver)
309 {
310 debug("freenas version:<%s>\n", ver);
311 ventoy_set_env(args[1], ver);
312 }
313 else
314 {
315 debug("freenas version:<%s>\n", "NOT FOUND");
316 grub_env_unset(args[1]);
317 }
318
319 end:
320 grub_check_free(buf);
321 check_free(json, vtoy_json_destroy);
322 grub_file_close(file);
323
324 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
325 }
326
327 grub_err_t ventoy_cmd_unix_freebsd_ver(grub_extcmd_context_t ctxt, int argc, char **args)
328 {
329 grub_file_t file;
330 char *buf;
331 char *start = NULL;
332 char *nextline = NULL;
333
334 (void)ctxt;
335 (void)argc;
336 (void)args;
337
338 file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s", args[0]);
339 if (!file)
340 {
341 debug("Failed to open file %s\n", args[0]);
342 return 1;
343 }
344
345 buf = grub_zalloc(file->size + 2);
346 if (!buf)
347 {
348 grub_file_close(file);
349 return 0;
350 }
351 grub_file_read(file, buf, file->size);
352
353 for (start = buf; start; start = nextline)
354 {
355 if (grub_strncmp(start, "USERLAND_VERSION", 16) == 0)
356 {
357 nextline = start;
358 while (*nextline && *nextline != '\r' && *nextline != '\n')
359 {
360 nextline++;
361 }
362
363 *nextline = 0;
364 break;
365 }
366 nextline = ventoy_get_line(start);
367 }
368
369 if (start)
370 {
371 debug("freebsd version:<%s>\n", start);
372 ventoy_set_env(args[1], start);
373 }
374 else
375 {
376 debug("freebsd version:<%s>\n", "NOT FOUND");
377 grub_env_unset(args[1]);
378 }
379
380 grub_free(buf);
381 grub_file_close(file);
382
383 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
384 }
385
386 grub_err_t ventoy_cmd_unix_replace_conf(grub_extcmd_context_t ctxt, int argc, char **args)
387 {
388 grub_uint32_t i;
389 char *data;
390 grub_uint64_t offset;
391 grub_file_t file;
392 const char *confile = NULL;
393 const char * loader_conf[] =
394 {
395 "/boot/loader.conf",
396 "/boot/defaults/loader.conf",
397 };
398
399 (void)ctxt;
400
401 if (argc != 2)
402 {
403 debug("Replace conf invalid argc %d\n", argc);
404 return 1;
405 }
406
407 for (i = 0; i < sizeof(loader_conf) / sizeof(loader_conf[0]); i++)
408 {
409 if (ventoy_get_file_override(loader_conf[i], &offset) == 0)
410 {
411 confile = loader_conf[i];
412 g_conf_override_offset = offset;
413 break;
414 }
415 }
416
417 if (confile == NULL)
418 {
419 debug("Can't find loader.conf file from %u locations\n", i);
420 return 1;
421 }
422
423 file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "(loop)/%s", confile);
424 if (!file)
425 {
426 debug("Failed to open %s \n", confile);
427 return 1;
428 }
429
430 debug("old conf file size:%d\n", (int)file->size);
431
432 data = grub_malloc(VTOY_MAX_SCRIPT_BUF);
433 if (!data)
434 {
435 grub_file_close(file);
436 return 1;
437 }
438
439 grub_file_read(file, data, file->size);
440 grub_file_close(file);
441
442 g_conf_new_data = data;
443 g_conf_new_len = (int)file->size;
444
445 if (grub_strcmp(args[0], "FreeBSD") == 0)
446 {
447 g_conf_new_len += ventoy_freebsd_append_conf(data + file->size, args[1]);
448 }
449 else if (grub_strcmp(args[0], "DragonFly") == 0)
450 {
451 g_conf_new_len += ventoy_dragonfly_append_conf(data + file->size, args[1]);
452 }
453
454 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
455 }
456
457 grub_err_t ventoy_cmd_unix_replace_ko(grub_extcmd_context_t ctxt, int argc, char **args)
458 {
459 char *data;
460 grub_uint64_t offset;
461 grub_file_t file;
462
463 (void)ctxt;
464
465 if (argc != 2)
466 {
467 debug("Replace ko invalid argc %d\n", argc);
468 return 1;
469 }
470
471 debug("replace ko %s\n", args[0]);
472
473 if (ventoy_get_file_override(args[0], &offset) == 0)
474 {
475 grub_snprintf(g_ko_mod_path, sizeof(g_ko_mod_path), "%s", args[0]);
476 g_mod_override_offset = offset;
477 }
478 else
479 {
480 debug("Can't find replace ko file from %s\n", args[0]);
481 return 1;
482 }
483
484 file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s", args[1]);
485 if (!file)
486 {
487 debug("Failed to open %s \n", args[1]);
488 return 1;
489 }
490
491 debug("new ko file size:%d\n", (int)file->size);
492
493 data = grub_malloc(file->size);
494 if (!data)
495 {
496 debug("Failed to alloc memory for new ko %d\n", (int)file->size);
497 grub_file_close(file);
498 return 1;
499 }
500
501 grub_file_read(file, data, file->size);
502 grub_file_close(file);
503
504 g_mod_new_data = data;
505 g_mod_new_len = (int)file->size;
506
507 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
508 }
509
510 grub_err_t ventoy_cmd_unix_fill_image_desc(grub_extcmd_context_t ctxt, int argc, char **args)
511 {
512 int i;
513 grub_uint8_t *byte;
514 grub_uint32_t memsize;
515 ventoy_image_desc *desc;
516 grub_uint8_t flag[32] = {
517 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00,
518 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
519 };
520
521 (void)ctxt;
522 (void)argc;
523 (void)args;
524
525 debug("ventoy_cmd_unix_fill_image_desc %p\n", g_mod_new_data);
526
527 if (!g_mod_new_data)
528 {
529 goto end;
530 }
531
532 byte = (grub_uint8_t *)g_mod_new_data;
533 for (i = 0; i < g_mod_new_len - 32; i += 16)
534 {
535 if (byte[i] == 0xFF && byte[i + 1] == 0xEE)
536 {
537 if (grub_memcmp(flag, byte + i, 32) == 0)
538 {
539 debug("Find position flag at %d(0x%x)\n", i, i);
540 break;
541 }
542 }
543 }
544
545 if (i >= g_mod_new_len - 32)
546 {
547 debug("Failed to find position flag %d\n", i);
548 goto end;
549 }
550
551 desc = (ventoy_image_desc *)(byte + i);
552 desc->disk_size = g_ventoy_disk_size;
553 desc->part1_size = ventoy_get_part1_size(g_ventoy_part_info);
554 grub_memcpy(desc->disk_uuid, g_ventoy_part_info->MBR.BootCode + 0x180, 16);
555 grub_memcpy(desc->disk_signature, g_ventoy_part_info->MBR.BootCode + 0x1B8, 4);
556
557 desc->img_chunk_count = g_img_chunk_list.cur_chunk;
558 memsize = g_img_chunk_list.cur_chunk * sizeof(ventoy_img_chunk);
559
560 debug("image chunk count:%u memsize:%u\n", desc->img_chunk_count, memsize);
561
562 if (memsize >= VTOY_SIZE_1MB * 8)
563 {
564 grub_printf("image chunk count:%u memsize:%u too big\n", desc->img_chunk_count, memsize);
565 goto end;
566 }
567
568 grub_memcpy(desc + 1, g_img_chunk_list.chunk, memsize);
569
570 end:
571 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
572 }
573
574 grub_err_t ventoy_cmd_unix_gzip_newko(grub_extcmd_context_t ctxt, int argc, char **args)
575 {
576 int newlen;
577 grub_uint8_t *buf;
578
579 (void)ctxt;
580 (void)argc;
581 (void)args;
582
583 debug("ventoy_cmd_unix_gzip_newko %p\n", g_mod_new_data);
584
585 if (!g_mod_new_data)
586 {
587 goto end;
588 }
589
590 buf = grub_malloc(g_mod_new_len);
591 if (!buf)
592 {
593 goto end;
594 }
595
596 newlen = ventoy_gzip_compress(g_mod_new_data, g_mod_new_len, buf, g_mod_new_len);
597
598 grub_free(g_mod_new_data);
599
600 debug("gzip org len:%d newlen:%d\n", g_mod_new_len, newlen);
601
602 g_mod_new_data = (char *)buf;
603 g_mod_new_len = newlen;
604
605 end:
606 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
607 }
608
609 grub_err_t ventoy_cmd_unix_chain_data(grub_extcmd_context_t ctxt, int argc, char **args)
610 {
611 int ventoy_compatible = 0;
612 grub_uint32_t size = 0;
613 grub_uint64_t isosize = 0;
614 grub_uint32_t boot_catlog = 0;
615 grub_uint32_t img_chunk_size = 0;
616 grub_uint32_t override_count = 0;
617 grub_uint32_t override_size = 0;
618 grub_uint32_t virt_chunk_size = 0;
619 grub_file_t file;
620 grub_disk_t disk;
621 const char *pLastChain = NULL;
622 const char *compatible;
623 ventoy_chain_head *chain;
624 char envbuf[64];
625
626 (void)ctxt;
627 (void)argc;
628
629 compatible = grub_env_get("ventoy_compatible");
630 if (compatible && compatible[0] == 'Y')
631 {
632 ventoy_compatible = 1;
633 }
634
635 if (NULL == g_img_chunk_list.chunk)
636 {
637 grub_printf("ventoy not ready\n");
638 return 1;
639 }
640
641 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
642 if (!file)
643 {
644 return 1;
645 }
646
647 isosize = file->size;
648
649 boot_catlog = ventoy_get_iso_boot_catlog(file);
650 if (boot_catlog)
651 {
652 if (ventoy_is_efi_os() && (!ventoy_has_efi_eltorito(file, boot_catlog)))
653 {
654 grub_env_set("LoadIsoEfiDriver", "on");
655 }
656 }
657 else
658 {
659 if (ventoy_is_efi_os())
660 {
661 grub_env_set("LoadIsoEfiDriver", "on");
662 }
663 else
664 {
665 return grub_error(GRUB_ERR_BAD_ARGUMENT, "File %s is not bootable", args[0]);
666 }
667 }
668
669 img_chunk_size = g_img_chunk_list.cur_chunk * sizeof(ventoy_img_chunk);
670
671 if (ventoy_compatible)
672 {
673 size = sizeof(ventoy_chain_head) + img_chunk_size;
674 }
675 else
676 {
677 override_count = ventoy_unix_get_override_chunk_count();
678 override_size = override_count * sizeof(ventoy_override_chunk);
679
680 virt_chunk_size = ventoy_unix_get_virt_chunk_size();
681 size = sizeof(ventoy_chain_head) + img_chunk_size + override_size + virt_chunk_size;
682 }
683
684 pLastChain = grub_env_get("vtoy_chain_mem_addr");
685 if (pLastChain)
686 {
687 chain = (ventoy_chain_head *)grub_strtoul(pLastChain, NULL, 16);
688 if (chain)
689 {
690 debug("free last chain memory %p\n", chain);
691 grub_free(chain);
692 }
693 }
694
695 chain = grub_malloc(size);
696 if (!chain)
697 {
698 grub_printf("Failed to alloc chain memory size %u\n", size);
699 grub_file_close(file);
700 return 1;
701 }
702
703 grub_snprintf(envbuf, sizeof(envbuf), "0x%lx", (unsigned long)chain);
704 grub_env_set("vtoy_chain_mem_addr", envbuf);
705 grub_snprintf(envbuf, sizeof(envbuf), "%u", size);
706 grub_env_set("vtoy_chain_mem_size", envbuf);
707
708 grub_memset(chain, 0, sizeof(ventoy_chain_head));
709
710 /* part 1: os parameter */
711 g_ventoy_chain_type = ventoy_chain_linux;
712 ventoy_fill_os_param(file, &(chain->os_param));
713
714 /* part 2: chain head */
715 disk = file->device->disk;
716 chain->disk_drive = disk->id;
717 chain->disk_sector_size = (1 << disk->log_sector_size);
718 chain->real_img_size_in_bytes = file->size;
719 chain->virt_img_size_in_bytes = (file->size + 2047) / 2048 * 2048;
720 chain->boot_catalog = boot_catlog;
721
722 if (!ventoy_is_efi_os())
723 {
724 grub_file_seek(file, boot_catlog * 2048);
725 grub_file_read(file, chain->boot_catalog_sector, sizeof(chain->boot_catalog_sector));
726 }
727
728 /* part 3: image chunk */
729 chain->img_chunk_offset = sizeof(ventoy_chain_head);
730 chain->img_chunk_num = g_img_chunk_list.cur_chunk;
731 grub_memcpy((char *)chain + chain->img_chunk_offset, g_img_chunk_list.chunk, img_chunk_size);
732
733 if (ventoy_compatible)
734 {
735 return 0;
736 }
737
738 /* part 4: override chunk */
739 chain->override_chunk_offset = chain->img_chunk_offset + img_chunk_size;
740 chain->override_chunk_num = override_count;
741 ventoy_unix_fill_override_data(isosize, (char *)chain + chain->override_chunk_offset);
742
743 /* part 5: virt chunk */
744 chain->virt_chunk_offset = chain->override_chunk_offset + override_size;
745 chain->virt_chunk_num = ventoy_unix_get_virt_chunk_count();
746 ventoy_unix_fill_virt_data(isosize, chain);
747
748 grub_file_close(file);
749
750 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
751 }
752