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
)
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
);
298 if (g_mod_search_magic
)
300 debug("hint.ventoy NO need\n");
304 disk
= isofile
->device
->disk
;
306 ventoy_get_disk_guid(isofile
->name
, disk_guid
, disk_sig
);
308 for (i
= 0; i
< 16; i
++)
310 grub_snprintf(uuid
+ i
* 2, sizeof(uuid
), "%02x", disk_guid
[i
]);
313 vtoy_ssprintf(buf
, pos
, "hint.ventoy.0.disksize=%llu\n", (ulonglong
)(disk
->total_sectors
* (1 << disk
->log_sector_size
)));
314 vtoy_ssprintf(buf
, pos
, "hint.ventoy.0.diskuuid=\"%s\"\n", uuid
);
315 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]);
316 vtoy_ssprintf(buf
, pos
, "hint.ventoy.0.segnum=%u\n", g_img_chunk_list
.cur_chunk
);
318 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
320 chunk
= g_img_chunk_list
.chunk
+ i
;
321 vtoy_ssprintf(buf
, pos
, "hint.ventoy.%u.seg=\"0x%llx@0x%llx\"\n",
322 i
, (ulonglong
)(chunk
->disk_start_sector
* 512),
323 (ulonglong
)((chunk
->disk_end_sector
+ 1) * 512));
327 grub_file_close(isofile
);
331 static int ventoy_dragonfly_append_conf(char *buf
, const char *isopath
)
335 debug("ventoy_dragonfly_append_conf %s\n", isopath
);
337 vtoy_ssprintf(buf
, pos
, "tmpfs_load=\"%s\"\n", "YES");
338 vtoy_ssprintf(buf
, pos
, "dm_target_linear_load=\"%s\"\n", "YES");
339 vtoy_ssprintf(buf
, pos
, "initrd.img_load=\"%s\"\n", "YES");
340 vtoy_ssprintf(buf
, pos
, "initrd.img_type=\"%s\"\n", "md_image");
341 vtoy_ssprintf(buf
, pos
, "vfs.root.mountfrom=\"%s\"\n", "ufs:md0s0");
346 grub_err_t
ventoy_cmd_unix_reset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
352 g_mod_search_magic
= 0;
355 g_mod_override_offset
= 0;
356 g_conf_override_offset
= 0;
357 g_ko_fillmap_len
= 0;
359 check_free(g_mod_new_data
, grub_free
);
360 check_free(g_conf_new_data
, grub_free
);
361 check_free(g_ko_fillmap_data
, grub_free
);
363 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
366 grub_err_t
ventoy_cmd_parse_freenas_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
369 const char *ver
= NULL
;
371 VTOY_JSON
*json
= NULL
;
376 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
379 debug("Failed to open file %s\n", args
[0]);
383 buf
= grub_malloc(file
->size
+ 2);
386 grub_file_close(file
);
389 grub_file_read(file
, buf
, file
->size
);
392 json
= vtoy_json_create();
398 if (vtoy_json_parse(json
, buf
))
403 ver
= vtoy_json_get_string_ex(json
->pstChild
, "Version");
406 debug("freenas version:<%s>\n", ver
);
407 ventoy_set_env(args
[1], ver
);
411 debug("freenas version:<%s>\n", "NOT FOUND");
412 grub_env_unset(args
[1]);
416 grub_check_free(buf
);
417 check_free(json
, vtoy_json_destroy
);
418 grub_file_close(file
);
420 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
423 grub_err_t
ventoy_cmd_unix_freebsd_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
428 char *nextline
= NULL
;
434 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
437 debug("Failed to open file %s\n", args
[0]);
441 buf
= grub_zalloc(file
->size
+ 2);
444 grub_file_close(file
);
447 grub_file_read(file
, buf
, file
->size
);
449 for (start
= buf
; start
; start
= nextline
)
451 if (grub_strncmp(start
, "USERLAND_VERSION", 16) == 0)
454 while (*nextline
&& *nextline
!= '\r' && *nextline
!= '\n')
462 nextline
= ventoy_get_line(start
);
467 debug("freebsd version:<%s>\n", start
);
468 ventoy_set_env(args
[1], start
);
472 debug("freebsd version:<%s>\n", "NOT FOUND");
473 grub_env_unset(args
[1]);
477 grub_file_close(file
);
479 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
482 grub_err_t
ventoy_cmd_unix_freebsd_ver_elf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
486 grub_elf_t elf
= NULL
;
487 grub_off_t offset
= 0;
488 grub_uint32_t len
= 0;
500 debug("Invalid argc %d\n", argc
);
504 data
= grub_zalloc(8192);
510 elf
= grub_elf_open(args
[0], GRUB_FILE_TYPE_LINUX_INITRD
);
513 debug("Failed to open file %s\n", args
[0]);
517 if (args
[1][0] == '6')
519 Elf64_Ehdr
*e
= &(elf
->ehdr
.ehdr64
);
525 h
= hdr
= grub_zalloc(e
->e_shnum
* e
->e_shentsize
);
531 debug("read section header %u %u %u\n", e
->e_shnum
, e
->e_shentsize
, e
->e_shstrndx
);
532 grub_file_seek(elf
->file
, e
->e_shoff
);
533 grub_file_read(elf
->file
, h
, e
->e_shnum
* e
->e_shentsize
);
535 s
= (Elf64_Shdr
*)((char *)h
+ e
->e_shstrndx
* e
->e_shentsize
);
536 str
= grub_malloc(s
->sh_size
+ 1);
543 debug("read string table %u %u\n", (grub_uint32_t
)s
->sh_offset
, (grub_uint32_t
)s
->sh_size
);
544 grub_file_seek(elf
->file
, s
->sh_offset
);
545 grub_file_read(elf
->file
, str
, s
->sh_size
);
547 for (t
= h
, i
= 0; i
< e
->e_shnum
; i
++)
549 if (grub_strcmp(str
+ t
->sh_name
, ".data") == 0)
551 offset
= t
->sh_offset
;
553 debug("find .data section at %u %u\n", (grub_uint32_t
)offset
, len
);
556 t
= (Elf64_Shdr
*)((char *)t
+ e
->e_shentsize
);
561 Elf32_Ehdr
*e
= &(elf
->ehdr
.ehdr32
);
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
= (Elf32_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
= (Elf32_Shdr
*)((char *)t
+ e
->e_shentsize
);
602 if (offset
== 0 || len
== 0)
604 debug(".data section not found %s\n", args
[0]);
608 grub_file_seek(elf
->file
, offset
+ len
- 8192);
609 grub_file_read(elf
->file
, data
, 8192);
611 for (j
= 0; j
< 8192 - 12; j
++)
613 if (grub_strncmp(data
+ j
, "@(#)FreeBSD ", 12) == 0)
615 for (k
= j
+ 12; k
< 8192; k
++)
617 if (0 == grub_isdigit(data
[k
]) && data
[k
] != '.')
624 grub_snprintf(ver
, sizeof(ver
), "%s", data
+ j
+ 12);
631 k
= (int)grub_strtoul(ver
, NULL
, 10);
632 debug("freebsd version:<%s> <%d.x>\n", ver
, k
);
633 grub_snprintf(ver
, sizeof(ver
), "%d.x", k
);
634 ventoy_set_env(args
[2], ver
);
638 debug("freebsd version:<%s>\n", "NOT FOUND");
642 grub_check_free(str
);
643 grub_check_free(hdr
);
644 grub_check_free(data
);
645 check_free(elf
, grub_elf_close
);
647 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
650 grub_err_t
ventoy_cmd_unix_replace_conf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
654 grub_uint64_t offset
;
656 const char *confile
= NULL
;
657 const char * loader_conf
[] =
660 "/boot/defaults/loader.conf",
667 debug("Replace conf invalid argc %d\n", argc
);
671 for (i
= 0; i
< sizeof(loader_conf
) / sizeof(loader_conf
[0]); i
++)
673 if (ventoy_get_file_override(loader_conf
[i
], &offset
) == 0)
675 confile
= loader_conf
[i
];
676 g_conf_override_offset
= offset
;
683 debug("Can't find loader.conf file from %u locations\n", i
);
687 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "(loop)/%s", confile
);
690 debug("Failed to open %s \n", confile
);
694 debug("old conf file size:%d\n", (int)file
->size
);
696 data
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
699 grub_file_close(file
);
703 grub_file_read(file
, data
, file
->size
);
704 grub_file_close(file
);
706 g_conf_new_data
= data
;
707 g_conf_new_len
= (int)file
->size
;
709 if (grub_strcmp(args
[0], "FreeBSD") == 0)
711 g_conf_new_len
+= ventoy_freebsd_append_conf(data
+ file
->size
, args
[1]);
713 else if (grub_strcmp(args
[0], "DragonFly") == 0)
715 g_conf_new_len
+= ventoy_dragonfly_append_conf(data
+ file
->size
, args
[1]);
718 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
721 static int ventoy_unix_search_magic(char *data
, int len
)
724 grub_uint32_t
*magic
= NULL
;
726 for (i
= 0; i
< len
; i
+= 65536)
728 magic
= (grub_uint32_t
*)(data
+ i
);
729 if (magic
[0] == VENTOY_UNIX_SEG_MAGIC0
&& magic
[1] == VENTOY_UNIX_SEG_MAGIC1
&&
730 magic
[2] == VENTOY_UNIX_SEG_MAGIC2
&& magic
[3] == VENTOY_UNIX_SEG_MAGIC3
)
732 debug("unix find search magic at 0x%x loop:%d\n", i
, (i
>> 16));
733 g_mod_search_magic
= i
;
738 debug("unix can not find search magic\n");
742 grub_err_t
ventoy_cmd_unix_replace_ko(grub_extcmd_context_t ctxt
, int argc
, char **args
)
745 grub_uint64_t offset
;
752 debug("Replace ko invalid argc %d\n", argc
);
756 debug("replace ko %s\n", args
[0]);
758 if (ventoy_get_file_override(args
[0], &offset
) == 0)
760 grub_snprintf(g_ko_mod_path
, sizeof(g_ko_mod_path
), "%s", args
[0]);
761 g_mod_override_offset
= offset
;
765 debug("Can't find replace ko file from %s\n", args
[0]);
769 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[1]);
772 debug("Failed to open %s \n", args
[1]);
776 debug("new ko file size:%d\n", (int)file
->size
);
778 data
= grub_malloc(file
->size
);
781 debug("Failed to alloc memory for new ko %d\n", (int)file
->size
);
782 grub_file_close(file
);
786 grub_file_read(file
, data
, file
->size
);
787 grub_file_close(file
);
789 g_mod_new_data
= data
;
790 g_mod_new_len
= (int)file
->size
;
792 ventoy_unix_search_magic(g_mod_new_data
, g_mod_new_len
);
794 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
797 grub_err_t
ventoy_cmd_unix_ko_fillmap(grub_extcmd_context_t ctxt
, int argc
, char **args
)
801 grub_uint32_t magic
[4];
808 debug("Fillmap ko invalid argc %d\n", argc
);
812 debug("Fillmap ko %s\n", args
[0]);
814 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", args
[0]);
817 grub_file_read(file
, magic
, 4); /* read for trigger */
818 g_mod_override_offset
= grub_iso9660_get_last_read_pos(file
);
822 debug("Can't find replace ko file from %s\n", args
[0]);
826 for (i
= 0; i
< (int)(file
->size
); i
+= 65536)
829 grub_file_seek(file
, i
);
830 grub_file_read(file
, magic
, sizeof(magic
));
832 if (magic
[0] == VENTOY_UNIX_SEG_MAGIC0
&& magic
[1] == VENTOY_UNIX_SEG_MAGIC1
&&
833 magic
[2] == VENTOY_UNIX_SEG_MAGIC2
&& magic
[3] == VENTOY_UNIX_SEG_MAGIC3
)
835 debug("unix find search magic at 0x%x loop:%d\n", i
, (i
>> 16));
836 g_mod_override_offset
+= i
;
841 len
= (grub_uint32_t
)OFFSET_OF(struct g_ventoy_map
, seglist
) +
842 (sizeof(struct g_ventoy_seg
) * g_img_chunk_list
.cur_chunk
);
844 g_ko_fillmap_len
= (int)len
;
845 g_ko_fillmap_data
= grub_malloc(len
);
846 if (!g_ko_fillmap_data
)
848 g_ko_fillmap_len
= 0;
849 debug("Failed to malloc fillmap data\n");
852 debug("Fillmap ko segnum:%u, override len:%u data:%p\n", g_img_chunk_list
.cur_chunk
, len
, g_ko_fillmap_data
);
854 grub_file_close(file
);
855 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
858 grub_err_t
ventoy_cmd_unix_fill_image_desc(grub_extcmd_context_t ctxt
, int argc
, char **args
)
862 grub_uint32_t memsize
;
863 ventoy_image_desc
*desc
;
864 grub_uint8_t flag
[32] = {
865 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00,
866 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
873 debug("ventoy_cmd_unix_fill_image_desc %p\n", g_mod_new_data
);
880 byte
= (grub_uint8_t
*)g_mod_new_data
;
881 for (i
= 0; i
< g_mod_new_len
- 32; i
+= 16)
883 if (byte
[i
] == 0xFF && byte
[i
+ 1] == 0xEE)
885 if (grub_memcmp(flag
, byte
+ i
, 32) == 0)
887 debug("Find position flag at %d(0x%x)\n", i
, i
);
893 if (i
>= g_mod_new_len
- 32)
895 debug("Failed to find position flag %d\n", i
);
899 desc
= (ventoy_image_desc
*)(byte
+ i
);
900 desc
->disk_size
= g_ventoy_disk_size
;
901 desc
->part1_size
= g_ventoy_disk_part_size
[0];
902 grub_memcpy(desc
->disk_uuid
, g_ventoy_part_info
->MBR
.BootCode
+ 0x180, 16);
903 grub_memcpy(desc
->disk_signature
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1B8, 4);
905 desc
->img_chunk_count
= g_img_chunk_list
.cur_chunk
;
906 memsize
= g_img_chunk_list
.cur_chunk
* sizeof(ventoy_img_chunk
);
908 debug("image chunk count:%u memsize:%u\n", desc
->img_chunk_count
, memsize
);
910 if (memsize
>= VTOY_SIZE_1MB
* 8)
912 grub_printf("image chunk count:%u memsize:%u too big\n", desc
->img_chunk_count
, memsize
);
916 grub_memcpy(desc
+ 1, g_img_chunk_list
.chunk
, memsize
);
919 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
922 grub_err_t
ventoy_cmd_unix_gzip_newko(grub_extcmd_context_t ctxt
, int argc
, char **args
)
931 debug("ventoy_cmd_unix_gzip_newko %p\n", g_mod_new_data
);
938 buf
= grub_malloc(g_mod_new_len
);
944 newlen
= ventoy_gzip_compress(g_mod_new_data
, g_mod_new_len
, buf
, g_mod_new_len
);
946 grub_free(g_mod_new_data
);
948 debug("gzip org len:%d newlen:%d\n", g_mod_new_len
, newlen
);
950 g_mod_new_data
= (char *)buf
;
951 g_mod_new_len
= newlen
;
954 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
957 grub_err_t
ventoy_cmd_unix_chain_data(grub_extcmd_context_t ctxt
, int argc
, char **args
)
959 int ventoy_compatible
= 0;
960 grub_uint32_t size
= 0;
961 grub_uint64_t isosize
= 0;
962 grub_uint32_t boot_catlog
= 0;
963 grub_uint32_t img_chunk_size
= 0;
964 grub_uint32_t override_count
= 0;
965 grub_uint32_t override_size
= 0;
966 grub_uint32_t virt_chunk_size
= 0;
969 const char *pLastChain
= NULL
;
970 const char *compatible
;
971 ventoy_chain_head
*chain
;
977 compatible
= grub_env_get("ventoy_compatible");
978 if (compatible
&& compatible
[0] == 'Y')
980 ventoy_compatible
= 1;
983 if (NULL
== g_img_chunk_list
.chunk
)
985 grub_printf("ventoy not ready\n");
989 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
995 isosize
= file
->size
;
997 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
1000 if (ventoy_is_efi_os() && (!ventoy_has_efi_eltorito(file
, boot_catlog
)))
1002 grub_env_set("LoadIsoEfiDriver", "on");
1007 if (ventoy_is_efi_os())
1009 grub_env_set("LoadIsoEfiDriver", "on");
1013 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "File %s is not bootable", args
[0]);
1017 img_chunk_size
= g_img_chunk_list
.cur_chunk
* sizeof(ventoy_img_chunk
);
1019 if (ventoy_compatible
)
1021 size
= sizeof(ventoy_chain_head
) + img_chunk_size
;
1025 override_count
= ventoy_unix_get_override_chunk_count();
1026 override_size
= override_count
* sizeof(ventoy_override_chunk
);
1028 virt_chunk_size
= ventoy_unix_get_virt_chunk_size();
1029 size
= sizeof(ventoy_chain_head
) + img_chunk_size
+ override_size
+ virt_chunk_size
;
1032 pLastChain
= grub_env_get("vtoy_chain_mem_addr");
1035 chain
= (ventoy_chain_head
*)grub_strtoul(pLastChain
, NULL
, 16);
1038 debug("free last chain memory %p\n", chain
);
1043 chain
= grub_malloc(size
);
1046 grub_printf("Failed to alloc chain memory size %u\n", size
);
1047 grub_file_close(file
);
1051 grub_snprintf(envbuf
, sizeof(envbuf
), "0x%lx", (unsigned long)chain
);
1052 grub_env_set("vtoy_chain_mem_addr", envbuf
);
1053 grub_snprintf(envbuf
, sizeof(envbuf
), "%u", size
);
1054 grub_env_set("vtoy_chain_mem_size", envbuf
);
1056 grub_memset(chain
, 0, sizeof(ventoy_chain_head
));
1058 /* part 1: os parameter */
1059 g_ventoy_chain_type
= ventoy_chain_linux
;
1060 ventoy_fill_os_param(file
, &(chain
->os_param
));
1062 /* part 2: chain head */
1063 disk
= file
->device
->disk
;
1064 chain
->disk_drive
= disk
->id
;
1065 chain
->disk_sector_size
= (1 << disk
->log_sector_size
);
1066 chain
->real_img_size_in_bytes
= file
->size
;
1067 chain
->virt_img_size_in_bytes
= (file
->size
+ 2047) / 2048 * 2048;
1068 chain
->boot_catalog
= boot_catlog
;
1070 if (!ventoy_is_efi_os())
1072 grub_file_seek(file
, boot_catlog
* 2048);
1073 grub_file_read(file
, chain
->boot_catalog_sector
, sizeof(chain
->boot_catalog_sector
));
1076 /* part 3: image chunk */
1077 chain
->img_chunk_offset
= sizeof(ventoy_chain_head
);
1078 chain
->img_chunk_num
= g_img_chunk_list
.cur_chunk
;
1079 grub_memcpy((char *)chain
+ chain
->img_chunk_offset
, g_img_chunk_list
.chunk
, img_chunk_size
);
1081 if (ventoy_compatible
)
1086 /* part 4: override chunk */
1087 chain
->override_chunk_offset
= chain
->img_chunk_offset
+ img_chunk_size
;
1088 chain
->override_chunk_num
= override_count
;
1089 ventoy_unix_fill_override_data(isosize
, chain
);
1091 /* part 5: virt chunk */
1092 chain
->virt_chunk_offset
= chain
->override_chunk_offset
+ override_size
;
1093 chain
->virt_chunk_num
= ventoy_unix_get_virt_chunk_count();
1094 ventoy_unix_fill_virt_data(isosize
, chain
);
1096 grub_file_close(file
);
1098 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);