]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_linux.c
21ac4f5feca8277843ee9fbe4bf74e5d6454fd65
[Ventoy.git] / GRUB2 / MOD_SRC / grub-2.04 / grub-core / ventoy / ventoy_linux.c
1 /******************************************************************************
2 * ventoy_linux.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 * ventoy_get_line(char *start)
42 {
43 if (start == NULL)
44 {
45 return NULL;
46 }
47
48 while (*start && *start != '\n')
49 {
50 start++;
51 }
52
53 if (*start == 0)
54 {
55 return NULL;
56 }
57 else
58 {
59 *start = 0;
60 return start + 1;
61 }
62 }
63
64 static initrd_info * ventoy_find_initrd_by_name(initrd_info *list, const char *name)
65 {
66 initrd_info *node = list;
67
68 while (node)
69 {
70 if (grub_strcmp(node->name, name) == 0)
71 {
72 return node;
73 }
74 node = node->next;
75 }
76
77 return NULL;
78 }
79
80 grub_err_t ventoy_cmd_clear_initrd_list(grub_extcmd_context_t ctxt, int argc, char **args)
81 {
82 initrd_info *node = g_initrd_img_list;
83 initrd_info *next;
84
85 (void)ctxt;
86 (void)argc;
87 (void)args;
88
89 while (node)
90 {
91 next = node->next;
92 grub_free(node);
93 node = next;
94 }
95
96 g_initrd_img_list = NULL;
97 g_initrd_img_tail = NULL;
98 g_initrd_img_count = 0;
99 g_valid_initrd_count = 0;
100
101 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
102 }
103
104 grub_err_t ventoy_cmd_dump_initrd_list(grub_extcmd_context_t ctxt, int argc, char **args)
105 {
106 int i = 0;
107 initrd_info *node = g_initrd_img_list;
108
109 (void)ctxt;
110 (void)argc;
111 (void)args;
112
113 grub_printf("###################\n");
114 grub_printf("initrd info list: valid count:%d\n", g_valid_initrd_count);
115
116 while (node)
117 {
118 grub_printf("%s ", node->size > 0 ? "*" : " ");
119 grub_printf("%02u %s offset:%llu size:%llu \n", i++, node->name, (unsigned long long)node->offset,
120 (unsigned long long)node->size);
121 node = node->next;
122 }
123
124 grub_printf("###################\n");
125
126 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
127 }
128
129 static void ventoy_parse_directory(char *path, char *dir, int buflen)
130 {
131 int end;
132 char *pos;
133
134 pos = grub_strstr(path, ")");
135 if (!pos)
136 {
137 pos = path;
138 }
139
140 end = grub_snprintf(dir, buflen, "%s", pos + 1);
141 while (end > 0)
142 {
143 if (dir[end] == '/')
144 {
145 dir[end + 1] = 0;
146 break;
147 }
148 end--;
149 }
150 }
151
152 static grub_err_t ventoy_isolinux_initrd_collect(grub_file_t file, const char *prefix)
153 {
154 int i = 0;
155 int offset;
156 int prefixlen = 0;
157 char *buf = NULL;
158 char *pos = NULL;
159 char *start = NULL;
160 char *nextline = NULL;
161 initrd_info *img = NULL;
162
163 prefixlen = grub_strlen(prefix);
164
165 buf = grub_zalloc(file->size + 2);
166 if (!buf)
167 {
168 return 0;
169 }
170
171 grub_file_read(file, buf, file->size);
172
173 for (start = buf; start; start = nextline)
174 {
175 nextline = ventoy_get_line(start);
176
177 while (ventoy_isspace(*start))
178 {
179 start++;
180 }
181
182 offset = 7; // strlen("initrd=") or "INITRD " or "initrd "
183 pos = grub_strstr(start, "initrd=");
184 if (pos == NULL)
185 {
186 pos = start;
187
188 if (grub_strncmp(start, "INITRD", 6) != 0 && grub_strncmp(start, "initrd", 6) != 0)
189 {
190 if (grub_strstr(start, "xen") &&
191 ((pos = grub_strstr(start, "--- /install.img")) != NULL ||
192 (pos = grub_strstr(start, "--- initrd.img")) != NULL
193 ))
194 {
195 offset = 4; // "--- "
196 }
197 else
198 {
199 continue;
200 }
201 }
202 }
203
204 pos += offset;
205
206 while (1)
207 {
208 i = 0;
209 img = grub_zalloc(sizeof(initrd_info));
210 if (!img)
211 {
212 break;
213 }
214
215 if (*pos != '/')
216 {
217 grub_strcpy(img->name, prefix);
218 i = prefixlen;
219 }
220
221 while (i < 255 && (0 == ventoy_is_word_end(*pos)))
222 {
223 img->name[i++] = *pos++;
224 }
225
226 if (ventoy_find_initrd_by_name(g_initrd_img_list, img->name))
227 {
228 grub_free(img);
229 }
230 else
231 {
232 if (g_initrd_img_list)
233 {
234 img->prev = g_initrd_img_tail;
235 g_initrd_img_tail->next = img;
236 }
237 else
238 {
239 g_initrd_img_list = img;
240 }
241
242 g_initrd_img_tail = img;
243 g_initrd_img_count++;
244 }
245
246 if (*pos == ',')
247 {
248 pos++;
249 }
250 else
251 {
252 break;
253 }
254 }
255 }
256
257 grub_free(buf);
258 return GRUB_ERR_NONE;
259 }
260
261 static int ventoy_isolinux_initrd_hook(const char *filename, const struct grub_dirhook_info *info, void *data)
262 {
263 grub_file_t file = NULL;
264 ventoy_initrd_ctx *ctx = (ventoy_initrd_ctx *)data;
265
266 (void)info;
267
268 if (NULL == grub_strstr(filename, ".cfg") && NULL == grub_strstr(filename, ".CFG"))
269 {
270 return 0;
271 }
272
273 debug("init hook dir <%s%s>\n", ctx->path_prefix, filename);
274
275 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", ctx->path_prefix, filename);
276 if (!file)
277 {
278 return 0;
279 }
280
281 ventoy_isolinux_initrd_collect(file, ctx->dir_prefix);
282 grub_file_close(file);
283
284 return 0;
285 }
286
287 grub_err_t ventoy_cmd_isolinux_initrd_collect(grub_extcmd_context_t ctxt, int argc, char **args)
288 {
289 grub_fs_t fs;
290 grub_device_t dev = NULL;
291 char *device_name = NULL;
292 ventoy_initrd_ctx ctx;
293 char directory[256];
294
295 (void)ctxt;
296 (void)argc;
297
298 device_name = grub_file_get_device_name(args[0]);
299 if (!device_name)
300 {
301 goto end;
302 }
303
304 dev = grub_device_open(device_name);
305 if (!dev)
306 {
307 goto end;
308 }
309
310 fs = grub_fs_probe(dev);
311 if (!fs)
312 {
313 goto end;
314 }
315
316 debug("isolinux initrd collect %s\n", args[0]);
317
318 ventoy_parse_directory(args[0], directory, sizeof(directory) - 1);
319 ctx.path_prefix = args[0];
320 ctx.dir_prefix = (argc > 1) ? args[1] : directory;
321
322 debug("path_prefix=<%s> dir_prefix=<%s>\n", ctx.path_prefix, ctx.dir_prefix);
323
324 fs->fs_dir(dev, directory, ventoy_isolinux_initrd_hook, &ctx);
325
326 end:
327 check_free(device_name, grub_free);
328 check_free(dev, grub_device_close);
329
330 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
331 }
332
333 static grub_err_t ventoy_grub_cfg_initrd_collect(const char *fileName)
334 {
335 int i = 0;
336 int dollar = 0;
337 grub_file_t file = NULL;
338 char *buf = NULL;
339 char *start = NULL;
340 char *nextline = NULL;
341 initrd_info *img = NULL;
342
343 debug("grub initrd collect %s\n", fileName);
344
345 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", fileName);
346 if (!file)
347 {
348 return 0;
349 }
350
351 buf = grub_zalloc(file->size + 2);
352 if (!buf)
353 {
354 grub_file_close(file);
355 return 0;
356 }
357
358 grub_file_read(file, buf, file->size);
359
360 for (start = buf; start; start = nextline)
361 {
362 nextline = ventoy_get_line(start);
363
364 while (ventoy_isspace(*start))
365 {
366 start++;
367 }
368
369 if (grub_strncmp(start, "initrd", 6) != 0)
370 {
371 continue;
372 }
373
374 start += 6;
375 while (*start && (!ventoy_isspace(*start)))
376 {
377 start++;
378 }
379
380 while (ventoy_isspace(*start))
381 {
382 start++;
383 }
384
385 while (*start)
386 {
387 img = grub_zalloc(sizeof(initrd_info));
388 if (!img)
389 {
390 break;
391 }
392
393 dollar = 0;
394 for (i = 0; i < 255 && (0 == ventoy_is_word_end(*start)); i++)
395 {
396 img->name[i] = *start++;
397 if (img->name[i] == '$')
398 {
399 dollar = 1;
400 }
401 }
402
403 if (dollar == 1 || ventoy_find_initrd_by_name(g_initrd_img_list, img->name))
404 {
405 grub_free(img);
406 }
407 else
408 {
409 if (g_initrd_img_list)
410 {
411 img->prev = g_initrd_img_tail;
412 g_initrd_img_tail->next = img;
413 }
414 else
415 {
416 g_initrd_img_list = img;
417 }
418
419 g_initrd_img_tail = img;
420 g_initrd_img_count++;
421 }
422
423 if (*start == ' ' || *start == '\t')
424 {
425 while (ventoy_isspace(*start))
426 {
427 start++;
428 }
429 }
430 else
431 {
432 break;
433 }
434 }
435 }
436
437 grub_free(buf);
438 grub_file_close(file);
439
440 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
441 }
442
443 static int ventoy_grub_initrd_hook(const char *filename, const struct grub_dirhook_info *info, void *data)
444 {
445 char filePath[256];
446 ventoy_initrd_ctx *ctx = (ventoy_initrd_ctx *)data;
447
448 (void)info;
449
450 debug("ventoy_grub_initrd_hook %s\n", filename);
451
452 if (NULL == grub_strstr(filename, ".cfg") &&
453 NULL == grub_strstr(filename, ".CFG") &&
454 NULL == grub_strstr(filename, ".conf"))
455 {
456 return 0;
457 }
458
459 debug("init hook dir <%s%s>\n", ctx->path_prefix, filename);
460
461 grub_snprintf(filePath, sizeof(filePath) - 1, "%s%s", ctx->dir_prefix, filename);
462 ventoy_grub_cfg_initrd_collect(filePath);
463
464 return 0;
465 }
466
467 grub_err_t ventoy_cmd_grub_initrd_collect(grub_extcmd_context_t ctxt, int argc, char **args)
468 {
469 grub_fs_t fs;
470 grub_device_t dev = NULL;
471 char *device_name = NULL;
472 ventoy_initrd_ctx ctx;
473
474 (void)ctxt;
475 (void)argc;
476
477 if (argc != 2)
478 {
479 return 0;
480 }
481
482 debug("grub initrd collect %s %s\n", args[0], args[1]);
483
484 if (grub_strcmp(args[0], "file") == 0)
485 {
486 return ventoy_grub_cfg_initrd_collect(args[1]);
487 }
488
489 device_name = grub_file_get_device_name(args[1]);
490 if (!device_name)
491 {
492 debug("failed to get device name %s\n", args[1]);
493 goto end;
494 }
495
496 dev = grub_device_open(device_name);
497 if (!dev)
498 {
499 debug("failed to open device %s\n", device_name);
500 goto end;
501 }
502
503 fs = grub_fs_probe(dev);
504 if (!fs)
505 {
506 debug("failed to probe fs %d\n", grub_errno);
507 goto end;
508 }
509
510 ctx.dir_prefix = args[1];
511 ctx.path_prefix = grub_strstr(args[1], device_name);
512 if (ctx.path_prefix)
513 {
514 ctx.path_prefix += grub_strlen(device_name) + 1;
515 }
516 else
517 {
518 ctx.path_prefix = args[1];
519 }
520
521 debug("ctx.path_prefix:<%s>\n", ctx.path_prefix);
522
523 fs->fs_dir(dev, ctx.path_prefix, ventoy_grub_initrd_hook, &ctx);
524
525 end:
526 check_free(device_name, grub_free);
527 check_free(dev, grub_device_close);
528
529
530 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
531 }
532
533 grub_err_t ventoy_cmd_specify_initrd_file(grub_extcmd_context_t ctxt, int argc, char **args)
534 {
535 initrd_info *img = NULL;
536
537 (void)ctxt;
538 (void)argc;
539
540 debug("ventoy_cmd_specify_initrd_file %s\n", args[0]);
541
542 img = grub_zalloc(sizeof(initrd_info));
543 if (!img)
544 {
545 return 1;
546 }
547
548 grub_strncpy(img->name, args[0], sizeof(img->name));
549 if (ventoy_find_initrd_by_name(g_initrd_img_list, img->name))
550 {
551 debug("%s is already exist\n", args[0]);
552 grub_free(img);
553 }
554 else
555 {
556 if (g_initrd_img_list)
557 {
558 img->prev = g_initrd_img_tail;
559 g_initrd_img_tail->next = img;
560 }
561 else
562 {
563 g_initrd_img_list = img;
564 }
565
566 g_initrd_img_tail = img;
567 g_initrd_img_count++;
568 }
569
570 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
571 }
572
573 static int ventoy_cpio_newc_get_int(char *value)
574 {
575 char buf[16] = {0};
576
577 grub_memcpy(buf, value, 8);
578 return (int)grub_strtoul(buf, NULL, 16);
579 }
580
581 static void ventoy_cpio_newc_fill_int(grub_uint32_t value, char *buf, int buflen)
582 {
583 int i;
584 int len;
585 char intbuf[32];
586
587 len = grub_snprintf(intbuf, sizeof(intbuf), "%x", value);
588
589 for (i = 0; i < buflen; i++)
590 {
591 buf[i] = '0';
592 }
593
594 if (len > buflen)
595 {
596 grub_printf("int buf len overflow %d %d\n", len, buflen);
597 }
598 else
599 {
600 grub_memcpy(buf + buflen - len, intbuf, len);
601 }
602 }
603
604 int ventoy_cpio_newc_fill_head(void *buf, int filesize, const void *filedata, const char *name)
605 {
606 int namelen = 0;
607 int headlen = 0;
608 static grub_uint32_t cpio_ino = 0xFFFFFFF0;
609 cpio_newc_header *cpio = (cpio_newc_header *)buf;
610
611 namelen = grub_strlen(name) + 1;
612 headlen = sizeof(cpio_newc_header) + namelen;
613 headlen = ventoy_align(headlen, 4);
614
615 grub_memset(cpio, '0', sizeof(cpio_newc_header));
616 grub_memset(cpio + 1, 0, headlen - sizeof(cpio_newc_header));
617
618 grub_memcpy(cpio->c_magic, "070701", 6);
619 ventoy_cpio_newc_fill_int(cpio_ino--, cpio->c_ino, 8);
620 ventoy_cpio_newc_fill_int(0100777, cpio->c_mode, 8);
621 ventoy_cpio_newc_fill_int(1, cpio->c_nlink, 8);
622 ventoy_cpio_newc_fill_int(filesize, cpio->c_filesize, 8);
623 ventoy_cpio_newc_fill_int(namelen, cpio->c_namesize, 8);
624 grub_memcpy(cpio + 1, name, namelen);
625
626 if (filedata)
627 {
628 grub_memcpy((char *)cpio + headlen, filedata, filesize);
629 }
630
631 return headlen;
632 }
633
634 static grub_uint32_t ventoy_linux_get_virt_chunk_count(void)
635 {
636 grub_uint32_t count = g_valid_initrd_count;
637
638 if (g_conf_replace_offset > 0)
639 {
640 count++;
641 }
642
643 return count;
644 }
645
646 static grub_uint32_t ventoy_linux_get_virt_chunk_size(void)
647 {
648 grub_uint32_t size;
649
650 size = (sizeof(ventoy_virt_chunk) + g_ventoy_cpio_size) * g_valid_initrd_count;
651
652 if (g_conf_replace_offset > 0)
653 {
654 size += sizeof(ventoy_virt_chunk) + g_conf_replace_new_len_align;
655 }
656
657 return size;
658 }
659
660 static void ventoy_linux_fill_virt_data( grub_uint64_t isosize, ventoy_chain_head *chain)
661 {
662 int id = 0;
663 initrd_info *node;
664 grub_uint64_t sector;
665 grub_uint32_t offset;
666 grub_uint32_t cpio_secs;
667 grub_uint32_t initrd_secs;
668 char *override;
669 ventoy_virt_chunk *cur;
670 char name[32];
671
672 override = (char *)chain + chain->virt_chunk_offset;
673 sector = (isosize + 2047) / 2048;
674 cpio_secs = g_ventoy_cpio_size / 2048;
675
676 offset = ventoy_linux_get_virt_chunk_count() * sizeof(ventoy_virt_chunk);
677 cur = (ventoy_virt_chunk *)override;
678
679 for (node = g_initrd_img_list; node; node = node->next)
680 {
681 if (node->size == 0)
682 {
683 continue;
684 }
685
686 initrd_secs = (grub_uint32_t)((node->size + 2047) / 2048);
687
688 cur->mem_sector_start = sector;
689 cur->mem_sector_end = cur->mem_sector_start + cpio_secs;
690 cur->mem_sector_offset = offset;
691 cur->remap_sector_start = cur->mem_sector_end;
692 cur->remap_sector_end = cur->remap_sector_start + initrd_secs;
693 cur->org_sector_start = (grub_uint32_t)(node->offset / 2048);
694
695 grub_memcpy(g_ventoy_runtime_buf, &chain->os_param, sizeof(ventoy_os_param));
696
697 grub_memset(name, 0, 16);
698 grub_snprintf(name, sizeof(name), "initrd%03d", ++id);
699
700 grub_memcpy(g_ventoy_initrd_head + 1, name, 16);
701 ventoy_cpio_newc_fill_int((grub_uint32_t)node->size, g_ventoy_initrd_head->c_filesize, 8);
702
703 grub_memcpy(override + offset, g_ventoy_cpio_buf, g_ventoy_cpio_size);
704
705 chain->virt_img_size_in_bytes += g_ventoy_cpio_size + initrd_secs * 2048;
706
707 offset += g_ventoy_cpio_size;
708 sector += cpio_secs + initrd_secs;
709 cur++;
710 }
711
712 if (g_conf_replace_offset > 0)
713 {
714 cpio_secs = g_conf_replace_new_len_align / 2048;
715
716 cur->mem_sector_start = sector;
717 cur->mem_sector_end = cur->mem_sector_start + cpio_secs;
718 cur->mem_sector_offset = offset;
719 cur->remap_sector_start = 0;
720 cur->remap_sector_end = 0;
721 cur->org_sector_start = 0;
722
723 grub_memcpy(override + offset, g_conf_replace_new_buf, g_conf_replace_new_len);
724
725 chain->virt_img_size_in_bytes += g_conf_replace_new_len_align;
726
727 offset += g_conf_replace_new_len_align;
728 sector += cpio_secs;
729 cur++;
730 }
731
732 return;
733 }
734
735 static grub_uint32_t ventoy_linux_get_override_chunk_count(void)
736 {
737 grub_uint32_t count = g_valid_initrd_count;
738
739 if (g_conf_replace_offset > 0)
740 {
741 count++;
742 }
743
744 return count;
745 }
746
747 static grub_uint32_t ventoy_linux_get_override_chunk_size(void)
748 {
749 int count = g_valid_initrd_count;
750
751 if (g_conf_replace_offset > 0)
752 {
753 count++;
754 }
755
756 return sizeof(ventoy_override_chunk) * count;
757 }
758
759 static void ventoy_linux_fill_override_data( grub_uint64_t isosize, void *override)
760 {
761 initrd_info *node;
762 grub_uint32_t mod;
763 grub_uint32_t newlen;
764 grub_uint64_t sector;
765 ventoy_override_chunk *cur;
766 ventoy_iso9660_override *dirent;
767 ventoy_udf_override *udf;
768
769 sector = (isosize + 2047) / 2048;
770
771 cur = (ventoy_override_chunk *)override;
772 for (node = g_initrd_img_list; node; node = node->next)
773 {
774 if (node->size == 0)
775 {
776 continue;
777 }
778
779 newlen = (grub_uint32_t)(node->size + g_ventoy_cpio_size);
780 mod = newlen % 4;
781 if (mod > 0)
782 {
783 newlen += 4 - mod; /* cpio must align with 4 */
784 }
785
786 if (node->iso_type == 0)
787 {
788 dirent = (ventoy_iso9660_override *)node->override_data;
789
790 node->override_length = sizeof(ventoy_iso9660_override);
791 dirent->first_sector = (grub_uint32_t)sector;
792 dirent->size = newlen;
793 dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
794 dirent->size_be = grub_swap_bytes32(dirent->size);
795
796 sector += (dirent->size + 2047) / 2048;
797 }
798 else
799 {
800 udf = (ventoy_udf_override *)node->override_data;
801
802 node->override_length = sizeof(ventoy_udf_override);
803 udf->length = newlen;
804 udf->position = (grub_uint32_t)sector - node->udf_start_block;
805
806 sector += (udf->length + 2047) / 2048;
807 }
808
809 cur->img_offset = node->override_offset;
810 cur->override_size = node->override_length;
811 grub_memcpy(cur->override_data, node->override_data, cur->override_size);
812 cur++;
813 }
814
815 if (g_conf_replace_offset > 0)
816 {
817 cur->img_offset = g_conf_replace_offset;
818 cur->override_size = sizeof(ventoy_iso9660_override);
819
820 newlen = (grub_uint32_t)(g_conf_replace_new_len);
821
822 dirent = (ventoy_iso9660_override *)cur->override_data;
823 dirent->first_sector = (grub_uint32_t)sector;
824 dirent->size = newlen;
825 dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
826 dirent->size_be = grub_swap_bytes32(dirent->size);
827
828 sector += (dirent->size + 2047) / 2048;
829 cur++;
830 }
831
832 return;
833 }
834
835 grub_err_t ventoy_cmd_initrd_count(grub_extcmd_context_t ctxt, int argc, char **args)
836 {
837 char buf[32] = {0};
838
839 (void)ctxt;
840 (void)argc;
841 (void)args;
842
843 if (argc == 1)
844 {
845 grub_snprintf(buf, sizeof(buf), "%d", g_initrd_img_count);
846 grub_env_set(args[0], buf);
847 }
848
849 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
850 }
851
852 grub_err_t ventoy_cmd_valid_initrd_count(grub_extcmd_context_t ctxt, int argc, char **args)
853 {
854 char buf[32] = {0};
855
856 (void)ctxt;
857 (void)argc;
858 (void)args;
859
860 if (argc == 1)
861 {
862 grub_snprintf(buf, sizeof(buf), "%d", g_valid_initrd_count);
863 grub_env_set(args[0], buf);
864 }
865
866 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
867 }
868
869 static grub_err_t ventoy_linux_locate_initrd(int filt, int *filtcnt)
870 {
871 int data;
872 int filtbysize = 1;
873 int sizefilt = 0;
874 grub_file_t file;
875 initrd_info *node;
876
877 debug("ventoy_linux_locate_initrd %d\n", filt);
878
879 g_valid_initrd_count = 0;
880
881 if (grub_env_get("INITRD_NO_SIZE_FILT"))
882 {
883 filtbysize = 0;
884 }
885
886 for (node = g_initrd_img_list; node; node = node->next)
887 {
888 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(loop)%s", node->name);
889 if (!file)
890 {
891 continue;
892 }
893
894 debug("file <%s> size:%d\n", node->name, (int)file->size);
895
896 /* initrd file too small */
897 if (filtbysize
898 && (NULL == grub_strstr(node->name, "minirt.gz"))
899 && (NULL == grub_strstr(node->name, "initrd.xz"))
900 )
901 {
902 if (filt > 0 && file->size <= g_ventoy_cpio_size + 2048)
903 {
904 debug("file size too small %d\n", (int)g_ventoy_cpio_size);
905 grub_file_close(file);
906 sizefilt++;
907 continue;
908 }
909 }
910
911 if (grub_strcmp(file->fs->name, "iso9660") == 0)
912 {
913 node->iso_type = 0;
914 node->override_offset = grub_iso9660_get_last_file_dirent_pos(file) + 2;
915
916 grub_file_read(file, &data, 1); // just read for hook trigger
917 node->offset = grub_iso9660_get_last_read_pos(file);
918 }
919 else
920 {
921 /* TBD */
922 }
923
924 node->size = file->size;
925 g_valid_initrd_count++;
926
927 grub_file_close(file);
928 }
929
930 *filtcnt = sizefilt;
931
932 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
933 }
934
935
936 grub_err_t ventoy_cmd_linux_get_main_initrd_index(grub_extcmd_context_t ctxt, int argc, char **args)
937 {
938 int index = 0;
939 char buf[32];
940 initrd_info *node = NULL;
941
942 (void)ctxt;
943 (void)argc;
944 (void)args;
945
946 if (argc != 1)
947 {
948 return 1;
949 }
950
951 if (g_initrd_img_count == 1)
952 {
953 ventoy_set_env(args[0], "0");
954 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
955 }
956
957 for (node = g_initrd_img_list; node; node = node->next)
958 {
959 if (node->size <= 0)
960 {
961 continue;
962 }
963
964 if (grub_strstr(node->name, "ucode") || grub_strstr(node->name, "-firmware"))
965 {
966 index++;
967 continue;
968 }
969
970 grub_snprintf(buf, sizeof(buf), "%d", index);
971 ventoy_set_env(args[0], buf);
972 break;
973 }
974
975 debug("main initrd index:%d\n", index);
976
977 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
978 }
979
980 grub_err_t ventoy_cmd_linux_locate_initrd(grub_extcmd_context_t ctxt, int argc, char **args)
981 {
982 int sizefilt = 0;
983
984 (void)ctxt;
985 (void)argc;
986 (void)args;
987
988 ventoy_linux_locate_initrd(1, &sizefilt);
989
990 if (g_valid_initrd_count == 0 && sizefilt > 0)
991 {
992 ventoy_linux_locate_initrd(0, &sizefilt);
993 }
994
995 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
996 }
997
998 static int ventoy_cpio_busybox64(cpio_newc_header *head)
999 {
1000 char *name;
1001 int namelen;
1002 int offset;
1003 int count = 0;
1004
1005 name = (char *)(head + 1);
1006 while (name[0] && count < 2)
1007 {
1008 if (grub_strcmp(name, "ventoy/busybox/ash") == 0)
1009 {
1010 grub_memcpy(name, "ventoy/busybox/32h", 18);
1011 count++;
1012 }
1013 else if (grub_strcmp(name, "ventoy/busybox/64h") == 0)
1014 {
1015 grub_memcpy(name, "ventoy/busybox/ash", 18);
1016 count++;
1017 }
1018
1019 namelen = ventoy_cpio_newc_get_int(head->c_namesize);
1020 offset = sizeof(cpio_newc_header) + namelen;
1021 offset = ventoy_align(offset, 4);
1022 offset += ventoy_cpio_newc_get_int(head->c_filesize);
1023 offset = ventoy_align(offset, 4);
1024
1025 head = (cpio_newc_header *)((char *)head + offset);
1026 name = (char *)(head + 1);
1027 }
1028
1029 return 0;
1030 }
1031
1032
1033 grub_err_t ventoy_cmd_cpio_busybox_64(grub_extcmd_context_t ctxt, int argc, char **args)
1034 {
1035 (void)ctxt;
1036 (void)argc;
1037 (void)args;
1038
1039 debug("ventoy_cmd_busybox_64 %d\n", argc);
1040 ventoy_cpio_busybox64((cpio_newc_header *)g_ventoy_cpio_buf);
1041 return 0;
1042 }
1043
1044
1045 grub_err_t ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt, int argc, char **args)
1046 {
1047 int i;
1048 int rc;
1049 char *pos = NULL;
1050 char *template_file = NULL;
1051 char *template_buf = NULL;
1052 char *persistent_buf = NULL;
1053 char *injection_buf = NULL;
1054 dud *dudnode = NULL;
1055 char tmpname[128];
1056 const char *injection_file = NULL;
1057 grub_uint8_t *buf = NULL;
1058 grub_uint32_t mod;
1059 grub_uint32_t headlen;
1060 grub_uint32_t initrd_head_len;
1061 grub_uint32_t padlen;
1062 grub_uint32_t img_chunk_size;
1063 grub_uint32_t template_size = 0;
1064 grub_uint32_t persistent_size = 0;
1065 grub_uint32_t injection_size = 0;
1066 grub_uint32_t dud_size = 0;
1067 grub_file_t file;
1068 grub_file_t tmpfile;
1069 ventoy_img_chunk_list chunk_list;
1070
1071 (void)ctxt;
1072 (void)argc;
1073
1074 if (argc != 4)
1075 {
1076 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s cpiofile\n", cmd_raw_name);
1077 }
1078
1079 if (g_img_chunk_list.chunk == NULL || g_img_chunk_list.cur_chunk == 0)
1080 {
1081 return grub_error(GRUB_ERR_BAD_ARGUMENT, "image chunk is null\n");
1082 }
1083
1084 img_chunk_size = g_img_chunk_list.cur_chunk * sizeof(ventoy_img_chunk);
1085
1086 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
1087 if (!file)
1088 {
1089 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't open file %s\n", args[0]);
1090 }
1091
1092 if (g_ventoy_cpio_buf)
1093 {
1094 grub_free(g_ventoy_cpio_buf);
1095 g_ventoy_cpio_buf = NULL;
1096 g_ventoy_cpio_size = 0;
1097 }
1098
1099 rc = ventoy_plugin_get_persistent_chunklist(args[1], -1, &chunk_list);
1100 if (rc == 0 && chunk_list.cur_chunk > 0 && chunk_list.chunk)
1101 {
1102 persistent_size = chunk_list.cur_chunk * sizeof(ventoy_img_chunk);
1103 persistent_buf = (char *)(chunk_list.chunk);
1104 }
1105
1106 template_file = ventoy_plugin_get_cur_install_template(args[1]);
1107 if (template_file)
1108 {
1109 debug("auto install template: <%s>\n", template_file);
1110 tmpfile = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", args[2], template_file);
1111 if (tmpfile)
1112 {
1113 debug("auto install script size %d\n", (int)tmpfile->size);
1114 template_size = tmpfile->size;
1115 template_buf = grub_malloc(template_size);
1116 if (template_buf)
1117 {
1118 grub_file_read(tmpfile, template_buf, template_size);
1119 }
1120
1121 grub_file_close(tmpfile);
1122 }
1123 else
1124 {
1125 debug("Failed to open install script %s%s\n", args[2], template_file);
1126 }
1127 }
1128 else
1129 {
1130 debug("auto install script skipped or not configed %s\n", args[1]);
1131 }
1132
1133 injection_file = ventoy_plugin_get_injection(args[1]);
1134 if (injection_file)
1135 {
1136 debug("injection archive: <%s>\n", injection_file);
1137 tmpfile = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", args[2], injection_file);
1138 if (tmpfile)
1139 {
1140 debug("injection archive size:%d\n", (int)tmpfile->size);
1141 injection_size = tmpfile->size;
1142 injection_buf = grub_malloc(injection_size);
1143 if (injection_buf)
1144 {
1145 grub_file_read(tmpfile, injection_buf, injection_size);
1146 }
1147
1148 grub_file_close(tmpfile);
1149 }
1150 else
1151 {
1152 debug("Failed to open injection archive %s%s\n", args[2], injection_file);
1153 }
1154 }
1155 else
1156 {
1157 debug("injection not configed %s\n", args[1]);
1158 }
1159
1160 dudnode = ventoy_plugin_find_dud(args[1]);
1161 if (dudnode)
1162 {
1163 debug("dud file: <%d>\n", dudnode->dudnum);
1164 ventoy_plugin_load_dud(dudnode, args[2]);
1165 for (i = 0; i < dudnode->dudnum; i++)
1166 {
1167 if (dudnode->files[i].size > 0)
1168 {
1169 dud_size += dudnode->files[i].size + sizeof(cpio_newc_header);
1170 }
1171 }
1172 }
1173 else
1174 {
1175 debug("dud not configed %s\n", args[1]);
1176 }
1177
1178 g_ventoy_cpio_buf = grub_malloc(file->size + 40960 + template_size +
1179 persistent_size + injection_size + dud_size + img_chunk_size);
1180 if (NULL == g_ventoy_cpio_buf)
1181 {
1182 grub_file_close(file);
1183 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't alloc memory %llu\n", file->size);
1184 }
1185
1186 grub_file_read(file, g_ventoy_cpio_buf, file->size);
1187
1188 buf = (grub_uint8_t *)(g_ventoy_cpio_buf + file->size - 4);
1189 while (*((grub_uint32_t *)buf) != 0x37303730)
1190 {
1191 buf -= 4;
1192 }
1193
1194 /* get initrd head len */
1195 initrd_head_len = ventoy_cpio_newc_fill_head(buf, 0, NULL, "initrd000.xx");
1196
1197 /* step1: insert image chunk data to cpio */
1198 headlen = ventoy_cpio_newc_fill_head(buf, img_chunk_size, g_img_chunk_list.chunk, "ventoy/ventoy_image_map");
1199 buf += headlen + ventoy_align(img_chunk_size, 4);
1200
1201 if (template_buf)
1202 {
1203 headlen = ventoy_cpio_newc_fill_head(buf, template_size, template_buf, "ventoy/autoinstall");
1204 buf += headlen + ventoy_align(template_size, 4);
1205 }
1206
1207 if (persistent_size > 0 && persistent_buf)
1208 {
1209 headlen = ventoy_cpio_newc_fill_head(buf, persistent_size, persistent_buf, "ventoy/ventoy_persistent_map");
1210 buf += headlen + ventoy_align(persistent_size, 4);
1211
1212 grub_free(persistent_buf);
1213 persistent_buf = NULL;
1214 }
1215
1216 if (injection_size > 0 && injection_buf)
1217 {
1218 headlen = ventoy_cpio_newc_fill_head(buf, injection_size, injection_buf, "ventoy/ventoy_injection");
1219 buf += headlen + ventoy_align(injection_size, 4);
1220
1221 grub_free(injection_buf);
1222 injection_buf = NULL;
1223 }
1224
1225 if (dud_size > 0)
1226 {
1227 for (i = 0; i < dudnode->dudnum; i++)
1228 {
1229 pos = grub_strrchr(dudnode->dudpath[i].path, '.');
1230 grub_snprintf(tmpname, sizeof(tmpname), "ventoy/ventoy_dud%d%s", i, (pos ? pos : ".iso"));
1231 dud_size = dudnode->files[i].size;
1232 headlen = ventoy_cpio_newc_fill_head(buf, dud_size, dudnode->files[i].buf, tmpname);
1233 buf += headlen + ventoy_align(dud_size, 4);
1234 }
1235 }
1236
1237 /* step2: insert os param to cpio */
1238 headlen = ventoy_cpio_newc_fill_head(buf, 0, NULL, "ventoy/ventoy_os_param");
1239 padlen = sizeof(ventoy_os_param);
1240 g_ventoy_cpio_size = (grub_uint32_t)(buf - g_ventoy_cpio_buf) + headlen + padlen + initrd_head_len;
1241 mod = g_ventoy_cpio_size % 2048;
1242 if (mod)
1243 {
1244 g_ventoy_cpio_size += 2048 - mod;
1245 padlen += 2048 - mod;
1246 }
1247
1248 /* update os param data size, the data will be updated before chain boot */
1249 ventoy_cpio_newc_fill_int(padlen, ((cpio_newc_header *)buf)->c_filesize, 8);
1250 g_ventoy_runtime_buf = (grub_uint8_t *)buf + headlen;
1251
1252 /* step3: fill initrd cpio head, the file size will be updated before chain boot */
1253 g_ventoy_initrd_head = (cpio_newc_header *)(g_ventoy_runtime_buf + padlen);
1254 ventoy_cpio_newc_fill_head(g_ventoy_initrd_head, 0, NULL, "initrd000.xx");
1255
1256 grub_file_close(file);
1257
1258 if (grub_strcmp(args[3], "busybox=64") == 0)
1259 {
1260 debug("cpio busybox proc %s\n", args[3]);
1261 ventoy_cpio_busybox64((cpio_newc_header *)g_ventoy_cpio_buf);
1262 }
1263
1264 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1265 }
1266
1267 grub_err_t ventoy_cmd_trailer_cpio(grub_extcmd_context_t ctxt, int argc, char **args)
1268 {
1269 int mod;
1270 int bufsize;
1271 int namelen;
1272 int offset;
1273 char *name;
1274 grub_uint8_t *bufend;
1275 cpio_newc_header *head;
1276 grub_file_t file;
1277 char value[64];
1278 const grub_uint8_t trailler[124] = {
1279 0x30, 0x37, 0x30, 0x37, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
1280 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
1281 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x30,
1282 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
1283 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
1284 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
1285 0x30, 0x30, 0x30, 0x30, 0x30, 0x42, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x54, 0x52,
1286 0x41, 0x49, 0x4C, 0x45, 0x52, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00
1287 };
1288
1289 (void)ctxt;
1290 (void)argc;
1291
1292 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", args[0], args[1]);
1293 if (!file)
1294 {
1295 return 1;
1296 }
1297
1298 grub_memset(g_ventoy_runtime_buf, 0, sizeof(ventoy_os_param));
1299 ventoy_fill_os_param(file, (ventoy_os_param *)g_ventoy_runtime_buf);
1300
1301 grub_file_close(file);
1302
1303 grub_memcpy(g_ventoy_initrd_head, trailler, sizeof(trailler));
1304 bufend = (grub_uint8_t *)g_ventoy_initrd_head + sizeof(trailler);
1305
1306 bufsize = (int)(bufend - g_ventoy_cpio_buf);
1307 mod = bufsize % 512;
1308 if (mod)
1309 {
1310 grub_memset(bufend, 0, 512 - mod);
1311 bufsize += 512 - mod;
1312 }
1313
1314 if (argc > 1 && grub_strcmp(args[2], "noinit") == 0)
1315 {
1316 head = (cpio_newc_header *)g_ventoy_cpio_buf;
1317 name = (char *)(head + 1);
1318
1319 while (grub_strcmp(name, "TRAILER!!!"))
1320 {
1321 if (grub_strcmp(name, "init") == 0)
1322 {
1323 grub_memcpy(name, "xxxx", 4);
1324 }
1325 else if (grub_strcmp(name, "linuxrc") == 0)
1326 {
1327 grub_memcpy(name, "vtoyxrc", 7);
1328 }
1329 else if (grub_strcmp(name, "sbin") == 0)
1330 {
1331 grub_memcpy(name, "vtoy", 4);
1332 }
1333 else if (grub_strcmp(name, "sbin/init") == 0)
1334 {
1335 grub_memcpy(name, "vtoy/vtoy", 9);
1336 }
1337
1338 namelen = ventoy_cpio_newc_get_int(head->c_namesize);
1339 offset = sizeof(cpio_newc_header) + namelen;
1340 offset = ventoy_align(offset, 4);
1341 offset += ventoy_cpio_newc_get_int(head->c_filesize);
1342 offset = ventoy_align(offset, 4);
1343
1344 head = (cpio_newc_header *)((char *)head + offset);
1345 name = (char *)(head + 1);
1346 }
1347 }
1348
1349 grub_snprintf(value, sizeof(value), "0x%llx", (ulonglong)(ulong)g_ventoy_cpio_buf);
1350 ventoy_set_env("ventoy_cpio_addr", value);
1351 grub_snprintf(value, sizeof(value), "%d", bufsize);
1352 ventoy_set_env("ventoy_cpio_size", value);
1353
1354 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1355 }
1356
1357
1358 grub_err_t ventoy_cmd_linux_chain_data(grub_extcmd_context_t ctxt, int argc, char **args)
1359 {
1360 int ventoy_compatible = 0;
1361 grub_uint32_t size = 0;
1362 grub_uint64_t isosize = 0;
1363 grub_uint32_t boot_catlog = 0;
1364 grub_uint32_t img_chunk_size = 0;
1365 grub_uint32_t override_count = 0;
1366 grub_uint32_t override_size = 0;
1367 grub_uint32_t virt_chunk_count = 0;
1368 grub_uint32_t virt_chunk_size = 0;
1369 grub_file_t file;
1370 grub_disk_t disk;
1371 const char *pLastChain = NULL;
1372 const char *compatible;
1373 ventoy_chain_head *chain;
1374 char envbuf[64];
1375
1376 (void)ctxt;
1377 (void)argc;
1378
1379 compatible = grub_env_get("ventoy_compatible");
1380 if (compatible && compatible[0] == 'Y')
1381 {
1382 ventoy_compatible = 1;
1383 }
1384
1385 if ((NULL == g_img_chunk_list.chunk) || (0 == ventoy_compatible && g_ventoy_cpio_buf == NULL))
1386 {
1387 grub_printf("ventoy not ready\n");
1388 return 1;
1389 }
1390
1391 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
1392 if (!file)
1393 {
1394 return 1;
1395 }
1396
1397 isosize = file->size;
1398
1399 boot_catlog = ventoy_get_iso_boot_catlog(file);
1400 if (boot_catlog)
1401 {
1402 if (ventoy_is_efi_os() && (!ventoy_has_efi_eltorito(file, boot_catlog)))
1403 {
1404 grub_env_set("LoadIsoEfiDriver", "on");
1405 }
1406 }
1407 else
1408 {
1409 if (ventoy_is_efi_os())
1410 {
1411 grub_env_set("LoadIsoEfiDriver", "on");
1412 }
1413 else
1414 {
1415 return grub_error(GRUB_ERR_BAD_ARGUMENT, "File %s is not bootable", args[0]);
1416 }
1417 }
1418
1419 img_chunk_size = g_img_chunk_list.cur_chunk * sizeof(ventoy_img_chunk);
1420
1421 override_count = ventoy_linux_get_override_chunk_count();
1422 virt_chunk_count = ventoy_linux_get_virt_chunk_count();
1423
1424 if (ventoy_compatible)
1425 {
1426 size = sizeof(ventoy_chain_head) + img_chunk_size;
1427 }
1428 else
1429 {
1430 override_size = ventoy_linux_get_override_chunk_size();
1431 virt_chunk_size = ventoy_linux_get_virt_chunk_size();
1432 size = sizeof(ventoy_chain_head) + img_chunk_size + override_size + virt_chunk_size;
1433 }
1434
1435 pLastChain = grub_env_get("vtoy_chain_mem_addr");
1436 if (pLastChain)
1437 {
1438 chain = (ventoy_chain_head *)grub_strtoul(pLastChain, NULL, 16);
1439 if (chain)
1440 {
1441 debug("free last chain memory %p\n", chain);
1442 grub_free(chain);
1443 }
1444 }
1445
1446 chain = grub_malloc(size);
1447 if (!chain)
1448 {
1449 grub_printf("Failed to alloc chain memory size %u\n", size);
1450 grub_file_close(file);
1451 return 1;
1452 }
1453
1454 grub_snprintf(envbuf, sizeof(envbuf), "0x%lx", (unsigned long)chain);
1455 grub_env_set("vtoy_chain_mem_addr", envbuf);
1456 grub_snprintf(envbuf, sizeof(envbuf), "%u", size);
1457 grub_env_set("vtoy_chain_mem_size", envbuf);
1458
1459 grub_memset(chain, 0, sizeof(ventoy_chain_head));
1460
1461 /* part 1: os parameter */
1462 g_ventoy_chain_type = ventoy_chain_linux;
1463 ventoy_fill_os_param(file, &(chain->os_param));
1464
1465 /* part 2: chain head */
1466 disk = file->device->disk;
1467 chain->disk_drive = disk->id;
1468 chain->disk_sector_size = (1 << disk->log_sector_size);
1469 chain->real_img_size_in_bytes = file->size;
1470 chain->virt_img_size_in_bytes = (file->size + 2047) / 2048 * 2048;
1471 chain->boot_catalog = boot_catlog;
1472
1473 if (!ventoy_is_efi_os())
1474 {
1475 grub_file_seek(file, boot_catlog * 2048);
1476 grub_file_read(file, chain->boot_catalog_sector, sizeof(chain->boot_catalog_sector));
1477 }
1478
1479 /* part 3: image chunk */
1480 chain->img_chunk_offset = sizeof(ventoy_chain_head);
1481 chain->img_chunk_num = g_img_chunk_list.cur_chunk;
1482 grub_memcpy((char *)chain + chain->img_chunk_offset, g_img_chunk_list.chunk, img_chunk_size);
1483
1484 if (ventoy_compatible)
1485 {
1486 return 0;
1487 }
1488
1489 /* part 4: override chunk */
1490 if (override_count > 0)
1491 {
1492 chain->override_chunk_offset = chain->img_chunk_offset + img_chunk_size;
1493 chain->override_chunk_num = override_count;
1494 ventoy_linux_fill_override_data(isosize, (char *)chain + chain->override_chunk_offset);
1495 }
1496
1497 /* part 5: virt chunk */
1498 if (virt_chunk_count > 0)
1499 {
1500 chain->virt_chunk_offset = chain->override_chunk_offset + override_size;
1501 chain->virt_chunk_num = virt_chunk_count;
1502 ventoy_linux_fill_virt_data(isosize, chain);
1503 }
1504
1505 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1506 }
1507