]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c
f2e62b63bef36d1b3aab81ca877069819a009651
[Ventoy.git] / GRUB2 / MOD_SRC / grub-2.04 / grub-core / ventoy / ventoy_cmd.c
1 /******************************************************************************
2 * ventoy_cmd.c
3 *
4 * Copyright (c) 2021, longpanda <admin@ventoy.net>
5 *
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.
10 *
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.
15 *
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/>.
18 *
19 */
20
21 #include <grub/types.h>
22 #include <grub/misc.h>
23 #include <grub/mm.h>
24 #include <grub/err.h>
25 #include <grub/dl.h>
26 #include <grub/disk.h>
27 #include <grub/device.h>
28 #include <grub/term.h>
29 #include <grub/partition.h>
30 #include <grub/file.h>
31 #include <grub/normal.h>
32 #include <grub/extcmd.h>
33 #include <grub/datetime.h>
34 #include <grub/i18n.h>
35 #include <grub/net.h>
36 #include <grub/misc.h>
37 #include <grub/kernel.h>
38 #ifdef GRUB_MACHINE_EFI
39 #include <grub/efi/api.h>
40 #include <grub/efi/efi.h>
41 #endif
42 #include <grub/time.h>
43 #include <grub/video.h>
44 #include <grub/acpi.h>
45 #include <grub/charset.h>
46 #include <grub/crypto.h>
47 #include <grub/lib/crc.h>
48 #include <grub/ventoy.h>
49 #include "ventoy_def.h"
50 #include "miniz.h"
51
52 GRUB_MOD_LICENSE ("GPLv3+");
53
54 static grub_uint8_t g_check_mbr_data[440] = {
55 0xEB, 0x63, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFA, 0x90, 0x90, 0xF6, 0xC2, 0x80, 0x74, 0x05, 0xF6, 0xC2, 0x70,
62 0x74, 0x02, 0xB2, 0x80, 0xEA, 0x79, 0x7C, 0x00, 0x00, 0x31, 0xC0, 0x8E, 0xD8, 0x8E, 0xD0, 0xBC,
63 0x00, 0x20, 0xFB, 0xA0, 0x64, 0x7C, 0x3C, 0xFF, 0x74, 0x02, 0x88, 0xC2, 0x52, 0xBE, 0x90, 0x7D,
64 0xE8, 0x16, 0x01, 0xBE, 0x05, 0x7C, 0xB4, 0x41, 0xBB, 0xAA, 0x55, 0xCD, 0x13, 0x5A, 0x52, 0x72,
65 0x3D, 0x81, 0xFB, 0x55, 0xAA, 0x75, 0x37, 0x83, 0xE1, 0x01, 0x74, 0x32, 0x31, 0xC0, 0x89, 0x44,
66 0x04, 0x40, 0x88, 0x44, 0xFF, 0x89, 0x44, 0x02, 0xC7, 0x04, 0x10, 0x00, 0x66, 0x8B, 0x1E, 0x5C,
67 0x7C, 0x66, 0x89, 0x5C, 0x08, 0x66, 0x8B, 0x1E, 0x60, 0x7C, 0x66, 0x89, 0x5C, 0x0C, 0xC7, 0x44,
68 0x06, 0x00, 0x70, 0xB4, 0x42, 0xCD, 0x13, 0x72, 0x05, 0xBB, 0x00, 0x70, 0xEB, 0x76, 0xB4, 0x08,
69 0xCD, 0x13, 0x73, 0x0D, 0x5A, 0x84, 0xD2, 0x0F, 0x83, 0xD8, 0x00, 0xBE, 0x96, 0x7D, 0xE9, 0x82,
70 0x00, 0x66, 0x0F, 0xB6, 0xC6, 0x88, 0x64, 0xFF, 0x40, 0x66, 0x89, 0x44, 0x04, 0x0F, 0xB6, 0xD1,
71 0xC1, 0xE2, 0x02, 0x88, 0xE8, 0x88, 0xF4, 0x40, 0x89, 0x44, 0x08, 0x0F, 0xB6, 0xC2, 0xC0, 0xE8,
72 0x02, 0x66, 0x89, 0x04, 0x66, 0xA1, 0x60, 0x7C, 0x66, 0x09, 0xC0, 0x75, 0x4E, 0x66, 0xA1, 0x5C,
73 0x7C, 0x66, 0x31, 0xD2, 0x66, 0xF7, 0x34, 0x88, 0xD1, 0x31, 0xD2, 0x66, 0xF7, 0x74, 0x04, 0x3B,
74 0x44, 0x08, 0x7D, 0x37, 0xFE, 0xC1, 0x88, 0xC5, 0x30, 0xC0, 0xC1, 0xE8, 0x02, 0x08, 0xC1, 0x88,
75 0xD0, 0x5A, 0x88, 0xC6, 0xBB, 0x00, 0x70, 0x8E, 0xC3, 0x31, 0xDB, 0xB8, 0x01, 0x02, 0xCD, 0x13,
76 0x72, 0x1E, 0x8C, 0xC3, 0x60, 0x1E, 0xB9, 0x00, 0x01, 0x8E, 0xDB, 0x31, 0xF6, 0xBF, 0x00, 0x80,
77 0x8E, 0xC6, 0xFC, 0xF3, 0xA5, 0x1F, 0x61, 0xFF, 0x26, 0x5A, 0x7C, 0xBE, 0x93, 0x7D, 0xEB, 0x03,
78 0xBE, 0x99, 0x7D, 0xE8, 0x33, 0x00, 0xBE, 0x9C, 0x7D, 0xE8, 0x2D, 0x00, 0xCD, 0x18, 0xEB, 0xFE,
79 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58,
80 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44, 0x00, 0x52, 0x64, 0x00, 0x20, 0x45, 0x72, 0x0D,
81 0x0A, 0x00, 0xBB, 0x01, 0x00, 0xB4, 0x0E, 0xCD, 0x10, 0xAC, 0x3C, 0x00, 0x75, 0xF4, 0xC3, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
83 };
84
85 initrd_info *g_initrd_img_list = NULL;
86 initrd_info *g_initrd_img_tail = NULL;
87 int g_initrd_img_count = 0;
88 int g_valid_initrd_count = 0;
89 int g_default_menu_mode = 0;
90 int g_filt_dot_underscore_file = 0;
91 int g_sort_case_sensitive = 0;
92 int g_tree_view_menu_style = 0;
93 static grub_file_t g_old_file;
94 static int g_ventoy_last_entry_back;
95
96 char g_iso_path[256];
97 char g_img_swap_tmp_buf[1024];
98 img_info g_img_swap_tmp;
99 img_info *g_ventoy_img_list = NULL;
100
101 int g_ventoy_img_count = 0;
102
103 grub_device_t g_enum_dev = NULL;
104 grub_fs_t g_enum_fs = NULL;
105 int g_img_max_search_level = -1;
106 img_iterator_node g_img_iterator_head;
107 img_iterator_node *g_img_iterator_tail = NULL;
108
109 grub_uint8_t g_ventoy_break_level = 0;
110 grub_uint8_t g_ventoy_debug_level = 0;
111 grub_uint8_t g_ventoy_chain_type = 0;
112
113 grub_uint8_t *g_ventoy_cpio_buf = NULL;
114 grub_uint32_t g_ventoy_cpio_size = 0;
115 cpio_newc_header *g_ventoy_initrd_head = NULL;
116 grub_uint8_t *g_ventoy_runtime_buf = NULL;
117
118 int g_plugin_image_list = 0;
119
120 ventoy_grub_param *g_grub_param = NULL;
121
122 ventoy_guid g_ventoy_guid = VENTOY_GUID;
123
124 ventoy_img_chunk_list g_img_chunk_list;
125
126 int g_wimboot_enable = 0;
127 ventoy_img_chunk_list g_wimiso_chunk_list;
128 char *g_wimiso_path = NULL;
129
130 int g_vhdboot_enable = 0;
131
132 grub_uint64_t g_conf_replace_offset = 0;
133 grub_uint64_t g_svd_replace_offset = 0;
134 conf_replace *g_conf_replace_node = NULL;
135 grub_uint8_t *g_conf_replace_new_buf = NULL;
136 int g_conf_replace_new_len = 0;
137 int g_conf_replace_new_len_align = 0;
138
139 ventoy_gpt_info *g_ventoy_part_info = NULL;
140 grub_uint64_t g_ventoy_disk_size = 0;
141 grub_uint64_t g_ventoy_disk_part_size[2];
142
143 static char *g_tree_script_buf = NULL;
144 static int g_tree_script_pos = 0;
145
146 static char *g_list_script_buf = NULL;
147 static int g_list_script_pos = 0;
148
149 static char *g_part_list_buf = NULL;
150 static int g_part_list_pos = 0;
151
152 static int g_video_mode_max = 0;
153 static int g_video_mode_num = 0;
154 static ventoy_video_mode *g_video_mode_list = NULL;
155
156 static int g_enumerate_time_checked = 0;
157 static grub_uint64_t g_enumerate_start_time_ms;
158 static grub_uint64_t g_enumerate_finish_time_ms;
159 static int g_vtoy_file_flt[VTOY_FILE_FLT_BUTT] = {0};
160
161 static int g_pager_flag = 0;
162 static char g_old_pager[32];
163
164 static const char *g_vtoy_winpeshl_ini = "[LaunchApps]\r\nvtoyjump.exe";
165
166 static const char *g_menu_class[] =
167 {
168 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
169 };
170
171 const char *g_menu_prefix[img_type_max] =
172 {
173 "iso", "wim", "efi", "img", "vhd", "vtoy"
174 };
175
176 static int g_vtoy_load_prompt = 0;
177 static char g_vtoy_prompt_msg[64];
178
179 static char g_json_case_mis_path[32];
180
181 static int ventoy_get_fs_type(const char *fs)
182 {
183 if (NULL == fs)
184 {
185 return ventoy_fs_max;
186 }
187 else if (grub_strncmp(fs, "exfat", 5) == 0)
188 {
189 return ventoy_fs_exfat;
190 }
191 else if (grub_strncmp(fs, "ntfs", 4) == 0)
192 {
193 return ventoy_fs_ntfs;
194 }
195 else if (grub_strncmp(fs, "ext", 3) == 0)
196 {
197 return ventoy_fs_ext;
198 }
199 else if (grub_strncmp(fs, "xfs", 3) == 0)
200 {
201 return ventoy_fs_xfs;
202 }
203 else if (grub_strncmp(fs, "udf", 3) == 0)
204 {
205 return ventoy_fs_udf;
206 }
207 else if (grub_strncmp(fs, "fat", 3) == 0)
208 {
209 return ventoy_fs_fat;
210 }
211
212 return ventoy_fs_max;
213 }
214
215 static int ventoy_string_check(const char *str, grub_char_check_func check)
216 {
217 if (!str)
218 {
219 return 0;
220 }
221
222 for ( ; *str; str++)
223 {
224 if (!check(*str))
225 {
226 return 0;
227 }
228 }
229
230 return 1;
231 }
232
233
234 static grub_ssize_t ventoy_fs_read(grub_file_t file, char *buf, grub_size_t len)
235 {
236 grub_memcpy(buf, (char *)file->data + file->offset, len);
237 return len;
238 }
239
240 static int ventoy_control_get_flag(const char *key)
241 {
242 const char *val = ventoy_get_env(key);
243
244 if (val && val[0] == '1' && val[1] == 0)
245 {
246 return 1;
247 }
248 return 0;
249 }
250
251 static grub_err_t ventoy_fs_close(grub_file_t file)
252 {
253 grub_file_close(g_old_file);
254 grub_free(file->data);
255
256 file->device = 0;
257 file->name = 0;
258
259 return 0;
260 }
261
262 static int ventoy_video_hook(const struct grub_video_mode_info *info, void *hook_arg)
263 {
264 int i;
265
266 (void)hook_arg;
267
268 if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT)
269 {
270 return 0;
271 }
272
273 for (i = 0; i < g_video_mode_num; i++)
274 {
275 if (g_video_mode_list[i].width == info->width &&
276 g_video_mode_list[i].height == info->height &&
277 g_video_mode_list[i].bpp == info->bpp)
278 {
279 return 0;
280 }
281 }
282
283 g_video_mode_list[g_video_mode_num].width = info->width;
284 g_video_mode_list[g_video_mode_num].height = info->height;
285 g_video_mode_list[g_video_mode_num].bpp = info->bpp;
286 g_video_mode_num++;
287
288 if (g_video_mode_num == g_video_mode_max)
289 {
290 g_video_mode_max *= 2;
291 g_video_mode_list = grub_realloc(g_video_mode_list, g_video_mode_max * sizeof(ventoy_video_mode));
292 }
293
294 return 0;
295 }
296
297 static int ventoy_video_mode_cmp(ventoy_video_mode *v1, ventoy_video_mode *v2)
298 {
299 if (v1->bpp == v2->bpp)
300 {
301 if (v1->width == v2->width)
302 {
303 if (v1->height == v2->height)
304 {
305 return 0;
306 }
307 else
308 {
309 return (v1->height < v2->height) ? -1 : 1;
310 }
311 }
312 else
313 {
314 return (v1->width < v2->width) ? -1 : 1;
315 }
316 }
317 else
318 {
319 return (v1->bpp < v2->bpp) ? -1 : 1;
320 }
321 }
322
323 static int ventoy_enum_video_mode(void)
324 {
325 int i, j;
326 grub_video_adapter_t adapter;
327 grub_video_driver_id_t id;
328 ventoy_video_mode mode;
329
330 g_video_mode_num = 0;
331 g_video_mode_max = 1024;
332 g_video_mode_list = grub_malloc(sizeof(ventoy_video_mode) * g_video_mode_max);
333 if (!g_video_mode_list)
334 {
335 return 0;
336 }
337
338 #ifdef GRUB_MACHINE_PCBIOS
339 grub_dl_load ("vbe");
340 #endif
341
342 id = grub_video_get_driver_id ();
343
344 FOR_VIDEO_ADAPTERS (adapter)
345 {
346 if (!adapter->iterate ||
347 (adapter->id != id && (id != GRUB_VIDEO_DRIVER_NONE ||
348 adapter->init() != GRUB_ERR_NONE)))
349 {
350 continue;
351 }
352
353 adapter->iterate(ventoy_video_hook, NULL);
354
355 if (adapter->id != id)
356 {
357 adapter->fini();
358 }
359 }
360
361 /* sort video mode */
362 for (i = 0; i < g_video_mode_num; i++)
363 for (j = i + 1; j < g_video_mode_num; j++)
364 {
365 if (ventoy_video_mode_cmp(g_video_mode_list + i, g_video_mode_list + j) < 0)
366 {
367 grub_memcpy(&mode, g_video_mode_list + i, sizeof(ventoy_video_mode));
368 grub_memcpy(g_video_mode_list + i, g_video_mode_list + j, sizeof(ventoy_video_mode));
369 grub_memcpy(g_video_mode_list + j, &mode, sizeof(ventoy_video_mode));
370 }
371 }
372
373 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
374 }
375
376 static grub_file_t ventoy_wrapper_open(grub_file_t rawFile, enum grub_file_type type)
377 {
378 int len;
379 grub_file_t file;
380 static struct grub_fs vtoy_fs =
381 {
382 .name = "vtoy",
383 .fs_dir = 0,
384 .fs_open = 0,
385 .fs_read = ventoy_fs_read,
386 .fs_close = ventoy_fs_close,
387 .fs_label = 0,
388 .next = 0
389 };
390
391 if (type != 52)
392 {
393 return rawFile;
394 }
395
396 file = (grub_file_t)grub_zalloc(sizeof (*file));
397 if (!file)
398 {
399 return 0;
400 }
401
402 file->data = grub_malloc(rawFile->size + 4096);
403 if (!file->data)
404 {
405 return 0;
406 }
407
408 grub_file_read(rawFile, file->data, rawFile->size);
409 len = ventoy_fill_data(4096, (char *)file->data + rawFile->size);
410
411 g_old_file = rawFile;
412
413 file->size = rawFile->size + len;
414 file->device = rawFile->device;
415 file->fs = &vtoy_fs;
416 file->not_easily_seekable = 1;
417
418 return file;
419 }
420
421 static int ventoy_check_decimal_var(const char *name, long *value)
422 {
423 const char *value_str = NULL;
424
425 value_str = grub_env_get(name);
426 if (NULL == value_str)
427 {
428 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Variable %s not found", name);
429 }
430
431 if (!ventoy_is_decimal(value_str))
432 {
433 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Variable %s value '%s' is not an integer", name, value_str);
434 }
435
436 *value = grub_strtol(value_str, NULL, 10);
437
438 return GRUB_ERR_NONE;
439 }
440
441 grub_uint64_t ventoy_get_vtoy_partsize(int part)
442 {
443 grub_uint64_t sectors;
444
445 if (grub_strncmp(g_ventoy_part_info->Head.Signature, "EFI PART", 8) == 0)
446 {
447 sectors = g_ventoy_part_info->PartTbl[part].LastLBA + 1 - g_ventoy_part_info->PartTbl[part].StartLBA;
448 }
449 else
450 {
451 sectors = g_ventoy_part_info->MBR.PartTbl[part].SectorCount;
452 }
453
454 return sectors * 512;
455 }
456
457 static int ventoy_load_efiboot_template(char **buf, int *datalen, int *direntoff)
458 {
459 int len;
460 grub_file_t file;
461 char exec[128];
462 char *data = NULL;
463 grub_uint32_t offset;
464
465 file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
466 if (file == NULL)
467 {
468 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
469 return 1;
470 }
471
472 len = (int)file->size;
473
474 data = (char *)grub_malloc(file->size);
475 if (!data)
476 {
477 return 1;
478 }
479
480 grub_file_read(file, data, file->size);
481 grub_file_close(file);
482
483 grub_snprintf(exec, sizeof(exec), "loopback efiboot mem:0x%llx:size:%d", (ulonglong)(ulong)data, len);
484 grub_script_execute_sourcecode(exec);
485
486 file = grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD);
487 offset = (grub_uint32_t)grub_iso9660_get_last_file_dirent_pos(file);
488 grub_file_close(file);
489
490 grub_script_execute_sourcecode("loopback -d efiboot");
491
492 *buf = data;
493 *datalen = len;
494 *direntoff = offset + 2;
495
496 return 0;
497 }
498
499 static int ventoy_set_check_result(int ret)
500 {
501 char buf[32];
502
503 grub_snprintf(buf, sizeof(buf), "%d", (ret & 0x7FFF));
504 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf);
505 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
506
507 if (ret)
508 {
509 grub_printf(VTOY_WARNING"\n");
510 grub_printf(VTOY_WARNING"\n");
511 grub_printf(VTOY_WARNING"\n\n\n");
512
513 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n\n", ret);
514 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
515
516 grub_printf("\n\nWill exit after 10 seconds ...... ");
517 grub_refresh();
518 grub_sleep(10);
519 }
520
521 return ret;
522 }
523
524 static int ventoy_check_official_device(grub_device_t dev)
525 {
526 int workaround = 0;
527 grub_file_t file;
528 grub_uint64_t offset;
529 char devname[64];
530 grub_fs_t fs;
531 grub_uint8_t mbr[512];
532 grub_disk_t disk;
533 grub_device_t dev2;
534 char *label = NULL;
535 struct grub_partition *partition;
536
537 if (dev->disk == NULL || dev->disk->partition == NULL)
538 {
539 return ventoy_set_check_result(1 | 0x1000);
540 }
541
542 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev->disk->name) ||
543 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev->disk->name) ||
544 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev->disk->name))
545 {
546 #ifndef GRUB_MACHINE_EFI
547 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev->disk->name) ||
548 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev->disk->name) ||
549 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev->disk->name))
550 {
551 return ventoy_set_check_result(2 | 0x1000);
552 }
553 else
554 {
555 workaround = 1;
556 }
557 #endif
558 }
559
560 /* We must have partition 2 */
561 if (workaround)
562 {
563 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
564 }
565 else
566 {
567 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(%s,2)/ventoy/ventoy.cpio", dev->disk->name);
568 }
569 if (!file)
570 {
571 return ventoy_set_check_result(3 | 0x1000);
572 }
573
574 if (NULL == grub_strstr(file->fs->name, "fat"))
575 {
576 grub_file_close(file);
577 return ventoy_set_check_result(4 | 0x1000);
578 }
579
580 partition = dev->disk->partition;
581 if (partition->number != 0 || partition->start != 2048)
582 {
583 return ventoy_set_check_result(5);
584 }
585
586 if (workaround)
587 {
588 if (grub_strncmp(g_ventoy_part_info->Head.Signature, "EFI PART", 8) == 0)
589 {
590 ventoy_gpt_part_tbl *PartTbl = g_ventoy_part_info->PartTbl;
591 if (PartTbl[1].StartLBA != PartTbl[0].LastLBA + 1 ||
592 (PartTbl[1].LastLBA + 1 - PartTbl[1].StartLBA) != 65536)
593 {
594 grub_file_close(file);
595 return ventoy_set_check_result(6);
596 }
597 }
598 else
599 {
600 ventoy_part_table *PartTbl = g_ventoy_part_info->MBR.PartTbl;
601 if (PartTbl[1].StartSectorId != PartTbl[0].StartSectorId + PartTbl[0].SectorCount ||
602 PartTbl[1].SectorCount != 65536)
603 {
604 grub_file_close(file);
605 return ventoy_set_check_result(6);
606 }
607 }
608 }
609 else
610 {
611 offset = partition->start + partition->len;
612 partition = file->device->disk->partition;
613 if ((partition->number != 1) || (partition->len != 65536) || (offset != partition->start))
614 {
615 grub_file_close(file);
616 return ventoy_set_check_result(7);
617 }
618 }
619
620 grub_file_close(file);
621
622 if (workaround == 0)
623 {
624 grub_snprintf(devname, sizeof(devname), "%s,2", dev->disk->name);
625 dev2 = grub_device_open(devname);
626 if (!dev2)
627 {
628 return ventoy_set_check_result(8);
629 }
630
631 fs = grub_fs_probe(dev2);
632 if (!fs)
633 {
634 grub_device_close(dev2);
635 return ventoy_set_check_result(9);
636 }
637
638 fs->fs_label(dev2, &label);
639 if ((!label) || grub_strncmp("VTOYEFI", label, 7))
640 {
641 grub_device_close(dev2);
642 return ventoy_set_check_result(10);
643 }
644
645 grub_device_close(dev2);
646 }
647
648 /* MBR check */
649 disk = grub_disk_open(dev->disk->name);
650 if (!disk)
651 {
652 return ventoy_set_check_result(11);
653 }
654
655 grub_memset(mbr, 0, 512);
656 grub_disk_read(disk, 0, 0, 512, mbr);
657 grub_disk_close(disk);
658
659 g_check_mbr_data[92] = mbr[92];
660 g_check_mbr_data[102] = mbr[102];
661 g_check_mbr_data[103] = mbr[103];
662 grub_memcpy(g_check_mbr_data + 0x180, mbr + 0x180, 16);
663 if (grub_memcmp(g_check_mbr_data, mbr, 440))
664 {
665 return ventoy_set_check_result(12);
666 }
667
668 return ventoy_set_check_result(0);
669 }
670
671 static int ventoy_check_ignore_flag(const char *filename, const struct grub_dirhook_info *info, void *data)
672 {
673 if (0 == info->dir)
674 {
675 if (filename && filename[0] == '.' && 0 == grub_strncmp(filename, ".ventoyignore", 13))
676 {
677 *((int *)data) = 1;
678 return 0;
679 }
680 }
681
682 return 0;
683 }
684
685 grub_uint64_t ventoy_grub_get_file_size(const char *fmt, ...)
686 {
687 grub_uint64_t size = 0;
688 grub_file_t file;
689 va_list ap;
690 char fullpath[256] = {0};
691
692 va_start (ap, fmt);
693 grub_vsnprintf(fullpath, 255, fmt, ap);
694 va_end (ap);
695
696 file = grub_file_open(fullpath, VENTOY_FILE_TYPE);
697 if (!file)
698 {
699 debug("grub_file_open failed <%s>\n", fullpath);
700 grub_errno = 0;
701 return 0;
702 }
703
704 size = file->size;
705 grub_file_close(file);
706 return size;
707 }
708
709 grub_file_t ventoy_grub_file_open(enum grub_file_type type, const char *fmt, ...)
710 {
711 va_list ap;
712 grub_file_t file;
713 char fullpath[256] = {0};
714
715 va_start (ap, fmt);
716 grub_vsnprintf(fullpath, 255, fmt, ap);
717 va_end (ap);
718
719 file = grub_file_open(fullpath, type);
720 if (!file)
721 {
722 debug("grub_file_open failed <%s> %d\n", fullpath, grub_errno);
723 grub_errno = 0;
724 }
725
726 return file;
727 }
728
729 int ventoy_is_file_exist(const char *fmt, ...)
730 {
731 va_list ap;
732 int len;
733 char *pos = NULL;
734 char buf[256] = {0};
735
736 grub_snprintf(buf, sizeof(buf), "%s", "[ -f \"");
737 pos = buf + 6;
738
739 va_start (ap, fmt);
740 len = grub_vsnprintf(pos, 255, fmt, ap);
741 va_end (ap);
742
743 grub_strncpy(pos + len, "\" ]", 3);
744
745 debug("script exec %s\n", buf);
746
747 if (0 == grub_script_execute_sourcecode(buf))
748 {
749 return 1;
750 }
751
752 return 0;
753 }
754
755 int ventoy_is_dir_exist(const char *fmt, ...)
756 {
757 va_list ap;
758 int len;
759 char *pos = NULL;
760 char buf[256] = {0};
761
762 grub_snprintf(buf, sizeof(buf), "%s", "[ -d \"");
763 pos = buf + 6;
764
765 va_start (ap, fmt);
766 len = grub_vsnprintf(pos, 255, fmt, ap);
767 va_end (ap);
768
769 grub_strncpy(pos + len, "\" ]", 3);
770
771 debug("script exec %s\n", buf);
772
773 if (0 == grub_script_execute_sourcecode(buf))
774 {
775 return 1;
776 }
777
778 return 0;
779 }
780
781 int ventoy_gzip_compress(void *mem_in, int mem_in_len, void *mem_out, int mem_out_len)
782 {
783 mz_stream s;
784 grub_uint8_t *outbuf;
785 grub_uint8_t gzHdr[10] =
786 {
787 0x1F, 0x8B, /* magic */
788 8, /* z method */
789 0, /* flags */
790 0,0,0,0, /* mtime */
791 4, /* xfl */
792 3, /* OS */
793 };
794
795 grub_memset(&s, 0, sizeof(mz_stream));
796
797 mz_deflateInit2(&s, 1, MZ_DEFLATED, -MZ_DEFAULT_WINDOW_BITS, 6, MZ_DEFAULT_STRATEGY);
798
799 outbuf = (grub_uint8_t *)mem_out;
800
801 mem_out_len -= sizeof(gzHdr) + 8;
802 grub_memcpy(outbuf, gzHdr, sizeof(gzHdr));
803 outbuf += sizeof(gzHdr);
804
805 s.avail_in = mem_in_len;
806 s.next_in = mem_in;
807
808 s.avail_out = mem_out_len;
809 s.next_out = outbuf;
810
811 mz_deflate(&s, MZ_FINISH);
812
813 mz_deflateEnd(&s);
814
815 outbuf += s.total_out;
816 *(grub_uint32_t *)outbuf = grub_getcrc32c(0, outbuf, s.total_out);
817 *(grub_uint32_t *)(outbuf + 4) = (grub_uint32_t)(s.total_out);
818
819 return s.total_out + sizeof(gzHdr) + 8;
820 }
821
822
823 #if 0
824 ventoy grub cmds
825 #endif
826
827 static grub_err_t ventoy_cmd_debug(grub_extcmd_context_t ctxt, int argc, char **args)
828 {
829 if (argc != 1)
830 {
831 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {on|off}", cmd_raw_name);
832 }
833
834 if (0 == grub_strcmp(args[0], "on"))
835 {
836 g_ventoy_debug = 1;
837 grub_env_set("vtdebug_flag", "debug");
838 }
839 else
840 {
841 g_ventoy_debug = 0;
842 grub_env_set("vtdebug_flag", "");
843 }
844
845 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
846 }
847
848 static grub_err_t ventoy_cmd_break(grub_extcmd_context_t ctxt, int argc, char **args)
849 {
850 (void)ctxt;
851
852 if (argc < 1 || (args[0][0] != '0' && args[0][0] != '1'))
853 {
854 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name);
855 grub_printf(" level:\r\n");
856 grub_printf(" 01/11: busybox / (+cat log)\r\n");
857 grub_printf(" 02/12: initrd / (+cat log)\r\n");
858 grub_printf(" 03/13: hook / (+cat log)\r\n");
859 grub_printf("\r\n");
860 grub_printf(" debug:\r\n");
861 grub_printf(" 0: debug is off\r\n");
862 grub_printf(" 1: debug is on\r\n");
863 grub_printf("\r\n");
864 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
865 }
866
867 g_ventoy_break_level = (grub_uint8_t)grub_strtoul(args[0], NULL, 16);
868
869 if (argc > 1 && grub_strtoul(args[1], NULL, 10) > 0)
870 {
871 g_ventoy_debug_level = 1;
872 }
873
874 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
875 }
876
877 static grub_err_t ventoy_cmd_strstr(grub_extcmd_context_t ctxt, int argc, char **args)
878 {
879 (void)ctxt;
880
881 if (argc != 2)
882 {
883 return 1;
884 }
885
886 return (grub_strstr(args[0], args[1])) ? 0 : 1;
887 }
888
889 static grub_err_t ventoy_cmd_strbegin(grub_extcmd_context_t ctxt, int argc, char **args)
890 {
891 char *c0, *c1;
892
893 (void)ctxt;
894
895 if (argc != 2)
896 {
897 return 1;
898 }
899
900 c0 = args[0];
901 c1 = args[1];
902
903 while (*c0 && *c1)
904 {
905 if (*c0 != *c1)
906 {
907 return 1;
908 }
909 c0++;
910 c1++;
911 }
912
913 if (*c1)
914 {
915 return 1;
916 }
917
918 return 0;
919 }
920
921 static grub_err_t ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt, int argc, char **args)
922 {
923 char *c0, *c1;
924
925 (void)ctxt;
926
927 if (argc != 2)
928 {
929 return 1;
930 }
931
932 c0 = args[0];
933 c1 = args[1];
934
935 while (*c0 && *c1)
936 {
937 if ((*c0 != *c1) && (*c0 != grub_toupper(*c1)))
938 {
939 return 1;
940 }
941 c0++;
942 c1++;
943 }
944
945 if (*c1)
946 {
947 return 1;
948 }
949
950 return 0;
951 }
952
953 static grub_err_t ventoy_cmd_incr(grub_extcmd_context_t ctxt, int argc, char **args)
954 {
955 long value_long = 0;
956 char buf[32];
957
958 if ((argc != 2) || (!ventoy_is_decimal(args[1])))
959 {
960 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Variable} {Int}", cmd_raw_name);
961 }
962
963 if (GRUB_ERR_NONE != ventoy_check_decimal_var(args[0], &value_long))
964 {
965 return grub_errno;
966 }
967
968 value_long += grub_strtol(args[1], NULL, 10);
969
970 grub_snprintf(buf, sizeof(buf), "%ld", value_long);
971 grub_env_set(args[0], buf);
972
973 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
974 }
975
976 static grub_err_t ventoy_cmd_mod(grub_extcmd_context_t ctxt, int argc, char **args)
977 {
978 ulonglong value1 = 0;
979 ulonglong value2 = 0;
980 char buf[32];
981
982 if (argc != 3)
983 {
984 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name);
985 }
986
987 value1 = grub_strtoull(args[0], NULL, 10);
988 value2 = grub_strtoull(args[1], NULL, 10);
989
990 grub_snprintf(buf, sizeof(buf), "%llu", (value1 & (value2 - 1)));
991 grub_env_set(args[2], buf);
992
993 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
994 }
995
996 static grub_err_t ventoy_cmd_file_size(grub_extcmd_context_t ctxt, int argc, char **args)
997 {
998 int rc = 1;
999 char buf[32];
1000 grub_file_t file;
1001
1002 (void)ctxt;
1003 (void)argc;
1004 (void)args;
1005
1006 if (argc != 2)
1007 {
1008 return rc;
1009 }
1010
1011 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
1012 if (file == NULL)
1013 {
1014 debug("failed to open file <%s> for udf check\n", args[0]);
1015 return 1;
1016 }
1017
1018 grub_snprintf(buf, sizeof(buf), "%llu", (unsigned long long)file->size);
1019
1020 grub_env_set(args[1], buf);
1021
1022 grub_file_close(file);
1023 rc = 0;
1024
1025 return rc;
1026 }
1027
1028 static grub_err_t ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt, int argc, char **args)
1029 {
1030 grub_file_t file;
1031
1032 (void)ctxt;
1033 (void)argc;
1034 (void)args;
1035
1036 g_wimboot_enable = 0;
1037 grub_check_free(g_wimiso_path);
1038 grub_check_free(g_wimiso_chunk_list.chunk);
1039
1040 file = grub_file_open(args[0], VENTOY_FILE_TYPE);
1041 if (!file)
1042 {
1043 return 0;
1044 }
1045
1046 grub_memset(&g_wimiso_chunk_list, 0, sizeof(g_wimiso_chunk_list));
1047 g_wimiso_chunk_list.chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
1048 if (NULL == g_wimiso_chunk_list.chunk)
1049 {
1050 return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n");
1051 }
1052
1053 g_wimiso_chunk_list.max_chunk = DEFAULT_CHUNK_NUM;
1054 g_wimiso_chunk_list.cur_chunk = 0;
1055
1056 ventoy_get_block_list(file, &g_wimiso_chunk_list, file->device->disk->partition->start);
1057
1058 g_wimboot_enable = 1;
1059 g_wimiso_path = grub_strdup(args[0]);
1060
1061 grub_file_close(file);
1062
1063 return 0;
1064 }
1065
1066 static grub_err_t ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt, int argc, char **args)
1067 {
1068 int len = 0;
1069 int totlen = 0;
1070 int offset = 0;
1071 grub_file_t file;
1072 char name[32];
1073 char value[32];
1074 char *buf = NULL;
1075 char *data = NULL;
1076 ventoy_iso9660_override *dirent;
1077
1078 (void)ctxt;
1079
1080 if (argc != 2)
1081 {
1082 return 1;
1083 }
1084
1085 totlen = sizeof(ventoy_chain_head);
1086
1087 if (ventoy_load_efiboot_template(&buf, &len, &offset))
1088 {
1089 debug("failed to load efiboot template %d\n", len);
1090 return 1;
1091 }
1092
1093 totlen += len;
1094
1095 debug("efiboot template len:%d offset:%d\n", len, offset);
1096
1097 file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s", args[0]);
1098 if (file == NULL)
1099 {
1100 debug("failed to open file <%s>\n", args[0]);
1101 return 1;
1102 }
1103
1104 totlen += ventoy_align_2k(file->size);
1105
1106 dirent = (ventoy_iso9660_override *)(buf + offset);
1107 dirent->first_sector = len / 2048;
1108 dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
1109 dirent->size = (grub_uint32_t)file->size;
1110 dirent->size_be = grub_swap_bytes32(dirent->size);
1111
1112 debug("rawiso len:%d efilen:%d total:%d\n", len, (int)file->size, totlen);
1113
1114 #ifdef GRUB_MACHINE_EFI
1115 data = (char *)grub_efi_allocate_iso_buf(totlen);
1116 #else
1117 data = (char *)grub_malloc(totlen);
1118 #endif
1119
1120 ventoy_fill_os_param(file, (ventoy_os_param *)data);
1121
1122 grub_memcpy(data + sizeof(ventoy_chain_head), buf, len);
1123 grub_check_free(buf);
1124
1125 grub_file_read(file, data + sizeof(ventoy_chain_head) + len, file->size);
1126 grub_file_close(file);
1127
1128 grub_snprintf(name, sizeof(name), "%s_addr", args[1]);
1129 grub_snprintf(value, sizeof(value), "0x%llx", (ulonglong)(ulong)data);
1130 grub_env_set(name, value);
1131
1132 grub_snprintf(name, sizeof(name), "%s_size", args[1]);
1133 grub_snprintf(value, sizeof(value), "%d", (int)(totlen));
1134 grub_env_set(name, value);
1135
1136 return 0;
1137 }
1138
1139 grub_err_t ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt, int argc, char **args)
1140 {
1141 (void)ctxt;
1142 (void)argc;
1143 (void)args;
1144
1145 g_vtoy_load_prompt = 0;
1146 grub_memset(g_vtoy_prompt_msg, 0, sizeof(g_vtoy_prompt_msg));
1147
1148 if (argc == 2 && args[0][0] == '1')
1149 {
1150 g_vtoy_load_prompt = 1;
1151 grub_snprintf(g_vtoy_prompt_msg, sizeof(g_vtoy_prompt_msg), "%s", args[1]);
1152 }
1153
1154 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1155 }
1156
1157 int ventoy_need_prompt_load_file(void)
1158 {
1159 return g_vtoy_load_prompt;
1160 }
1161
1162 grub_ssize_t ventoy_load_file_with_prompt(grub_file_t file, void *buf, grub_ssize_t size)
1163 {
1164 grub_uint64_t ro = 0;
1165 grub_uint64_t div = 0;
1166 grub_ssize_t left = size;
1167 char *cur = (char *)buf;
1168
1169 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg);
1170 grub_refresh();
1171
1172 while (left >= VTOY_SIZE_2MB)
1173 {
1174 grub_file_read(file, cur, VTOY_SIZE_2MB);
1175 cur += VTOY_SIZE_2MB;
1176 left -= VTOY_SIZE_2MB;
1177
1178 div = grub_divmod64((grub_uint64_t)((size - left) * 100), (grub_uint64_t)size, &ro);
1179 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg, (int)div);
1180 grub_refresh();
1181 }
1182
1183 if (left > 0)
1184 {
1185 grub_file_read(file, cur, left);
1186 }
1187
1188 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg);
1189 grub_refresh();
1190
1191 return size;
1192 }
1193
1194 static grub_err_t ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt, int argc, char **args)
1195 {
1196 int rc = 1;
1197 char name[32];
1198 char value[32];
1199 char *buf = NULL;
1200 grub_file_t file;
1201 enum grub_file_type type;
1202
1203 (void)ctxt;
1204 (void)argc;
1205 (void)args;
1206
1207 if (argc != 3)
1208 {
1209 return rc;
1210 }
1211
1212 if (grub_strcmp(args[0], "nodecompress") == 0)
1213 {
1214 type = VENTOY_FILE_TYPE;
1215 }
1216 else
1217 {
1218 type = GRUB_FILE_TYPE_LINUX_INITRD;
1219 }
1220
1221 file = ventoy_grub_file_open(type, "%s", args[1]);
1222 if (file == NULL)
1223 {
1224 debug("failed to open file <%s>\n", args[1]);
1225 return 1;
1226 }
1227
1228 #ifdef GRUB_MACHINE_EFI
1229 buf = (char *)grub_efi_allocate_chain_buf(file->size);
1230 #else
1231 buf = (char *)grub_malloc(file->size);
1232 #endif
1233
1234 if (!buf)
1235 {
1236 grub_file_close(file);
1237 return 1;
1238 }
1239
1240 if (g_vtoy_load_prompt)
1241 {
1242 ventoy_load_file_with_prompt(file, buf, file->size);
1243 }
1244 else
1245 {
1246 grub_file_read(file, buf, file->size);
1247 }
1248
1249 grub_snprintf(name, sizeof(name), "%s_addr", args[2]);
1250 grub_snprintf(value, sizeof(value), "0x%llx", (unsigned long long)(unsigned long)buf);
1251 grub_env_set(name, value);
1252
1253 grub_snprintf(name, sizeof(name), "%s_size", args[2]);
1254 grub_snprintf(value, sizeof(value), "%llu", (unsigned long long)file->size);
1255 grub_env_set(name, value);
1256
1257 grub_file_close(file);
1258 rc = 0;
1259
1260 return rc;
1261 }
1262
1263 static grub_err_t ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt, int argc, char **args)
1264 {
1265 int rc = 1;
1266 int headlen;
1267 char name[32];
1268 char value[32];
1269 char *buf = NULL;
1270 grub_file_t file;
1271
1272 (void)ctxt;
1273 (void)argc;
1274 (void)args;
1275
1276 if (argc != 2)
1277 {
1278 return rc;
1279 }
1280
1281 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
1282 if (file == NULL)
1283 {
1284 debug("failed to open file <%s> for udf check\n", args[0]);
1285 return 1;
1286 }
1287
1288 headlen = sizeof(ventoy_chain_head);
1289
1290 #ifdef GRUB_MACHINE_EFI
1291 buf = (char *)grub_efi_allocate_iso_buf(headlen + file->size);
1292 #else
1293 buf = (char *)grub_malloc(headlen + file->size);
1294 #endif
1295
1296 ventoy_fill_os_param(file, (ventoy_os_param *)buf);
1297
1298 grub_file_read(file, buf + headlen, file->size);
1299
1300 grub_snprintf(name, sizeof(name), "%s_addr", args[1]);
1301 grub_snprintf(value, sizeof(value), "0x%llx", (unsigned long long)(unsigned long)buf);
1302 grub_env_set(name, value);
1303
1304 grub_snprintf(name, sizeof(name), "%s_size", args[1]);
1305 grub_snprintf(value, sizeof(value), "%llu", (unsigned long long)file->size);
1306 grub_env_set(name, value);
1307
1308 grub_file_close(file);
1309 rc = 0;
1310
1311 return rc;
1312 }
1313
1314 static grub_err_t ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt, int argc, char **args)
1315 {
1316 (void)ctxt;
1317 (void)argc;
1318 (void)args;
1319
1320 if (grub_iso9660_is_joliet())
1321 {
1322 debug("This time has joliet process\n");
1323 return 0;
1324 }
1325 else
1326 {
1327 return 1;
1328 }
1329 }
1330
1331 static grub_err_t ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt, int argc, char **args)
1332 {
1333 (void)ctxt;
1334
1335 if (argc != 1)
1336 {
1337 return 1;
1338 }
1339
1340 if (args[0][0] == '1')
1341 {
1342 grub_iso9660_set_nojoliet(1);
1343 }
1344 else
1345 {
1346 grub_iso9660_set_nojoliet(0);
1347 }
1348
1349 return 0;
1350 }
1351
1352 static grub_err_t ventoy_cmd_is_udf(grub_extcmd_context_t ctxt, int argc, char **args)
1353 {
1354 int i;
1355 int rc = 1;
1356 grub_file_t file;
1357 grub_uint8_t buf[32];
1358
1359 (void)ctxt;
1360 (void)argc;
1361 (void)args;
1362
1363 if (argc != 1)
1364 {
1365 return rc;
1366 }
1367
1368 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
1369 if (file == NULL)
1370 {
1371 debug("failed to open file <%s> for udf check\n", args[0]);
1372 return 1;
1373 }
1374
1375 for (i = 16; i < 32; i++)
1376 {
1377 grub_file_seek(file, i * 2048);
1378 grub_file_read(file, buf, sizeof(buf));
1379 if (buf[0] == 255)
1380 {
1381 break;
1382 }
1383 }
1384
1385 i++;
1386 grub_file_seek(file, i * 2048);
1387 grub_file_read(file, buf, sizeof(buf));
1388
1389 if (grub_memcmp(buf + 1, "BEA01", 5) == 0)
1390 {
1391 i++;
1392 grub_file_seek(file, i * 2048);
1393 grub_file_read(file, buf, sizeof(buf));
1394
1395 if (grub_memcmp(buf + 1, "NSR02", 5) == 0 ||
1396 grub_memcmp(buf + 1, "NSR03", 5) == 0)
1397 {
1398 rc = 0;
1399 }
1400 }
1401
1402 grub_file_close(file);
1403
1404 debug("ISO UDF: %s\n", rc ? "NO" : "YES");
1405
1406 return rc;
1407 }
1408
1409 static grub_err_t ventoy_cmd_cmp(grub_extcmd_context_t ctxt, int argc, char **args)
1410 {
1411 long value_long1 = 0;
1412 long value_long2 = 0;
1413
1414 if ((argc != 3) || (!ventoy_is_decimal(args[0])) || (!ventoy_is_decimal(args[2])))
1415 {
1416 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name);
1417 }
1418
1419 value_long1 = grub_strtol(args[0], NULL, 10);
1420 value_long2 = grub_strtol(args[2], NULL, 10);
1421
1422 if (0 == grub_strcmp(args[1], "eq"))
1423 {
1424 grub_errno = (value_long1 == value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
1425 }
1426 else if (0 == grub_strcmp(args[1], "ne"))
1427 {
1428 grub_errno = (value_long1 != value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
1429 }
1430 else if (0 == grub_strcmp(args[1], "gt"))
1431 {
1432 grub_errno = (value_long1 > value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
1433 }
1434 else if (0 == grub_strcmp(args[1], "lt"))
1435 {
1436 grub_errno = (value_long1 < value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
1437 }
1438 else if (0 == grub_strcmp(args[1], "ge"))
1439 {
1440 grub_errno = (value_long1 >= value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
1441 }
1442 else if (0 == grub_strcmp(args[1], "le"))
1443 {
1444 grub_errno = (value_long1 <= value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
1445 }
1446 else
1447 {
1448 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name);
1449 }
1450
1451 return grub_errno;
1452 }
1453
1454 static grub_err_t ventoy_cmd_device(grub_extcmd_context_t ctxt, int argc, char **args)
1455 {
1456 char *pos = NULL;
1457 char buf[128] = {0};
1458
1459 if (argc != 2)
1460 {
1461 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s path var", cmd_raw_name);
1462 }
1463
1464 grub_strncpy(buf, (args[0][0] == '(') ? args[0] + 1 : args[0], sizeof(buf) - 1);
1465 pos = grub_strstr(buf, ",");
1466 if (pos)
1467 {
1468 *pos = 0;
1469 }
1470
1471 grub_env_set(args[1], buf);
1472
1473 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1474 }
1475
1476 static grub_err_t ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt, int argc, char **args)
1477 {
1478 int i;
1479 char buf[256];
1480 grub_disk_t disk;
1481 char *pos = NULL;
1482 const char *files[] = { "ventoy.dat", "VENTOY.DAT" };
1483
1484 (void)ctxt;
1485
1486 if (argc != 1)
1487 {
1488 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s (loop)", cmd_raw_name);
1489 }
1490
1491 for (i = 0; i < (int)ARRAY_SIZE(files); i++)
1492 {
1493 grub_snprintf(buf, sizeof(buf) - 1, "[ -e \"%s/%s\" ]", args[0], files[i]);
1494 if (0 == grub_script_execute_sourcecode(buf))
1495 {
1496 debug("file %s exist, ventoy_compatible YES\n", buf);
1497 grub_env_set("ventoy_compatible", "YES");
1498 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1499 }
1500 else
1501 {
1502 debug("file %s NOT exist\n", buf);
1503 }
1504 }
1505
1506 grub_snprintf(buf, sizeof(buf) - 1, "%s", args[0][0] == '(' ? (args[0] + 1) : args[0]);
1507 pos = grub_strstr(buf, ")");
1508 if (pos)
1509 {
1510 *pos = 0;
1511 }
1512
1513 disk = grub_disk_open(buf);
1514 if (disk)
1515 {
1516 grub_disk_read(disk, 16 << 2, 0, 1024, g_img_swap_tmp_buf);
1517 grub_disk_close(disk);
1518
1519 g_img_swap_tmp_buf[703] = 0;
1520 for (i = 318; i < 703; i++)
1521 {
1522 if (g_img_swap_tmp_buf[i] == 'V' &&
1523 0 == grub_strncmp(g_img_swap_tmp_buf + i, VENTOY_COMPATIBLE_STR, VENTOY_COMPATIBLE_STR_LEN))
1524 {
1525 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i);
1526 grub_env_set("ventoy_compatible", "YES");
1527 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1528 }
1529 }
1530 }
1531 else
1532 {
1533 debug("failed to open disk <%s>\n", buf);
1534 }
1535
1536 grub_env_set("ventoy_compatible", "NO");
1537 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1538 }
1539
1540 int ventoy_cmp_img(img_info *img1, img_info *img2)
1541 {
1542 char *s1, *s2;
1543 int c1 = 0;
1544 int c2 = 0;
1545
1546 if (g_plugin_image_list == VENTOY_IMG_WHITE_LIST)
1547 {
1548 return (img1->plugin_list_index - img2->plugin_list_index);
1549 }
1550
1551 for (s1 = img1->name, s2 = img2->name; *s1 && *s2; s1++, s2++)
1552 {
1553 c1 = *s1;
1554 c2 = *s2;
1555
1556 if (0 == g_sort_case_sensitive)
1557 {
1558 if (grub_islower(c1))
1559 {
1560 c1 = c1 - 'a' + 'A';
1561 }
1562
1563 if (grub_islower(c2))
1564 {
1565 c2 = c2 - 'a' + 'A';
1566 }
1567 }
1568
1569 if (c1 != c2)
1570 {
1571 break;
1572 }
1573 }
1574
1575 return (c1 - c2);
1576 }
1577
1578 static int ventoy_cmp_subdir(img_iterator_node *node1, img_iterator_node *node2)
1579 {
1580 char *s1, *s2;
1581 int c1 = 0;
1582 int c2 = 0;
1583
1584 if (g_plugin_image_list == VENTOY_IMG_WHITE_LIST)
1585 {
1586 return (node1->plugin_list_index - node2->plugin_list_index);
1587 }
1588
1589 for (s1 = node1->dir, s2 = node2->dir; *s1 && *s2; s1++, s2++)
1590 {
1591 c1 = *s1;
1592 c2 = *s2;
1593
1594 if (0 == g_sort_case_sensitive)
1595 {
1596 if (grub_islower(c1))
1597 {
1598 c1 = c1 - 'a' + 'A';
1599 }
1600
1601 if (grub_islower(c2))
1602 {
1603 c2 = c2 - 'a' + 'A';
1604 }
1605 }
1606
1607 if (c1 != c2)
1608 {
1609 break;
1610 }
1611 }
1612
1613 return (c1 - c2);
1614 }
1615
1616 void ventoy_swap_img(img_info *img1, img_info *img2)
1617 {
1618 grub_memcpy(&g_img_swap_tmp, img1, sizeof(img_info));
1619
1620 grub_memcpy(img1, img2, sizeof(img_info));
1621 img1->next = g_img_swap_tmp.next;
1622 img1->prev = g_img_swap_tmp.prev;
1623
1624 g_img_swap_tmp.next = img2->next;
1625 g_img_swap_tmp.prev = img2->prev;
1626 grub_memcpy(img2, &g_img_swap_tmp, sizeof(img_info));
1627 }
1628
1629 static int ventoy_img_name_valid(const char *filename, grub_size_t namelen)
1630 {
1631 (void)namelen;
1632
1633 if (g_filt_dot_underscore_file && filename[0] == '.' && filename[1] == '_')
1634 {
1635 return 0;
1636 }
1637
1638 return 1;
1639 }
1640
1641 static int ventoy_collect_img_files(const char *filename, const struct grub_dirhook_info *info, void *data)
1642 {
1643 //int i = 0;
1644 int type = 0;
1645 int ignore = 0;
1646 int index = 0;
1647 grub_size_t len;
1648 img_info *img;
1649 img_info *tail;
1650 const menu_tip *tip;
1651 img_iterator_node *tmp;
1652 img_iterator_node *new_node;
1653 img_iterator_node *node = (img_iterator_node *)data;
1654
1655 if (g_enumerate_time_checked == 0)
1656 {
1657 g_enumerate_finish_time_ms = grub_get_time_ms();
1658 if ((g_enumerate_finish_time_ms - g_enumerate_start_time_ms) >= 3000)
1659 {
1660 grub_cls();
1661 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1662 grub_refresh();
1663 g_enumerate_time_checked = 1;
1664 }
1665 }
1666
1667 len = grub_strlen(filename);
1668
1669 if (info->dir)
1670 {
1671 if (node->level + 1 > g_img_max_search_level)
1672 {
1673 return 0;
1674 }
1675
1676 if ((len == 1 && filename[0] == '.') ||
1677 (len == 2 && filename[0] == '.' && filename[1] == '.'))
1678 {
1679 return 0;
1680 }
1681
1682 if (!ventoy_img_name_valid(filename, len))
1683 {
1684 return 0;
1685 }
1686
1687 if (filename[0] == '$' && 0 == grub_strncmp(filename, "$RECYCLE.BIN", 12))
1688 {
1689 return 0;
1690 }
1691
1692 if (g_plugin_image_list == VENTOY_IMG_WHITE_LIST)
1693 {
1694 grub_snprintf(g_img_swap_tmp_buf, sizeof(g_img_swap_tmp_buf), "%s%s/", node->dir, filename);
1695 index = ventoy_plugin_get_image_list_index(vtoy_class_directory, g_img_swap_tmp_buf);
1696 if (index == 0)
1697 {
1698 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf);
1699 return 0;
1700 }
1701 }
1702
1703 new_node = grub_zalloc(sizeof(img_iterator_node));
1704 if (new_node)
1705 {
1706 new_node->level = node->level + 1;
1707 new_node->plugin_list_index = index;
1708 new_node->dirlen = grub_snprintf(new_node->dir, sizeof(new_node->dir), "%s%s/", node->dir, filename);
1709
1710 g_enum_fs->fs_dir(g_enum_dev, new_node->dir, ventoy_check_ignore_flag, &ignore);
1711 if (ignore)
1712 {
1713 debug("Directory %s ignored...\n", new_node->dir);
1714 grub_free(new_node);
1715 return 0;
1716 }
1717
1718 new_node->tail = node->tail;
1719
1720 new_node->parent = node;
1721 if (!node->firstchild)
1722 {
1723 node->firstchild = new_node;
1724 }
1725
1726 if (g_img_iterator_tail)
1727 {
1728 g_img_iterator_tail->next = new_node;
1729 g_img_iterator_tail = new_node;
1730 }
1731 else
1732 {
1733 g_img_iterator_head.next = new_node;
1734 g_img_iterator_tail = new_node;
1735 }
1736 }
1737 }
1738 else
1739 {
1740 debug("Find a file %s\n", filename);
1741 if (len < 4)
1742 {
1743 return 0;
1744 }
1745
1746 if (FILE_FLT(ISO) && 0 == grub_strcasecmp(filename + len - 4, ".iso"))
1747 {
1748 type = img_type_iso;
1749 }
1750 else if (FILE_FLT(WIM) && g_wimboot_enable && (0 == grub_strcasecmp(filename + len - 4, ".wim")))
1751 {
1752 type = img_type_wim;
1753 }
1754 else if (FILE_FLT(VHD) && g_vhdboot_enable && (0 == grub_strcasecmp(filename + len - 4, ".vhd") ||
1755 (len >= 5 && 0 == grub_strcasecmp(filename + len - 5, ".vhdx"))))
1756 {
1757 type = img_type_vhd;
1758 }
1759 #ifdef GRUB_MACHINE_EFI
1760 else if (FILE_FLT(EFI) && 0 == grub_strcasecmp(filename + len - 4, ".efi"))
1761 {
1762 type = img_type_efi;
1763 }
1764 #endif
1765 else if (FILE_FLT(IMG) && 0 == grub_strcasecmp(filename + len - 4, ".img"))
1766 {
1767 if (len == 18 && grub_strncmp(filename, "ventoy_", 7) == 0)
1768 {
1769 if (grub_strncmp(filename + 7, "wimboot", 7) == 0 ||
1770 grub_strncmp(filename + 7, "vhdboot", 7) == 0)
1771 {
1772 return 0;
1773 }
1774 }
1775 type = img_type_img;
1776 }
1777 else if (FILE_FLT(VTOY) && len >= 5 && 0 == grub_strcasecmp(filename + len - 5, ".vtoy"))
1778 {
1779 type = img_type_vtoy;
1780 }
1781 else if (len >= 9 && 0 == grub_strcasecmp(filename + len - 5, ".vcfg"))
1782 {
1783 if (filename[len - 9] == '.' || (len >= 10 && filename[len - 10] == '.'))
1784 {
1785 grub_snprintf(g_img_swap_tmp_buf, sizeof(g_img_swap_tmp_buf), "%s%s", node->dir, filename);
1786 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf);
1787 }
1788 return 0;
1789 }
1790 else
1791 {
1792 return 0;
1793 }
1794
1795 if (g_filt_dot_underscore_file && filename[0] == '.' && filename[1] == '_')
1796 {
1797 return 0;
1798 }
1799
1800 if (g_plugin_image_list)
1801 {
1802 grub_snprintf(g_img_swap_tmp_buf, sizeof(g_img_swap_tmp_buf), "%s%s", node->dir, filename);
1803 index = ventoy_plugin_get_image_list_index(vtoy_class_image_file, g_img_swap_tmp_buf);
1804 if (VENTOY_IMG_WHITE_LIST == g_plugin_image_list && index == 0)
1805 {
1806 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf);
1807 return 0;
1808 }
1809 else if (VENTOY_IMG_BLACK_LIST == g_plugin_image_list && index > 0)
1810 {
1811 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf, index);
1812 return 0;
1813 }
1814 }
1815
1816 img = grub_zalloc(sizeof(img_info));
1817 if (img)
1818 {
1819 img->type = type;
1820 img->plugin_list_index = index;
1821 grub_snprintf(img->name, sizeof(img->name), "%s", filename);
1822
1823 img->pathlen = grub_snprintf(img->path, sizeof(img->path), "%s%s", node->dir, img->name);
1824
1825 img->size = info->size;
1826 if (0 == img->size)
1827 {
1828 img->size = ventoy_grub_get_file_size("%s/%s%s", g_iso_path, node->dir, filename);
1829 }
1830
1831 if (img->size < VTOY_FILT_MIN_FILE_SIZE)
1832 {
1833 debug("img <%s> size too small %llu\n", img->name, (ulonglong)img->size);
1834 grub_free(img);
1835 return 0;
1836 }
1837
1838 if (g_ventoy_img_list)
1839 {
1840 tail = *(node->tail);
1841 img->prev = tail;
1842 tail->next = img;
1843 }
1844 else
1845 {
1846 g_ventoy_img_list = img;
1847 }
1848
1849 img->id = g_ventoy_img_count;
1850 img->parent = node;
1851 if (node && NULL == node->firstiso)
1852 {
1853 node->firstiso = img;
1854 }
1855
1856 node->isocnt++;
1857 tmp = node->parent;
1858 while (tmp)
1859 {
1860 tmp->isocnt++;
1861 tmp = tmp->parent;
1862 }
1863
1864 *((img_info **)(node->tail)) = img;
1865 g_ventoy_img_count++;
1866
1867 img->alias = ventoy_plugin_get_menu_alias(vtoy_alias_image_file, img->path);
1868
1869 tip = ventoy_plugin_get_menu_tip(img->path);
1870 if (tip)
1871 {
1872 img->tip1 = tip->tip1;
1873 img->tip2 = tip->tip2;
1874 }
1875
1876 img->class = ventoy_plugin_get_menu_class(vtoy_class_image_file, img->name, img->path);
1877 if (!img->class)
1878 {
1879 img->class = g_menu_class[type];
1880 }
1881 img->menu_prefix = g_menu_prefix[type];
1882
1883 if (img_type_iso == type)
1884 {
1885 if (ventoy_plugin_check_memdisk(img->path))
1886 {
1887 img->menu_prefix = "miso";
1888 }
1889 }
1890
1891 debug("Add %s%s to list %d\n", node->dir, filename, g_ventoy_img_count);
1892 }
1893 }
1894
1895 return 0;
1896 }
1897
1898 int ventoy_fill_data(grub_uint32_t buflen, char *buffer)
1899 {
1900 int len = GRUB_UINT_MAX;
1901 const char *value = NULL;
1902 char name[32] = {0};
1903 char plat[32] = {0};
1904 char guidstr[32] = {0};
1905 ventoy_guid guid = VENTOY_GUID;
1906 const char *fmt1 = NULL;
1907 const char *fmt2 = NULL;
1908 const char *fmt3 = NULL;
1909 grub_uint32_t *puint = (grub_uint32_t *)name;
1910 grub_uint32_t *puint2 = (grub_uint32_t *)plat;
1911 const char fmtdata[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1912 const char fmtcode[]={
1913 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1914 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1915 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1916 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1917 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1918 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1919 };
1920
1921 grub_memset(name, 0, sizeof(name));
1922 puint[0] = grub_swap_bytes32(0x56454e54);
1923 puint[3] = grub_swap_bytes32(0x4f4e0000);
1924 puint[2] = grub_swap_bytes32(0x45525349);
1925 puint[1] = grub_swap_bytes32(0x4f595f56);
1926 value = ventoy_get_env(name);
1927
1928 grub_memset(name, 0, sizeof(name));
1929 puint[1] = grub_swap_bytes32(0x5f544f50);
1930 puint[0] = grub_swap_bytes32(0x56544c45);
1931 fmt1 = ventoy_get_env(name);
1932 if (!fmt1)
1933 {
1934 fmt1 = fmtdata;
1935 }
1936
1937 grub_memset(name, 0, sizeof(name));
1938 puint[1] = grub_swap_bytes32(0x5f4c4654);
1939 puint[0] = grub_swap_bytes32(0x56544c45);
1940 fmt2 = ventoy_get_env(name);
1941
1942 grub_memset(name, 0, sizeof(name));
1943 puint[1] = grub_swap_bytes32(0x5f434c52);
1944 puint[0] = grub_swap_bytes32(0x56544c45);
1945 fmt3 = ventoy_get_env(name);
1946
1947 grub_memcpy(guidstr, &guid, sizeof(guid));
1948
1949 puint2[0] = grub_swap_bytes32(g_ventoy_plat_data);
1950
1951 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1952 #pragma GCC diagnostic push
1953 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1954 len = grub_snprintf(buffer, buflen, fmtcode,
1955 fmt1 ? fmt1 : fmtdata,
1956 fmt2 ? fmt2 : fmtdata + 4,
1957 value ? value : "", plat, guidstr,
1958 fmt3 ? fmt3 : fmtdata + 6);
1959 #pragma GCC diagnostic pop
1960
1961 grub_memset(name, 0, sizeof(name));
1962 puint[0] = grub_swap_bytes32(0x76746f79);
1963 puint[2] = grub_swap_bytes32(0x656e7365);
1964 puint[1] = grub_swap_bytes32(0x5f6c6963);
1965 ventoy_set_env(name, guidstr);
1966
1967 return len;
1968 }
1969
1970 int ventoy_check_password(const vtoy_password *pwd, int retry)
1971 {
1972 int offset;
1973 char input[256];
1974 grub_uint8_t md5[16];
1975
1976 while (retry--)
1977 {
1978 grub_memset(input, 0, sizeof(input));
1979
1980 grub_printf("Enter password: ");
1981 grub_refresh();
1982
1983 if (pwd->type == VTOY_PASSWORD_TXT)
1984 {
1985 grub_password_get(input, 128);
1986 if (grub_strcmp(pwd->text, input) == 0)
1987 {
1988 return 0;
1989 }
1990 }
1991 else if (pwd->type == VTOY_PASSWORD_MD5)
1992 {
1993 grub_password_get(input, 128);
1994 grub_crypto_hash(GRUB_MD_MD5, md5, input, grub_strlen(input));
1995 if (grub_memcmp(pwd->md5, md5, 16) == 0)
1996 {
1997 return 0;
1998 }
1999 }
2000 else if (pwd->type == VTOY_PASSWORD_SALT_MD5)
2001 {
2002 offset = (int)grub_snprintf(input, 128, "%s", pwd->salt);
2003 grub_password_get(input + offset, 128);
2004
2005 grub_crypto_hash(GRUB_MD_MD5, md5, input, grub_strlen(input));
2006 if (grub_memcmp(pwd->md5, md5, 16) == 0)
2007 {
2008 return 0;
2009 }
2010 }
2011
2012 grub_printf("Invalid password!\n\n");
2013 grub_refresh();
2014 }
2015
2016 return 1;
2017 }
2018
2019 static img_info * ventoy_get_min_iso(img_iterator_node *node)
2020 {
2021 img_info *minimg = NULL;
2022 img_info *img = (img_info *)(node->firstiso);
2023
2024 while (img && (img_iterator_node *)(img->parent) == node)
2025 {
2026 if (img->select == 0 && (NULL == minimg || ventoy_cmp_img(img, minimg) < 0))
2027 {
2028 minimg = img;
2029 }
2030 img = img->next;
2031 }
2032
2033 if (minimg)
2034 {
2035 minimg->select = 1;
2036 }
2037
2038 return minimg;
2039 }
2040
2041 static img_iterator_node * ventoy_get_min_child(img_iterator_node *node)
2042 {
2043 img_iterator_node *Minchild = NULL;
2044 img_iterator_node *child = node->firstchild;
2045
2046 while (child && child->parent == node)
2047 {
2048 if (child->select == 0 && (NULL == Minchild || ventoy_cmp_subdir(child, Minchild) < 0))
2049 {
2050 Minchild = child;
2051 }
2052 child = child->next;
2053 }
2054
2055 if (Minchild)
2056 {
2057 Minchild->select = 1;
2058 }
2059
2060 return Minchild;
2061 }
2062
2063 static int ventoy_dynamic_tree_menu(img_iterator_node *node)
2064 {
2065 int offset = 1;
2066 img_info *img = NULL;
2067 const char *dir_class = NULL;
2068 const char *dir_alias = NULL;
2069 img_iterator_node *child = NULL;
2070
2071 if (node->isocnt == 0 || node->done == 1)
2072 {
2073 return 0;
2074 }
2075
2076 if (node->parent && node->parent->dirlen < node->dirlen)
2077 {
2078 offset = node->parent->dirlen;
2079 }
2080
2081 if (node == &g_img_iterator_head)
2082 {
2083 if (g_default_menu_mode == 0)
2084 {
2085 if (g_tree_view_menu_style == 0)
2086 {
2087 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
2088 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2089 " echo 'return ...' \n"
2090 "}\n", "<--");
2091 }
2092 else
2093 {
2094 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
2095 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2096 " echo '%s ...' \n"
2097 "}\n", "return");
2098 }
2099 }
2100 }
2101 else
2102 {
2103 node->dir[node->dirlen - 1] = 0;
2104 dir_class = ventoy_plugin_get_menu_class(vtoy_class_directory, node->dir, node->dir);
2105 if (!dir_class)
2106 {
2107 dir_class = "vtoydir";
2108 }
2109
2110 dir_alias = ventoy_plugin_get_menu_alias(vtoy_alias_directory, node->dir);
2111 if (dir_alias)
2112 {
2113 if (g_tree_view_menu_style == 0)
2114 {
2115 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
2116 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2117 "DIR", dir_alias, dir_class, node->dir + offset);
2118 }
2119 else
2120 {
2121 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
2122 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2123 dir_alias, dir_class, node->dir + offset);
2124 }
2125 }
2126 else
2127 {
2128 dir_alias = node->dir + offset;
2129
2130 if (g_tree_view_menu_style == 0)
2131 {
2132 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
2133 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2134 "DIR", dir_alias, dir_class, node->dir + offset);
2135 }
2136 else
2137 {
2138 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
2139 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2140 dir_alias, dir_class, node->dir + offset);
2141 }
2142 }
2143
2144 if (g_tree_view_menu_style == 0)
2145 {
2146 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
2147 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
2148 " echo 'return ...' \n"
2149 "}\n", "<--");
2150 }
2151 else
2152 {
2153 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
2154 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
2155 " echo '%s ...' \n"
2156 "}\n", "return");
2157 }
2158 }
2159
2160 while ((child = ventoy_get_min_child(node)) != NULL)
2161 {
2162 ventoy_dynamic_tree_menu(child);
2163 }
2164
2165 while ((img = ventoy_get_min_iso(node)) != NULL)
2166 {
2167 if (g_tree_view_menu_style == 0)
2168 {
2169 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
2170 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2171 " %s_%s \n"
2172 "}\n",
2173 grub_get_human_size(img->size, GRUB_HUMAN_SIZE_SHORT),
2174 img->unsupport ? "[***********] " : "",
2175 img->alias ? img->alias : img->name, img->class, img,
2176 img->menu_prefix,
2177 img->unsupport ? "unsupport_menuentry" : "common_menuentry");
2178 }
2179 else
2180 {
2181 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
2182 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2183 " %s_%s \n"
2184 "}\n",
2185 img->unsupport ? "[***********] " : "",
2186 img->alias ? img->alias : img->name, img->class, img,
2187 img->menu_prefix,
2188 img->unsupport ? "unsupport_menuentry" : "common_menuentry");
2189 }
2190 }
2191
2192 if (node != &g_img_iterator_head)
2193 {
2194 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "%s", "}\n");
2195 }
2196
2197 node->done = 1;
2198 return 0;
2199 }
2200
2201 static int ventoy_set_default_menu(void)
2202 {
2203 int img_len = 0;
2204 char *pos = NULL;
2205 char *end = NULL;
2206 char *def = NULL;
2207 const char *strdata = NULL;
2208 img_info *cur = NULL;
2209 img_info *default_node = NULL;
2210 const char *default_image = NULL;
2211
2212 default_image = ventoy_get_env("VTOY_DEFAULT_IMAGE");
2213 if (default_image && default_image[0] == '/')
2214 {
2215 img_len = grub_strlen(default_image);
2216
2217 for (cur = g_ventoy_img_list; cur; cur = cur->next)
2218 {
2219 if (img_len == cur->pathlen && grub_strcmp(default_image, cur->path) == 0)
2220 {
2221 default_node = cur;
2222 break;
2223 }
2224 }
2225
2226 if (!default_node)
2227 {
2228 return 1;
2229 }
2230
2231 if (0 == g_default_menu_mode)
2232 {
2233 vtoy_ssprintf(g_list_script_buf, g_list_script_pos, "set default='VID_%p'\n", default_node);
2234 }
2235 else
2236 {
2237 def = grub_strdup(default_image);
2238 if (!def)
2239 {
2240 return 1;
2241 }
2242
2243 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "set default=%c", '\'');
2244
2245 strdata = ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2246 if (strdata && strdata[0] == '/')
2247 {
2248 pos = def + grub_strlen(strdata);
2249 if (*pos == '/')
2250 {
2251 pos++;
2252 }
2253 }
2254 else
2255 {
2256 pos = def + 1;
2257 }
2258
2259 while ((end = grub_strchr(pos, '/')) != NULL)
2260 {
2261 *end = 0;
2262 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "DIR_%s>", pos);
2263 pos = end + 1;
2264 }
2265
2266 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "VID_%p'\n", default_node);
2267 grub_free(def);
2268 }
2269 }
2270
2271 return 0;
2272 }
2273
2274 static grub_err_t ventoy_cmd_clear_img(grub_extcmd_context_t ctxt, int argc, char **args)
2275 {
2276 img_info *next = NULL;
2277 img_info *cur = g_ventoy_img_list;
2278
2279 (void)ctxt;
2280 (void)argc;
2281 (void)args;
2282
2283 while (cur)
2284 {
2285 next = cur->next;
2286 grub_free(cur);
2287 cur = next;
2288 }
2289
2290 g_ventoy_img_list = NULL;
2291 g_ventoy_img_count = 0;
2292
2293 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2294 }
2295
2296 static grub_err_t ventoy_cmd_img_name(grub_extcmd_context_t ctxt, int argc, char **args)
2297 {
2298 long img_id = 0;
2299 img_info *cur = g_ventoy_img_list;
2300
2301 (void)ctxt;
2302
2303 if (argc != 2 || (!ventoy_is_decimal(args[0])))
2304 {
2305 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {imageID} {var}", cmd_raw_name);
2306 }
2307
2308 img_id = grub_strtol(args[0], NULL, 10);
2309 if (img_id >= g_ventoy_img_count)
2310 {
2311 return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such many images %ld %ld", img_id, g_ventoy_img_count);
2312 }
2313
2314 debug("Find image %ld name \n", img_id);
2315
2316 while (cur && img_id > 0)
2317 {
2318 img_id--;
2319 cur = cur->next;
2320 }
2321
2322 if (!cur)
2323 {
2324 return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such many images");
2325 }
2326
2327 debug("image name is %s\n", cur->name);
2328
2329 grub_env_set(args[1], cur->name);
2330
2331 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2332 }
2333
2334 static grub_err_t ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt, int argc, char **args)
2335 {
2336 int len = 0;
2337 char id[32] = {0};
2338 img_info *cur = g_ventoy_img_list;
2339
2340 (void)ctxt;
2341
2342 if (argc != 1)
2343 {
2344 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {var}", cmd_raw_name);
2345 }
2346
2347 len = (int)grub_strlen(args[0]);
2348
2349 while (cur)
2350 {
2351 if (len == cur->pathlen && 0 == grub_strcmp(args[0], cur->path))
2352 {
2353 break;
2354 }
2355 cur = cur->next;
2356 }
2357
2358 if (!cur)
2359 {
2360 return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such image");
2361 }
2362
2363 grub_snprintf(id, sizeof(id), "VID_%p", cur);
2364 grub_env_set("chosen", id);
2365 grub_env_export("chosen");
2366
2367 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2368 }
2369
2370 static grub_err_t ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt, int argc, char **args)
2371 {
2372 char value[32];
2373 char *pos = NULL;
2374 const char *id = NULL;
2375 img_info *cur = NULL;
2376
2377 (void)ctxt;
2378
2379 if (argc < 1 || argc > 2)
2380 {
2381 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {var}", cmd_raw_name);
2382 }
2383
2384 id = grub_env_get("chosen");
2385
2386 pos = grub_strstr(id, "VID_");
2387 if (pos)
2388 {
2389 cur = (img_info *)(void *)grub_strtoul(pos + 4, NULL, 16);
2390 }
2391 else
2392 {
2393 cur = g_ventoy_img_list;
2394 }
2395
2396 if (!cur)
2397 {
2398 return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such image");
2399 }
2400
2401 grub_env_set(args[0], cur->path);
2402
2403 if (argc > 1)
2404 {
2405 grub_snprintf(value, sizeof(value), "%llu", (ulonglong)(cur->size));
2406 grub_env_set(args[1], value);
2407 }
2408
2409 g_svd_replace_offset = 0;
2410
2411 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2412 }
2413
2414
2415 static grub_err_t ventoy_cmd_list_img(grub_extcmd_context_t ctxt, int argc, char **args)
2416 {
2417 int len;
2418 grub_fs_t fs;
2419 grub_device_t dev = NULL;
2420 img_info *cur = NULL;
2421 img_info *tail = NULL;
2422 img_info *min = NULL;
2423 img_info *head = NULL;
2424 const char *strdata = NULL;
2425 char *device_name = NULL;
2426 char buf[32];
2427 img_iterator_node *node = NULL;
2428 img_iterator_node *tmp = NULL;
2429
2430 (void)ctxt;
2431
2432 if (argc != 2)
2433 {
2434 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {device} {cntvar}", cmd_raw_name);
2435 }
2436
2437 if (g_ventoy_img_list || g_ventoy_img_count)
2438 {
2439 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Must clear image before list");
2440 }
2441
2442 VTOY_CMD_CHECK(1);
2443
2444 g_enumerate_time_checked = 0;
2445 g_enumerate_start_time_ms = grub_get_time_ms();
2446
2447 strdata = ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2448 if (strdata && strdata[0] == '1' && strdata[1] == 0)
2449 {
2450 g_filt_dot_underscore_file = 1;
2451 }
2452
2453 strdata = ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2454 if (strdata && strdata[0] == '1' && strdata[1] == 0)
2455 {
2456 g_sort_case_sensitive = 1;
2457 }
2458
2459 device_name = grub_file_get_device_name(args[0]);
2460 if (!device_name)
2461 {
2462 goto fail;
2463 }
2464
2465 g_enum_dev = dev = grub_device_open(device_name);
2466 if (!dev)
2467 {
2468 goto fail;
2469 }
2470
2471 g_enum_fs = fs = grub_fs_probe(dev);
2472 if (!fs)
2473 {
2474 goto fail;
2475 }
2476
2477 if (ventoy_get_fs_type(fs->name) >= ventoy_fs_max)
2478 {
2479 debug("unsupported fs:<%s>\n", fs->name);
2480 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2481 goto fail;
2482 }
2483
2484 ventoy_set_env("vtoy_iso_fs", fs->name);
2485
2486 strdata = ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2487 if (strdata && strdata[0] == '1')
2488 {
2489 g_default_menu_mode = 1;
2490 }
2491
2492 grub_memset(&g_img_iterator_head, 0, sizeof(g_img_iterator_head));
2493
2494 grub_snprintf(g_iso_path, sizeof(g_iso_path), "%s", args[0]);
2495
2496 strdata = ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2497 if (strdata && strdata[0] == '/')
2498 {
2499 len = grub_snprintf(g_img_iterator_head.dir, sizeof(g_img_iterator_head.dir) - 1, "%s", strdata);
2500 if (g_img_iterator_head.dir[len - 1] != '/')
2501 {
2502 g_img_iterator_head.dir[len++] = '/';
2503 }
2504 g_img_iterator_head.dirlen = len;
2505 }
2506 else
2507 {
2508 g_img_iterator_head.dirlen = 1;
2509 grub_strcpy(g_img_iterator_head.dir, "/");
2510 }
2511
2512 g_img_iterator_head.tail = &tail;
2513
2514 if (g_img_max_search_level < 0)
2515 {
2516 g_img_max_search_level = GRUB_INT_MAX;
2517 strdata = ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2518 if (strdata && ventoy_is_decimal(strdata))
2519 {
2520 g_img_max_search_level = (int)grub_strtoul(strdata, NULL, 10);
2521 }
2522 }
2523
2524 g_vtoy_file_flt[VTOY_FILE_FLT_ISO] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2525 g_vtoy_file_flt[VTOY_FILE_FLT_WIM] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2526 g_vtoy_file_flt[VTOY_FILE_FLT_EFI] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2527 g_vtoy_file_flt[VTOY_FILE_FLT_IMG] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2528 g_vtoy_file_flt[VTOY_FILE_FLT_VHD] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2529 g_vtoy_file_flt[VTOY_FILE_FLT_VTOY] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2530
2531 for (node = &g_img_iterator_head; node; node = node->next)
2532 {
2533 fs->fs_dir(dev, node->dir, ventoy_collect_img_files, node);
2534 }
2535
2536 strdata = ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2537 if (strdata && strdata[0] == '1' && strdata[1] == 0)
2538 {
2539 g_tree_view_menu_style = 1;
2540 }
2541
2542 ventoy_set_default_menu();
2543
2544 for (node = &g_img_iterator_head; node; node = node->next)
2545 {
2546 ventoy_dynamic_tree_menu(node);
2547 }
2548
2549 /* free node */
2550 node = g_img_iterator_head.next;
2551 while (node)
2552 {
2553 tmp = node->next;
2554 grub_free(node);
2555 node = tmp;
2556 }
2557
2558 /* sort image list by image name */
2559 while (g_ventoy_img_list)
2560 {
2561 min = g_ventoy_img_list;
2562 for (cur = g_ventoy_img_list->next; cur; cur = cur->next)
2563 {
2564 if (ventoy_cmp_img(min, cur) > 0)
2565 {
2566 min = cur;
2567 }
2568 }
2569
2570 if (min->prev)
2571 {
2572 min->prev->next = min->next;
2573 }
2574
2575 if (min->next)
2576 {
2577 min->next->prev = min->prev;
2578 }
2579
2580 if (min == g_ventoy_img_list)
2581 {
2582 g_ventoy_img_list = min->next;
2583 }
2584
2585 if (head == NULL)
2586 {
2587 head = tail = min;
2588 min->prev = NULL;
2589 min->next = NULL;
2590 }
2591 else
2592 {
2593 tail->next = min;
2594 min->prev = tail;
2595 min->next = NULL;
2596 tail = min;
2597 }
2598 }
2599
2600 g_ventoy_img_list = head;
2601
2602 if (g_default_menu_mode == 1)
2603 {
2604 vtoy_ssprintf(g_list_script_buf, g_list_script_pos,
2605 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2606 " echo 'return ...' \n"
2607 "}\n", "<--");
2608 }
2609
2610 for (cur = g_ventoy_img_list; cur; cur = cur->next)
2611 {
2612 vtoy_ssprintf(g_list_script_buf, g_list_script_pos,
2613 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2614 " %s_%s \n"
2615 "}\n",
2616 cur->unsupport ? "[***********] " : "",
2617 cur->alias ? cur->alias : cur->name, cur->class, cur,
2618 cur->menu_prefix,
2619 cur->unsupport ? "unsupport_menuentry" : "common_menuentry");
2620 }
2621
2622 g_tree_script_buf[g_tree_script_pos] = 0;
2623 g_list_script_buf[g_list_script_pos] = 0;
2624
2625 grub_snprintf(buf, sizeof(buf), "%d", g_ventoy_img_count);
2626 grub_env_set(args[1], buf);
2627
2628 fail:
2629
2630 check_free(device_name, grub_free);
2631 check_free(dev, grub_device_close);
2632
2633 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2634 }
2635
2636 int ventoy_get_disk_guid(const char *filename, grub_uint8_t *guid, grub_uint8_t *signature)
2637 {
2638 grub_disk_t disk;
2639 char *device_name;
2640 char *pos;
2641 char *pos2;
2642
2643 device_name = grub_file_get_device_name(filename);
2644 if (!device_name)
2645 {
2646 return 1;
2647 }
2648
2649 pos = device_name;
2650 if (pos[0] == '(')
2651 {
2652 pos++;
2653 }
2654
2655 pos2 = grub_strstr(pos, ",");
2656 if (!pos2)
2657 {
2658 pos2 = grub_strstr(pos, ")");
2659 }
2660
2661 if (pos2)
2662 {
2663 *pos2 = 0;
2664 }
2665
2666 disk = grub_disk_open(pos);
2667 if (disk)
2668 {
2669 grub_disk_read(disk, 0, 0x180, 16, guid);
2670 grub_disk_read(disk, 0, 0x1b8, 4, signature);
2671 grub_disk_close(disk);
2672 }
2673 else
2674 {
2675 return 1;
2676 }
2677
2678 grub_free(device_name);
2679 return 0;
2680 }
2681
2682 grub_uint32_t ventoy_get_iso_boot_catlog(grub_file_t file)
2683 {
2684 eltorito_descriptor desc;
2685
2686 grub_memset(&desc, 0, sizeof(desc));
2687 grub_file_seek(file, 17 * 2048);
2688 grub_file_read(file, &desc, sizeof(desc));
2689
2690 if (desc.type != 0 || desc.version != 1)
2691 {
2692 return 0;
2693 }
2694
2695 if (grub_strncmp((char *)desc.id, "CD001", 5) != 0 ||
2696 grub_strncmp((char *)desc.system_id, "EL TORITO SPECIFICATION", 23) != 0)
2697 {
2698 return 0;
2699 }
2700
2701 return desc.sector;
2702 }
2703
2704 int ventoy_has_efi_eltorito(grub_file_t file, grub_uint32_t sector)
2705 {
2706 int i;
2707 int x86count = 0;
2708 grub_uint8_t buf[512];
2709 grub_uint8_t parttype[] = { 0x04, 0x06, 0x0B, 0x0C };
2710
2711 grub_file_seek(file, sector * 2048);
2712 grub_file_read(file, buf, sizeof(buf));
2713
2714 if (buf[0] == 0x01 && buf[1] == 0xEF)
2715 {
2716 debug("%s efi eltorito in Validation Entry\n", file->name);
2717 return 1;
2718 }
2719
2720 if (buf[0] == 0x01 && buf[1] == 0x00)
2721 {
2722 x86count++;
2723 }
2724
2725 for (i = 64; i < (int)sizeof(buf); i += 32)
2726 {
2727 if ((buf[i] == 0x90 || buf[i] == 0x91) && buf[i + 1] == 0xEF)
2728 {
2729 debug("%s efi eltorito offset %d 0x%02x\n", file->name, i, buf[i]);
2730 return 1;
2731 }
2732
2733 if ((buf[i] == 0x90 || buf[i] == 0x91) && buf[i + 1] == 0x00 && x86count == 1)
2734 {
2735 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file->name, i, buf[i]);
2736 return 1;
2737 }
2738 }
2739
2740 if (x86count && buf[32] == 0x88 && buf[33] == 0x04)
2741 {
2742 for (i = 0; i < (int)(ARRAY_SIZE(parttype)); i++)
2743 {
2744 if (buf[36] == parttype[i])
2745 {
2746 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file->name, buf[36]);
2747 return 1;
2748 }
2749 }
2750 }
2751
2752 debug("%s does not contain efi eltorito\n", file->name);
2753 return 0;
2754 }
2755
2756 void ventoy_fill_os_param(grub_file_t file, ventoy_os_param *param)
2757 {
2758 char *pos;
2759 const char *fs = NULL;
2760 const char *cdprompt = NULL;
2761 grub_uint32_t i;
2762 grub_uint8_t chksum = 0;
2763 grub_disk_t disk;
2764
2765 disk = file->device->disk;
2766 grub_memcpy(&param->guid, &g_ventoy_guid, sizeof(ventoy_guid));
2767
2768 param->vtoy_disk_size = disk->total_sectors * (1 << disk->log_sector_size);
2769 param->vtoy_disk_part_id = disk->partition->number + 1;
2770 param->vtoy_disk_part_type = ventoy_get_fs_type(file->fs->name);
2771
2772 pos = grub_strstr(file->name, "/");
2773 if (!pos)
2774 {
2775 pos = file->name;
2776 }
2777
2778 grub_snprintf(param->vtoy_img_path, sizeof(param->vtoy_img_path), "%s", pos);
2779
2780 ventoy_get_disk_guid(file->name, param->vtoy_disk_guid, param->vtoy_disk_signature);
2781
2782 param->vtoy_img_size = file->size;
2783
2784 param->vtoy_reserved[0] = g_ventoy_break_level;
2785 param->vtoy_reserved[1] = g_ventoy_debug_level;
2786
2787 param->vtoy_reserved[2] = g_ventoy_chain_type;
2788
2789 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2790 param->vtoy_reserved[4] = 0;
2791 if (g_ventoy_chain_type == 1) /* Windows */
2792 {
2793 cdprompt = ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2794 if (cdprompt && cdprompt[0] == '1' && cdprompt[1] == 0)
2795 {
2796 param->vtoy_reserved[4] = 1;
2797 }
2798 }
2799
2800 fs = ventoy_get_env("ventoy_fs_probe");
2801 if (fs && grub_strcmp(fs, "udf") == 0)
2802 {
2803 param->vtoy_reserved[3] = 1;
2804 }
2805
2806 /* calculate checksum */
2807 for (i = 0; i < sizeof(ventoy_os_param); i++)
2808 {
2809 chksum += *((grub_uint8_t *)param + i);
2810 }
2811 param->chksum = (grub_uint8_t)(0x100 - chksum);
2812
2813 return;
2814 }
2815
2816 int ventoy_check_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start)
2817 {
2818 grub_uint32_t i = 0;
2819 grub_uint64_t total = 0;
2820 grub_uint64_t fileblk = 0;
2821 ventoy_img_chunk *chunk = NULL;
2822
2823 for (i = 0; i < chunklist->cur_chunk; i++)
2824 {
2825 chunk = chunklist->chunk + i;
2826
2827 if (chunk->disk_start_sector <= start)
2828 {
2829 debug("%u disk start invalid %lu\n", i, (ulong)start);
2830 return 1;
2831 }
2832
2833 total += chunk->disk_end_sector + 1 - chunk->disk_start_sector;
2834 }
2835
2836 fileblk = (file->size + 511) / 512;
2837
2838 if (total != fileblk)
2839 {
2840 debug("Invalid total: %llu %llu\n", (ulonglong)total, (ulonglong)fileblk);
2841 if ((file->size % 512) && (total + 1 == fileblk))
2842 {
2843 debug("maybe img file to be processed.\n");
2844 return 0;
2845 }
2846
2847 return 1;
2848 }
2849
2850 return 0;
2851 }
2852
2853 int ventoy_get_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start)
2854 {
2855 int fs_type;
2856 int len;
2857 grub_uint32_t i = 0;
2858 grub_uint32_t sector = 0;
2859 grub_uint32_t count = 0;
2860 grub_off_t size = 0;
2861 grub_off_t read = 0;
2862
2863 fs_type = ventoy_get_fs_type(file->fs->name);
2864 if (fs_type == ventoy_fs_exfat)
2865 {
2866 grub_fat_get_file_chunk(start, file, chunklist);
2867 }
2868 else if (fs_type == ventoy_fs_ext)
2869 {
2870 grub_ext_get_file_chunk(start, file, chunklist);
2871 }
2872 else
2873 {
2874 file->read_hook = (grub_disk_read_hook_t)grub_disk_blocklist_read;
2875 file->read_hook_data = chunklist;
2876
2877 for (size = file->size; size > 0; size -= read)
2878 {
2879 read = (size > VTOY_SIZE_1GB) ? VTOY_SIZE_1GB : size;
2880 grub_file_read(file, NULL, read);
2881 }
2882
2883 for (i = 0; start > 0 && i < chunklist->cur_chunk; i++)
2884 {
2885 chunklist->chunk[i].disk_start_sector += start;
2886 chunklist->chunk[i].disk_end_sector += start;
2887 }
2888
2889 if (ventoy_fs_udf == fs_type)
2890 {
2891 for (i = 0; i < chunklist->cur_chunk; i++)
2892 {
2893 count = (chunklist->chunk[i].disk_end_sector + 1 - chunklist->chunk[i].disk_start_sector) >> 2;
2894 chunklist->chunk[i].img_start_sector = sector;
2895 chunklist->chunk[i].img_end_sector = sector + count - 1;
2896 sector += count;
2897 }
2898 }
2899 }
2900
2901 len = (int)grub_strlen(file->name);
2902 if ((len > 4 && grub_strncasecmp(file->name + len - 4, ".img", 4) == 0) ||
2903 (len > 4 && grub_strncasecmp(file->name + len - 4, ".vhd", 4) == 0) ||
2904 (len > 5 && grub_strncasecmp(file->name + len - 5, ".vhdx", 5) == 0) ||
2905 (len > 5 && grub_strncasecmp(file->name + len - 5, ".vtoy", 5) == 0))
2906 {
2907 for (i = 0; i < chunklist->cur_chunk; i++)
2908 {
2909 count = chunklist->chunk[i].disk_end_sector + 1 - chunklist->chunk[i].disk_start_sector;
2910 if (count < 4)
2911 {
2912 count = 1;
2913 }
2914 else
2915 {
2916 count >>= 2;
2917 }
2918
2919 chunklist->chunk[i].img_start_sector = sector;
2920 chunklist->chunk[i].img_end_sector = sector + count - 1;
2921 sector += count;
2922 }
2923 }
2924
2925 return 0;
2926 }
2927
2928 static grub_err_t ventoy_cmd_img_sector(grub_extcmd_context_t ctxt, int argc, char **args)
2929 {
2930 int rc;
2931 grub_file_t file;
2932 grub_disk_addr_t start;
2933
2934 (void)ctxt;
2935 (void)argc;
2936
2937 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
2938 if (!file)
2939 {
2940 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't open file %s\n", args[0]);
2941 }
2942
2943 g_conf_replace_node = NULL;
2944 g_conf_replace_offset = 0;
2945
2946 if (g_img_chunk_list.chunk)
2947 {
2948 grub_free(g_img_chunk_list.chunk);
2949 }
2950
2951 if (ventoy_get_fs_type(file->fs->name) >= ventoy_fs_max)
2952 {
2953 grub_file_close(file);
2954 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Unsupported filesystem %s\n", file->fs->name);
2955 }
2956
2957 /* get image chunk data */
2958 grub_memset(&g_img_chunk_list, 0, sizeof(g_img_chunk_list));
2959 g_img_chunk_list.chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
2960 if (NULL == g_img_chunk_list.chunk)
2961 {
2962 return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n");
2963 }
2964
2965 g_img_chunk_list.max_chunk = DEFAULT_CHUNK_NUM;
2966 g_img_chunk_list.cur_chunk = 0;
2967
2968 start = file->device->disk->partition->start;
2969
2970 ventoy_get_block_list(file, &g_img_chunk_list, start);
2971
2972 rc = ventoy_check_block_list(file, &g_img_chunk_list, start);
2973 grub_file_close(file);
2974
2975 if (rc)
2976 {
2977 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET, "Unsupported chunk list.\n");
2978 }
2979
2980 grub_memset(&g_grub_param->file_replace, 0, sizeof(g_grub_param->file_replace));
2981 grub_memset(&g_grub_param->img_replace, 0, sizeof(g_grub_param->img_replace));
2982 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2983 }
2984
2985 static grub_err_t ventoy_select_conf_replace(grub_extcmd_context_t ctxt, int argc, char **args)
2986 {
2987 grub_uint64_t offset = 0;
2988 grub_uint32_t align = 0;
2989 grub_file_t file = NULL;
2990 conf_replace *node = NULL;
2991
2992 (void)ctxt;
2993 (void)argc;
2994 (void)args;
2995
2996 debug("select conf replace argc:%d\n", argc);
2997
2998 if (argc < 2)
2999 {
3000 return 0;
3001 }
3002
3003 node = ventoy_plugin_find_conf_replace(args[1]);
3004 if (!node)
3005 {
3006 debug("Conf replace not found for %s\n", args[1]);
3007 goto end;
3008 }
3009
3010 debug("Find conf replace for %s\n", args[1]);
3011
3012 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(loop)%s", node->orgconf);
3013 if (file)
3014 {
3015 offset = grub_iso9660_get_last_file_dirent_pos(file);
3016 grub_file_close(file);
3017 }
3018 else if (node->img > 0)
3019 {
3020 offset = 0;
3021 }
3022 else
3023 {
3024 debug("<(loop)%s> NOT exist\n", node->orgconf);
3025 goto end;
3026 }
3027
3028 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", args[0], node->newconf);
3029 if (!file)
3030 {
3031 debug("New config file <%s%s> NOT exist\n", args[0], node->newconf);
3032 goto end;
3033 }
3034
3035 align = ((int)file->size + 2047) / 2048 * 2048;
3036
3037 if (align > vtoy_max_replace_file_size)
3038 {
3039 debug("New config file <%s%s> too big\n", args[0], node->newconf);
3040 goto end;
3041 }
3042
3043 grub_file_read(file, g_conf_replace_new_buf, file->size);
3044 g_conf_replace_new_len = (int)file->size;
3045 g_conf_replace_new_len_align = align;
3046
3047 g_conf_replace_node = node;
3048 g_conf_replace_offset = offset + 2;
3049
3050 if (node->img > 0)
3051 {
3052 g_grub_param->img_replace.magic = GRUB_IMG_REPLACE_MAGIC;
3053 g_grub_param->img_replace.old_name_cnt = 1;
3054 grub_snprintf(g_grub_param->img_replace.old_file_name[0], 256, "%s", node->orgconf);
3055 }
3056
3057 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len);
3058
3059 end:
3060 if (file)
3061 {
3062 grub_file_close(file);
3063 }
3064 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3065 }
3066
3067 static grub_err_t ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt, int argc, char **args)
3068 {
3069 int i = 0;
3070 int pos = 0;
3071 int defidx = 1;
3072 char *buf = NULL;
3073 char configfile[128];
3074 install_template *node = NULL;
3075
3076 (void)ctxt;
3077 (void)argc;
3078 (void)args;
3079
3080 debug("select auto installation argc:%d\n", argc);
3081
3082 if (argc < 1)
3083 {
3084 return 0;
3085 }
3086
3087 node = ventoy_plugin_find_install_template(args[0]);
3088 if (!node)
3089 {
3090 debug("Auto install template not found for %s\n", args[0]);
3091 return 0;
3092 }
3093
3094 if (node->autosel >= 0 && node->autosel <= node->templatenum)
3095 {
3096 defidx = node->autosel;
3097 if (node->timeout < 0)
3098 {
3099 node->cursel = node->autosel - 1;
3100 debug("Auto install template auto select %d\n", node->autosel);
3101 return 0;
3102 }
3103 }
3104
3105 buf = (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF);
3106 if (!buf)
3107 {
3108 return 0;
3109 }
3110
3111 if (node->timeout > 0)
3112 {
3113 vtoy_ssprintf(buf, pos, "set timeout=%d\n", node->timeout);
3114 }
3115
3116 vtoy_ssprintf(buf, pos, "menuentry \"Boot without auto installation template\" {\n"
3117 " echo %s\n}\n", "");
3118
3119 for (i = 0; i < node->templatenum; i++)
3120 {
3121 vtoy_ssprintf(buf, pos, "menuentry \"Boot with %s\"{\n"
3122 " echo \"\"\n}\n",
3123 node->templatepath[i].path);
3124 }
3125
3126 g_ventoy_menu_esc = 1;
3127 g_ventoy_suppress_esc = 1;
3128 g_ventoy_suppress_esc_default = defidx;
3129
3130 grub_snprintf(configfile, sizeof(configfile), "configfile mem:0x%llx:size:%d", (ulonglong)(ulong)buf, pos);
3131 grub_script_execute_sourcecode(configfile);
3132
3133 g_ventoy_menu_esc = 0;
3134 g_ventoy_suppress_esc = 0;
3135 g_ventoy_suppress_esc_default = 1;
3136
3137 grub_free(buf);
3138
3139 node->cursel = g_ventoy_last_entry - 1;
3140
3141 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3142 }
3143
3144 static grub_err_t ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt, int argc, char **args)
3145 {
3146 int i = 0;
3147 int pos = 0;
3148 int defidx = 1;
3149 char *buf = NULL;
3150 char configfile[128];
3151 persistence_config *node;
3152
3153 (void)ctxt;
3154 (void)argc;
3155 (void)args;
3156
3157 debug("select persistence argc:%d\n", argc);
3158
3159 if (argc < 1)
3160 {
3161 return 0;
3162 }
3163
3164 node = ventoy_plugin_find_persistent(args[0]);
3165 if (!node)
3166 {
3167 debug("Persistence image not found for %s\n", args[0]);
3168 return 0;
3169 }
3170
3171 if (node->autosel >= 0 && node->autosel <= node->backendnum)
3172 {
3173 defidx = node->autosel;
3174 if (node->timeout < 0)
3175 {
3176 node->cursel = node->autosel - 1;
3177 debug("Persistence image auto select %d\n", node->autosel);
3178 return 0;
3179 }
3180 }
3181
3182 buf = (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF);
3183 if (!buf)
3184 {
3185 return 0;
3186 }
3187
3188 if (node->timeout > 0)
3189 {
3190 vtoy_ssprintf(buf, pos, "set timeout=%d\n", node->timeout);
3191 }
3192
3193 vtoy_ssprintf(buf, pos, "menuentry \"Boot without persistence\" {\n"
3194 " echo %s\n}\n", "");
3195
3196 for (i = 0; i < node->backendnum; i++)
3197 {
3198 vtoy_ssprintf(buf, pos, "menuentry \"Boot with %s\" {\n"
3199 " echo \"\"\n}\n",
3200 node->backendpath[i].path);
3201
3202 }
3203
3204 g_ventoy_menu_esc = 1;
3205 g_ventoy_suppress_esc = 1;
3206 g_ventoy_suppress_esc_default = defidx;
3207
3208 grub_snprintf(configfile, sizeof(configfile), "configfile mem:0x%llx:size:%d", (ulonglong)(ulong)buf, pos);
3209 grub_script_execute_sourcecode(configfile);
3210
3211 g_ventoy_menu_esc = 0;
3212 g_ventoy_suppress_esc = 0;
3213 g_ventoy_suppress_esc_default = 1;
3214
3215 grub_free(buf);
3216
3217 node->cursel = g_ventoy_last_entry - 1;
3218
3219 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3220 }
3221
3222 static grub_err_t ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt, int argc, char **args)
3223 {
3224 grub_uint32_t i;
3225 ventoy_img_chunk *cur;
3226
3227 (void)ctxt;
3228 (void)argc;
3229 (void)args;
3230
3231 for (i = 0; i < g_img_chunk_list.cur_chunk; i++)
3232 {
3233 cur = g_img_chunk_list.chunk + i;
3234 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3235 cur->img_start_sector, cur->img_end_sector,
3236 (unsigned long long)cur->disk_start_sector, (unsigned long long)cur->disk_end_sector
3237 );
3238 }
3239
3240 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3241 }
3242
3243 static grub_err_t ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt, int argc, char **args)
3244 {
3245 grub_uint32_t i;
3246 grub_file_t file;
3247 ventoy_img_chunk_list chunklist;
3248
3249 (void)ctxt;
3250 (void)argc;
3251
3252 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
3253 if (!file)
3254 {
3255 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't open file %s\n", args[0]);
3256 }
3257
3258 /* get image chunk data */
3259 grub_memset(&chunklist, 0, sizeof(chunklist));
3260 chunklist.chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
3261 if (NULL == chunklist.chunk)
3262 {
3263 return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n");
3264 }
3265
3266 chunklist.max_chunk = DEFAULT_CHUNK_NUM;
3267 chunklist.cur_chunk = 0;
3268
3269 ventoy_get_block_list(file, &chunklist, 0);
3270
3271 if (0 != ventoy_check_block_list(file, &chunklist, 0))
3272 {
3273 grub_printf("########## UNSUPPORTED ###############\n");
3274 }
3275
3276 grub_printf("filesystem: <%s> entry number:<%u>\n", file->fs->name, chunklist.cur_chunk);
3277
3278 for (i = 0; i < chunklist.cur_chunk; i++)
3279 {
3280 grub_printf("%llu+%llu,", (ulonglong)chunklist.chunk[i].disk_start_sector,
3281 (ulonglong)(chunklist.chunk[i].disk_end_sector + 1 - chunklist.chunk[i].disk_start_sector));
3282 }
3283
3284 grub_printf("\n==================================\n");
3285
3286 for (i = 0; i < chunklist.cur_chunk; i++)
3287 {
3288 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i,
3289 (ulonglong)chunklist.chunk[i].img_start_sector,
3290 (ulonglong)chunklist.chunk[i].img_end_sector,
3291 (ulonglong)chunklist.chunk[i].disk_start_sector,
3292 (ulonglong)chunklist.chunk[i].disk_end_sector
3293 );
3294 }
3295
3296 grub_free(chunklist.chunk);
3297 grub_file_close(file);
3298
3299 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3300 }
3301
3302 static grub_err_t ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt, int argc, char **args)
3303 {
3304 int i;
3305 ventoy_grub_param_file_replace *replace = NULL;
3306
3307 (void)ctxt;
3308 (void)argc;
3309 (void)args;
3310
3311 if (argc >= 2)
3312 {
3313 replace = &(g_grub_param->file_replace);
3314 replace->magic = GRUB_FILE_REPLACE_MAGIC;
3315
3316 replace->old_name_cnt = 0;
3317 for (i = 0; i < 4 && i + 1 < argc; i++)
3318 {
3319 replace->old_name_cnt++;
3320 grub_snprintf(replace->old_file_name[i], sizeof(replace->old_file_name[i]), "%s", args[i + 1]);
3321 }
3322
3323 replace->new_file_virtual_id = (grub_uint32_t)grub_strtoul(args[0], NULL, 10);
3324 }
3325
3326 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3327 }
3328
3329 static grub_err_t ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt, int argc, char **args)
3330 {
3331 char buf[32];
3332 ventoy_grub_param_file_replace *replace = &(g_grub_param->file_replace);
3333
3334 (void)ctxt;
3335
3336 if (argc >= 1)
3337 {
3338 grub_snprintf(buf, sizeof(buf), "%u", replace->old_name_cnt);
3339 grub_env_set(args[0], buf);
3340 }
3341
3342 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3343 }
3344
3345 static grub_err_t ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt, int argc, char **args)
3346 {
3347 (void)ctxt;
3348 (void)argc;
3349 (void)args;
3350
3351 if (argc == 0)
3352 {
3353 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos, VTOY_MAX_SCRIPT_BUF);
3354 grub_printf("%s", g_list_script_buf);
3355 }
3356 else
3357 {
3358 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos, VTOY_MAX_SCRIPT_BUF);
3359 grub_printf("%s", g_tree_script_buf);
3360 }
3361
3362 return 0;
3363 }
3364
3365 static grub_err_t ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt, int argc, char **args)
3366 {
3367 img_info *cur = g_ventoy_img_list;
3368
3369 (void)ctxt;
3370 (void)argc;
3371 (void)args;
3372
3373 while (cur)
3374 {
3375 grub_printf("path:<%s> id=%d list_index=%d\n", cur->path, cur->id, cur->plugin_list_index);
3376 grub_printf("name:<%s>\n\n", cur->name);
3377 cur = cur->next;
3378 }
3379
3380 return 0;
3381 }
3382
3383 static grub_err_t ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt, int argc, char **args)
3384 {
3385 (void)ctxt;
3386 (void)argc;
3387 (void)args;
3388
3389 ventoy_plugin_dump_injection();
3390
3391 return 0;
3392 }
3393
3394 static grub_err_t ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt, int argc, char **args)
3395 {
3396 (void)ctxt;
3397 (void)argc;
3398 (void)args;
3399
3400 ventoy_plugin_dump_auto_install();
3401
3402 return 0;
3403 }
3404
3405 static grub_err_t ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt, int argc, char **args)
3406 {
3407 (void)ctxt;
3408 (void)argc;
3409 (void)args;
3410
3411 ventoy_plugin_dump_persistence();
3412
3413 return 0;
3414 }
3415
3416 static grub_err_t ventoy_cmd_check_mode(grub_extcmd_context_t ctxt, int argc, char **args)
3417 {
3418 (void)ctxt;
3419 (void)argc;
3420 (void)args;
3421
3422 if (argc != 1)
3423 {
3424 return 1;
3425 }
3426
3427 if (args[0][0] == '0')
3428 {
3429 return g_ventoy_memdisk_mode ? 0 : 1;
3430 }
3431 else if (args[0][0] == '1')
3432 {
3433 return g_ventoy_iso_raw ? 0 : 1;
3434 }
3435 else if (args[0][0] == '2')
3436 {
3437 return g_ventoy_iso_uefi_drv ? 0 : 1;
3438 }
3439 else if (args[0][0] == '3')
3440 {
3441 return g_ventoy_grub2_mode ? 0 : 1;
3442 }
3443 else if (args[0][0] == '4')
3444 {
3445 return g_ventoy_wimboot_mode ? 0 : 1;
3446 }
3447
3448 return 1;
3449 }
3450
3451 static grub_err_t ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt, int argc, char **args)
3452 {
3453 static int configfile_mode = 0;
3454 char memfile[128] = {0};
3455
3456 (void)ctxt;
3457 (void)argc;
3458 (void)args;
3459
3460 /*
3461 * args[0]: 0:normal 1:configfile
3462 * args[1]: 0:list_buf 1:tree_buf
3463 */
3464
3465 if (argc != 2)
3466 {
3467 debug("Invalid argc %d\n", argc);
3468 return 0;
3469 }
3470
3471 VTOY_CMD_CHECK(1);
3472
3473 if (args[0][0] == '0')
3474 {
3475 if (args[1][0] == '0')
3476 {
3477 grub_script_execute_sourcecode(g_list_script_buf);
3478 }
3479 else
3480 {
3481 grub_script_execute_sourcecode(g_tree_script_buf);
3482 }
3483 }
3484 else
3485 {
3486 if (configfile_mode)
3487 {
3488 debug("Now already in F3 mode %d\n", configfile_mode);
3489 return 0;
3490 }
3491
3492 if (args[1][0] == '0')
3493 {
3494 grub_snprintf(memfile, sizeof(memfile), "configfile mem:0x%llx:size:%d",
3495 (ulonglong)(ulong)g_list_script_buf, g_list_script_pos);
3496 }
3497 else
3498 {
3499 g_ventoy_last_entry = -1;
3500 grub_snprintf(memfile, sizeof(memfile), "configfile mem:0x%llx:size:%d",
3501 (ulonglong)(ulong)g_tree_script_buf, g_tree_script_pos);
3502 }
3503
3504 configfile_mode = 1;
3505 grub_script_execute_sourcecode(memfile);
3506 configfile_mode = 0;
3507 }
3508
3509 return 0;
3510 }
3511
3512 static grub_err_t ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt, int argc, char **args)
3513 {
3514 grub_file_t file;
3515
3516 (void)ctxt;
3517
3518 if (argc != 1)
3519 {
3520 return 1;
3521 }
3522
3523 g_ventoy_case_insensitive = 1;
3524 file = grub_file_open(args[0], VENTOY_FILE_TYPE);
3525 g_ventoy_case_insensitive = 0;
3526
3527 grub_errno = 0;
3528
3529 if (file)
3530 {
3531 grub_file_close(file);
3532 return 0;
3533 }
3534 return 1;
3535 }
3536
3537 static grub_err_t ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt, int argc, char **args)
3538 {
3539 int id = 0;
3540 int find = 0;
3541 grub_disk_t disk;
3542 const char *isopath = NULL;
3543 char hdname[32];
3544 ventoy_mbr_head mbr;
3545
3546 (void)ctxt;
3547 (void)argc;
3548
3549 if (argc != 1)
3550 {
3551 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s variable\n", cmd_raw_name);
3552 }
3553
3554 isopath = grub_env_get("vtoy_iso_part");
3555 if (!isopath)
3556 {
3557 debug("isopath is null %p\n", isopath);
3558 return 0;
3559 }
3560
3561 debug("isopath is %s\n", isopath);
3562
3563 for (id = 0; id < 30 && (find == 0); id++)
3564 {
3565 grub_snprintf(hdname, sizeof(hdname), "hd%d,", id);
3566 if (grub_strstr(isopath, hdname))
3567 {
3568 debug("skip %s ...\n", hdname);
3569 continue;
3570 }
3571
3572 grub_snprintf(hdname, sizeof(hdname), "hd%d", id);
3573
3574 disk = grub_disk_open(hdname);
3575 if (!disk)
3576 {
3577 debug("%s not exist\n", hdname);
3578 break;
3579 }
3580
3581 grub_memset(&mbr, 0, sizeof(mbr));
3582 if (0 == grub_disk_read(disk, 0, 0, 512, &mbr))
3583 {
3584 if (mbr.Byte55 == 0x55 && mbr.ByteAA == 0xAA)
3585 {
3586 if (mbr.PartTbl[0].Active == 0x80 || mbr.PartTbl[1].Active == 0x80 ||
3587 mbr.PartTbl[2].Active == 0x80 || mbr.PartTbl[3].Active == 0x80)
3588 {
3589
3590 grub_env_set(args[0], hdname);
3591 find = 1;
3592 }
3593 }
3594 debug("%s is %s\n", hdname, find ? "bootable" : "NOT bootable");
3595 }
3596 else
3597 {
3598 debug("read %s failed\n", hdname);
3599 }
3600
3601 grub_disk_close(disk);
3602 }
3603
3604 return 0;
3605 }
3606
3607 static grub_err_t ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt, int argc, char **args)
3608 {
3609 int len = 1024;
3610 grub_file_t file;
3611 char *buf = NULL;
3612
3613 (void)ctxt;
3614 (void)argc;
3615
3616 if (argc != 2)
3617 {
3618 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s file var \n", cmd_raw_name);
3619 }
3620
3621 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
3622 if (!file)
3623 {
3624 debug("failed to open file %s\n", args[0]);
3625 return 0;
3626 }
3627
3628 buf = grub_malloc(len);
3629 if (!buf)
3630 {
3631 goto end;
3632 }
3633
3634 buf[len - 1] = 0;
3635 grub_file_read(file, buf, len - 1);
3636
3637 ventoy_get_line(buf);
3638 ventoy_set_env(args[1], buf);
3639
3640 end:
3641
3642 grub_check_free(buf);
3643 grub_file_close(file);
3644
3645 return 0;
3646 }
3647
3648 static int ventoy_img_partition_callback (struct grub_disk *disk, const grub_partition_t partition, void *data)
3649 {
3650 int *pCnt = (int *)data;
3651
3652 (void)disk;
3653
3654 (*pCnt)++;
3655 g_part_list_pos += grub_snprintf(g_part_list_buf + g_part_list_pos, VTOY_MAX_SCRIPT_BUF - g_part_list_pos,
3656 "0 %llu linear /dev/ventoy %llu\n",
3657 (ulonglong)partition->len, (ulonglong)partition->start);
3658
3659 return 0;
3660 }
3661
3662 static grub_err_t ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt, int argc, char **args)
3663 {
3664 int cnt = 0;
3665 char *device_name = NULL;
3666 grub_device_t dev = NULL;
3667 char buf[64];
3668
3669 (void)ctxt;
3670
3671 g_part_list_pos = 0;
3672 grub_env_unset("vtoy_img_part_file");
3673
3674 if (argc != 1)
3675 {
3676 return 1;
3677 }
3678
3679 device_name = grub_file_get_device_name(args[0]);
3680 if (!device_name)
3681 {
3682 debug("ventoy_cmd_img_part_info failed, %s\n", args[0]);
3683 goto end;
3684 }
3685
3686 dev = grub_device_open(device_name);
3687 if (!dev)
3688 {
3689 debug("grub_device_open failed, %s\n", device_name);
3690 goto end;
3691 }
3692
3693 grub_partition_iterate(dev->disk, ventoy_img_partition_callback, &cnt);
3694
3695 grub_snprintf(buf, sizeof(buf), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong)(ulong)g_part_list_buf, g_part_list_pos);
3696 grub_env_set("vtoy_img_part_file", buf);
3697
3698 grub_snprintf(buf, sizeof(buf), "%d", cnt);
3699 grub_env_set("vtoy_img_part_cnt", buf);
3700
3701 end:
3702
3703 check_free(device_name, grub_free);
3704 check_free(dev, grub_device_close);
3705
3706 return 0;
3707 }
3708
3709
3710 static grub_err_t ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt, int argc, char **args)
3711 {
3712 int rc = 1;
3713 grub_file_t file;
3714 char *buf = NULL;
3715
3716 (void)ctxt;
3717 (void)argc;
3718
3719 if (argc != 2)
3720 {
3721 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s file str \n", cmd_raw_name);
3722 }
3723
3724 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
3725 if (!file)
3726 {
3727 debug("failed to open file %s\n", args[0]);
3728 return 1;
3729 }
3730
3731 buf = grub_malloc(file->size + 1);
3732 if (!buf)
3733 {
3734 goto end;
3735 }
3736
3737 buf[file->size] = 0;
3738 grub_file_read(file, buf, file->size);
3739
3740 if (grub_strstr(buf, args[1]))
3741 {
3742 rc = 0;
3743 }
3744
3745 end:
3746
3747 grub_check_free(buf);
3748 grub_file_close(file);
3749
3750 return rc;
3751 }
3752
3753 static grub_err_t ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt, int argc, char **args)
3754 {
3755 int len;
3756 grub_file_t file;
3757 char buf[64];
3758 grub_uint64_t size;
3759 ventoy_iso9660_vd pvd;
3760
3761 (void)ctxt;
3762 (void)argc;
3763
3764 if (argc != 4)
3765 {
3766 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s sysid volid space \n", cmd_raw_name);
3767 }
3768
3769 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
3770 if (!file)
3771 {
3772 debug("failed to open file %s\n", args[0]);
3773 return 0;
3774 }
3775
3776 grub_file_seek(file, 16 * 2048);
3777 len = (int)grub_file_read(file, &pvd, sizeof(pvd));
3778 if (len != sizeof(pvd))
3779 {
3780 debug("failed to read pvd %d\n", len);
3781 goto end;
3782 }
3783
3784 grub_memset(buf, 0, sizeof(buf));
3785 grub_memcpy(buf, pvd.sys, sizeof(pvd.sys));
3786 ventoy_set_env(args[1], buf);
3787
3788 grub_memset(buf, 0, sizeof(buf));
3789 grub_memcpy(buf, pvd.vol, sizeof(pvd.vol));
3790 ventoy_set_env(args[2], buf);
3791
3792 size = pvd.space;
3793 size *= 2048;
3794 grub_snprintf(buf, sizeof(buf), "%llu", (ulonglong)size);
3795 ventoy_set_env(args[3], buf);
3796
3797 end:
3798 grub_file_close(file);
3799
3800 return 0;
3801 }
3802
3803 static grub_err_t ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt, int argc, char **args)
3804 {
3805 int len;
3806 grub_file_t file;
3807 char buf[64];
3808
3809 (void)ctxt;
3810 (void)argc;
3811
3812 if (argc != 2)
3813 {
3814 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s var \n", cmd_raw_name);
3815 }
3816
3817 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
3818 if (!file)
3819 {
3820 debug("failed to open file %s\n", args[0]);
3821 return 0;
3822 }
3823
3824 grub_memset(buf, 0, sizeof(buf));
3825 grub_file_seek(file, 16 * 2048 + 813);
3826 len = (int)grub_file_read(file, buf, 17);
3827 if (len != 17)
3828 {
3829 debug("failed to read create date %d\n", len);
3830 goto end;
3831 }
3832
3833 ventoy_set_env(args[1], buf);
3834
3835 end:
3836 grub_file_close(file);
3837
3838 return 0;
3839 }
3840
3841 static grub_err_t ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt, int argc, char **args)
3842 {
3843 (void)ctxt;
3844 (void)argc;
3845 (void)args;
3846
3847 ventoy_env_hook_root(1);
3848
3849 return 0;
3850 }
3851
3852 static grub_err_t ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt, int argc, char **args)
3853 {
3854 (void)ctxt;
3855 (void)argc;
3856 (void)args;
3857
3858 ventoy_env_hook_root(0);
3859
3860 return 0;
3861 }
3862
3863 #ifdef GRUB_MACHINE_EFI
3864 static grub_err_t ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt, int argc, char **args)
3865 {
3866 int ret = 1;
3867 grub_uint8_t *var;
3868 grub_size_t size;
3869 grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID;
3870
3871 (void)ctxt;
3872 (void)argc;
3873 (void)args;
3874
3875 var = grub_efi_get_variable("SecureBoot", &global, &size);
3876 if (var && *var == 1)
3877 {
3878 return 0;
3879 }
3880
3881 return ret;
3882 }
3883 #else
3884 static grub_err_t ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt, int argc, char **args)
3885 {
3886 (void)ctxt;
3887 (void)argc;
3888 (void)args;
3889 return 1;
3890 }
3891 #endif
3892
3893 static grub_err_t ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt, int argc, char **args)
3894 {
3895 int i;
3896 int ret = 1;
3897 grub_file_t file;
3898 grub_uint64_t FileSectors = 0;
3899 ventoy_gpt_info *gpt = NULL;
3900 ventoy_part_table *pt = NULL;
3901 grub_uint8_t zeroguid[16] = {0};
3902
3903 (void)ctxt;
3904 (void)argc;
3905
3906 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
3907 if (!file)
3908 {
3909 debug("failed to open file %s\n", args[0]);
3910 return 1;
3911 }
3912
3913 if (file->size % 512)
3914 {
3915 debug("unaligned file size: %llu\n", (ulonglong)file->size);
3916 goto out;
3917 }
3918
3919 gpt = grub_zalloc(sizeof(ventoy_gpt_info));
3920 if (!gpt)
3921 {
3922 goto out;
3923 }
3924
3925 FileSectors = file->size / 512;
3926
3927 grub_file_read(file, gpt, sizeof(ventoy_gpt_info));
3928 if (grub_strncmp(gpt->Head.Signature, "EFI PART", 8) == 0)
3929 {
3930 debug("This is EFI partition table\n");
3931
3932 for (i = 0; i < 128; i++)
3933 {
3934 if (grub_memcmp(gpt->PartTbl[i].PartGuid, zeroguid, 16))
3935 {
3936 if (FileSectors < gpt->PartTbl[i].LastLBA)
3937 {
3938 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i,
3939 (ulonglong)gpt->PartTbl[i].LastLBA, (ulonglong)FileSectors);
3940 goto out;
3941 }
3942 }
3943 }
3944 }
3945 else
3946 {
3947 debug("This is MBR partition table\n");
3948
3949 for (i = 0; i < 4; i++)
3950 {
3951 pt = gpt->MBR.PartTbl + i;
3952 if (FileSectors < pt->StartSectorId + pt->SectorCount)
3953 {
3954 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i,
3955 (ulonglong)(pt->StartSectorId + pt->SectorCount),
3956 (ulonglong)FileSectors);
3957 goto out;
3958 }
3959 }
3960 }
3961
3962 ret = 0;
3963
3964 out:
3965 grub_file_close(file);
3966 grub_check_free(gpt);
3967 grub_errno = GRUB_ERR_NONE;
3968 return ret;
3969 }
3970
3971 static grub_err_t ventoy_cmd_clear_key(grub_extcmd_context_t ctxt, int argc, char **args)
3972 {
3973 int i;
3974 int ret;
3975
3976 (void)ctxt;
3977 (void)argc;
3978 (void)args;
3979
3980 for (i = 0; i < 500; i++)
3981 {
3982 ret = grub_getkey_noblock();
3983 if (ret == GRUB_TERM_NO_KEY)
3984 {
3985 break;
3986 }
3987 }
3988
3989 if (i >= 500)
3990 {
3991 grub_cls();
3992 grub_printf("\n\n Still have key input after clear.\n");
3993 grub_refresh();
3994 grub_sleep(5);
3995 }
3996
3997 return 0;
3998 }
3999
4000 static grub_err_t ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt, int argc, char **args)
4001 {
4002 int i;
4003 int buflen;
4004 int datalen;
4005 int loclen;
4006 int img_chunk_num;
4007 int image_sector_size;
4008 char cmd[64];
4009 ventoy_chain_head *chain;
4010 ventoy_img_chunk *chunk;
4011 ventoy_os_param *osparam;
4012 ventoy_image_location *location;
4013 ventoy_image_disk_region *region;
4014 struct grub_acpi_table_header *acpi;
4015
4016 (void)ctxt;
4017
4018 if (argc != 2)
4019 {
4020 return 1;
4021 }
4022
4023 debug("ventoy_cmd_acpi_param %s %s\n", args[0], args[1]);
4024
4025 chain = (ventoy_chain_head *)(ulong)grub_strtoul(args[0], NULL, 16);
4026 if (!chain)
4027 {
4028 return 1;
4029 }
4030
4031 image_sector_size = (int)grub_strtol(args[1], NULL, 10);
4032
4033 if (grub_memcmp(&g_ventoy_guid, &(chain->os_param.guid), 16))
4034 {
4035 debug("Invalid ventoy guid 0x%x\n", chain->os_param.guid.data1);
4036 return 1;
4037 }
4038
4039 img_chunk_num = chain->img_chunk_num;
4040
4041 loclen = sizeof(ventoy_image_location) + (img_chunk_num - 1) * sizeof(ventoy_image_disk_region);
4042 datalen = sizeof(ventoy_os_param) + loclen;
4043
4044 buflen = sizeof(struct grub_acpi_table_header) + datalen;
4045 acpi = grub_zalloc(buflen);
4046 if (!acpi)
4047 {
4048 return 1;
4049 }
4050
4051 /* Step1: Fill acpi table header */
4052 grub_memcpy(acpi->signature, "VTOY", 4);
4053 acpi->length = buflen;
4054 acpi->revision = 1;
4055 grub_memcpy(acpi->oemid, "VENTOY", 6);
4056 grub_memcpy(acpi->oemtable, "OSPARAMS", 8);
4057 acpi->oemrev = 1;
4058 acpi->creator_id[0] = 1;
4059 acpi->creator_rev = 1;
4060
4061 /* Step2: Fill data */
4062 osparam = (ventoy_os_param *)(acpi + 1);
4063 grub_memcpy(osparam, &chain->os_param, sizeof(ventoy_os_param));
4064 osparam->vtoy_img_location_addr = 0;
4065 osparam->vtoy_img_location_len = loclen;
4066 osparam->chksum = 0;
4067 osparam->chksum = 0x100 - grub_byte_checksum(osparam, sizeof(ventoy_os_param));
4068
4069 location = (ventoy_image_location *)(osparam + 1);
4070 grub_memcpy(&location->guid, &osparam->guid, sizeof(ventoy_guid));
4071 location->image_sector_size = image_sector_size;
4072 location->disk_sector_size = chain->disk_sector_size;
4073 location->region_count = img_chunk_num;
4074
4075 region = location->regions;
4076 chunk = (ventoy_img_chunk *)((char *)chain + chain->img_chunk_offset);
4077 if (512 == image_sector_size)
4078 {
4079 for (i = 0; i < img_chunk_num; i++)
4080 {
4081 region->image_sector_count = chunk->disk_end_sector - chunk->disk_start_sector + 1;
4082 region->image_start_sector = chunk->img_start_sector * 4;
4083 region->disk_start_sector = chunk->disk_start_sector;
4084 region++;
4085 chunk++;
4086 }
4087 }
4088 else
4089 {
4090 for (i = 0; i < img_chunk_num; i++)
4091 {
4092 region->image_sector_count = chunk->img_end_sector - chunk->img_start_sector + 1;
4093 region->image_start_sector = chunk->img_start_sector;
4094 region->disk_start_sector = chunk->disk_start_sector;
4095 region++;
4096 chunk++;
4097 }
4098 }
4099
4100 /* Step3: Fill acpi checksum */
4101 acpi->checksum = 0;
4102 acpi->checksum = 0x100 - grub_byte_checksum(acpi, acpi->length);
4103
4104 /* load acpi table */
4105 grub_snprintf(cmd, sizeof(cmd), "acpi mem:0x%lx:size:%d", (ulong)acpi, acpi->length);
4106 grub_script_execute_sourcecode(cmd);
4107
4108 grub_free(acpi);
4109
4110 VENTOY_CMD_RETURN(0);
4111 }
4112
4113 static grub_err_t ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt, int argc, char **args)
4114 {
4115 (void)ctxt;
4116 (void)argc;
4117 (void)args;
4118
4119 g_ventoy_last_entry_back = g_ventoy_last_entry;
4120 g_ventoy_last_entry = -1;
4121
4122 return 0;
4123 }
4124
4125 static grub_err_t ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt, int argc, char **args)
4126 {
4127 (void)ctxt;
4128 (void)argc;
4129 (void)args;
4130
4131 g_ventoy_last_entry = g_ventoy_last_entry_back;
4132
4133 return 0;
4134 }
4135
4136 static int ventoy_lib_module_callback(const char *filename, const struct grub_dirhook_info *info, void *data)
4137 {
4138 const char *pos = filename + 1;
4139
4140 if (info->dir)
4141 {
4142 while (*pos)
4143 {
4144 if (*pos == '.')
4145 {
4146 if ((*(pos - 1) >= '0' && *(pos - 1) <= '9') && (*(pos + 1) >= '0' && *(pos + 1) <= '9'))
4147 {
4148 grub_strncpy((char *)data, filename, 128);
4149 return 1;
4150 }
4151 }
4152 pos++;
4153 }
4154 }
4155
4156 return 0;
4157 }
4158
4159 static grub_err_t ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt, int argc, char **args)
4160 {
4161 int rc = 1;
4162 char *device_name = NULL;
4163 grub_device_t dev = NULL;
4164 grub_fs_t fs = NULL;
4165 char buf[128] = {0};
4166
4167 (void)ctxt;
4168
4169 if (argc != 3)
4170 {
4171 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc);
4172 return 1;
4173 }
4174
4175 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args[0], args[1], args[2]);
4176
4177 device_name = grub_file_get_device_name(args[0]);
4178 if (!device_name)
4179 {
4180 debug("grub_file_get_device_name failed, %s\n", args[0]);
4181 goto end;
4182 }
4183
4184 dev = grub_device_open(device_name);
4185 if (!dev)
4186 {
4187 debug("grub_device_open failed, %s\n", device_name);
4188 goto end;
4189 }
4190
4191 fs = grub_fs_probe(dev);
4192 if (!fs)
4193 {
4194 debug("grub_fs_probe failed, %s\n", device_name);
4195 goto end;
4196 }
4197
4198 fs->fs_dir(dev, args[1], ventoy_lib_module_callback, buf);
4199
4200 if (buf[0])
4201 {
4202 ventoy_set_env(args[2], buf);
4203 }
4204
4205 rc = 0;
4206
4207 end:
4208
4209 check_free(device_name, grub_free);
4210 check_free(dev, grub_device_close);
4211
4212 return rc;
4213 }
4214
4215 int ventoy_load_part_table(const char *diskname)
4216 {
4217 char name[64];
4218 int ret;
4219 grub_disk_t disk;
4220 grub_device_t dev;
4221
4222 g_ventoy_part_info = grub_zalloc(sizeof(ventoy_gpt_info));
4223 if (!g_ventoy_part_info)
4224 {
4225 return 1;
4226 }
4227
4228 disk = grub_disk_open(diskname);
4229 if (!disk)
4230 {
4231 debug("Failed to open disk %s\n", diskname);
4232 return 1;
4233 }
4234
4235 g_ventoy_disk_size = disk->total_sectors * (1U << disk->log_sector_size);
4236
4237 grub_disk_read(disk, 0, 0, sizeof(ventoy_gpt_info), g_ventoy_part_info);
4238 grub_disk_close(disk);
4239
4240 grub_snprintf(name, sizeof(name), "%s,1", diskname);
4241 dev = grub_device_open(name);
4242 if (dev)
4243 {
4244 /* Check for official Ventoy device */
4245 ret = ventoy_check_official_device(dev);
4246 grub_device_close(dev);
4247
4248 if (ret)
4249 {
4250 return 1;
4251 }
4252 }
4253
4254 g_ventoy_disk_part_size[0] = ventoy_get_vtoy_partsize(0);
4255 g_ventoy_disk_part_size[1] = ventoy_get_vtoy_partsize(1);
4256
4257 return 0;
4258 }
4259
4260 static grub_err_t ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt, int argc, char **args)
4261 {
4262 int ret;
4263
4264 (void)argc;
4265 (void)ctxt;
4266
4267 ret = ventoy_load_part_table(args[0]);
4268 if (ret)
4269 {
4270 grub_exit();
4271 }
4272
4273 g_ventoy_disk_part_size[0] = ventoy_get_vtoy_partsize(0);
4274 g_ventoy_disk_part_size[1] = ventoy_get_vtoy_partsize(1);
4275
4276 return 0;
4277 }
4278
4279 static grub_err_t ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt, int argc, char **args)
4280 {
4281 int ret = 1;
4282 const char *vcfg = NULL;
4283
4284 (void)argc;
4285 (void)ctxt;
4286
4287 vcfg = ventoy_plugin_get_custom_boot(args[0]);
4288 if (vcfg)
4289 {
4290 debug("custom boot <%s>:<%s>\n", args[0], vcfg);
4291 grub_env_set(args[1], vcfg);
4292 ret = 0;
4293 }
4294 else
4295 {
4296 debug("custom boot <%s>:<NOT FOUND>\n", args[0]);
4297 }
4298
4299 grub_errno = 0;
4300 return ret;
4301 }
4302
4303
4304 static grub_err_t ventoy_cmd_part_exist(grub_extcmd_context_t ctxt, int argc, char **args)
4305 {
4306 int id;
4307 grub_uint8_t zeroguid[16] = {0};
4308
4309 (void)argc;
4310 (void)ctxt;
4311
4312 id = (int)grub_strtoul(args[0], NULL, 10);
4313 grub_errno = 0;
4314
4315 if (grub_memcmp(g_ventoy_part_info->Head.Signature, "EFI PART", 8) == 0)
4316 {
4317 if (id >= 1 && id <= 128)
4318 {
4319 if (grub_memcmp(g_ventoy_part_info->PartTbl[id - 1].PartGuid, zeroguid, 16))
4320 {
4321 return 0;
4322 }
4323 }
4324 }
4325 else
4326 {
4327 if (id >= 1 && id <= 4)
4328 {
4329 if (g_ventoy_part_info->MBR.PartTbl[id - 1].FsFlag)
4330 {
4331 return 0;
4332 }
4333 }
4334 }
4335
4336 return 1;
4337 }
4338
4339 static grub_err_t ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt, int argc, char **args)
4340 {
4341 int rc = 1;
4342 char *device_name = NULL;
4343 grub_device_t dev = NULL;
4344 grub_fs_t fs = NULL;
4345 char *label = NULL;
4346
4347 (void)ctxt;
4348
4349 debug("get fs label for %s\n", args[0]);
4350
4351 if (argc != 2)
4352 {
4353 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc);
4354 return 1;
4355 }
4356
4357 device_name = grub_file_get_device_name(args[0]);
4358 if (!device_name)
4359 {
4360 debug("grub_file_get_device_name failed, %s\n", args[0]);
4361 goto end;
4362 }
4363
4364 dev = grub_device_open(device_name);
4365 if (!dev)
4366 {
4367 debug("grub_device_open failed, %s\n", device_name);
4368 goto end;
4369 }
4370
4371 fs = grub_fs_probe(dev);
4372 if (NULL == fs || NULL == fs->fs_label)
4373 {
4374 debug("grub_fs_probe failed, %s %p %p\n", device_name, fs, fs->fs_label);
4375 goto end;
4376 }
4377
4378 fs->fs_label(dev, &label);
4379 if (label)
4380 {
4381 debug("label=<%s>\n", label);
4382 ventoy_set_env(args[1], label);
4383 grub_free(label);
4384 }
4385
4386 rc = 0;
4387
4388 end:
4389
4390 check_free(device_name, grub_free);
4391 check_free(dev, grub_device_close);
4392
4393 return rc;
4394 }
4395
4396 static int ventoy_fs_enum_1st_file(const char *filename, const struct grub_dirhook_info *info, void *data)
4397 {
4398 if (!info->dir)
4399 {
4400 grub_snprintf((char *)data, 256, "%s", filename);
4401 return 1;
4402 }
4403
4404 return 0;
4405 }
4406
4407 static int ventoy_fs_enum_1st_dir(const char *filename, const struct grub_dirhook_info *info, void *data)
4408 {
4409 if (info->dir && filename && filename[0] != '.')
4410 {
4411 grub_snprintf((char *)data, 256, "%s", filename);
4412 return 1;
4413 }
4414
4415 return 0;
4416 }
4417
4418 static grub_err_t ventoy_fs_enum_1st_child(int argc, char **args, grub_fs_dir_hook_t hook)
4419 {
4420 int rc = 1;
4421 char *device_name = NULL;
4422 grub_device_t dev = NULL;
4423 grub_fs_t fs = NULL;
4424 char name[256] ={0};
4425
4426 if (argc != 3)
4427 {
4428 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc);
4429 return 1;
4430 }
4431
4432 device_name = grub_file_get_device_name(args[0]);
4433 if (!device_name)
4434 {
4435 debug("grub_file_get_device_name failed, %s\n", args[0]);
4436 goto end;
4437 }
4438
4439 dev = grub_device_open(device_name);
4440 if (!dev)
4441 {
4442 debug("grub_device_open failed, %s\n", device_name);
4443 goto end;
4444 }
4445
4446 fs = grub_fs_probe(dev);
4447 if (!fs)
4448 {
4449 debug("grub_fs_probe failed, %s\n", device_name);
4450 goto end;
4451 }
4452
4453 fs->fs_dir(dev, args[1], hook, name);
4454 if (name[0])
4455 {
4456 ventoy_set_env(args[2], name);
4457 }
4458
4459 rc = 0;
4460
4461 end:
4462
4463 check_free(device_name, grub_free);
4464 check_free(dev, grub_device_close);
4465
4466 return rc;
4467 }
4468
4469 static grub_err_t ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt, int argc, char **args)
4470 {
4471 (void)ctxt;
4472 return ventoy_fs_enum_1st_child(argc, args, ventoy_fs_enum_1st_file);
4473 }
4474
4475 static grub_err_t ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt, int argc, char **args)
4476 {
4477 (void)ctxt;
4478 return ventoy_fs_enum_1st_child(argc, args, ventoy_fs_enum_1st_dir);
4479 }
4480
4481 static grub_err_t ventoy_cmd_basename(grub_extcmd_context_t ctxt, int argc, char **args)
4482 {
4483 char c;
4484 char *pos = NULL;
4485 char *end = NULL;
4486
4487 (void)ctxt;
4488
4489 if (argc != 2)
4490 {
4491 debug("ventoy_cmd_basename, invalid param num %d\n", argc);
4492 return 1;
4493 }
4494
4495 for (pos = args[0]; *pos; pos++)
4496 {
4497 if (*pos == '.')
4498 {
4499 end = pos;
4500 }
4501 }
4502
4503 if (end)
4504 {
4505 c = *end;
4506 *end = 0;
4507 }
4508
4509 grub_env_set(args[1], args[0]);
4510
4511 if (end)
4512 {
4513 *end = c;
4514 }
4515
4516 return 0;
4517 }
4518
4519 static grub_err_t ventoy_cmd_basefile(grub_extcmd_context_t ctxt, int argc, char **args)
4520 {
4521 int i;
4522 int len;
4523 const char *buf;
4524
4525 (void)ctxt;
4526
4527 if (argc != 2)
4528 {
4529 debug("ventoy_cmd_basefile, invalid param num %d\n", argc);
4530 return 1;
4531 }
4532
4533 buf = args[0];
4534 len = (int)grub_strlen(buf);
4535 for (i = len; i > 0; i--)
4536 {
4537 if (buf[i - 1] == '/')
4538 {
4539 grub_env_set(args[1], buf + i);
4540 return 0;
4541 }
4542 }
4543
4544 grub_env_set(args[1], buf);
4545
4546 return 0;
4547 }
4548
4549 static grub_err_t ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt, int argc, char **args)
4550 {
4551 struct grub_video_mode_info info;
4552 char buf[32];
4553
4554 (void)ctxt;
4555 (void)argc;
4556 (void)args;
4557
4558 if (!g_video_mode_list)
4559 {
4560 ventoy_enum_video_mode();
4561 }
4562
4563 if (grub_video_get_info(&info) == GRUB_ERR_NONE)
4564 {
4565 grub_snprintf(buf, sizeof(buf), "Resolution (%ux%u)", info.width, info.height);
4566 }
4567 else
4568 {
4569 grub_snprintf(buf, sizeof(buf), "Resolution (0x0)");
4570 }
4571
4572 grub_env_set("VTOY_CUR_VIDEO_MODE", buf);
4573
4574 grub_snprintf(buf, sizeof(buf), "%d", g_video_mode_num);
4575 grub_env_set("VTOY_VIDEO_MODE_NUM", buf);
4576
4577 VENTOY_CMD_RETURN(0);
4578 }
4579
4580 static grub_err_t vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt, int argc, char **args)
4581 {
4582 struct grub_video_mode_info info;
4583 char buf[32];
4584
4585 (void)ctxt;
4586 (void)argc;
4587 (void)args;
4588
4589 if (grub_video_get_info(&info) == GRUB_ERR_NONE)
4590 {
4591 grub_snprintf(buf, sizeof(buf), "%ux%ux%u", info.width, info.height, info.bpp);
4592 }
4593 else
4594 {
4595 grub_snprintf(buf, sizeof(buf), "0x0x0");
4596 }
4597
4598 grub_env_set(args[0], buf);
4599
4600 VENTOY_CMD_RETURN(0);
4601 }
4602
4603 static grub_err_t ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt, int argc, char **args)
4604 {
4605 int id;
4606 char buf[32];
4607
4608 (void)ctxt;
4609 (void)argc;
4610
4611 if (!g_video_mode_list)
4612 {
4613 return 0;
4614 }
4615
4616 id = (int)grub_strtoul(args[0], NULL, 10);
4617 if (id < g_video_mode_num)
4618 {
4619 grub_snprintf(buf, sizeof(buf), "%ux%ux%u",
4620 g_video_mode_list[id].width, g_video_mode_list[id].height, g_video_mode_list[id].bpp);
4621 }
4622
4623 grub_env_set(args[1], buf);
4624
4625 VENTOY_CMD_RETURN(0);
4626 }
4627
4628 static grub_err_t ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt, int argc, char **args)
4629 {
4630 grub_uint32_t i;
4631 grub_uint32_t loadsector = 0;
4632 grub_file_t file;
4633 char value[32];
4634 grub_uint32_t boot_catlog = 0;
4635 grub_uint8_t buf[512];
4636
4637 (void)ctxt;
4638
4639 if (argc != 2)
4640 {
4641 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc);
4642 return 1;
4643 }
4644
4645 file = grub_file_open(args[0], VENTOY_FILE_TYPE);
4646 if (!file)
4647 {
4648 debug("failed to open %s\n", args[0]);
4649 return 1;
4650 }
4651
4652 boot_catlog = ventoy_get_iso_boot_catlog(file);
4653 if (boot_catlog == 0)
4654 {
4655 debug("No bootcatlog found\n");
4656 grub_file_close(file);
4657 return 1;
4658 }
4659
4660 grub_memset(buf, 0, sizeof(buf));
4661 grub_file_seek(file, boot_catlog * 2048);
4662 grub_file_read(file, buf, sizeof(buf));
4663 grub_file_close(file);
4664
4665 for (i = 0; i < sizeof(buf); i += 32)
4666 {
4667 if ((buf[i] == 0 || buf[i] == 0x90 || buf[i] == 0x91) && buf[i + 1] == 0xEF)
4668 {
4669 if (buf[i + 32] == 0x88)
4670 {
4671 loadsector = *(grub_uint32_t *)(buf + i + 32 + 8);
4672 grub_snprintf(value, sizeof(value), "%u", loadsector * 4); //change to sector size 512
4673 break;
4674 }
4675 }
4676 }
4677
4678 if (loadsector == 0)
4679 {
4680 debug("No EFI eltorito info found\n");
4681 return 1;
4682 }
4683
4684 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value);
4685 grub_env_set(args[1], value);
4686 VENTOY_CMD_RETURN(0);
4687 }
4688
4689 static int ventoy_collect_replace_initrd(const char *filename, const struct grub_dirhook_info *info, void *data)
4690 {
4691 int curpos;
4692 int printlen;
4693 grub_size_t len;
4694 replace_fs_dir *pfsdir = (replace_fs_dir *)data;
4695
4696 if (pfsdir->initrd[0])
4697 {
4698 return 1;
4699 }
4700
4701 curpos = pfsdir->curpos;
4702 len = grub_strlen(filename);
4703
4704 if (info->dir)
4705 {
4706 if ((len == 1 && filename[0] == '.') ||
4707 (len == 2 && filename[0] == '.' && filename[1] == '.'))
4708 {
4709 return 0;
4710 }
4711
4712 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
4713 pfsdir->dircnt++;
4714
4715 printlen = grub_snprintf(pfsdir->fullpath + curpos, 512 - curpos, "%s/", filename);
4716 pfsdir->curpos = curpos + printlen;
4717 pfsdir->fs->fs_dir(pfsdir->dev, pfsdir->fullpath, ventoy_collect_replace_initrd, pfsdir);
4718 pfsdir->curpos = curpos;
4719 pfsdir->fullpath[curpos] = 0;
4720 }
4721 else
4722 {
4723 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
4724 pfsdir->filecnt++;
4725
4726 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
4727 if (len > 4 && grub_strncmp(filename + len - 4, ".img", 4) == 0)
4728 {
4729 if (info->size > 32 * VTOY_SIZE_1MB)
4730 {
4731 grub_snprintf(pfsdir->initrd, sizeof(pfsdir->initrd), "%s%s", pfsdir->fullpath, filename);
4732 return 1;
4733 }
4734 }
4735 }
4736
4737 return 0;
4738 }
4739
4740 static grub_err_t ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt, int argc, char **args)
4741 {
4742 int i;
4743 char *pos = NULL;
4744 char *device_name = NULL;
4745 grub_device_t dev = NULL;
4746 grub_fs_t fs = NULL;
4747 replace_fs_dir *pfsdir = NULL;
4748
4749 (void)ctxt;
4750
4751 if (argc != 2)
4752 {
4753 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc);
4754 return 1;
4755 }
4756
4757 pfsdir = grub_zalloc(sizeof(replace_fs_dir));
4758 if (!pfsdir)
4759 {
4760 return 1;
4761 }
4762
4763 device_name = grub_file_get_device_name(args[0]);
4764 if (!device_name)
4765 {
4766 goto fail;
4767 }
4768
4769 dev = grub_device_open(device_name);
4770 if (!dev)
4771 {
4772 goto fail;
4773 }
4774
4775 fs = grub_fs_probe(dev);
4776 if (!fs)
4777 {
4778 goto fail;
4779 }
4780
4781 pfsdir->dev = dev;
4782 pfsdir->fs = fs;
4783 pfsdir->curpos = 1;
4784 pfsdir->fullpath[0] = '/';
4785 fs->fs_dir(dev, "/", ventoy_collect_replace_initrd, pfsdir);
4786
4787 if (pfsdir->initrd[0])
4788 {
4789 debug("Replace initrd <%s> <%d %d>\n", pfsdir->initrd, pfsdir->dircnt, pfsdir->filecnt);
4790
4791 for (i = 0; i < (int)sizeof(pfsdir->initrd) && pfsdir->initrd[i]; i++)
4792 {
4793 if (pfsdir->initrd[i] == '/')
4794 {
4795 pfsdir->initrd[i] = '\\';
4796 }
4797 }
4798
4799 pos = (pfsdir->initrd[0] == '\\') ? pfsdir->initrd + 1 : pfsdir->initrd;
4800 grub_env_set(args[1], pos);
4801 }
4802 else
4803 {
4804 debug("Replace initrd NOT found <%s> <%d %d>\n", args[0], pfsdir->dircnt, pfsdir->filecnt);
4805 }
4806
4807 fail:
4808
4809 grub_check_free(pfsdir);
4810 grub_check_free(device_name);
4811 check_free(dev, grub_device_close);
4812
4813 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
4814 }
4815
4816 static grub_err_t ventoy_cmd_push_pager(grub_extcmd_context_t ctxt, int argc, char **args)
4817 {
4818 const char *pager = NULL;
4819
4820 (void)ctxt;
4821 (void)argc;
4822 (void)args;
4823
4824 pager = grub_env_get("pager");
4825 if (NULL == pager)
4826 {
4827 g_pager_flag = 1;
4828 grub_env_set("pager", "1");
4829 }
4830 else if (pager[0] == '1')
4831 {
4832 g_pager_flag = 0;
4833 }
4834 else
4835 {
4836 grub_snprintf(g_old_pager, sizeof(g_old_pager), "%s", pager);
4837 g_pager_flag = 2;
4838 grub_env_set("pager", "1");
4839 }
4840
4841 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
4842 }
4843
4844 static grub_err_t ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt, int argc, char **args)
4845 {
4846 (void)ctxt;
4847 (void)argc;
4848 (void)args;
4849
4850 if (g_pager_flag == 1)
4851 {
4852 grub_env_unset("pager");
4853 }
4854 else if (g_pager_flag == 2)
4855 {
4856 grub_env_set("pager", g_old_pager);
4857 }
4858
4859 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
4860 }
4861
4862 static int ventoy_chk_case_file(const char *filename, const struct grub_dirhook_info *info, void *data)
4863 {
4864 if (g_json_case_mis_path[0])
4865 {
4866 return 1;
4867 }
4868
4869 if (0 == info->dir && grub_strcasecmp(filename, "ventoy.json") == 0)
4870 {
4871 grub_snprintf(g_json_case_mis_path, 32, "%s/%s", (char *)data, filename);
4872 return 1;
4873 }
4874 return 0;
4875 }
4876
4877 static int ventoy_chk_case_dir(const char *filename, const struct grub_dirhook_info *info, void *data)
4878 {
4879 char path[16];
4880 chk_case_fs_dir *fs_dir = (chk_case_fs_dir *)data;
4881
4882 if (g_json_case_mis_path[0])
4883 {
4884 return 1;
4885 }
4886
4887 if (info->dir && (filename[0] == 'v' || filename[0] == 'V'))
4888 {
4889 if (grub_strcasecmp(filename, "ventoy") == 0)
4890 {
4891 grub_snprintf(path, sizeof(path), "/%s", filename);
4892 fs_dir->fs->fs_dir(fs_dir->dev, path, ventoy_chk_case_file, path);
4893 if (g_json_case_mis_path[0])
4894 {
4895 return 1;
4896 }
4897 }
4898 }
4899
4900 return 0;
4901 }
4902
4903 static grub_err_t ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt, int argc, char **args)
4904 {
4905 int fstype = 0;
4906 char *device_name = NULL;
4907 grub_device_t dev = NULL;
4908 grub_fs_t fs = NULL;
4909 chk_case_fs_dir fs_dir;
4910
4911 (void)ctxt;
4912 (void)argc;
4913 (void)args;
4914
4915 device_name = grub_file_get_device_name(args[0]);
4916 if (!device_name)
4917 {
4918 goto out;
4919 }
4920
4921 dev = grub_device_open(device_name);
4922 if (!dev)
4923 {
4924 goto out;
4925 }
4926
4927 fs = grub_fs_probe(dev);
4928 if (!fs)
4929 {
4930 goto out;
4931 }
4932
4933 fstype = ventoy_get_fs_type(fs->name);
4934 if (fstype == ventoy_fs_fat || fstype == ventoy_fs_exfat || fstype >= ventoy_fs_max)
4935 {
4936 goto out;
4937 }
4938
4939 g_json_case_mis_path[0] = 0;
4940 fs_dir.dev = dev;
4941 fs_dir.fs = fs;
4942 fs->fs_dir(dev, "/", ventoy_chk_case_dir, &fs_dir);
4943
4944 if (g_json_case_mis_path[0])
4945 {
4946 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path);
4947 }
4948
4949 out:
4950
4951 grub_check_free(device_name);
4952 check_free(dev, grub_device_close);
4953
4954 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
4955 }
4956
4957 static grub_err_t grub_cmd_gptpriority(grub_extcmd_context_t ctxt, int argc, char **args)
4958 {
4959 grub_disk_t disk;
4960 grub_partition_t part;
4961 char priority_str[3]; /* Maximum value 15 */
4962
4963 (void)ctxt;
4964
4965 if (argc < 2 || argc > 3)
4966 return grub_error (GRUB_ERR_BAD_ARGUMENT,
4967 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
4968
4969 /* Open the disk if it exists */
4970 disk = grub_disk_open (args[0]);
4971 if (!disk)
4972 {
4973 return grub_error (GRUB_ERR_BAD_ARGUMENT,
4974 "Not a disk");
4975 }
4976
4977 part = grub_partition_probe (disk, args[1]);
4978 if (!part)
4979 {
4980 grub_disk_close (disk);
4981 return grub_error (GRUB_ERR_BAD_ARGUMENT,
4982 "No such partition");
4983 }
4984
4985 if (grub_strcmp (part->partmap->name, "gpt"))
4986 {
4987 grub_disk_close (disk);
4988 return grub_error (GRUB_ERR_BAD_PART_TABLE,
4989 "Not a GPT partition");
4990 }
4991
4992 grub_snprintf (priority_str, sizeof(priority_str), "%u",
4993 (grub_uint32_t)((part->gpt_attrib >> 48) & 0xfULL));
4994
4995 if (argc == 3)
4996 {
4997 grub_env_set (args[2], priority_str);
4998 grub_env_export (args[2]);
4999 }
5000 else
5001 {
5002 grub_printf ("Priority is %s\n", priority_str);
5003 }
5004
5005 grub_disk_close (disk);
5006 return GRUB_ERR_NONE;
5007 }
5008
5009
5010
5011 /* <BEGIN>: Deleted by longpanda, 20210916 PN:XX LABEL:XX */
5012 #if 0
5013 void ventoy_tip_set_menu_label(const char *vid)
5014 {
5015 img_info *node;
5016
5017 g_ventoy_tip_msg1 = g_ventoy_tip_msg2 = NULL;
5018 if (vid)
5019 {
5020 node = (img_info *)(void *)grub_strtoul(vid + 4, NULL, 16);
5021 if (node)
5022 {
5023 g_ventoy_tip_msg1 = node->tip1;
5024 g_ventoy_tip_msg2 = node->tip2;
5025 }
5026 }
5027 }
5028 #endif /* #if 0 */
5029 /* <END> : Deleted by longpanda, 20210916 PN:XX LABEL:XX */
5030
5031 int ventoy_env_init(void)
5032 {
5033 char buf[64];
5034
5035 grub_env_set("vtdebug_flag", "");
5036
5037 g_part_list_buf = grub_malloc(VTOY_PART_BUF_LEN);
5038 g_tree_script_buf = grub_malloc(VTOY_MAX_SCRIPT_BUF);
5039 g_list_script_buf = grub_malloc(VTOY_MAX_SCRIPT_BUF);
5040 g_conf_replace_new_buf = grub_malloc(vtoy_max_replace_file_size);
5041
5042 ventoy_filt_register(0, ventoy_wrapper_open);
5043
5044 g_grub_param = (ventoy_grub_param *)grub_zalloc(sizeof(ventoy_grub_param));
5045 if (g_grub_param)
5046 {
5047 g_grub_param->grub_env_get = grub_env_get;
5048 g_grub_param->grub_env_set = (grub_env_set_pf)grub_env_set;
5049 g_grub_param->grub_env_printf = (grub_env_printf_pf)grub_printf;
5050 grub_snprintf(buf, sizeof(buf), "%p", g_grub_param);
5051 grub_env_set("env_param", buf);
5052 grub_env_set("ventoy_env_param", buf);
5053
5054 grub_env_export("env_param");
5055 grub_env_export("ventoy_env_param");
5056 }
5057
5058 grub_snprintf(buf, sizeof(buf), "0x%lx", (ulong)g_vtoy_winpeshl_ini);
5059 grub_env_set("vtoy_winpeshl_ini_addr", buf);
5060
5061 grub_snprintf(buf, sizeof(buf), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini));
5062 grub_env_set("vtoy_winpeshl_ini_size", buf);
5063
5064 grub_env_export("vtoy_winpeshl_ini_addr");
5065 grub_env_export("vtoy_winpeshl_ini_size");
5066
5067 grub_snprintf(buf, sizeof(buf), "0x%lx", (ulong)ventoy_chain_file_size);
5068 grub_env_set("vtoy_chain_file_size", buf);
5069 grub_env_export("vtoy_chain_file_size");
5070
5071 grub_snprintf(buf, sizeof(buf), "0x%lx", (ulong)ventoy_chain_file_read);
5072 grub_env_set("vtoy_chain_file_read", buf);
5073 grub_env_export("vtoy_chain_file_read");
5074
5075 return 0;
5076 }
5077
5078
5079
5080 static cmd_para ventoy_cmds[] =
5081 {
5082 { "vt_incr", ventoy_cmd_incr, 0, NULL, "{Var} {INT}", "Increase integer variable", NULL },
5083 { "vt_mod", ventoy_cmd_mod, 0, NULL, "{Int} {Int} {Var}", "mod integer variable", NULL },
5084 { "vt_strstr", ventoy_cmd_strstr, 0, NULL, "", "", NULL },
5085 { "vt_str_begin", ventoy_cmd_strbegin, 0, NULL, "", "", NULL },
5086 { "vt_str_casebegin", ventoy_cmd_strcasebegin, 0, NULL, "", "", NULL },
5087 { "vt_debug", ventoy_cmd_debug, 0, NULL, "{on|off}", "turn debug on/off", NULL },
5088 { "vtdebug", ventoy_cmd_debug, 0, NULL, "{on|off}", "turn debug on/off", NULL },
5089 { "vtbreak", ventoy_cmd_break, 0, NULL, "{level}", "set debug break", NULL },
5090 { "vt_cmp", ventoy_cmd_cmp, 0, NULL, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL },
5091 { "vt_device", ventoy_cmd_device, 0, NULL, "path var", "", NULL },
5092 { "vt_check_compatible", ventoy_cmd_check_compatible, 0, NULL, "", "", NULL },
5093 { "vt_list_img", ventoy_cmd_list_img, 0, NULL, "{device} {cntvar}", "find all iso file in device", NULL },
5094 { "vt_clear_img", ventoy_cmd_clear_img, 0, NULL, "", "clear image list", NULL },
5095 { "vt_img_name", ventoy_cmd_img_name, 0, NULL, "{imageID} {var}", "get image name", NULL },
5096 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path, 0, NULL, "{var}", "get chosen img path", NULL },
5097 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path, 0, NULL, "{var}", "select chosen img path", NULL },
5098 { "vt_img_sector", ventoy_cmd_img_sector, 0, NULL, "{imageName}", "", NULL },
5099 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector, 0, NULL, "", "", NULL },
5100 { "vt_load_wimboot", ventoy_cmd_load_wimboot, 0, NULL, "", "", NULL },
5101 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot, 0, NULL, "", "", NULL },
5102 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot, 0, NULL, "", "", NULL },
5103 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data, 0, NULL, "", "", NULL },
5104 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type, 0, NULL, "", "", NULL },
5105 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot, 0, NULL, "", "", NULL },
5106 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot, 0, NULL, "", "", NULL },
5107
5108 { "vt_skip_svd", ventoy_cmd_skip_svd, 0, NULL, "", "", NULL },
5109 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64, 0, NULL, "", "", NULL },
5110 { "vt_load_cpio", ventoy_cmd_load_cpio, 0, NULL, "", "", NULL },
5111 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio, 0, NULL, "", "", NULL },
5112 { "vt_push_last_entry", ventoy_cmd_push_last_entry, 0, NULL, "", "", NULL },
5113 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry, 0, NULL, "", "", NULL },
5114 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver, 0, NULL, "", "", NULL },
5115
5116 { "vt_load_part_table", ventoy_cmd_load_part_table, 0, NULL, "", "", NULL },
5117 { "vt_check_part_exist", ventoy_cmd_part_exist, 0, NULL, "", "", NULL },
5118 { "vt_get_fs_label", ventoy_cmd_get_fs_label, 0, NULL, "", "", NULL },
5119 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file, 0, NULL, "", "", NULL },
5120 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir, 0, NULL, "", "", NULL },
5121 { "vt_file_basename", ventoy_cmd_basename, 0, NULL, "", "", NULL },
5122 { "vt_file_basefile", ventoy_cmd_basefile, 0, NULL, "", "", NULL },
5123 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode, 0, NULL, "", "", NULL },
5124 { "vt_get_video_mode", ventoy_cmd_get_video_mode, 0, NULL, "", "", NULL },
5125 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode, 0, NULL, "", "", NULL },
5126
5127
5128 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd, 0, NULL, "", "", NULL },
5129 { "vt_dump_menu", ventoy_cmd_dump_menu, 0, NULL, "", "", NULL },
5130 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu, 0, NULL, "", "", NULL },
5131 { "vt_check_mode", ventoy_cmd_check_mode, 0, NULL, "", "", NULL },
5132 { "vt_dump_img_list", ventoy_cmd_dump_img_list, 0, NULL, "", "", NULL },
5133 { "vt_dump_injection", ventoy_cmd_dump_injection, 0, NULL, "", "", NULL },
5134 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install, 0, NULL, "", "", NULL },
5135 { "vt_dump_persistence", ventoy_cmd_dump_persistence, 0, NULL, "", "", NULL },
5136 { "vt_select_auto_install", ventoy_cmd_sel_auto_install, 0, NULL, "", "", NULL },
5137 { "vt_select_persistence", ventoy_cmd_sel_persistence, 0, NULL, "", "", NULL },
5138 { "vt_select_conf_replace", ventoy_select_conf_replace, 0, NULL, "", "", NULL },
5139
5140 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet, 0, NULL, "", "", NULL },
5141 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet, 0, NULL, "", "", NULL },
5142 { "vt_is_udf", ventoy_cmd_is_udf, 0, NULL, "", "", NULL },
5143 { "vt_file_size", ventoy_cmd_file_size, 0, NULL, "", "", NULL },
5144 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem, 0, NULL, "", "", NULL },
5145 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk, 0, NULL, "", "", NULL },
5146 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso, 0, NULL, "", "", NULL },
5147
5148 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect, 0, NULL, "{cfgfile}", "", NULL },
5149 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect, 0, NULL, "{cfgfile}", "", NULL },
5150 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file, 0, NULL, "", "", NULL },
5151 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list, 0, NULL, "", "", NULL },
5152 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list, 0, NULL, "", "", NULL },
5153 { "vt_linux_initrd_count", ventoy_cmd_initrd_count, 0, NULL, "", "", NULL },
5154 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count, 0, NULL, "", "", NULL },
5155 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd, 0, NULL, "", "", NULL },
5156 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data, 0, NULL, "", "", NULL },
5157 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index, 0, NULL, "", "", NULL },
5158
5159 { "vt_windows_reset", ventoy_cmd_wimdows_reset, 0, NULL, "", "", NULL },
5160 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data, 0, NULL, "", "", NULL },
5161 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data, 0, NULL, "", "", NULL },
5162 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch, 0, NULL, "", "", NULL },
5163 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch, 0, NULL, "", "", NULL },
5164 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count, 0, NULL, "", "", NULL },
5165 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch, 0, NULL, "", "", NULL },
5166 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable, 0, NULL, "", "", NULL },
5167 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data, 0, NULL, "", "", NULL },
5168
5169 { "vt_add_replace_file", ventoy_cmd_add_replace_file, 0, NULL, "", "", NULL },
5170 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt, 0, NULL, "", "", NULL },
5171 { "vt_test_block_list", ventoy_cmd_test_block_list, 0, NULL, "", "", NULL },
5172 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase, 0, NULL, "", "", NULL },
5173
5174
5175 { "vt_load_plugin", ventoy_cmd_load_plugin, 0, NULL, "", "", NULL },
5176 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json, 0, NULL, "", "", NULL },
5177 { "vt_check_password", ventoy_cmd_check_password, 0, NULL, "", "", NULL },
5178
5179 { "vt_1st_line", ventoy_cmd_read_1st_line, 0, NULL, "", "", NULL },
5180 { "vt_file_strstr", ventoy_cmd_file_strstr, 0, NULL, "", "", NULL },
5181 { "vt_img_part_info", ventoy_cmd_img_part_info, 0, NULL, "", "", NULL },
5182
5183
5184 { "vt_parse_iso_volume", ventoy_cmd_parse_volume, 0, NULL, "", "", NULL },
5185 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date, 0, NULL, "", "", NULL },
5186 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver, 0, NULL, "", "", NULL },
5187 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver, 0, NULL, "", "", NULL },
5188 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf, 0, NULL, "", "", NULL },
5189 { "vt_unix_reset", ventoy_cmd_unix_reset, 0, NULL, "", "", NULL },
5190 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf, 0, NULL, "", "", NULL },
5191 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko, 0, NULL, "", "", NULL },
5192 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc, 0, NULL, "", "", NULL },
5193 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko, 0, NULL, "", "", NULL },
5194 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data, 0, NULL, "", "", NULL },
5195
5196 { "vt_img_hook_root", ventoy_cmd_img_hook_root, 0, NULL, "", "", NULL },
5197 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root, 0, NULL, "", "", NULL },
5198 { "vt_acpi_param", ventoy_cmd_acpi_param, 0, NULL, "", "", NULL },
5199 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var, 0, NULL, "", "", NULL },
5200 { "vt_clear_key", ventoy_cmd_clear_key, 0, NULL, "", "", NULL },
5201 { "vt_img_check_range", ventoy_cmd_img_check_range, 0, NULL, "", "", NULL },
5202 { "vt_is_pe64", ventoy_cmd_is_pe64, 0, NULL, "", "", NULL },
5203 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot, 0, NULL, "", "", NULL },
5204 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt, 0, NULL, "", "", NULL },
5205 { "vt_set_theme", ventoy_cmd_set_theme, 0, NULL, "", "", NULL },
5206
5207 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset, 0, NULL, "", "", NULL },
5208 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd, 0, NULL, "", "", NULL },
5209 { "vt_push_pager", ventoy_cmd_push_pager, 0, NULL, "", "", NULL },
5210 { "vt_pop_pager", ventoy_cmd_pop_pager, 0, NULL, "", "", NULL },
5211 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase, 0, NULL, "", "", NULL },
5212 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector, 0, NULL, "", "", NULL },
5213 { "gptpriority", grub_cmd_gptpriority, 0, NULL, "", "", NULL },
5214 };
5215
5216 int ventoy_register_all_cmd(void)
5217 {
5218 grub_uint32_t i;
5219 cmd_para *cur = NULL;
5220
5221 for (i = 0; i < ARRAY_SIZE(ventoy_cmds); i++)
5222 {
5223 cur = ventoy_cmds + i;
5224 cur->cmd = grub_register_extcmd(cur->name, cur->func, cur->flags,
5225 cur->summary, cur->description, cur->parser);
5226 }
5227
5228 return 0;
5229 }
5230
5231 int ventoy_unregister_all_cmd(void)
5232 {
5233 grub_uint32_t i;
5234
5235 for (i = 0; i < ARRAY_SIZE(ventoy_cmds); i++)
5236 {
5237 grub_unregister_extcmd(ventoy_cmds[i].cmd);
5238 }
5239
5240 return 0;
5241 }
5242
5243