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;
52 int g_ko_fillmap_len
= 0;
53 char *g_ko_fillmap_data
= NULL
;
55 grub_uint64_t g_mod_override_offset
= 0;
56 grub_uint64_t g_conf_override_offset
= 0;
58 static int ventoy_get_file_override(const char *filename
, grub_uint64_t
*offset
)
64 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", filename
);
70 *offset
= grub_iso9660_get_last_file_dirent_pos(file
) + 2;
72 grub_file_close(file
);
77 static grub_uint32_t
ventoy_unix_get_override_chunk_count(void)
79 grub_uint32_t count
= 0;
81 if (g_conf_new_len
> 0)
86 if (g_mod_new_len
> 0)
91 if (g_ko_fillmap_len
> 0)
93 count
+= (g_ko_fillmap_len
/ 512);
94 if ((g_ko_fillmap_len
% 512) > 0)
103 static grub_uint32_t
ventoy_unix_get_virt_chunk_count(void)
105 grub_uint32_t count
= 0;
107 if (g_conf_new_len
> 0)
112 if (g_mod_new_len
> 0)
119 static grub_uint32_t
ventoy_unix_get_virt_chunk_size(void)
123 size
= sizeof(ventoy_virt_chunk
) * ventoy_unix_get_virt_chunk_count();
125 if (g_conf_new_len
> 0)
127 size
+= ventoy_align_2k(g_conf_new_len
);
130 if (g_mod_new_len
> 0)
132 size
+= ventoy_align_2k(g_mod_new_len
);
138 static void ventoy_unix_fill_map_data(ventoy_chain_head
*chain
, struct g_ventoy_map
*map
)
141 ventoy_img_chunk
*chunk
= NULL
;
143 debug("Fill unix map data: <%llu> <%u> %p\n",
144 (unsigned long long)chain
->os_param
.vtoy_disk_size
, g_img_chunk_list
.cur_chunk
, map
);
146 map
->magic1
[0] = map
->magic2
[0] = VENTOY_UNIX_SEG_MAGIC0
;
147 map
->magic1
[1] = map
->magic2
[1] = VENTOY_UNIX_SEG_MAGIC1
;
148 map
->magic1
[2] = map
->magic2
[2] = VENTOY_UNIX_SEG_MAGIC2
;
149 map
->magic1
[3] = map
->magic2
[3] = VENTOY_UNIX_SEG_MAGIC3
;
151 map
->disksize
= chain
->os_param
.vtoy_disk_size
;
152 grub_memcpy(map
->diskuuid
, chain
->os_param
.vtoy_disk_guid
, 16);
154 map
->segnum
= g_img_chunk_list
.cur_chunk
;
155 if (g_img_chunk_list
.cur_chunk
> VENTOY_UNIX_MAX_SEGNUM
)
157 debug("####[FAIL] Too many segments for the ISO file %u\n", g_img_chunk_list
.cur_chunk
);
158 map
->segnum
= VENTOY_UNIX_MAX_SEGNUM
;
161 for (i
= 0; i
< (grub_uint32_t
)(map
->segnum
); i
++)
163 chunk
= g_img_chunk_list
.chunk
+ i
;
164 map
->seglist
[i
].seg_start_bytes
= chunk
->disk_start_sector
* 512ULL;
165 map
->seglist
[i
].seg_end_bytes
= (chunk
->disk_end_sector
+ 1) * 512ULL;
169 static void ventoy_unix_fill_override_data( grub_uint64_t isosize
, ventoy_chain_head
*chain
)
174 grub_uint64_t offset
;
175 grub_uint64_t sector
;
176 ventoy_override_chunk
*cur
;
177 ventoy_iso9660_override
*dirent
;
179 sector
= (isosize
+ 2047) / 2048;
181 cur
= (ventoy_override_chunk
*)((char *)chain
+ chain
->override_chunk_offset
);
183 if (g_conf_new_len
> 0)
186 cur
->img_offset
= g_conf_override_offset
;
187 cur
->override_size
= sizeof(ventoy_iso9660_override
);
188 dirent
= (ventoy_iso9660_override
*)cur
->override_data
;
189 dirent
->first_sector
= (grub_uint32_t
)sector
;
190 dirent
->size
= (grub_uint32_t
)g_conf_new_len
;
191 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
192 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
193 sector
+= (dirent
->size
+ 2047) / 2048;
197 if (g_mod_new_len
> 0)
200 cur
->img_offset
= g_mod_override_offset
;
201 cur
->override_size
= sizeof(ventoy_iso9660_override
);
202 dirent
= (ventoy_iso9660_override
*)cur
->override_data
;
203 dirent
->first_sector
= (grub_uint32_t
)sector
;
204 dirent
->size
= (grub_uint32_t
)g_mod_new_len
;
205 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
206 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
207 sector
+= (dirent
->size
+ 2047) / 2048;
211 if (g_ko_fillmap_len
> 0)
213 data
= g_ko_fillmap_data
;
214 offset
= g_mod_override_offset
;
216 ventoy_unix_fill_map_data(chain
, (struct g_ventoy_map
*)data
);
218 for (i
= 0; i
< g_ko_fillmap_len
/ 512; i
++)
220 cur
->img_offset
= offset
;
221 cur
->override_size
= 512;
222 grub_memcpy(cur
->override_data
, data
, 512);
229 left
= (g_ko_fillmap_len
% 512);
232 cur
->img_offset
= offset
;
233 cur
->override_size
= left
;
234 grub_memcpy(cur
->override_data
, data
, left
);
244 static void ventoy_unix_fill_virt_data( grub_uint64_t isosize
, ventoy_chain_head
*chain
)
246 grub_uint64_t sector
;
247 grub_uint32_t offset
;
248 grub_uint32_t data_secs
;
250 ventoy_virt_chunk
*cur
;
252 override
= (char *)chain
+ chain
->virt_chunk_offset
;
253 cur
= (ventoy_virt_chunk
*)override
;
255 sector
= (isosize
+ 2047) / 2048;
256 offset
= 2 * sizeof(ventoy_virt_chunk
);
258 if (g_conf_new_len
> 0)
260 ventoy_unix_fill_virt(g_conf_new_data
, g_conf_new_len
);
263 if (g_mod_new_len
> 0)
265 if (g_mod_search_magic
> 0)
267 ventoy_unix_fill_map_data(chain
, (struct g_ventoy_map
*)(g_mod_new_data
+ g_mod_search_magic
));
270 ventoy_unix_fill_virt(g_mod_new_data
, g_mod_new_len
);
276 static int ventoy_freebsd_append_conf(char *buf
, const char *isopath
, const char *alias
)
283 ventoy_img_chunk
*chunk
;
284 grub_uint8_t disk_sig
[4];
285 grub_uint8_t disk_guid
[16];
287 debug("ventoy_freebsd_append_conf %s\n", isopath
);
289 isofile
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", isopath
);
295 vtoy_ssprintf(buf
, pos
, "ventoy_load=\"%s\"\n", "YES");
296 vtoy_ssprintf(buf
, pos
, "ventoy_name=\"%s\"\n", g_ko_mod_path
);
299 vtoy_ssprintf(buf
, pos
, "hint.ventoy.0.alias=\"%s\"\n", alias
);
302 if (g_mod_search_magic
)
304 debug("hint.ventoy NO need\n");
308 disk
= isofile
->device
->disk
;
310 ventoy_get_disk_guid(isofile
->name
, disk_guid
, disk_sig
);
312 for (i
= 0; i
< 16; i
++)
314 grub_snprintf(uuid
+ i
* 2, sizeof(uuid
), "%02x", disk_guid
[i
]);
317 vtoy_ssprintf(buf
, pos
, "hint.ventoy.0.disksize=%llu\n", (ulonglong
)(disk
->total_sectors
* (1 << disk
->log_sector_size
)));
318 vtoy_ssprintf(buf
, pos
, "hint.ventoy.0.diskuuid=\"%s\"\n", uuid
);
319 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]);
320 vtoy_ssprintf(buf
, pos
, "hint.ventoy.0.segnum=%u\n", g_img_chunk_list
.cur_chunk
);
322 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
324 chunk
= g_img_chunk_list
.chunk
+ i
;
325 vtoy_ssprintf(buf
, pos
, "hint.ventoy.%u.seg=\"0x%llx@0x%llx\"\n",
326 i
, (ulonglong
)(chunk
->disk_start_sector
* 512),
327 (ulonglong
)((chunk
->disk_end_sector
+ 1) * 512));
331 grub_file_close(isofile
);
335 static int ventoy_dragonfly_append_conf(char *buf
, const char *isopath
)
339 debug("ventoy_dragonfly_append_conf %s\n", isopath
);
341 vtoy_ssprintf(buf
, pos
, "tmpfs_load=\"%s\"\n", "YES");
342 vtoy_ssprintf(buf
, pos
, "dm_target_linear_load=\"%s\"\n", "YES");
343 vtoy_ssprintf(buf
, pos
, "initrd.img_load=\"%s\"\n", "YES");
344 vtoy_ssprintf(buf
, pos
, "initrd.img_type=\"%s\"\n", "md_image");
345 vtoy_ssprintf(buf
, pos
, "vfs.root.mountfrom=\"%s\"\n", "ufs:md0s0");
350 grub_err_t
ventoy_cmd_unix_reset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
356 g_mod_search_magic
= 0;
359 g_mod_override_offset
= 0;
360 g_conf_override_offset
= 0;
361 g_ko_fillmap_len
= 0;
363 check_free(g_mod_new_data
, grub_free
);
364 check_free(g_conf_new_data
, grub_free
);
365 check_free(g_ko_fillmap_data
, grub_free
);
367 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
370 grub_err_t
ventoy_cmd_parse_freenas_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
373 const char *ver
= NULL
;
375 VTOY_JSON
*json
= NULL
;
380 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
383 debug("Failed to open file %s\n", args
[0]);
387 buf
= grub_malloc(file
->size
+ 2);
390 grub_file_close(file
);
393 grub_file_read(file
, buf
, file
->size
);
396 json
= vtoy_json_create();
402 if (vtoy_json_parse(json
, buf
))
407 ver
= vtoy_json_get_string_ex(json
->pstChild
, "Version");
410 debug("freenas version:<%s>\n", ver
);
411 ventoy_set_env(args
[1], ver
);
415 debug("freenas version:<%s>\n", "NOT FOUND");
416 grub_env_unset(args
[1]);
420 grub_check_free(buf
);
421 check_free(json
, vtoy_json_destroy
);
422 grub_file_close(file
);
424 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
427 grub_err_t
ventoy_cmd_unix_freebsd_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
432 char *nextline
= NULL
;
438 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
441 debug("Failed to open file %s\n", args
[0]);
445 buf
= grub_zalloc(file
->size
+ 2);
448 grub_file_close(file
);
451 grub_file_read(file
, buf
, file
->size
);
453 for (start
= buf
; start
; start
= nextline
)
455 if (grub_strncmp(start
, "USERLAND_VERSION", 16) == 0)
458 while (*nextline
&& *nextline
!= '\r' && *nextline
!= '\n')
466 nextline
= ventoy_get_line(start
);
471 debug("freebsd version:<%s>\n", start
);
472 ventoy_set_env(args
[1], start
);
476 debug("freebsd version:<%s>\n", "NOT FOUND");
477 grub_env_unset(args
[1]);
481 grub_file_close(file
);
483 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
486 grub_err_t
ventoy_cmd_unix_freebsd_ver_elf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
490 grub_elf_t elf
= NULL
;
491 grub_off_t offset
= 0;
492 grub_uint32_t len
= 0;
504 debug("Invalid argc %d\n", argc
);
508 data
= grub_zalloc(8192);
514 elf
= grub_elf_open(args
[0], GRUB_FILE_TYPE_LINUX_INITRD
);
517 debug("Failed to open file %s\n", args
[0]);
521 if (args
[1][0] == '6')
523 Elf64_Ehdr
*e
= &(elf
->ehdr
.ehdr64
);
529 h
= hdr
= grub_zalloc(e
->e_shnum
* e
->e_shentsize
);
535 debug("read section header %u %u %u\n", e
->e_shnum
, e
->e_shentsize
, e
->e_shstrndx
);
536 grub_file_seek(elf
->file
, e
->e_shoff
);
537 grub_file_read(elf
->file
, h
, e
->e_shnum
* e
->e_shentsize
);
539 s
= (Elf64_Shdr
*)((char *)h
+ e
->e_shstrndx
* e
->e_shentsize
);
540 str
= grub_malloc(s
->sh_size
+ 1);
547 debug("read string table %u %u\n", (grub_uint32_t
)s
->sh_offset
, (grub_uint32_t
)s
->sh_size
);
548 grub_file_seek(elf
->file
, s
->sh_offset
);
549 grub_file_read(elf
->file
, str
, s
->sh_size
);
551 for (t
= h
, i
= 0; i
< e
->e_shnum
; i
++)
553 if (grub_strcmp(str
+ t
->sh_name
, ".data") == 0)
555 offset
= t
->sh_offset
;
557 debug("find .data section at %u %u\n", (grub_uint32_t
)offset
, len
);
560 t
= (Elf64_Shdr
*)((char *)t
+ e
->e_shentsize
);
565 Elf32_Ehdr
*e
= &(elf
->ehdr
.ehdr32
);
571 h
= hdr
= grub_zalloc(e
->e_shnum
* e
->e_shentsize
);
577 debug("read section header %u %u %u\n", e
->e_shnum
, e
->e_shentsize
, e
->e_shstrndx
);
578 grub_file_seek(elf
->file
, e
->e_shoff
);
579 grub_file_read(elf
->file
, h
, e
->e_shnum
* e
->e_shentsize
);
581 s
= (Elf32_Shdr
*)((char *)h
+ e
->e_shstrndx
* e
->e_shentsize
);
582 str
= grub_malloc(s
->sh_size
+ 1);
589 debug("read string table %u %u\n", (grub_uint32_t
)s
->sh_offset
, (grub_uint32_t
)s
->sh_size
);
590 grub_file_seek(elf
->file
, s
->sh_offset
);
591 grub_file_read(elf
->file
, str
, s
->sh_size
);
593 for (t
= h
, i
= 0; i
< e
->e_shnum
; i
++)
595 if (grub_strcmp(str
+ t
->sh_name
, ".data") == 0)
597 offset
= t
->sh_offset
;
599 debug("find .data section at %u %u\n", (grub_uint32_t
)offset
, len
);
602 t
= (Elf32_Shdr
*)((char *)t
+ e
->e_shentsize
);
606 if (offset
== 0 || len
== 0)
608 debug(".data section not found %s\n", args
[0]);
612 grub_file_seek(elf
->file
, offset
+ len
- 8192);
613 grub_file_read(elf
->file
, data
, 8192);
615 for (j
= 0; j
< 8192 - 12; j
++)
617 if (grub_strncmp(data
+ j
, "@(#)FreeBSD ", 12) == 0)
619 for (k
= j
+ 12; k
< 8192; k
++)
621 if (0 == grub_isdigit(data
[k
]) && data
[k
] != '.')
628 grub_snprintf(ver
, sizeof(ver
), "%s", data
+ j
+ 12);
635 k
= (int)grub_strtoul(ver
, NULL
, 10);
636 debug("freebsd version:<%s> <%d.x>\n", ver
, k
);
637 grub_snprintf(ver
, sizeof(ver
), "%d.x", k
);
638 ventoy_set_env(args
[2], ver
);
642 debug("freebsd version:<%s>\n", "NOT FOUND");
646 grub_check_free(str
);
647 grub_check_free(hdr
);
648 grub_check_free(data
);
649 check_free(elf
, grub_elf_close
);
651 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
654 grub_err_t
ventoy_cmd_unix_replace_grub_conf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
660 grub_uint64_t offset
;
663 const char *confile
= NULL
;
664 const char * loader_conf
[] =
666 "/boot/grub/grub.cfg",
671 if (argc
!= 1 && argc
!= 2)
673 debug("Replace conf invalid argc %d\n", argc
);
677 for (i
= 0; i
< sizeof(loader_conf
) / sizeof(loader_conf
[0]); i
++)
679 if (ventoy_get_file_override(loader_conf
[i
], &offset
) == 0)
681 confile
= loader_conf
[i
];
682 g_conf_override_offset
= offset
;
689 debug("Can't find grub.cfg file from %u locations\n", i
);
693 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "(loop)/%s", confile
);
696 debug("Failed to open %s \n", confile
);
700 debug("old grub2 conf file size:%d\n", (int)file
->size
);
702 data
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
705 grub_file_close(file
);
709 grub_file_read(file
, data
, file
->size
);
710 grub_file_close(file
);
712 g_conf_new_data
= data
;
713 g_conf_new_len
= (int)file
->size
;
715 pos
= grub_strstr(data
, "kfreebsd /boot/kernel/kernel");
718 pos
+= grub_strlen("kfreebsd /boot/kernel/kernel");
722 len
= grub_snprintf(extcfg
, sizeof(extcfg
),
723 ";kfreebsd_module_elf %s; set kFreeBSD.hint.ventoy.0.alias=\"%s\"",
728 len
= grub_snprintf(extcfg
, sizeof(extcfg
), ";kfreebsd_module_elf %s", args
[0]);
731 grub_memmove(pos
+ len
, pos
, (int)(file
->size
- (pos
- data
)));
732 grub_memcpy(pos
, extcfg
, len
);
733 g_conf_new_len
+= len
;
737 debug("no kfreebsd found\n");
740 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
743 grub_err_t
ventoy_cmd_unix_replace_conf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
747 grub_uint64_t offset
;
749 const char *confile
= NULL
;
750 const char * loader_conf
[] =
753 "/boot/defaults/loader.conf",
758 if (argc
!= 2 && argc
!= 3)
760 debug("Replace conf invalid argc %d\n", argc
);
764 for (i
= 0; i
< sizeof(loader_conf
) / sizeof(loader_conf
[0]); i
++)
766 if (ventoy_get_file_override(loader_conf
[i
], &offset
) == 0)
768 confile
= loader_conf
[i
];
769 g_conf_override_offset
= offset
;
776 debug("Can't find loader.conf file from %u locations\n", i
);
780 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "(loop)/%s", confile
);
783 debug("Failed to open %s \n", confile
);
787 debug("old conf file size:%d\n", (int)file
->size
);
789 data
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
792 grub_file_close(file
);
796 grub_file_read(file
, data
, file
->size
);
797 grub_file_close(file
);
799 g_conf_new_data
= data
;
800 g_conf_new_len
= (int)file
->size
;
802 if (grub_strcmp(args
[0], "FreeBSD") == 0)
804 g_conf_new_len
+= ventoy_freebsd_append_conf(data
+ file
->size
, args
[1], (argc
> 2) ? args
[2] : NULL
);
806 else if (grub_strcmp(args
[0], "DragonFly") == 0)
808 g_conf_new_len
+= ventoy_dragonfly_append_conf(data
+ file
->size
, args
[1]);
811 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
814 static int ventoy_unix_search_magic(char *data
, int len
)
817 grub_uint32_t
*magic
= NULL
;
819 for (i
= 0; i
< len
; i
+= 65536)
821 magic
= (grub_uint32_t
*)(data
+ i
);
822 if (magic
[0] == VENTOY_UNIX_SEG_MAGIC0
&& magic
[1] == VENTOY_UNIX_SEG_MAGIC1
&&
823 magic
[2] == VENTOY_UNIX_SEG_MAGIC2
&& magic
[3] == VENTOY_UNIX_SEG_MAGIC3
)
825 debug("unix find search magic at 0x%x loop:%d\n", i
, (i
>> 16));
826 g_mod_search_magic
= i
;
831 debug("unix can not find search magic\n");
835 grub_err_t
ventoy_cmd_unix_replace_ko(grub_extcmd_context_t ctxt
, int argc
, char **args
)
838 grub_uint64_t offset
;
845 debug("Replace ko invalid argc %d\n", argc
);
849 debug("replace ko %s\n", args
[0]);
851 if (ventoy_get_file_override(args
[0], &offset
) == 0)
853 grub_snprintf(g_ko_mod_path
, sizeof(g_ko_mod_path
), "%s", args
[0]);
854 g_mod_override_offset
= offset
;
858 debug("Can't find replace ko file from %s\n", args
[0]);
862 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[1]);
865 debug("Failed to open %s \n", args
[1]);
869 debug("new ko file size:%d\n", (int)file
->size
);
871 data
= grub_malloc(file
->size
);
874 debug("Failed to alloc memory for new ko %d\n", (int)file
->size
);
875 grub_file_close(file
);
879 grub_file_read(file
, data
, file
->size
);
880 grub_file_close(file
);
882 g_mod_new_data
= data
;
883 g_mod_new_len
= (int)file
->size
;
885 ventoy_unix_search_magic(g_mod_new_data
, g_mod_new_len
);
887 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
890 grub_err_t
ventoy_cmd_unix_ko_fillmap(grub_extcmd_context_t ctxt
, int argc
, char **args
)
894 grub_uint32_t magic
[4];
901 debug("Fillmap ko invalid argc %d\n", argc
);
905 debug("Fillmap ko %s\n", args
[0]);
907 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", args
[0]);
910 grub_file_read(file
, magic
, 4); /* read for trigger */
911 g_mod_override_offset
= grub_iso9660_get_last_read_pos(file
);
915 debug("Can't find replace ko file from %s\n", args
[0]);
919 for (i
= 0; i
< (int)(file
->size
); i
+= 65536)
922 grub_file_seek(file
, i
);
923 grub_file_read(file
, magic
, sizeof(magic
));
925 if (magic
[0] == VENTOY_UNIX_SEG_MAGIC0
&& magic
[1] == VENTOY_UNIX_SEG_MAGIC1
&&
926 magic
[2] == VENTOY_UNIX_SEG_MAGIC2
&& magic
[3] == VENTOY_UNIX_SEG_MAGIC3
)
928 debug("unix find search magic at 0x%x loop:%d\n", i
, (i
>> 16));
929 g_mod_override_offset
+= i
;
934 len
= (grub_uint32_t
)OFFSET_OF(struct g_ventoy_map
, seglist
) +
935 (sizeof(struct g_ventoy_seg
) * g_img_chunk_list
.cur_chunk
);
937 g_ko_fillmap_len
= (int)len
;
938 g_ko_fillmap_data
= grub_malloc(len
);
939 if (!g_ko_fillmap_data
)
941 g_ko_fillmap_len
= 0;
942 debug("Failed to malloc fillmap data\n");
945 debug("Fillmap ko segnum:%u, override len:%u data:%p\n", g_img_chunk_list
.cur_chunk
, len
, g_ko_fillmap_data
);
947 grub_file_close(file
);
948 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
951 grub_err_t
ventoy_cmd_unix_fill_image_desc(grub_extcmd_context_t ctxt
, int argc
, char **args
)
955 grub_uint32_t memsize
;
956 ventoy_image_desc
*desc
;
957 grub_uint8_t flag
[32] = {
958 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00,
959 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
966 debug("ventoy_cmd_unix_fill_image_desc %p\n", g_mod_new_data
);
973 byte
= (grub_uint8_t
*)g_mod_new_data
;
974 for (i
= 0; i
< g_mod_new_len
- 32; i
+= 16)
976 if (byte
[i
] == 0xFF && byte
[i
+ 1] == 0xEE)
978 if (grub_memcmp(flag
, byte
+ i
, 32) == 0)
980 debug("Find position flag at %d(0x%x)\n", i
, i
);
986 if (i
>= g_mod_new_len
- 32)
988 debug("Failed to find position flag %d\n", i
);
992 desc
= (ventoy_image_desc
*)(byte
+ i
);
993 desc
->disk_size
= g_ventoy_disk_size
;
994 desc
->part1_size
= g_ventoy_disk_part_size
[0];
995 grub_memcpy(desc
->disk_uuid
, g_ventoy_part_info
->MBR
.BootCode
+ 0x180, 16);
996 grub_memcpy(desc
->disk_signature
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1B8, 4);
998 desc
->img_chunk_count
= g_img_chunk_list
.cur_chunk
;
999 memsize
= g_img_chunk_list
.cur_chunk
* sizeof(ventoy_img_chunk
);
1001 debug("image chunk count:%u memsize:%u\n", desc
->img_chunk_count
, memsize
);
1003 if (memsize
>= VTOY_SIZE_1MB
* 8)
1005 grub_printf("image chunk count:%u memsize:%u too big\n", desc
->img_chunk_count
, memsize
);
1009 grub_memcpy(desc
+ 1, g_img_chunk_list
.chunk
, memsize
);
1012 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1015 grub_err_t
ventoy_cmd_unix_gzip_newko(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1024 debug("ventoy_cmd_unix_gzip_newko %p\n", g_mod_new_data
);
1026 if (!g_mod_new_data
)
1031 buf
= grub_malloc(g_mod_new_len
);
1037 newlen
= ventoy_gzip_compress(g_mod_new_data
, g_mod_new_len
, buf
, g_mod_new_len
);
1039 grub_free(g_mod_new_data
);
1041 debug("gzip org len:%d newlen:%d\n", g_mod_new_len
, newlen
);
1043 g_mod_new_data
= (char *)buf
;
1044 g_mod_new_len
= newlen
;
1047 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1050 grub_err_t
ventoy_cmd_unix_chain_data(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1052 int ventoy_compatible
= 0;
1053 grub_uint32_t size
= 0;
1054 grub_uint64_t isosize
= 0;
1055 grub_uint32_t boot_catlog
= 0;
1056 grub_uint32_t img_chunk_size
= 0;
1057 grub_uint32_t override_count
= 0;
1058 grub_uint32_t override_size
= 0;
1059 grub_uint32_t virt_chunk_size
= 0;
1062 const char *pLastChain
= NULL
;
1063 const char *compatible
;
1064 ventoy_chain_head
*chain
;
1070 compatible
= grub_env_get("ventoy_compatible");
1071 if (compatible
&& compatible
[0] == 'Y')
1073 ventoy_compatible
= 1;
1076 if (NULL
== g_img_chunk_list
.chunk
)
1078 grub_printf("ventoy not ready\n");
1082 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1088 isosize
= file
->size
;
1090 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
1093 if (ventoy_is_efi_os() && (!ventoy_has_efi_eltorito(file
, boot_catlog
)))
1095 grub_env_set("LoadIsoEfiDriver", "on");
1100 if (ventoy_is_efi_os())
1102 grub_env_set("LoadIsoEfiDriver", "on");
1106 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "File %s is not bootable", args
[0]);
1110 img_chunk_size
= g_img_chunk_list
.cur_chunk
* sizeof(ventoy_img_chunk
);
1112 if (ventoy_compatible
)
1114 size
= sizeof(ventoy_chain_head
) + img_chunk_size
;
1118 override_count
= ventoy_unix_get_override_chunk_count();
1119 override_size
= override_count
* sizeof(ventoy_override_chunk
);
1121 virt_chunk_size
= ventoy_unix_get_virt_chunk_size();
1122 size
= sizeof(ventoy_chain_head
) + img_chunk_size
+ override_size
+ virt_chunk_size
;
1125 pLastChain
= grub_env_get("vtoy_chain_mem_addr");
1128 chain
= (ventoy_chain_head
*)grub_strtoul(pLastChain
, NULL
, 16);
1131 debug("free last chain memory %p\n", chain
);
1136 chain
= grub_malloc(size
);
1139 grub_printf("Failed to alloc chain memory size %u\n", size
);
1140 grub_file_close(file
);
1144 grub_snprintf(envbuf
, sizeof(envbuf
), "0x%lx", (unsigned long)chain
);
1145 grub_env_set("vtoy_chain_mem_addr", envbuf
);
1146 grub_snprintf(envbuf
, sizeof(envbuf
), "%u", size
);
1147 grub_env_set("vtoy_chain_mem_size", envbuf
);
1149 grub_memset(chain
, 0, sizeof(ventoy_chain_head
));
1151 /* part 1: os parameter */
1152 g_ventoy_chain_type
= ventoy_chain_linux
;
1153 ventoy_fill_os_param(file
, &(chain
->os_param
));
1155 /* part 2: chain head */
1156 disk
= file
->device
->disk
;
1157 chain
->disk_drive
= disk
->id
;
1158 chain
->disk_sector_size
= (1 << disk
->log_sector_size
);
1159 chain
->real_img_size_in_bytes
= file
->size
;
1160 chain
->virt_img_size_in_bytes
= (file
->size
+ 2047) / 2048 * 2048;
1161 chain
->boot_catalog
= boot_catlog
;
1163 if (!ventoy_is_efi_os())
1165 grub_file_seek(file
, boot_catlog
* 2048);
1166 grub_file_read(file
, chain
->boot_catalog_sector
, sizeof(chain
->boot_catalog_sector
));
1169 /* part 3: image chunk */
1170 chain
->img_chunk_offset
= sizeof(ventoy_chain_head
);
1171 chain
->img_chunk_num
= g_img_chunk_list
.cur_chunk
;
1172 grub_memcpy((char *)chain
+ chain
->img_chunk_offset
, g_img_chunk_list
.chunk
, img_chunk_size
);
1174 if (ventoy_compatible
)
1179 /* part 4: override chunk */
1180 chain
->override_chunk_offset
= chain
->img_chunk_offset
+ img_chunk_size
;
1181 chain
->override_chunk_num
= override_count
;
1182 ventoy_unix_fill_override_data(isosize
, chain
);
1184 /* part 5: virt chunk */
1185 chain
->virt_chunk_offset
= chain
->override_chunk_offset
+ override_size
;
1186 chain
->virt_chunk_num
= ventoy_unix_get_virt_chunk_count();
1187 ventoy_unix_fill_virt_data(isosize
, chain
);
1189 grub_file_close(file
);
1191 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);