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>
36 #include <grub/ventoy.h>
37 #include "ventoy_def.h"
39 GRUB_MOD_LICENSE ("GPLv3+");
42 static char * ventoy_get_line(char *start
)
49 while (*start
&& *start
!= '\n')
65 static initrd_info
* ventoy_find_initrd_by_name(initrd_info
*list
, const char *name
)
67 initrd_info
*node
= list
;
71 if (grub_strcmp(node
->name
, name
) == 0)
81 grub_err_t
ventoy_cmd_clear_initrd_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
83 initrd_info
*node
= g_initrd_img_list
;
97 g_initrd_img_list
= NULL
;
98 g_initrd_img_tail
= NULL
;
99 g_initrd_img_count
= 0;
100 g_valid_initrd_count
= 0;
102 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
105 grub_err_t
ventoy_cmd_dump_initrd_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
108 initrd_info
*node
= g_initrd_img_list
;
114 grub_printf("###################\n");
115 grub_printf("initrd info list: valid count:%d\n", g_valid_initrd_count
);
119 grub_printf("%s ", node
->size
> 0 ? "*" : " ");
120 grub_printf("%02u %s offset:%llu size:%llu \n", i
++, node
->name
, (unsigned long long)node
->offset
,
121 (unsigned long long)node
->size
);
125 grub_printf("###################\n");
127 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
130 static void ventoy_parse_directory(char *path
, char *dir
, int buflen
)
135 pos
= grub_strstr(path
, ")");
141 end
= grub_snprintf(dir
, buflen
, "%s", pos
+ 1);
153 static grub_err_t
ventoy_isolinux_initrd_collect(grub_file_t file
, const char *prefix
)
161 char *nextline
= NULL
;
162 initrd_info
*img
= NULL
;
164 prefixlen
= grub_strlen(prefix
);
166 buf
= grub_zalloc(file
->size
+ 2);
172 grub_file_read(file
, buf
, file
->size
);
174 for (start
= buf
; start
; start
= nextline
)
176 nextline
= ventoy_get_line(start
);
178 while (ventoy_isspace(*start
))
183 offset
= 7; // strlen("initrd=") or "INITRD " or "initrd "
184 pos
= grub_strstr(start
, "initrd=");
189 if (grub_strncmp(start
, "INITRD", 6) != 0 && grub_strncmp(start
, "initrd", 6) != 0)
191 if (grub_strstr(start
, "xen") &&
192 ((pos
= grub_strstr(start
, "--- /install.img")) != NULL
||
193 (pos
= grub_strstr(start
, "--- initrd.img")) != NULL
196 offset
= 4; // "--- "
210 img
= grub_zalloc(sizeof(initrd_info
));
218 grub_strcpy(img
->name
, prefix
);
222 while (i
< 255 && (0 == ventoy_is_word_end(*pos
)))
224 img
->name
[i
++] = *pos
++;
227 if (ventoy_find_initrd_by_name(g_initrd_img_list
, img
->name
))
233 if (g_initrd_img_list
)
235 img
->prev
= g_initrd_img_tail
;
236 g_initrd_img_tail
->next
= img
;
240 g_initrd_img_list
= img
;
243 g_initrd_img_tail
= img
;
244 g_initrd_img_count
++;
259 return GRUB_ERR_NONE
;
262 static int ventoy_isolinux_initrd_hook(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
264 grub_file_t file
= NULL
;
265 ventoy_initrd_ctx
*ctx
= (ventoy_initrd_ctx
*)data
;
269 if (NULL
== grub_strstr(filename
, ".cfg") && NULL
== grub_strstr(filename
, ".CFG"))
274 debug("init hook dir <%s%s>\n", ctx
->path_prefix
, filename
);
276 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", ctx
->path_prefix
, filename
);
282 ventoy_isolinux_initrd_collect(file
, ctx
->dir_prefix
);
283 grub_file_close(file
);
288 grub_err_t
ventoy_cmd_isolinux_initrd_collect(grub_extcmd_context_t ctxt
, int argc
, char **args
)
291 grub_device_t dev
= NULL
;
292 char *device_name
= NULL
;
293 ventoy_initrd_ctx ctx
;
299 device_name
= grub_file_get_device_name(args
[0]);
305 dev
= grub_device_open(device_name
);
311 fs
= grub_fs_probe(dev
);
317 debug("isolinux initrd collect %s\n", args
[0]);
319 ventoy_parse_directory(args
[0], directory
, sizeof(directory
) - 1);
320 ctx
.path_prefix
= args
[0];
321 ctx
.dir_prefix
= (argc
> 1) ? args
[1] : directory
;
323 debug("path_prefix=<%s> dir_prefix=<%s>\n", ctx
.path_prefix
, ctx
.dir_prefix
);
325 fs
->fs_dir(dev
, directory
, ventoy_isolinux_initrd_hook
, &ctx
);
328 check_free(device_name
, grub_free
);
329 check_free(dev
, grub_device_close
);
331 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
334 static grub_err_t
ventoy_grub_cfg_initrd_collect(const char *fileName
)
337 grub_file_t file
= NULL
;
340 char *nextline
= NULL
;
341 initrd_info
*img
= NULL
;
343 debug("grub initrd collect %s\n", fileName
);
345 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", fileName
);
351 buf
= grub_zalloc(file
->size
+ 2);
354 grub_file_close(file
);
358 grub_file_read(file
, buf
, file
->size
);
360 for (start
= buf
; start
; start
= nextline
)
362 nextline
= ventoy_get_line(start
);
364 while (ventoy_isspace(*start
))
369 if (grub_strncmp(start
, "initrd", 6) != 0)
375 while (*start
&& (!ventoy_isspace(*start
)))
380 while (ventoy_isspace(*start
))
387 img
= grub_zalloc(sizeof(initrd_info
));
393 for (i
= 0; i
< 255 && (0 == ventoy_is_word_end(*start
)); i
++)
395 img
->name
[i
] = *start
++;
398 if (ventoy_find_initrd_by_name(g_initrd_img_list
, img
->name
))
404 if (g_initrd_img_list
)
406 img
->prev
= g_initrd_img_tail
;
407 g_initrd_img_tail
->next
= img
;
411 g_initrd_img_list
= img
;
414 g_initrd_img_tail
= img
;
415 g_initrd_img_count
++;
418 if (*start
== ' ' || *start
== '\t')
420 while (ventoy_isspace(*start
))
433 grub_file_close(file
);
435 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
438 static int ventoy_grub_initrd_hook(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
441 ventoy_initrd_ctx
*ctx
= (ventoy_initrd_ctx
*)data
;
445 debug("ventoy_grub_initrd_hook %s\n", filename
);
447 if (NULL
== grub_strstr(filename
, ".cfg") &&
448 NULL
== grub_strstr(filename
, ".CFG") &&
449 NULL
== grub_strstr(filename
, ".conf"))
454 debug("init hook dir <%s%s>\n", ctx
->path_prefix
, filename
);
456 grub_snprintf(filePath
, sizeof(filePath
) - 1, "%s%s", ctx
->dir_prefix
, filename
);
457 ventoy_grub_cfg_initrd_collect(filePath
);
462 grub_err_t
ventoy_cmd_grub_initrd_collect(grub_extcmd_context_t ctxt
, int argc
, char **args
)
465 grub_device_t dev
= NULL
;
466 char *device_name
= NULL
;
467 ventoy_initrd_ctx ctx
;
477 debug("grub initrd collect %s %s\n", args
[0], args
[1]);
479 if (grub_strcmp(args
[0], "file") == 0)
481 return ventoy_grub_cfg_initrd_collect(args
[1]);
484 device_name
= grub_file_get_device_name(args
[1]);
487 debug("failed to get device name %s\n", args
[1]);
491 dev
= grub_device_open(device_name
);
494 debug("failed to open device %s\n", device_name
);
498 fs
= grub_fs_probe(dev
);
501 debug("failed to probe fs %d\n", grub_errno
);
505 ctx
.dir_prefix
= args
[1];
506 ctx
.path_prefix
= grub_strstr(args
[1], device_name
);
509 ctx
.path_prefix
+= grub_strlen(device_name
) + 1;
513 ctx
.path_prefix
= args
[1];
516 debug("ctx.path_prefix:<%s>\n", ctx
.path_prefix
);
518 fs
->fs_dir(dev
, ctx
.path_prefix
, ventoy_grub_initrd_hook
, &ctx
);
521 check_free(device_name
, grub_free
);
522 check_free(dev
, grub_device_close
);
525 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
528 grub_err_t
ventoy_cmd_specify_initrd_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
530 initrd_info
*img
= NULL
;
535 debug("ventoy_cmd_specify_initrd_file %s\n", args
[0]);
537 img
= grub_zalloc(sizeof(initrd_info
));
543 grub_strncpy(img
->name
, args
[0], sizeof(img
->name
));
544 if (ventoy_find_initrd_by_name(g_initrd_img_list
, img
->name
))
546 debug("%s is already exist\n", args
[0]);
551 if (g_initrd_img_list
)
553 img
->prev
= g_initrd_img_tail
;
554 g_initrd_img_tail
->next
= img
;
558 g_initrd_img_list
= img
;
561 g_initrd_img_tail
= img
;
562 g_initrd_img_count
++;
565 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
568 static void ventoy_cpio_newc_fill_int(grub_uint32_t value
, char *buf
, int buflen
)
574 len
= grub_snprintf(intbuf
, sizeof(intbuf
), "%x", value
);
576 for (i
= 0; i
< buflen
; i
++)
583 grub_printf("int buf len overflow %d %d\n", len
, buflen
);
587 grub_memcpy(buf
+ buflen
- len
, intbuf
, len
);
591 int ventoy_cpio_newc_fill_head(void *buf
, int filesize
, const void *filedata
, const char *name
)
595 static grub_uint32_t cpio_ino
= 0xFFFFFFF0;
596 cpio_newc_header
*cpio
= (cpio_newc_header
*)buf
;
598 namelen
= grub_strlen(name
) + 1;
599 headlen
= sizeof(cpio_newc_header
) + namelen
;
600 headlen
= ventoy_align(headlen
, 4);
602 grub_memset(cpio
, '0', sizeof(cpio_newc_header
));
603 grub_memset(cpio
+ 1, 0, headlen
- sizeof(cpio_newc_header
));
605 grub_memcpy(cpio
->c_magic
, "070701", 6);
606 ventoy_cpio_newc_fill_int(cpio_ino
--, cpio
->c_ino
, 8);
607 ventoy_cpio_newc_fill_int(0100777, cpio
->c_mode
, 8);
608 ventoy_cpio_newc_fill_int(1, cpio
->c_nlink
, 8);
609 ventoy_cpio_newc_fill_int(filesize
, cpio
->c_filesize
, 8);
610 ventoy_cpio_newc_fill_int(namelen
, cpio
->c_namesize
, 8);
611 grub_memcpy(cpio
+ 1, name
, namelen
);
615 grub_memcpy((char *)cpio
+ headlen
, filedata
, filesize
);
621 static grub_uint32_t
ventoy_linux_get_virt_chunk_size(void)
623 return (sizeof(ventoy_virt_chunk
) + g_ventoy_cpio_size
) * g_valid_initrd_count
;
626 static void ventoy_linux_fill_virt_data( grub_uint64_t isosize
, ventoy_chain_head
*chain
)
630 grub_uint64_t sector
;
631 grub_uint32_t offset
;
632 grub_uint32_t cpio_secs
;
633 grub_uint32_t initrd_secs
;
635 ventoy_virt_chunk
*cur
;
638 override
= (char *)chain
+ chain
->virt_chunk_offset
;
639 sector
= (isosize
+ 2047) / 2048;
640 cpio_secs
= g_ventoy_cpio_size
/ 2048;
642 offset
= g_valid_initrd_count
* sizeof(ventoy_virt_chunk
);
643 cur
= (ventoy_virt_chunk
*)override
;
645 for (node
= g_initrd_img_list
; node
; node
= node
->next
)
652 initrd_secs
= (grub_uint32_t
)((node
->size
+ 2047) / 2048);
654 cur
->mem_sector_start
= sector
;
655 cur
->mem_sector_end
= cur
->mem_sector_start
+ cpio_secs
;
656 cur
->mem_sector_offset
= offset
;
657 cur
->remap_sector_start
= cur
->mem_sector_end
;
658 cur
->remap_sector_end
= cur
->remap_sector_start
+ initrd_secs
;
659 cur
->org_sector_start
= (grub_uint32_t
)(node
->offset
/ 2048);
661 grub_memcpy(g_ventoy_runtime_buf
, &chain
->os_param
, sizeof(ventoy_os_param
));
663 grub_memset(name
, 0, 16);
664 grub_snprintf(name
, sizeof(name
), "initrd%03d", ++id
);
666 grub_memcpy(g_ventoy_initrd_head
+ 1, name
, 16);
667 ventoy_cpio_newc_fill_int((grub_uint32_t
)node
->size
, g_ventoy_initrd_head
->c_filesize
, 8);
669 grub_memcpy(override
+ offset
, g_ventoy_cpio_buf
, g_ventoy_cpio_size
);
671 chain
->virt_img_size_in_bytes
+= g_ventoy_cpio_size
+ initrd_secs
* 2048;
673 offset
+= g_ventoy_cpio_size
;
674 sector
+= cpio_secs
+ initrd_secs
;
681 static grub_uint32_t
ventoy_linux_get_override_chunk_size(void)
683 return sizeof(ventoy_override_chunk
) * g_valid_initrd_count
;
686 static void ventoy_linux_fill_override_data( grub_uint64_t isosize
, void *override
)
689 grub_uint64_t sector
;
690 ventoy_override_chunk
*cur
;
692 sector
= (isosize
+ 2047) / 2048;
694 cur
= (ventoy_override_chunk
*)override
;
695 for (node
= g_initrd_img_list
; node
; node
= node
->next
)
702 if (node
->iso_type
== 0)
704 ventoy_iso9660_override
*dirent
= (ventoy_iso9660_override
*)node
->override_data
;
706 node
->override_length
= sizeof(ventoy_iso9660_override
);
707 dirent
->first_sector
= (grub_uint32_t
)sector
;
708 dirent
->size
= (grub_uint32_t
)(node
->size
+ g_ventoy_cpio_size
);
709 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
710 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
712 sector
+= (dirent
->size
+ 2047) / 2048;
716 ventoy_udf_override
*udf
= (ventoy_udf_override
*)node
->override_data
;
718 node
->override_length
= sizeof(ventoy_udf_override
);
719 udf
->length
= (grub_uint32_t
)(node
->size
+ g_ventoy_cpio_size
);
720 udf
->position
= (grub_uint32_t
)sector
- node
->udf_start_block
;
722 sector
+= (udf
->length
+ 2047) / 2048;
725 cur
->img_offset
= node
->override_offset
;
726 cur
->override_size
= node
->override_length
;
727 grub_memcpy(cur
->override_data
, node
->override_data
, cur
->override_size
);
734 grub_err_t
ventoy_cmd_initrd_count(grub_extcmd_context_t ctxt
, int argc
, char **args
)
744 grub_snprintf(buf
, sizeof(buf
), "%d", g_initrd_img_count
);
745 grub_env_set(args
[0], buf
);
748 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
751 grub_err_t
ventoy_cmd_valid_initrd_count(grub_extcmd_context_t ctxt
, int argc
, char **args
)
761 grub_snprintf(buf
, sizeof(buf
), "%d", g_valid_initrd_count
);
762 grub_env_set(args
[0], buf
);
765 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
768 static grub_err_t
ventoy_linux_locate_initrd(int filt
, int *filtcnt
)
776 debug("ventoy_linux_locate_initrd %d\n", filt
);
778 g_valid_initrd_count
= 0;
780 if (grub_env_get("INITRD_NO_SIZE_FILT"))
785 for (node
= g_initrd_img_list
; node
; node
= node
->next
)
787 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->name
);
793 debug("file <%s> size:%d\n", node
->name
, (int)file
->size
);
795 /* initrd file too small */
797 && (NULL
== grub_strstr(node
->name
, "minirt.gz"))
798 && (NULL
== grub_strstr(node
->name
, "initrd.xz"))
801 if (filt
> 0 && file
->size
<= g_ventoy_cpio_size
+ 2048)
803 debug("file size too small %d\n", (int)g_ventoy_cpio_size
);
804 grub_file_close(file
);
810 if (grub_strcmp(file
->fs
->name
, "iso9660") == 0)
813 node
->override_offset
= grub_iso9660_get_last_file_dirent_pos(file
) + 2;
815 grub_file_read(file
, &data
, 1); // just read for hook trigger
816 node
->offset
= grub_iso9660_get_last_read_pos(file
);
823 node
->size
= file
->size
;
824 g_valid_initrd_count
++;
826 grub_file_close(file
);
831 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
835 grub_err_t
ventoy_cmd_linux_locate_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
843 ventoy_linux_locate_initrd(1, &sizefilt
);
845 if (g_valid_initrd_count
== 0 && sizefilt
> 0)
847 ventoy_linux_locate_initrd(0, &sizefilt
);
850 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
853 grub_err_t
ventoy_cmd_load_cpio(grub_extcmd_context_t ctxt
, int argc
, char **args
)
855 char *template_file
= NULL
;
856 char *template_buf
= NULL
;
857 grub_uint8_t
*buf
= NULL
;
859 grub_uint32_t headlen
;
860 grub_uint32_t initrd_head_len
;
861 grub_uint32_t padlen
;
862 grub_uint32_t img_chunk_size
;
863 grub_uint32_t template_size
= 0;
865 grub_file_t scriptfile
;
872 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s cpiofile\n", cmd_raw_name
);
875 if (g_img_chunk_list
.chunk
== NULL
|| g_img_chunk_list
.cur_chunk
== 0)
877 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "image chunk is null\n");
880 img_chunk_size
= g_img_chunk_list
.cur_chunk
* sizeof(ventoy_img_chunk
);
882 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
885 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
888 if (g_ventoy_cpio_buf
)
890 grub_free(g_ventoy_cpio_buf
);
891 g_ventoy_cpio_buf
= NULL
;
892 g_ventoy_cpio_size
= 0;
895 template_file
= ventoy_plugin_get_install_template(args
[1]);
898 debug("auto install template: <%s>\n", template_file
);
899 scriptfile
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[2], template_file
);
902 debug("auto install script size %d\n", (int)scriptfile
->size
);
903 template_size
= scriptfile
->size
;
904 template_buf
= grub_malloc(template_size
);
907 grub_file_read(scriptfile
, template_buf
, template_size
);
910 grub_file_close(scriptfile
);
914 debug("Failed to open install script %s%s\n", args
[2], template_file
);
918 g_ventoy_cpio_buf
= grub_malloc(file
->size
+ 4096 + template_size
+ img_chunk_size
);
919 if (NULL
== g_ventoy_cpio_buf
)
921 grub_file_close(file
);
922 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't alloc memory %llu\n", file
->size
+ 4096 + img_chunk_size
);
925 grub_file_read(file
, g_ventoy_cpio_buf
, file
->size
);
927 buf
= (grub_uint8_t
*)(g_ventoy_cpio_buf
+ file
->size
- 4);
928 while (*((grub_uint32_t
*)buf
) != 0x37303730)
933 /* get initrd head len */
934 initrd_head_len
= ventoy_cpio_newc_fill_head(buf
, 0, NULL
, "initrd000.xx");
936 /* step1: insert image chunk data to cpio */
937 headlen
= ventoy_cpio_newc_fill_head(buf
, img_chunk_size
, g_img_chunk_list
.chunk
, "ventoy/ventoy_image_map");
938 buf
+= headlen
+ ventoy_align(img_chunk_size
, 4);
942 headlen
= ventoy_cpio_newc_fill_head(buf
, template_size
, template_buf
, "ventoy/autoinstall");
943 buf
+= headlen
+ ventoy_align(template_size
, 4);
946 /* step2: insert os param to cpio */
947 headlen
= ventoy_cpio_newc_fill_head(buf
, 0, NULL
, "ventoy/ventoy_os_param");
948 padlen
= sizeof(ventoy_os_param
);
949 g_ventoy_cpio_size
= (grub_uint32_t
)(buf
- g_ventoy_cpio_buf
) + headlen
+ padlen
+ initrd_head_len
;
950 mod
= g_ventoy_cpio_size
% 2048;
953 g_ventoy_cpio_size
+= 2048 - mod
;
954 padlen
+= 2048 - mod
;
957 /* update os param data size, the data will be updated before chain boot */
958 ventoy_cpio_newc_fill_int(padlen
, ((cpio_newc_header
*)buf
)->c_filesize
, 8);
959 g_ventoy_runtime_buf
= (grub_uint8_t
*)buf
+ headlen
;
961 /* step3: fill initrd cpio head, the file size will be updated before chain boot */
962 g_ventoy_initrd_head
= (cpio_newc_header
*)(g_ventoy_runtime_buf
+ padlen
);
963 ventoy_cpio_newc_fill_head(g_ventoy_initrd_head
, 0, NULL
, "initrd000.xx");
965 grub_file_close(file
);
967 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
971 grub_err_t
ventoy_cmd_linux_chain_data(grub_extcmd_context_t ctxt
, int argc
, char **args
)
973 int ventoy_compatible
= 0;
974 grub_uint32_t size
= 0;
975 grub_uint64_t isosize
= 0;
976 grub_uint32_t boot_catlog
= 0;
977 grub_uint32_t img_chunk_size
= 0;
978 grub_uint32_t override_size
= 0;
979 grub_uint32_t virt_chunk_size
= 0;
982 const char *pLastChain
= NULL
;
983 const char *compatible
;
984 ventoy_chain_head
*chain
;
990 compatible
= grub_env_get("ventoy_compatible");
991 if (compatible
&& compatible
[0] == 'Y')
993 ventoy_compatible
= 1;
996 if ((NULL
== g_img_chunk_list
.chunk
) || (0 == ventoy_compatible
&& g_ventoy_cpio_buf
== NULL
))
998 grub_printf("ventoy not ready\n");
1002 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1008 isosize
= file
->size
;
1010 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
1013 if (ventoy_is_efi_os() && (!ventoy_has_efi_eltorito(file
, boot_catlog
)))
1015 grub_env_set("LoadIsoEfiDriver", "on");
1020 if (ventoy_is_efi_os())
1022 grub_env_set("LoadIsoEfiDriver", "on");
1026 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "File %s is not bootable", args
[0]);
1030 img_chunk_size
= g_img_chunk_list
.cur_chunk
* sizeof(ventoy_img_chunk
);
1032 if (ventoy_compatible
)
1034 size
= sizeof(ventoy_chain_head
) + img_chunk_size
;
1038 override_size
= ventoy_linux_get_override_chunk_size();
1039 virt_chunk_size
= ventoy_linux_get_virt_chunk_size();
1040 size
= sizeof(ventoy_chain_head
) + img_chunk_size
+ override_size
+ virt_chunk_size
;
1043 pLastChain
= grub_env_get("vtoy_chain_mem_addr");
1046 chain
= (ventoy_chain_head
*)grub_strtoul(pLastChain
, NULL
, 16);
1049 debug("free last chain memory %p\n", chain
);
1054 chain
= grub_malloc(size
);
1057 grub_printf("Failed to alloc chain memory size %u\n", size
);
1058 grub_file_close(file
);
1062 grub_snprintf(envbuf
, sizeof(envbuf
), "0x%lx", (unsigned long)chain
);
1063 grub_env_set("vtoy_chain_mem_addr", envbuf
);
1064 grub_snprintf(envbuf
, sizeof(envbuf
), "%u", size
);
1065 grub_env_set("vtoy_chain_mem_size", envbuf
);
1067 grub_memset(chain
, 0, sizeof(ventoy_chain_head
));
1069 /* part 1: os parameter */
1070 ventoy_fill_os_param(file
, &(chain
->os_param
));
1072 /* part 2: chain head */
1073 disk
= file
->device
->disk
;
1074 chain
->disk_drive
= disk
->id
;
1075 chain
->disk_sector_size
= (1 << disk
->log_sector_size
);
1076 chain
->real_img_size_in_bytes
= file
->size
;
1077 chain
->virt_img_size_in_bytes
= (file
->size
+ 2047) / 2048 * 2048;
1078 chain
->boot_catalog
= boot_catlog
;
1080 if (!ventoy_is_efi_os())
1082 grub_file_seek(file
, boot_catlog
* 2048);
1083 grub_file_read(file
, chain
->boot_catalog_sector
, sizeof(chain
->boot_catalog_sector
));
1086 /* part 3: image chunk */
1087 chain
->img_chunk_offset
= sizeof(ventoy_chain_head
);
1088 chain
->img_chunk_num
= g_img_chunk_list
.cur_chunk
;
1089 grub_memcpy((char *)chain
+ chain
->img_chunk_offset
, g_img_chunk_list
.chunk
, img_chunk_size
);
1091 if (ventoy_compatible
)
1096 if (g_valid_initrd_count
== 0)
1101 /* part 4: override chunk */
1102 chain
->override_chunk_offset
= chain
->img_chunk_offset
+ img_chunk_size
;
1103 chain
->override_chunk_num
= g_valid_initrd_count
;
1104 ventoy_linux_fill_override_data(isosize
, (char *)chain
+ chain
->override_chunk_offset
);
1106 /* part 5: virt chunk */
1107 chain
->virt_chunk_offset
= chain
->override_chunk_offset
+ override_size
;
1108 chain
->virt_chunk_num
= g_valid_initrd_count
;
1109 ventoy_linux_fill_virt_data(isosize
, chain
);
1111 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);