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>\n", (unsigned long long)chain
->os_param
.vtoy_disk_size
, g_img_chunk_list
.cur_chunk
);
145 map
->magic1
[0] = map
->magic2
[0] = map
->magic3
[0] = VENTOY_UNIX_SEG_MAGIC0
;
146 map
->magic1
[1] = map
->magic2
[1] = map
->magic3
[1] = VENTOY_UNIX_SEG_MAGIC1
;
147 map
->magic1
[2] = map
->magic2
[2] = map
->magic3
[2] = VENTOY_UNIX_SEG_MAGIC2
;
148 map
->magic1
[3] = map
->magic2
[3] = map
->magic3
[3] = VENTOY_UNIX_SEG_MAGIC3
;
150 map
->disksize
= chain
->os_param
.vtoy_disk_size
;
151 grub_memcpy(map
->diskuuid
, chain
->os_param
.vtoy_disk_guid
, 16);
153 map
->segnum
= g_img_chunk_list
.cur_chunk
;
154 if (g_img_chunk_list
.cur_chunk
> VENTOY_UNIX_MAX_SEGNUM
)
156 debug("####[FAIL] Too many segments for the ISO file %u\n", g_img_chunk_list
.cur_chunk
);
157 map
->segnum
= VENTOY_UNIX_MAX_SEGNUM
;
160 for (i
= 0; i
< (grub_uint32_t
)(map
->segnum
); i
++)
162 chunk
= g_img_chunk_list
.chunk
+ i
;
163 map
->seglist
[i
].seg_start_bytes
= chunk
->disk_start_sector
* 512ULL;
164 map
->seglist
[i
].seg_end_bytes
= (chunk
->disk_end_sector
+ 1) * 512ULL;
168 static void ventoy_unix_fill_override_data( grub_uint64_t isosize
, ventoy_chain_head
*chain
)
173 grub_uint64_t offset
;
174 grub_uint64_t sector
;
175 ventoy_override_chunk
*cur
;
176 ventoy_iso9660_override
*dirent
;
178 sector
= (isosize
+ 2047) / 2048;
180 cur
= (ventoy_override_chunk
*)((char *)chain
+ chain
->override_chunk_offset
);
182 if (g_conf_new_len
> 0)
185 cur
->img_offset
= g_conf_override_offset
;
186 cur
->override_size
= sizeof(ventoy_iso9660_override
);
187 dirent
= (ventoy_iso9660_override
*)cur
->override_data
;
188 dirent
->first_sector
= (grub_uint32_t
)sector
;
189 dirent
->size
= (grub_uint32_t
)g_conf_new_len
;
190 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
191 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
192 sector
+= (dirent
->size
+ 2047) / 2048;
195 if (g_mod_new_len
> 0)
199 cur
->img_offset
= g_mod_override_offset
;
200 cur
->override_size
= sizeof(ventoy_iso9660_override
);
201 dirent
= (ventoy_iso9660_override
*)cur
->override_data
;
202 dirent
->first_sector
= (grub_uint32_t
)sector
;
203 dirent
->size
= (grub_uint32_t
)g_mod_new_len
;
204 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
205 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
206 sector
+= (dirent
->size
+ 2047) / 2048;
209 if (g_ko_fillmap_len
> 0)
211 data
= g_ko_fillmap_data
;
212 offset
= g_mod_override_offset
;
214 ventoy_unix_fill_map_data(chain
, (struct g_ventoy_map
*)data
);
216 for (i
= 0; i
< g_ko_fillmap_len
/ 512; i
++)
219 cur
->img_offset
= offset
;
220 cur
->override_size
= 512;
221 grub_memcpy(cur
->override_data
, data
, 512);
227 left
= (g_ko_fillmap_len
% 512);
231 cur
->img_offset
= offset
;
232 cur
->override_size
= left
;
233 grub_memcpy(cur
->override_data
, data
, left
);
241 static void ventoy_unix_fill_virt_data( grub_uint64_t isosize
, ventoy_chain_head
*chain
)
243 grub_uint64_t sector
;
244 grub_uint32_t offset
;
245 grub_uint32_t data_secs
;
247 ventoy_virt_chunk
*cur
;
249 override
= (char *)chain
+ chain
->virt_chunk_offset
;
250 cur
= (ventoy_virt_chunk
*)override
;
252 sector
= (isosize
+ 2047) / 2048;
253 offset
= 2 * sizeof(ventoy_virt_chunk
);
255 if (g_conf_new_len
> 0)
257 ventoy_unix_fill_virt(g_conf_new_data
, g_conf_new_len
);
260 if (g_mod_new_len
> 0)
262 if (g_mod_search_magic
> 0)
264 ventoy_unix_fill_map_data(chain
, (struct g_ventoy_map
*)(g_mod_new_data
+ g_mod_search_magic
));
267 ventoy_unix_fill_virt(g_mod_new_data
, g_mod_new_len
);
273 static int ventoy_freebsd_append_conf(char *buf
, const char *isopath
)
280 ventoy_img_chunk
*chunk
;
281 grub_uint8_t disk_sig
[4];
282 grub_uint8_t disk_guid
[16];
284 debug("ventoy_freebsd_append_conf %s\n", isopath
);
286 isofile
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", isopath
);
292 vtoy_ssprintf(buf
, pos
, "ventoy_load=\"%s\"\n", "YES");
293 vtoy_ssprintf(buf
, pos
, "ventoy_name=\"%s\"\n", g_ko_mod_path
);
295 if (g_mod_search_magic
)
297 debug("hint.ventoy NO need\n");
301 disk
= isofile
->device
->disk
;
303 ventoy_get_disk_guid(isofile
->name
, disk_guid
, disk_sig
);
305 for (i
= 0; i
< 16; i
++)
307 grub_snprintf(uuid
+ i
* 2, sizeof(uuid
), "%02x", disk_guid
[i
]);
310 vtoy_ssprintf(buf
, pos
, "hint.ventoy.0.disksize=%llu\n", (ulonglong
)(disk
->total_sectors
* (1 << disk
->log_sector_size
)));
311 vtoy_ssprintf(buf
, pos
, "hint.ventoy.0.diskuuid=\"%s\"\n", uuid
);
312 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]);
313 vtoy_ssprintf(buf
, pos
, "hint.ventoy.0.segnum=%u\n", g_img_chunk_list
.cur_chunk
);
315 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
317 chunk
= g_img_chunk_list
.chunk
+ i
;
318 vtoy_ssprintf(buf
, pos
, "hint.ventoy.%u.seg=\"0x%llx@0x%llx\"\n",
319 i
, (ulonglong
)(chunk
->disk_start_sector
* 512),
320 (ulonglong
)((chunk
->disk_end_sector
+ 1) * 512));
324 grub_file_close(isofile
);
328 static int ventoy_dragonfly_append_conf(char *buf
, const char *isopath
)
332 debug("ventoy_dragonfly_append_conf %s\n", isopath
);
334 vtoy_ssprintf(buf
, pos
, "tmpfs_load=\"%s\"\n", "YES");
335 vtoy_ssprintf(buf
, pos
, "dm_target_linear_load=\"%s\"\n", "YES");
336 vtoy_ssprintf(buf
, pos
, "initrd.img_load=\"%s\"\n", "YES");
337 vtoy_ssprintf(buf
, pos
, "initrd.img_type=\"%s\"\n", "md_image");
338 vtoy_ssprintf(buf
, pos
, "vfs.root.mountfrom=\"%s\"\n", "ufs:md0s0");
343 grub_err_t
ventoy_cmd_unix_reset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
349 g_mod_search_magic
= 0;
352 g_mod_override_offset
= 0;
353 g_conf_override_offset
= 0;
354 g_ko_fillmap_len
= 0;
356 check_free(g_mod_new_data
, grub_free
);
357 check_free(g_conf_new_data
, grub_free
);
358 check_free(g_ko_fillmap_data
, grub_free
);
360 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
363 grub_err_t
ventoy_cmd_parse_freenas_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
366 const char *ver
= NULL
;
368 VTOY_JSON
*json
= NULL
;
373 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
376 debug("Failed to open file %s\n", args
[0]);
380 buf
= grub_malloc(file
->size
+ 2);
383 grub_file_close(file
);
386 grub_file_read(file
, buf
, file
->size
);
389 json
= vtoy_json_create();
395 if (vtoy_json_parse(json
, buf
))
400 ver
= vtoy_json_get_string_ex(json
->pstChild
, "Version");
403 debug("freenas version:<%s>\n", ver
);
404 ventoy_set_env(args
[1], ver
);
408 debug("freenas version:<%s>\n", "NOT FOUND");
409 grub_env_unset(args
[1]);
413 grub_check_free(buf
);
414 check_free(json
, vtoy_json_destroy
);
415 grub_file_close(file
);
417 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
420 grub_err_t
ventoy_cmd_unix_freebsd_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
425 char *nextline
= NULL
;
431 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
434 debug("Failed to open file %s\n", args
[0]);
438 buf
= grub_zalloc(file
->size
+ 2);
441 grub_file_close(file
);
444 grub_file_read(file
, buf
, file
->size
);
446 for (start
= buf
; start
; start
= nextline
)
448 if (grub_strncmp(start
, "USERLAND_VERSION", 16) == 0)
451 while (*nextline
&& *nextline
!= '\r' && *nextline
!= '\n')
459 nextline
= ventoy_get_line(start
);
464 debug("freebsd version:<%s>\n", start
);
465 ventoy_set_env(args
[1], start
);
469 debug("freebsd version:<%s>\n", "NOT FOUND");
470 grub_env_unset(args
[1]);
474 grub_file_close(file
);
476 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
479 grub_err_t
ventoy_cmd_unix_freebsd_ver_elf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
483 grub_elf_t elf
= NULL
;
484 grub_off_t offset
= 0;
485 grub_uint32_t len
= 0;
497 debug("Invalid argc %d\n", argc
);
501 data
= grub_zalloc(8192);
507 elf
= grub_elf_open(args
[0], GRUB_FILE_TYPE_LINUX_INITRD
);
510 debug("Failed to open file %s\n", args
[0]);
514 if (args
[1][0] == '6')
516 Elf64_Ehdr
*e
= &(elf
->ehdr
.ehdr64
);
522 h
= hdr
= grub_zalloc(e
->e_shnum
* e
->e_shentsize
);
528 debug("read section header %u %u %u\n", e
->e_shnum
, e
->e_shentsize
, e
->e_shstrndx
);
529 grub_file_seek(elf
->file
, e
->e_shoff
);
530 grub_file_read(elf
->file
, h
, e
->e_shnum
* e
->e_shentsize
);
532 s
= (Elf64_Shdr
*)((char *)h
+ e
->e_shstrndx
* e
->e_shentsize
);
533 str
= grub_malloc(s
->sh_size
+ 1);
540 debug("read string table %u %u\n", (grub_uint32_t
)s
->sh_offset
, (grub_uint32_t
)s
->sh_size
);
541 grub_file_seek(elf
->file
, s
->sh_offset
);
542 grub_file_read(elf
->file
, str
, s
->sh_size
);
544 for (t
= h
, i
= 0; i
< e
->e_shnum
; i
++)
546 if (grub_strcmp(str
+ t
->sh_name
, ".data") == 0)
548 offset
= t
->sh_offset
;
550 debug("find .data section at %u %u\n", (grub_uint32_t
)offset
, len
);
553 t
= (Elf64_Shdr
*)((char *)t
+ e
->e_shentsize
);
558 Elf32_Ehdr
*e
= &(elf
->ehdr
.ehdr32
);
564 h
= hdr
= grub_zalloc(e
->e_shnum
* e
->e_shentsize
);
570 debug("read section header %u %u %u\n", e
->e_shnum
, e
->e_shentsize
, e
->e_shstrndx
);
571 grub_file_seek(elf
->file
, e
->e_shoff
);
572 grub_file_read(elf
->file
, h
, e
->e_shnum
* e
->e_shentsize
);
574 s
= (Elf32_Shdr
*)((char *)h
+ e
->e_shstrndx
* e
->e_shentsize
);
575 str
= grub_malloc(s
->sh_size
+ 1);
582 debug("read string table %u %u\n", (grub_uint32_t
)s
->sh_offset
, (grub_uint32_t
)s
->sh_size
);
583 grub_file_seek(elf
->file
, s
->sh_offset
);
584 grub_file_read(elf
->file
, str
, s
->sh_size
);
586 for (t
= h
, i
= 0; i
< e
->e_shnum
; i
++)
588 if (grub_strcmp(str
+ t
->sh_name
, ".data") == 0)
590 offset
= t
->sh_offset
;
592 debug("find .data section at %u %u\n", (grub_uint32_t
)offset
, len
);
595 t
= (Elf32_Shdr
*)((char *)t
+ e
->e_shentsize
);
599 if (offset
== 0 || len
== 0)
601 debug(".data section not found %s\n", args
[0]);
605 grub_file_seek(elf
->file
, offset
+ len
- 8192);
606 grub_file_read(elf
->file
, data
, 8192);
608 for (j
= 0; j
< 8192 - 12; j
++)
610 if (grub_strncmp(data
+ j
, "@(#)FreeBSD ", 12) == 0)
612 for (k
= j
+ 12; k
< 8192; k
++)
614 if (0 == grub_isdigit(data
[k
]) && data
[k
] != '.')
621 grub_snprintf(ver
, sizeof(ver
), "%s", data
+ j
+ 12);
628 k
= (int)grub_strtoul(ver
, NULL
, 10);
629 debug("freebsd version:<%s> <%d.x>\n", ver
, k
);
630 grub_snprintf(ver
, sizeof(ver
), "%d.x", k
);
631 ventoy_set_env(args
[2], ver
);
635 debug("freebsd version:<%s>\n", "NOT FOUND");
639 grub_check_free(str
);
640 grub_check_free(hdr
);
641 grub_check_free(data
);
642 check_free(elf
, grub_elf_close
);
644 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
647 grub_err_t
ventoy_cmd_unix_replace_conf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
651 grub_uint64_t offset
;
653 const char *confile
= NULL
;
654 const char * loader_conf
[] =
657 "/boot/defaults/loader.conf",
664 debug("Replace conf invalid argc %d\n", argc
);
668 for (i
= 0; i
< sizeof(loader_conf
) / sizeof(loader_conf
[0]); i
++)
670 if (ventoy_get_file_override(loader_conf
[i
], &offset
) == 0)
672 confile
= loader_conf
[i
];
673 g_conf_override_offset
= offset
;
680 debug("Can't find loader.conf file from %u locations\n", i
);
684 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "(loop)/%s", confile
);
687 debug("Failed to open %s \n", confile
);
691 debug("old conf file size:%d\n", (int)file
->size
);
693 data
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
696 grub_file_close(file
);
700 grub_file_read(file
, data
, file
->size
);
701 grub_file_close(file
);
703 g_conf_new_data
= data
;
704 g_conf_new_len
= (int)file
->size
;
706 if (grub_strcmp(args
[0], "FreeBSD") == 0)
708 g_conf_new_len
+= ventoy_freebsd_append_conf(data
+ file
->size
, args
[1]);
710 else if (grub_strcmp(args
[0], "DragonFly") == 0)
712 g_conf_new_len
+= ventoy_dragonfly_append_conf(data
+ file
->size
, args
[1]);
715 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
718 static int ventoy_unix_search_magic(char *data
, int len
)
721 grub_uint32_t
*magic
= NULL
;
723 for (i
= 0; i
< len
; i
+= 65536)
725 magic
= (grub_uint32_t
*)(data
+ i
);
726 if (magic
[0] == VENTOY_UNIX_SEG_MAGIC0
&& magic
[1] == VENTOY_UNIX_SEG_MAGIC1
&&
727 magic
[2] == VENTOY_UNIX_SEG_MAGIC2
&& magic
[3] == VENTOY_UNIX_SEG_MAGIC3
)
729 debug("unix find search magic at 0x%x loop:%d\n", i
, (i
>> 16));
730 g_mod_search_magic
= i
;
735 debug("unix can not find search magic\n");
739 grub_err_t
ventoy_cmd_unix_replace_ko(grub_extcmd_context_t ctxt
, int argc
, char **args
)
742 grub_uint64_t offset
;
749 debug("Replace ko invalid argc %d\n", argc
);
753 debug("replace ko %s\n", args
[0]);
755 if (ventoy_get_file_override(args
[0], &offset
) == 0)
757 grub_snprintf(g_ko_mod_path
, sizeof(g_ko_mod_path
), "%s", args
[0]);
758 g_mod_override_offset
= offset
;
762 debug("Can't find replace ko file from %s\n", args
[0]);
766 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[1]);
769 debug("Failed to open %s \n", args
[1]);
773 debug("new ko file size:%d\n", (int)file
->size
);
775 data
= grub_malloc(file
->size
);
778 debug("Failed to alloc memory for new ko %d\n", (int)file
->size
);
779 grub_file_close(file
);
783 grub_file_read(file
, data
, file
->size
);
784 grub_file_close(file
);
786 g_mod_new_data
= data
;
787 g_mod_new_len
= (int)file
->size
;
789 ventoy_unix_search_magic(g_mod_new_data
, g_mod_new_len
);
791 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
794 grub_err_t
ventoy_cmd_unix_ko_fillmap(grub_extcmd_context_t ctxt
, int argc
, char **args
)
798 grub_uint32_t magic
[4];
805 debug("Fillmap ko invalid argc %d\n", argc
);
809 debug("Fillmap ko %s\n", args
[0]);
811 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", args
[0]);
814 g_mod_override_offset
= grub_iso9660_get_last_read_pos(file
);
818 debug("Can't find replace ko file from %s\n", args
[0]);
822 for (i
= 0; i
< (int)(file
->size
); i
+= 65536)
825 grub_file_seek(file
, i
);
826 grub_file_read(file
, magic
, sizeof(magic
));
828 if (magic
[0] == VENTOY_UNIX_SEG_MAGIC0
&& magic
[1] == VENTOY_UNIX_SEG_MAGIC1
&&
829 magic
[2] == VENTOY_UNIX_SEG_MAGIC2
&& magic
[3] == VENTOY_UNIX_SEG_MAGIC3
)
831 debug("unix find search magic at 0x%x loop:%d\n", i
, (i
>> 16));
832 g_mod_override_offset
+= i
;
837 len
= (grub_uint32_t
)OFFSET_OF(struct g_ventoy_map
, seglist
) +
838 (sizeof(struct g_ventoy_seg
) * g_img_chunk_list
.cur_chunk
);
840 g_ko_fillmap_len
= (int)len
;
841 g_ko_fillmap_data
= grub_malloc(len
);
842 if (!g_ko_fillmap_data
)
844 g_ko_fillmap_len
= 0;
845 debug("Failed to malloc fillmap data\n");
848 debug("Fillmap ko segnum:%u, override len:%d", g_img_chunk_list
.cur_chunk
, g_ko_fillmap_len
);
850 grub_file_close(file
);
851 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
854 grub_err_t
ventoy_cmd_unix_fill_image_desc(grub_extcmd_context_t ctxt
, int argc
, char **args
)
858 grub_uint32_t memsize
;
859 ventoy_image_desc
*desc
;
860 grub_uint8_t flag
[32] = {
861 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00,
862 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
869 debug("ventoy_cmd_unix_fill_image_desc %p\n", g_mod_new_data
);
876 byte
= (grub_uint8_t
*)g_mod_new_data
;
877 for (i
= 0; i
< g_mod_new_len
- 32; i
+= 16)
879 if (byte
[i
] == 0xFF && byte
[i
+ 1] == 0xEE)
881 if (grub_memcmp(flag
, byte
+ i
, 32) == 0)
883 debug("Find position flag at %d(0x%x)\n", i
, i
);
889 if (i
>= g_mod_new_len
- 32)
891 debug("Failed to find position flag %d\n", i
);
895 desc
= (ventoy_image_desc
*)(byte
+ i
);
896 desc
->disk_size
= g_ventoy_disk_size
;
897 desc
->part1_size
= g_ventoy_disk_part_size
[0];
898 grub_memcpy(desc
->disk_uuid
, g_ventoy_part_info
->MBR
.BootCode
+ 0x180, 16);
899 grub_memcpy(desc
->disk_signature
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1B8, 4);
901 desc
->img_chunk_count
= g_img_chunk_list
.cur_chunk
;
902 memsize
= g_img_chunk_list
.cur_chunk
* sizeof(ventoy_img_chunk
);
904 debug("image chunk count:%u memsize:%u\n", desc
->img_chunk_count
, memsize
);
906 if (memsize
>= VTOY_SIZE_1MB
* 8)
908 grub_printf("image chunk count:%u memsize:%u too big\n", desc
->img_chunk_count
, memsize
);
912 grub_memcpy(desc
+ 1, g_img_chunk_list
.chunk
, memsize
);
915 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
918 grub_err_t
ventoy_cmd_unix_gzip_newko(grub_extcmd_context_t ctxt
, int argc
, char **args
)
927 debug("ventoy_cmd_unix_gzip_newko %p\n", g_mod_new_data
);
934 buf
= grub_malloc(g_mod_new_len
);
940 newlen
= ventoy_gzip_compress(g_mod_new_data
, g_mod_new_len
, buf
, g_mod_new_len
);
942 grub_free(g_mod_new_data
);
944 debug("gzip org len:%d newlen:%d\n", g_mod_new_len
, newlen
);
946 g_mod_new_data
= (char *)buf
;
947 g_mod_new_len
= newlen
;
950 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
953 grub_err_t
ventoy_cmd_unix_chain_data(grub_extcmd_context_t ctxt
, int argc
, char **args
)
955 int ventoy_compatible
= 0;
956 grub_uint32_t size
= 0;
957 grub_uint64_t isosize
= 0;
958 grub_uint32_t boot_catlog
= 0;
959 grub_uint32_t img_chunk_size
= 0;
960 grub_uint32_t override_count
= 0;
961 grub_uint32_t override_size
= 0;
962 grub_uint32_t virt_chunk_size
= 0;
965 const char *pLastChain
= NULL
;
966 const char *compatible
;
967 ventoy_chain_head
*chain
;
973 compatible
= grub_env_get("ventoy_compatible");
974 if (compatible
&& compatible
[0] == 'Y')
976 ventoy_compatible
= 1;
979 if (NULL
== g_img_chunk_list
.chunk
)
981 grub_printf("ventoy not ready\n");
985 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
991 isosize
= file
->size
;
993 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
996 if (ventoy_is_efi_os() && (!ventoy_has_efi_eltorito(file
, boot_catlog
)))
998 grub_env_set("LoadIsoEfiDriver", "on");
1003 if (ventoy_is_efi_os())
1005 grub_env_set("LoadIsoEfiDriver", "on");
1009 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "File %s is not bootable", args
[0]);
1013 img_chunk_size
= g_img_chunk_list
.cur_chunk
* sizeof(ventoy_img_chunk
);
1015 if (ventoy_compatible
)
1017 size
= sizeof(ventoy_chain_head
) + img_chunk_size
;
1021 override_count
= ventoy_unix_get_override_chunk_count();
1022 override_size
= override_count
* sizeof(ventoy_override_chunk
);
1024 virt_chunk_size
= ventoy_unix_get_virt_chunk_size();
1025 size
= sizeof(ventoy_chain_head
) + img_chunk_size
+ override_size
+ virt_chunk_size
;
1028 pLastChain
= grub_env_get("vtoy_chain_mem_addr");
1031 chain
= (ventoy_chain_head
*)grub_strtoul(pLastChain
, NULL
, 16);
1034 debug("free last chain memory %p\n", chain
);
1039 chain
= grub_malloc(size
);
1042 grub_printf("Failed to alloc chain memory size %u\n", size
);
1043 grub_file_close(file
);
1047 grub_snprintf(envbuf
, sizeof(envbuf
), "0x%lx", (unsigned long)chain
);
1048 grub_env_set("vtoy_chain_mem_addr", envbuf
);
1049 grub_snprintf(envbuf
, sizeof(envbuf
), "%u", size
);
1050 grub_env_set("vtoy_chain_mem_size", envbuf
);
1052 grub_memset(chain
, 0, sizeof(ventoy_chain_head
));
1054 /* part 1: os parameter */
1055 g_ventoy_chain_type
= ventoy_chain_linux
;
1056 ventoy_fill_os_param(file
, &(chain
->os_param
));
1058 /* part 2: chain head */
1059 disk
= file
->device
->disk
;
1060 chain
->disk_drive
= disk
->id
;
1061 chain
->disk_sector_size
= (1 << disk
->log_sector_size
);
1062 chain
->real_img_size_in_bytes
= file
->size
;
1063 chain
->virt_img_size_in_bytes
= (file
->size
+ 2047) / 2048 * 2048;
1064 chain
->boot_catalog
= boot_catlog
;
1066 if (!ventoy_is_efi_os())
1068 grub_file_seek(file
, boot_catlog
* 2048);
1069 grub_file_read(file
, chain
->boot_catalog_sector
, sizeof(chain
->boot_catalog_sector
));
1072 /* part 3: image chunk */
1073 chain
->img_chunk_offset
= sizeof(ventoy_chain_head
);
1074 chain
->img_chunk_num
= g_img_chunk_list
.cur_chunk
;
1075 grub_memcpy((char *)chain
+ chain
->img_chunk_offset
, g_img_chunk_list
.chunk
, img_chunk_size
);
1077 if (ventoy_compatible
)
1082 /* part 4: override chunk */
1083 chain
->override_chunk_offset
= chain
->img_chunk_offset
+ img_chunk_size
;
1084 chain
->override_chunk_num
= override_count
;
1085 ventoy_unix_fill_override_data(isosize
, chain
);
1087 /* part 5: virt chunk */
1088 chain
->virt_chunk_offset
= chain
->override_chunk_offset
+ override_size
;
1089 chain
->virt_chunk_num
= ventoy_unix_get_virt_chunk_count();
1090 ventoy_unix_fill_virt_data(isosize
, chain
);
1092 grub_file_close(file
);
1094 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);