1 /******************************************************************************
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include <grub/types.h>
22 #include <grub/misc.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>
36 #include <grub/time.h>
37 #include <grub/ventoy.h>
38 #include "ventoy_def.h"
40 GRUB_MOD_LICENSE ("GPLv3+");
42 int g_ventoy_debug
= 0;
43 static int g_efi_os
= 0xFF;
44 initrd_info
*g_initrd_img_list
= NULL
;
45 initrd_info
*g_initrd_img_tail
= NULL
;
46 int g_initrd_img_count
= 0;
47 int g_valid_initrd_count
= 0;
49 static grub_file_t g_old_file
;
51 char g_img_swap_tmp_buf
[1024];
53 img_info
*g_ventoy_img_list
= NULL
;
54 int g_ventoy_img_count
= 0;
56 img_iterator_node g_img_iterator_head
;
58 grub_uint8_t g_ventoy_break_level
= 0;
59 grub_uint8_t g_ventoy_debug_level
= 0;
60 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
61 grub_uint32_t g_ventoy_cpio_size
= 0;
62 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
63 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
65 ventoy_grub_param g_grub_param
;
67 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
69 ventoy_img_chunk_list g_img_chunk_list
;
71 void ventoy_debug(const char *fmt
, ...)
76 grub_vprintf (fmt
, args
);
80 int ventoy_is_efi_os(void)
84 g_efi_os
= (grub_strstr(GRUB_PLATFORM
, "efi")) ? 1 : 0;
90 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
109 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
111 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
115 static grub_err_t
ventoy_fs_close(grub_file_t file
)
117 grub_file_close(g_old_file
);
118 grub_free(file
->data
);
126 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
130 static struct grub_fs vtoy_fs
=
135 .fs_read
= ventoy_fs_read
,
136 .fs_close
= ventoy_fs_close
,
146 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
152 file
->data
= grub_malloc(rawFile
->size
+ 4096);
158 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
159 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
161 g_old_file
= rawFile
;
163 file
->size
= rawFile
->size
+ len
;
164 file
->device
= rawFile
->device
;
166 file
->not_easily_seekable
= 1;
171 static int ventoy_check_decimal_var(const char *name
, long *value
)
173 const char *value_str
= NULL
;
175 value_str
= grub_env_get(name
);
176 if (NULL
== value_str
)
178 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
181 if (!ventoy_is_decimal(value_str
))
183 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
186 *value
= grub_strtol(value_str
, NULL
, 10);
188 return GRUB_ERR_NONE
;
191 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
195 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
198 if (0 == grub_strcmp(args
[0], "on"))
201 grub_env_set("vtdebug_flag", "debug");
206 grub_env_set("vtdebug_flag", "");
209 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
212 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
216 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
218 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
219 grub_printf(" level:\r\n");
220 grub_printf(" 01/11: busybox / (+cat log)\r\n");
221 grub_printf(" 02/12: initrd / (+cat log)\r\n");
222 grub_printf(" 03/13: hook / (+cat log)\r\n");
224 grub_printf(" debug:\r\n");
225 grub_printf(" 0: debug is on\r\n");
226 grub_printf(" 1: debug is off\r\n");
228 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
231 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
233 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
235 g_ventoy_debug_level
= 1;
238 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
241 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
246 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
248 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
251 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
256 value_long
+= grub_strtol(args
[1], NULL
, 10);
258 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
259 grub_env_set(args
[0], buf
);
261 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
264 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
269 grub_uint8_t buf
[32];
280 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
283 debug("failed to open file <%s> for udf check\n", args
[0]);
287 for (i
= 16; i
< 32; i
++)
289 grub_file_seek(file
, i
* 2048);
290 grub_file_read(file
, buf
, sizeof(buf
));
298 grub_file_seek(file
, i
* 2048);
299 grub_file_read(file
, buf
, sizeof(buf
));
301 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
304 grub_file_seek(file
, i
* 2048);
305 grub_file_read(file
, buf
, sizeof(buf
));
307 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
308 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
314 grub_file_close(file
);
316 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
321 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
323 long value_long1
= 0;
324 long value_long2
= 0;
326 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
328 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
331 value_long1
= grub_strtol(args
[0], NULL
, 10);
332 value_long2
= grub_strtol(args
[2], NULL
, 10);
334 if (0 == grub_strcmp(args
[1], "eq"))
336 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
338 else if (0 == grub_strcmp(args
[1], "ne"))
340 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
342 else if (0 == grub_strcmp(args
[1], "gt"))
344 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
346 else if (0 == grub_strcmp(args
[1], "lt"))
348 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
350 else if (0 == grub_strcmp(args
[1], "ge"))
352 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
354 else if (0 == grub_strcmp(args
[1], "le"))
356 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
360 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
366 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
373 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
376 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
377 pos
= grub_strstr(buf
, ",");
383 grub_env_set(args
[1], buf
);
385 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
388 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
394 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
400 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
403 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
405 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e %s/%s ]", args
[0], files
[i
]);
406 if (0 == grub_script_execute_sourcecode(buf
))
408 debug("file %s exist, ventoy_compatible YES\n", buf
);
409 grub_env_set("ventoy_compatible", "YES");
410 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
414 debug("file %s NOT exist\n", buf
);
418 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
419 pos
= grub_strstr(buf
, ")");
425 disk
= grub_disk_open(buf
);
428 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
429 grub_disk_close(disk
);
431 g_img_swap_tmp_buf
[703] = 0;
432 for (i
= 319; i
< 703; i
++)
434 if (g_img_swap_tmp_buf
[i
] == 'V' &&
435 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
437 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
438 grub_env_set("ventoy_compatible", "YES");
439 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
445 debug("failed to open disk <%s>\n", buf
);
448 grub_env_set("ventoy_compatible", "NO");
449 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
452 static int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
458 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
463 if (grub_islower(c1
))
468 if (grub_islower(c2
))
482 static void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
484 grub_memcpy(g_img_swap_tmp_buf
, img1
->name
, sizeof(img1
->name
));
485 grub_memcpy(img1
->name
, img2
->name
, sizeof(img1
->name
));
486 grub_memcpy(img2
->name
, g_img_swap_tmp_buf
, sizeof(img1
->name
));
488 grub_memcpy(g_img_swap_tmp_buf
, img1
->path
, sizeof(img1
->path
));
489 grub_memcpy(img1
->path
, img2
->path
, sizeof(img1
->path
));
490 grub_memcpy(img2
->path
, g_img_swap_tmp_buf
, sizeof(img1
->path
));
493 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
497 for (i
= 0; i
< namelen
; i
++)
499 if (filename
[i
] == ' ' || filename
[i
] == '\t')
504 if ((grub_uint8_t
)(filename
[i
]) >= 127)
513 static int ventoy_colect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
518 img_iterator_node
*new_node
;
519 img_iterator_node
*node
= (img_iterator_node
*)data
;
521 len
= grub_strlen(filename
);
525 if ((len
== 1 && filename
[0] == '.') ||
526 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
531 new_node
= grub_malloc(sizeof(img_iterator_node
));
534 new_node
->tail
= node
->tail
;
535 grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
537 new_node
->next
= g_img_iterator_head
.next
;
538 g_img_iterator_head
.next
= new_node
;
543 debug("Find a file %s\n", filename
);
545 if ((len
> 4) && (0 == grub_strcasecmp(filename
+ len
- 4, ".iso")))
547 if (!ventoy_img_name_valid(filename
, len
))
552 img
= grub_zalloc(sizeof(img_info
));
555 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
556 grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, filename
);
558 if (g_ventoy_img_list
)
560 tail
= *(node
->tail
);
566 g_ventoy_img_list
= img
;
569 *((img_info
**)(node
->tail
)) = img
;
570 g_ventoy_img_count
++;
572 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
580 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
582 int len
= GRUB_UINT_MAX
;
583 const char *value
= NULL
;
586 char guidstr
[32] = {0};
587 ventoy_guid guid
= VENTOY_GUID
;
588 const char *fmt1
= NULL
;
589 const char *fmt2
= NULL
;
590 const char *fmt3
= NULL
;
591 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
592 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
593 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
594 const char fmtcode
[]={
595 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
596 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
597 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
598 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
599 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
600 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
603 grub_memset(name
, 0, sizeof(name
));
604 puint
[0] = grub_swap_bytes32(0x56454e54);
605 puint
[3] = grub_swap_bytes32(0x4f4e0000);
606 puint
[2] = grub_swap_bytes32(0x45525349);
607 puint
[1] = grub_swap_bytes32(0x4f595f56);
608 value
= ventoy_get_env(name
);
610 grub_memset(name
, 0, sizeof(name
));
611 puint
[1] = grub_swap_bytes32(0x5f544f50);
612 puint
[0] = grub_swap_bytes32(0x56544c45);
613 fmt1
= ventoy_get_env(name
);
619 grub_memset(name
, 0, sizeof(name
));
620 puint
[1] = grub_swap_bytes32(0x5f4c4654);
621 puint
[0] = grub_swap_bytes32(0x56544c45);
622 fmt2
= ventoy_get_env(name
);
624 grub_memset(name
, 0, sizeof(name
));
625 puint
[1] = grub_swap_bytes32(0x5f434c52);
626 puint
[0] = grub_swap_bytes32(0x56544c45);
627 fmt3
= ventoy_get_env(name
);
629 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
631 #if defined (GRUB_MACHINE_EFI)
632 puint2
[0] = grub_swap_bytes32(0x55454649);
634 puint2
[0] = grub_swap_bytes32(0x42494f53);
637 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
638 #pragma GCC diagnostic push
639 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
640 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
641 fmt1
? fmt1
: fmtdata
,
642 fmt2
? fmt2
: fmtdata
+ 4,
643 value
? value
: "", plat
, guidstr
,
644 fmt3
? fmt3
: fmtdata
+ 6);
645 #pragma GCC diagnostic pop
647 grub_memset(name
, 0, sizeof(name
));
648 puint
[0] = grub_swap_bytes32(0x76746f79);
649 puint
[2] = grub_swap_bytes32(0x656e7365);
650 puint
[1] = grub_swap_bytes32(0x5f6c6963);
651 ventoy_set_env(name
, guidstr
);
656 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
659 grub_device_t dev
= NULL
;
660 img_info
*cur
= NULL
;
661 img_info
*tail
= NULL
;
662 char *device_name
= NULL
;
664 img_iterator_node
*node
= NULL
;
670 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
673 if (g_ventoy_img_list
|| g_ventoy_img_count
)
675 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
678 device_name
= grub_file_get_device_name(args
[0]);
684 dev
= grub_device_open(device_name
);
690 fs
= grub_fs_probe(dev
);
696 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
698 g_img_iterator_head
.tail
= &tail
;
699 grub_strcpy(g_img_iterator_head
.dir
, "/");
701 fs
->fs_dir(dev
, "/", ventoy_colect_img_files
, &g_img_iterator_head
);
703 while (g_img_iterator_head
.next
)
705 node
= g_img_iterator_head
.next
;
706 g_img_iterator_head
.next
= node
->next
;
708 fs
->fs_dir(dev
, node
->dir
, ventoy_colect_img_files
, node
);
712 /* sort image list by image name */
713 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
715 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
717 if (ventoy_cmp_img(cur
, tail
) > 0)
719 ventoy_swap_img(cur
, tail
);
724 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
725 grub_env_set(args
[1], buf
);
729 check_free(device_name
, grub_free
);
730 check_free(dev
, grub_device_close
);
732 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
736 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
738 img_info
*next
= NULL
;
739 img_info
*cur
= g_ventoy_img_list
;
752 g_ventoy_img_list
= NULL
;
753 g_ventoy_img_count
= 0;
755 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
758 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
761 img_info
*cur
= g_ventoy_img_list
;
765 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
767 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
770 img_id
= grub_strtol(args
[0], NULL
, 10);
771 if (img_id
>= g_ventoy_img_count
)
773 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
776 debug("Find image %ld name \n", img_id
);
778 while (cur
&& img_id
> 0)
786 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
789 debug("image name is %s\n", cur
->name
);
791 grub_env_set(args
[1], cur
->name
);
793 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
796 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
798 const char *name
= NULL
;
799 img_info
*cur
= g_ventoy_img_list
;
805 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
808 name
= grub_env_get("chosen");
812 if (0 == grub_strcmp(name
, cur
->name
))
814 grub_env_set(args
[0], cur
->path
);
822 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
825 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
828 static int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
)
835 device_name
= grub_file_get_device_name(filename
);
847 pos2
= grub_strstr(pos
, ",");
850 pos2
= grub_strstr(pos
, ")");
858 disk
= grub_disk_open(pos
);
861 grub_disk_read(disk
, 0, 0x180, 16, guid
);
862 grub_disk_close(disk
);
869 grub_free(device_name
);
873 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
875 eltorito_descriptor desc
;
877 grub_memset(&desc
, 0, sizeof(desc
));
878 grub_file_seek(file
, 17 * 2048);
879 grub_file_read(file
, &desc
, sizeof(desc
));
881 if (desc
.type
!= 0 || desc
.version
!= 1)
886 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
887 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
895 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
898 grub_uint8_t buf
[512];
900 grub_file_seek(file
, sector
* 2048);
901 grub_file_read(file
, buf
, sizeof(buf
));
903 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
905 debug("%s efi eltorito in Validation Entry\n", file
->name
);
909 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
911 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
913 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
918 debug("%s does not contain efi eltorito\n", file
->name
);
922 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
926 grub_uint8_t chksum
= 0;
929 disk
= file
->device
->disk
;
930 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
932 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
933 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
935 if (grub_strcmp(file
->fs
->name
, "exfat") == 0)
937 param
->vtoy_disk_part_type
= 0;
939 else if (grub_strcmp(file
->fs
->name
, "ntfs") == 0)
941 param
->vtoy_disk_part_type
= 1;
945 param
->vtoy_disk_part_type
= 0xFFFF;
948 pos
= grub_strstr(file
->name
, "/");
954 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
956 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
);
958 param
->vtoy_img_size
= file
->size
;
960 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
961 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
963 /* calculate checksum */
964 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
966 chksum
+= *((grub_uint8_t
*)param
+ i
);
968 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
973 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
980 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
983 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
986 if (g_img_chunk_list
.chunk
)
988 grub_free(g_img_chunk_list
.chunk
);
991 /* get image chunk data */
992 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
993 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
994 if (NULL
== g_img_chunk_list
.chunk
)
996 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
999 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1000 g_img_chunk_list
.cur_chunk
= 0;
1002 debug("get fat file chunk part start:%llu\n", (unsigned long long)file
->device
->disk
->partition
->start
);
1003 grub_fat_get_file_chunk(file
->device
->disk
->partition
->start
, file
, &g_img_chunk_list
);
1005 grub_file_close(file
);
1007 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1010 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1013 ventoy_img_chunk
*cur
;
1019 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
1021 cur
= g_img_chunk_list
.chunk
+ i
;
1022 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
1023 cur
->img_start_sector
, cur
->img_end_sector
,
1024 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
1028 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1031 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
1035 char fullpath
[256] = {0};
1038 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
1041 file
= grub_file_open(fullpath
, type
);
1044 debug("grub_file_open failed <%s>\n", fullpath
);
1051 int ventoy_is_file_exist(const char *fmt
, ...)
1056 char buf
[256] = {0};
1058 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f ");
1062 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
1065 grub_strncpy(pos
+ len
, " ]", 2);
1067 debug("script exec %s\n", buf
);
1069 if (0 == grub_script_execute_sourcecode(buf
))
1077 static int ventoy_env_init(void)
1081 grub_env_set("vtdebug_flag", "");
1083 ventoy_filt_register(0, ventoy_wrapper_open
);
1085 g_grub_param
.grub_env_get
= grub_env_get
;
1086 grub_snprintf(buf
, sizeof(buf
), "%p", &g_grub_param
);
1087 grub_env_set("env_param", buf
);
1092 static cmd_para ventoy_cmds
[] =
1094 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
1095 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
1096 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
1097 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
1098 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
1099 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
1100 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
1101 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
1102 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
1103 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
1104 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
1105 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
1106 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
1107 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
1109 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
1111 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
1112 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
1113 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
1114 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
1115 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
1116 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
1117 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
1118 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
1120 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
1121 { "vt_windows_locate_wim", ventoy_cmd_wimdows_locate_wim
, 0, NULL
, "", "", NULL
},
1122 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
1124 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
1129 GRUB_MOD_INIT(ventoy
)
1132 cmd_para
*cur
= NULL
;
1136 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
1138 cur
= ventoy_cmds
+ i
;
1139 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
1140 cur
->summary
, cur
->description
, cur
->parser
);
1144 GRUB_MOD_FINI(ventoy
)
1148 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
1150 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);