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 int g_mod_search_magic
= 0;
51 int g_unix_vlnk_boot
= 0;
53 int g_ko_fillmap_len
= 0;
54 char *g_ko_fillmap_data
= NULL
;
56 grub_uint64_t g_mod_override_offset
= 0;
57 grub_uint64_t g_conf_override_offset
= 0;
59 static int ventoy_get_file_override(const char *filename
, grub_uint64_t
*offset
)
65 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", filename
);
71 *offset
= grub_iso9660_get_last_file_dirent_pos(file
) + 2;
73 grub_file_close(file
);
78 static grub_uint32_t
ventoy_unix_get_override_chunk_count(void)
80 grub_uint32_t count
= 0;
82 if (g_conf_new_len
> 0)
87 if (g_mod_new_len
> 0)
92 if (g_ko_fillmap_len
> 0)
94 count
+= (g_ko_fillmap_len
/ 512);
95 if ((g_ko_fillmap_len
% 512) > 0)
104 static grub_uint32_t
ventoy_unix_get_virt_chunk_count(void)
106 grub_uint32_t count
= 0;
108 if (g_conf_new_len
> 0)
113 if (g_mod_new_len
> 0)
120 static grub_uint32_t
ventoy_unix_get_virt_chunk_size(void)
124 size
= sizeof(ventoy_virt_chunk
) * ventoy_unix_get_virt_chunk_count();
126 if (g_conf_new_len
> 0)
128 size
+= ventoy_align_2k(g_conf_new_len
);
131 if (g_mod_new_len
> 0)
133 size
+= ventoy_align_2k(g_mod_new_len
);
139 static void ventoy_unix_fill_map_data(ventoy_chain_head
*chain
, struct g_ventoy_map
*map
)
142 ventoy_img_chunk
*chunk
= NULL
;
144 debug("Fill unix map data: <%llu> <%u> %p\n",
145 (unsigned long long)chain
->os_param
.vtoy_disk_size
, g_img_chunk_list
.cur_chunk
, map
);
147 map
->magic1
[0] = map
->magic2
[0] = VENTOY_UNIX_SEG_MAGIC0
;
148 map
->magic1
[1] = map
->magic2
[1] = VENTOY_UNIX_SEG_MAGIC1
;
149 map
->magic1
[2] = map
->magic2
[2] = VENTOY_UNIX_SEG_MAGIC2
;
150 map
->magic1
[3] = map
->magic2
[3] = VENTOY_UNIX_SEG_MAGIC3
;
152 map
->disksize
= chain
->os_param
.vtoy_disk_size
;
153 grub_memcpy(map
->diskuuid
, chain
->os_param
.vtoy_disk_guid
, 16);
155 map
->segnum
= g_img_chunk_list
.cur_chunk
;
156 if (g_img_chunk_list
.cur_chunk
> VENTOY_UNIX_MAX_SEGNUM
)
158 debug("####[FAIL] Too many segments for the ISO file %u\n", g_img_chunk_list
.cur_chunk
);
159 map
->segnum
= VENTOY_UNIX_MAX_SEGNUM
;
162 for (i
= 0; i
< (grub_uint32_t
)(map
->segnum
); i
++)
164 chunk
= g_img_chunk_list
.chunk
+ i
;
165 map
->seglist
[i
].seg_start_bytes
= chunk
->disk_start_sector
* 512ULL;
166 map
->seglist
[i
].seg_end_bytes
= (chunk
->disk_end_sector
+ 1) * 512ULL;
170 static void ventoy_unix_fill_override_data( grub_uint64_t isosize
, ventoy_chain_head
*chain
)
175 grub_uint64_t offset
;
176 grub_uint64_t sector
;
177 ventoy_override_chunk
*cur
;
178 ventoy_iso9660_override
*dirent
;
180 sector
= (isosize
+ 2047) / 2048;
182 cur
= (ventoy_override_chunk
*)((char *)chain
+ chain
->override_chunk_offset
);
184 if (g_conf_new_len
> 0)
187 cur
->img_offset
= g_conf_override_offset
;
188 cur
->override_size
= sizeof(ventoy_iso9660_override
);
189 dirent
= (ventoy_iso9660_override
*)cur
->override_data
;
190 dirent
->first_sector
= (grub_uint32_t
)sector
;
191 dirent
->size
= (grub_uint32_t
)g_conf_new_len
;
192 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
193 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
194 sector
+= (dirent
->size
+ 2047) / 2048;
198 if (g_mod_new_len
> 0)
201 cur
->img_offset
= g_mod_override_offset
;
202 cur
->override_size
= sizeof(ventoy_iso9660_override
);
203 dirent
= (ventoy_iso9660_override
*)cur
->override_data
;
204 dirent
->first_sector
= (grub_uint32_t
)sector
;
205 dirent
->size
= (grub_uint32_t
)g_mod_new_len
;
206 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
207 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
208 sector
+= (dirent
->size
+ 2047) / 2048;
212 if (g_ko_fillmap_len
> 0)
214 data
= g_ko_fillmap_data
;
215 offset
= g_mod_override_offset
;
217 ventoy_unix_fill_map_data(chain
, (struct g_ventoy_map
*)data
);
219 for (i
= 0; i
< g_ko_fillmap_len
/ 512; i
++)
221 cur
->img_offset
= offset
;
222 cur
->override_size
= 512;
223 grub_memcpy(cur
->override_data
, data
, 512);
230 left
= (g_ko_fillmap_len
% 512);
233 cur
->img_offset
= offset
;
234 cur
->override_size
= left
;
235 grub_memcpy(cur
->override_data
, data
, left
);
245 static void ventoy_unix_fill_virt_data( grub_uint64_t isosize
, ventoy_chain_head
*chain
)
247 grub_uint64_t sector
;
248 grub_uint32_t offset
;
249 grub_uint32_t data_secs
;
251 ventoy_virt_chunk
*cur
;
253 override
= (char *)chain
+ chain
->virt_chunk_offset
;
254 cur
= (ventoy_virt_chunk
*)override
;
256 sector
= (isosize
+ 2047) / 2048;
257 offset
= 2 * sizeof(ventoy_virt_chunk
);
259 if (g_conf_new_len
> 0)
261 ventoy_unix_fill_virt(g_conf_new_data
, g_conf_new_len
);
264 if (g_mod_new_len
> 0)
266 if (g_mod_search_magic
> 0)
268 ventoy_unix_fill_map_data(chain
, (struct g_ventoy_map
*)(g_mod_new_data
+ g_mod_search_magic
));
271 ventoy_unix_fill_virt(g_mod_new_data
, g_mod_new_len
);
277 static int ventoy_freebsd_append_conf(char *buf
, const char *isopath
, const char *alias
)
284 const char *val
= NULL
;
285 ventoy_img_chunk
*chunk
;
286 grub_uint8_t disk_sig
[4];
287 grub_uint8_t disk_guid
[16];
289 debug("ventoy_freebsd_append_conf %s\n", isopath
);
291 isofile
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", isopath
);
297 vtoy_ssprintf(buf
, pos
, "ventoy_load=\"%s\"\n", "YES");
298 vtoy_ssprintf(buf
, pos
, "ventoy_name=\"%s\"\n", g_ko_mod_path
);
302 vtoy_ssprintf(buf
, pos
, "hint.ventoy.0.alias=\"%s\"\n", alias
);
305 if (g_unix_vlnk_boot
)
307 vtoy_ssprintf(buf
, pos
, "hint.ventoy.0.vlnk=%d\n", 1);
310 val
= ventoy_get_env("VTOY_UNIX_REMOUNT");
311 if (val
&& val
[0] == '1' && val
[1] == 0)
313 vtoy_ssprintf(buf
, pos
, "hint.ventoy.0.remount=%d\n", 1);
316 if (g_mod_search_magic
)
318 debug("hint.ventoy NO need\n");
322 debug("Fill hint.ventoy info\n");
324 disk
= isofile
->device
->disk
;
326 ventoy_get_disk_guid(isofile
->name
, disk_guid
, disk_sig
);
328 for (i
= 0; i
< 16; i
++)
330 grub_snprintf(uuid
+ i
* 2, sizeof(uuid
), "%02x", disk_guid
[i
]);
333 vtoy_ssprintf(buf
, pos
, "hint.ventoy.0.disksize=%llu\n", (ulonglong
)(disk
->total_sectors
* (1 << disk
->log_sector_size
)));
334 vtoy_ssprintf(buf
, pos
, "hint.ventoy.0.diskuuid=\"%s\"\n", uuid
);
335 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]);
336 vtoy_ssprintf(buf
, pos
, "hint.ventoy.0.segnum=%u\n", g_img_chunk_list
.cur_chunk
);
338 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
340 chunk
= g_img_chunk_list
.chunk
+ i
;
341 vtoy_ssprintf(buf
, pos
, "hint.ventoy.%u.seg=\"0x%llx@0x%llx\"\n",
342 i
, (ulonglong
)(chunk
->disk_start_sector
* 512),
343 (ulonglong
)((chunk
->disk_end_sector
+ 1) * 512));
347 grub_file_close(isofile
);
351 static int ventoy_dragonfly_append_conf(char *buf
, const char *isopath
)
355 debug("ventoy_dragonfly_append_conf %s\n", isopath
);
357 vtoy_ssprintf(buf
, pos
, "tmpfs_load=\"%s\"\n", "YES");
358 vtoy_ssprintf(buf
, pos
, "dm_target_linear_load=\"%s\"\n", "YES");
359 vtoy_ssprintf(buf
, pos
, "initrd.img_load=\"%s\"\n", "YES");
360 vtoy_ssprintf(buf
, pos
, "initrd.img_type=\"%s\"\n", "md_image");
361 vtoy_ssprintf(buf
, pos
, "vfs.root.mountfrom=\"%s\"\n", "ufs:md0s0");
366 grub_err_t
ventoy_cmd_unix_reset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
372 g_unix_vlnk_boot
= 0;
373 g_mod_search_magic
= 0;
376 g_mod_override_offset
= 0;
377 g_conf_override_offset
= 0;
378 g_ko_fillmap_len
= 0;
380 check_free(g_mod_new_data
, grub_free
);
381 check_free(g_conf_new_data
, grub_free
);
382 check_free(g_ko_fillmap_data
, grub_free
);
384 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
387 grub_err_t
ventoy_cmd_unix_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
398 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
401 g_unix_vlnk_boot
= file
->vlnk
;
402 grub_file_close(file
);
405 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
408 grub_err_t
ventoy_cmd_parse_freenas_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
411 const char *ver
= NULL
;
413 VTOY_JSON
*json
= NULL
;
418 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
421 debug("Failed to open file %s\n", args
[0]);
425 buf
= grub_malloc(file
->size
+ 2);
428 grub_file_close(file
);
431 grub_file_read(file
, buf
, file
->size
);
434 json
= vtoy_json_create();
440 if (vtoy_json_parse(json
, buf
))
445 ver
= vtoy_json_get_string_ex(json
->pstChild
, "Version");
448 debug("freenas version:<%s>\n", ver
);
449 ventoy_set_env(args
[1], ver
);
453 debug("freenas version:<%s>\n", "NOT FOUND");
454 grub_env_unset(args
[1]);
458 grub_check_free(buf
);
459 check_free(json
, vtoy_json_destroy
);
460 grub_file_close(file
);
462 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
465 grub_err_t
ventoy_cmd_unix_freebsd_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
470 char *nextline
= NULL
;
476 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
479 debug("Failed to open file %s\n", args
[0]);
483 buf
= grub_zalloc(file
->size
+ 2);
486 grub_file_close(file
);
489 grub_file_read(file
, buf
, file
->size
);
491 for (start
= buf
; start
; start
= nextline
)
493 if (grub_strncmp(start
, "USERLAND_VERSION", 16) == 0)
496 while (*nextline
&& *nextline
!= '\r' && *nextline
!= '\n')
504 nextline
= ventoy_get_line(start
);
509 debug("freebsd version:<%s>\n", start
);
510 ventoy_set_env(args
[1], start
);
514 debug("freebsd version:<%s>\n", "NOT FOUND");
515 grub_env_unset(args
[1]);
519 grub_file_close(file
);
521 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
524 grub_err_t
ventoy_cmd_unix_freebsd_ver_elf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
528 grub_elf_t elf
= NULL
;
529 grub_off_t offset
= 0;
530 grub_uint32_t len
= 0;
542 debug("Invalid argc %d\n", argc
);
546 data
= grub_zalloc(8192);
552 elf
= grub_elf_open(args
[0], GRUB_FILE_TYPE_LINUX_INITRD
);
555 debug("Failed to open file %s\n", args
[0]);
559 if (args
[1][0] == '6')
561 Elf64_Ehdr
*e
= &(elf
->ehdr
.ehdr64
);
567 h
= hdr
= grub_zalloc(e
->e_shnum
* e
->e_shentsize
);
573 debug("read section header %u %u %u\n", e
->e_shnum
, e
->e_shentsize
, e
->e_shstrndx
);
574 grub_file_seek(elf
->file
, e
->e_shoff
);
575 grub_file_read(elf
->file
, h
, e
->e_shnum
* e
->e_shentsize
);
577 s
= (Elf64_Shdr
*)((char *)h
+ e
->e_shstrndx
* e
->e_shentsize
);
578 str
= grub_malloc(s
->sh_size
+ 1);
585 debug("read string table %u %u\n", (grub_uint32_t
)s
->sh_offset
, (grub_uint32_t
)s
->sh_size
);
586 grub_file_seek(elf
->file
, s
->sh_offset
);
587 grub_file_read(elf
->file
, str
, s
->sh_size
);
589 for (t
= h
, i
= 0; i
< e
->e_shnum
; i
++)
591 if (grub_strcmp(str
+ t
->sh_name
, ".data") == 0)
593 offset
= t
->sh_offset
;
595 debug("find .data section at %u %u\n", (grub_uint32_t
)offset
, len
);
598 t
= (Elf64_Shdr
*)((char *)t
+ e
->e_shentsize
);
603 Elf32_Ehdr
*e
= &(elf
->ehdr
.ehdr32
);
609 h
= hdr
= grub_zalloc(e
->e_shnum
* e
->e_shentsize
);
615 debug("read section header %u %u %u\n", e
->e_shnum
, e
->e_shentsize
, e
->e_shstrndx
);
616 grub_file_seek(elf
->file
, e
->e_shoff
);
617 grub_file_read(elf
->file
, h
, e
->e_shnum
* e
->e_shentsize
);
619 s
= (Elf32_Shdr
*)((char *)h
+ e
->e_shstrndx
* e
->e_shentsize
);
620 str
= grub_malloc(s
->sh_size
+ 1);
627 debug("read string table %u %u\n", (grub_uint32_t
)s
->sh_offset
, (grub_uint32_t
)s
->sh_size
);
628 grub_file_seek(elf
->file
, s
->sh_offset
);
629 grub_file_read(elf
->file
, str
, s
->sh_size
);
631 for (t
= h
, i
= 0; i
< e
->e_shnum
; i
++)
633 if (grub_strcmp(str
+ t
->sh_name
, ".data") == 0)
635 offset
= t
->sh_offset
;
637 debug("find .data section at %u %u\n", (grub_uint32_t
)offset
, len
);
640 t
= (Elf32_Shdr
*)((char *)t
+ e
->e_shentsize
);
644 if (offset
== 0 || len
== 0)
646 debug(".data section not found %s\n", args
[0]);
650 grub_file_seek(elf
->file
, offset
+ len
- 8192);
651 grub_file_read(elf
->file
, data
, 8192);
653 for (j
= 0; j
< 8192 - 12; j
++)
655 if (grub_strncmp(data
+ j
, "@(#)FreeBSD ", 12) == 0)
657 for (k
= j
+ 12; k
< 8192; k
++)
659 if (0 == grub_isdigit(data
[k
]) && data
[k
] != '.')
666 grub_snprintf(ver
, sizeof(ver
), "%s", data
+ j
+ 12);
673 k
= (int)grub_strtoul(ver
, NULL
, 10);
674 debug("freebsd version:<%s> <%d.x>\n", ver
, k
);
675 grub_snprintf(ver
, sizeof(ver
), "%d.x", k
);
676 ventoy_set_env(args
[2], ver
);
680 debug("freebsd version:<%s>\n", "NOT FOUND");
684 grub_check_free(str
);
685 grub_check_free(hdr
);
686 grub_check_free(data
);
687 check_free(elf
, grub_elf_close
);
689 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
692 grub_err_t
ventoy_cmd_unix_replace_grub_conf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
698 const char *val
= NULL
;
699 grub_uint64_t offset
;
702 const char *confile
= NULL
;
703 const char * loader_conf
[] =
705 "/boot/grub/grub.cfg",
710 if (argc
!= 1 && argc
!= 2)
712 debug("Replace conf invalid argc %d\n", argc
);
716 for (i
= 0; i
< sizeof(loader_conf
) / sizeof(loader_conf
[0]); i
++)
718 if (ventoy_get_file_override(loader_conf
[i
], &offset
) == 0)
720 confile
= loader_conf
[i
];
721 g_conf_override_offset
= offset
;
728 debug("Can't find grub.cfg file from %u locations\n", i
);
732 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "(loop)/%s", confile
);
735 debug("Failed to open %s \n", confile
);
739 debug("old grub2 conf file size:%d\n", (int)file
->size
);
741 data
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
744 grub_file_close(file
);
748 grub_file_read(file
, data
, file
->size
);
749 grub_file_close(file
);
751 g_conf_new_data
= data
;
752 g_conf_new_len
= (int)file
->size
;
754 pos
= grub_strstr(data
, "kfreebsd /boot/kernel/kernel");
757 pos
+= grub_strlen("kfreebsd /boot/kernel/kernel");
758 if (grub_strncmp(pos
, ".gz", 3) == 0)
765 vtoy_ssprintf(extcfg
, len
, ";kfreebsd_module_elf %s; set kFreeBSD.hint.ventoy.0.alias=\"%s\"", args
[0], args
[1]);
769 vtoy_ssprintf(extcfg
, len
, ";kfreebsd_module_elf %s", args
[0]);
772 if (g_unix_vlnk_boot
)
774 vtoy_ssprintf(extcfg
, len
, ";set kFreeBSD.hint.ventoy.0.vlnk=%d", 1);
777 val
= ventoy_get_env("VTOY_UNIX_REMOUNT");
778 if (val
&& val
[0] == '1' && val
[1] == 0)
780 vtoy_ssprintf(extcfg
, len
, ";set kFreeBSD.hint.ventoy.0.remount=%d", 1);
783 grub_memmove(pos
+ len
, pos
, (int)(file
->size
- (pos
- data
)));
784 grub_memcpy(pos
, extcfg
, len
);
785 g_conf_new_len
+= len
;
789 debug("no kfreebsd found\n");
792 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
795 grub_err_t
ventoy_cmd_unix_replace_conf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
799 grub_uint64_t offset
;
801 const char *confile
= NULL
;
802 const char * loader_conf
[] =
805 "/boot/defaults/loader.conf",
810 if (argc
!= 2 && argc
!= 3)
812 debug("Replace conf invalid argc %d\n", argc
);
816 for (i
= 0; i
< sizeof(loader_conf
) / sizeof(loader_conf
[0]); i
++)
818 if (ventoy_get_file_override(loader_conf
[i
], &offset
) == 0)
820 confile
= loader_conf
[i
];
821 g_conf_override_offset
= offset
;
828 debug("Can't find loader.conf file from %u locations\n", i
);
832 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "(loop)/%s", confile
);
835 debug("Failed to open %s \n", confile
);
839 debug("old conf file <%s> size:%d\n", confile
, (int)file
->size
);
841 data
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
844 grub_file_close(file
);
848 grub_file_read(file
, data
, file
->size
);
849 grub_file_close(file
);
851 g_conf_new_data
= data
;
852 g_conf_new_len
= (int)file
->size
;
854 if (grub_strcmp(args
[0], "FreeBSD") == 0)
856 g_conf_new_len
+= ventoy_freebsd_append_conf(data
+ file
->size
, args
[1], (argc
> 2) ? args
[2] : NULL
);
858 else if (grub_strcmp(args
[0], "DragonFly") == 0)
860 g_conf_new_len
+= ventoy_dragonfly_append_conf(data
+ file
->size
, args
[1]);
863 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
866 static int ventoy_unix_search_magic(char *data
, int len
)
869 grub_uint32_t
*magic
= NULL
;
871 for (i
= 0; i
< len
; i
+= 4096)
873 magic
= (grub_uint32_t
*)(data
+ i
);
874 if (magic
[0] == VENTOY_UNIX_SEG_MAGIC0
&& magic
[1] == VENTOY_UNIX_SEG_MAGIC1
&&
875 magic
[2] == VENTOY_UNIX_SEG_MAGIC2
&& magic
[3] == VENTOY_UNIX_SEG_MAGIC3
)
877 debug("unix find search magic at 0x%x loop:%d\n", i
, (i
>> 12));
878 g_mod_search_magic
= i
;
883 debug("unix can not find search magic\n");
887 grub_err_t
ventoy_cmd_unix_replace_ko(grub_extcmd_context_t ctxt
, int argc
, char **args
)
890 grub_uint64_t offset
;
897 debug("Replace ko invalid argc %d\n", argc
);
901 debug("replace ko %s\n", args
[0]);
903 if (ventoy_get_file_override(args
[0], &offset
) == 0)
905 grub_snprintf(g_ko_mod_path
, sizeof(g_ko_mod_path
), "%s", args
[0]);
906 g_mod_override_offset
= offset
;
910 debug("Can't find replace ko file from %s\n", args
[0]);
914 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[1]);
917 debug("Failed to open %s \n", args
[1]);
921 debug("new ko file size:%d\n", (int)file
->size
);
923 data
= grub_malloc(file
->size
);
926 debug("Failed to alloc memory for new ko %d\n", (int)file
->size
);
927 grub_file_close(file
);
931 grub_file_read(file
, data
, file
->size
);
932 grub_file_close(file
);
934 g_mod_new_data
= data
;
935 g_mod_new_len
= (int)file
->size
;
937 ventoy_unix_search_magic(g_mod_new_data
, g_mod_new_len
);
939 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
942 grub_err_t
ventoy_cmd_unix_ko_fillmap(grub_extcmd_context_t ctxt
, int argc
, char **args
)
946 grub_uint32_t magic
[4];
953 debug("Fillmap ko invalid argc %d\n", argc
);
957 debug("Fillmap ko %s\n", args
[0]);
959 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", args
[0]);
962 grub_file_read(file
, magic
, 4); /* read for trigger */
963 g_mod_override_offset
= grub_iso9660_get_last_read_pos(file
);
967 debug("Can't find replace ko file from %s\n", args
[0]);
971 for (i
= 0; i
< (int)(file
->size
); i
+= 65536)
974 grub_file_seek(file
, i
);
975 grub_file_read(file
, magic
, sizeof(magic
));
977 if (magic
[0] == VENTOY_UNIX_SEG_MAGIC0
&& magic
[1] == VENTOY_UNIX_SEG_MAGIC1
&&
978 magic
[2] == VENTOY_UNIX_SEG_MAGIC2
&& magic
[3] == VENTOY_UNIX_SEG_MAGIC3
)
980 debug("unix find search magic at 0x%x loop:%d\n", i
, (i
>> 16));
981 g_mod_override_offset
+= i
;
986 len
= (grub_uint32_t
)OFFSET_OF(struct g_ventoy_map
, seglist
) +
987 (sizeof(struct g_ventoy_seg
) * g_img_chunk_list
.cur_chunk
);
989 g_ko_fillmap_len
= (int)len
;
990 g_ko_fillmap_data
= grub_malloc(len
);
991 if (!g_ko_fillmap_data
)
993 g_ko_fillmap_len
= 0;
994 debug("Failed to malloc fillmap data\n");
997 debug("Fillmap ko segnum:%u, override len:%u data:%p\n", g_img_chunk_list
.cur_chunk
, len
, g_ko_fillmap_data
);
999 grub_file_close(file
);
1000 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1003 grub_err_t
ventoy_cmd_unix_fill_image_desc(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1007 grub_uint32_t memsize
;
1008 ventoy_image_desc
*desc
;
1009 grub_uint8_t flag
[32] = {
1010 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00,
1011 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
1018 debug("ventoy_cmd_unix_fill_image_desc %p\n", g_mod_new_data
);
1020 if (!g_mod_new_data
)
1025 byte
= (grub_uint8_t
*)g_mod_new_data
;
1026 for (i
= 0; i
< g_mod_new_len
- 32; i
+= 16)
1028 if (byte
[i
] == 0xFF && byte
[i
+ 1] == 0xEE)
1030 if (grub_memcmp(flag
, byte
+ i
, 32) == 0)
1032 debug("Find position flag at %d(0x%x)\n", i
, i
);
1038 if (i
>= g_mod_new_len
- 32)
1040 debug("Failed to find position flag %d\n", i
);
1044 desc
= (ventoy_image_desc
*)(byte
+ i
);
1045 desc
->disk_size
= g_ventoy_disk_size
;
1046 desc
->part1_size
= g_ventoy_disk_part_size
[0];
1047 grub_memcpy(desc
->disk_uuid
, g_ventoy_part_info
->MBR
.BootCode
+ 0x180, 16);
1048 grub_memcpy(desc
->disk_signature
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1B8, 4);
1050 desc
->img_chunk_count
= g_img_chunk_list
.cur_chunk
;
1051 memsize
= g_img_chunk_list
.cur_chunk
* sizeof(ventoy_img_chunk
);
1053 debug("image chunk count:%u memsize:%u\n", desc
->img_chunk_count
, memsize
);
1055 if (memsize
>= VTOY_SIZE_1MB
* 8)
1057 grub_printf("image chunk count:%u memsize:%u too big\n", desc
->img_chunk_count
, memsize
);
1061 grub_memcpy(desc
+ 1, g_img_chunk_list
.chunk
, memsize
);
1064 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1067 grub_err_t
ventoy_cmd_unix_gzip_newko(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1076 debug("ventoy_cmd_unix_gzip_newko %p\n", g_mod_new_data
);
1078 if (!g_mod_new_data
)
1083 buf
= grub_malloc(g_mod_new_len
);
1089 newlen
= ventoy_gzip_compress(g_mod_new_data
, g_mod_new_len
, buf
, g_mod_new_len
);
1091 grub_free(g_mod_new_data
);
1093 debug("gzip org len:%d newlen:%d\n", g_mod_new_len
, newlen
);
1095 g_mod_new_data
= (char *)buf
;
1096 g_mod_new_len
= newlen
;
1099 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1102 grub_err_t
ventoy_cmd_unix_chain_data(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1104 int ventoy_compatible
= 0;
1105 grub_uint32_t size
= 0;
1106 grub_uint64_t isosize
= 0;
1107 grub_uint32_t boot_catlog
= 0;
1108 grub_uint32_t img_chunk_size
= 0;
1109 grub_uint32_t override_count
= 0;
1110 grub_uint32_t override_size
= 0;
1111 grub_uint32_t virt_chunk_size
= 0;
1114 const char *pLastChain
= NULL
;
1115 const char *compatible
;
1116 ventoy_chain_head
*chain
;
1122 compatible
= grub_env_get("ventoy_compatible");
1123 if (compatible
&& compatible
[0] == 'Y')
1125 ventoy_compatible
= 1;
1128 if (NULL
== g_img_chunk_list
.chunk
)
1130 grub_printf("ventoy not ready\n");
1134 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1140 isosize
= file
->size
;
1142 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
1145 if (ventoy_is_efi_os() && (!ventoy_has_efi_eltorito(file
, boot_catlog
)))
1147 grub_env_set("LoadIsoEfiDriver", "on");
1152 if (ventoy_is_efi_os())
1154 grub_env_set("LoadIsoEfiDriver", "on");
1158 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "File %s is not bootable", args
[0]);
1162 img_chunk_size
= g_img_chunk_list
.cur_chunk
* sizeof(ventoy_img_chunk
);
1164 if (ventoy_compatible
)
1166 size
= sizeof(ventoy_chain_head
) + img_chunk_size
;
1170 override_count
= ventoy_unix_get_override_chunk_count();
1171 override_size
= override_count
* sizeof(ventoy_override_chunk
);
1173 virt_chunk_size
= ventoy_unix_get_virt_chunk_size();
1174 size
= sizeof(ventoy_chain_head
) + img_chunk_size
+ override_size
+ virt_chunk_size
;
1177 pLastChain
= grub_env_get("vtoy_chain_mem_addr");
1180 chain
= (ventoy_chain_head
*)grub_strtoul(pLastChain
, NULL
, 16);
1183 debug("free last chain memory %p\n", chain
);
1188 chain
= grub_malloc(size
);
1191 grub_printf("Failed to alloc chain memory size %u\n", size
);
1192 grub_file_close(file
);
1196 grub_snprintf(envbuf
, sizeof(envbuf
), "0x%lx", (unsigned long)chain
);
1197 grub_env_set("vtoy_chain_mem_addr", envbuf
);
1198 grub_snprintf(envbuf
, sizeof(envbuf
), "%u", size
);
1199 grub_env_set("vtoy_chain_mem_size", envbuf
);
1201 grub_memset(chain
, 0, sizeof(ventoy_chain_head
));
1203 /* part 1: os parameter */
1204 g_ventoy_chain_type
= ventoy_chain_linux
;
1205 ventoy_fill_os_param(file
, &(chain
->os_param
));
1207 /* part 2: chain head */
1208 disk
= file
->device
->disk
;
1209 chain
->disk_drive
= disk
->id
;
1210 chain
->disk_sector_size
= (1 << disk
->log_sector_size
);
1211 chain
->real_img_size_in_bytes
= file
->size
;
1212 chain
->virt_img_size_in_bytes
= (file
->size
+ 2047) / 2048 * 2048;
1213 chain
->boot_catalog
= boot_catlog
;
1215 if (!ventoy_is_efi_os())
1217 grub_file_seek(file
, boot_catlog
* 2048);
1218 grub_file_read(file
, chain
->boot_catalog_sector
, sizeof(chain
->boot_catalog_sector
));
1221 /* part 3: image chunk */
1222 chain
->img_chunk_offset
= sizeof(ventoy_chain_head
);
1223 chain
->img_chunk_num
= g_img_chunk_list
.cur_chunk
;
1224 grub_memcpy((char *)chain
+ chain
->img_chunk_offset
, g_img_chunk_list
.chunk
, img_chunk_size
);
1226 if (ventoy_compatible
)
1231 /* part 4: override chunk */
1232 chain
->override_chunk_offset
= chain
->img_chunk_offset
+ img_chunk_size
;
1233 chain
->override_chunk_num
= override_count
;
1234 ventoy_unix_fill_override_data(isosize
, chain
);
1236 /* part 5: virt chunk */
1237 chain
->virt_chunk_offset
= chain
->override_chunk_offset
+ override_size
;
1238 chain
->virt_chunk_num
= ventoy_unix_get_virt_chunk_count();
1239 ventoy_unix_fill_virt_data(isosize
, chain
);
1241 grub_file_close(file
);
1243 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);