1 /******************************************************************************
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <grub/types.h>
21 #include <grub/misc.h>
25 #include <grub/disk.h>
26 #include <grub/device.h>
27 #include <grub/term.h>
28 #include <grub/partition.h>
29 #include <grub/file.h>
30 #include <grub/normal.h>
31 #include <grub/extcmd.h>
32 #include <grub/datetime.h>
33 #include <grub/i18n.h>
35 #include <grub/time.h>
36 #include <grub/font.h>
37 #include <grub/ventoy.h>
38 #include "ventoy_def.h"
40 GRUB_MOD_LICENSE ("GPLv3+");
42 static char g_iso_disk_name
[128];
43 static install_template
*g_install_template_head
= NULL
;
44 static persistence_config
*g_persistence_head
= NULL
;
45 static menu_alias
*g_menu_alias_head
= NULL
;
46 static menu_class
*g_menu_class_head
= NULL
;
47 static injection_config
*g_injection_head
= NULL
;
48 static auto_memdisk
*g_auto_memdisk_head
= NULL
;
49 static image_list
*g_image_list_head
= NULL
;
50 static conf_replace
*g_conf_replace_head
= NULL
;
52 static int ventoy_plugin_control_check(VTOY_JSON
*json
, const char *isodisk
)
55 VTOY_JSON
*pNode
= NULL
;
56 VTOY_JSON
*pChild
= NULL
;
60 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
62 grub_printf("Not array type %d\n", json
->enDataType
);
66 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
68 if (pNode
->enDataType
== JSON_TYPE_OBJECT
)
70 pChild
= pNode
->pstChild
;
71 if (pChild
->enDataType
== JSON_TYPE_STRING
)
73 if (grub_strcmp(pChild
->pcName
, "VTOY_DEFAULT_IMAGE") == 0)
75 grub_printf("%s: %s [%s]\n", pChild
->pcName
, pChild
->unData
.pcStrVal
,
76 ventoy_check_file_exist("%s%s", isodisk
, pChild
->unData
.pcStrVal
) ? "OK" : "NOT EXIST");
80 grub_printf("%s: %s\n", pChild
->pcName
, pChild
->unData
.pcStrVal
);
85 grub_printf("%s is NOT string type\n", pChild
->pcName
);
91 grub_printf("%s is not an object\n", pNode
->pcName
);
99 static int ventoy_plugin_control_entry(VTOY_JSON
*json
, const char *isodisk
)
101 VTOY_JSON
*pNode
= NULL
;
102 VTOY_JSON
*pChild
= NULL
;
106 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
108 debug("Not array %d\n", json
->enDataType
);
112 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
114 if (pNode
->enDataType
== JSON_TYPE_OBJECT
)
116 pChild
= pNode
->pstChild
;
117 if (pChild
->enDataType
== JSON_TYPE_STRING
&& pChild
->pcName
&& pChild
->unData
.pcStrVal
)
119 ventoy_set_env(pChild
->pcName
, pChild
->unData
.pcStrVal
);
127 static int ventoy_plugin_theme_check(VTOY_JSON
*json
, const char *isodisk
)
133 value
= vtoy_json_get_string_ex(json
->pstChild
, "file");
136 grub_printf("file: %s\n", value
);
139 exist
= ventoy_is_file_exist("%s%s", isodisk
, value
);
143 exist
= ventoy_is_file_exist("%s/ventoy/%s", isodisk
, value
);
148 grub_printf("Theme file %s does NOT exist\n", value
);
153 value
= vtoy_json_get_string_ex(json
->pstChild
, "gfxmode");
156 grub_printf("gfxmode: %s\n", value
);
159 value
= vtoy_json_get_string_ex(json
->pstChild
, "display_mode");
162 grub_printf("display_mode: %s\n", value
);
165 value
= vtoy_json_get_string_ex(json
->pstChild
, "serial_param");
168 grub_printf("serial_param %s\n", value
);
171 value
= vtoy_json_get_string_ex(json
->pstChild
, "ventoy_left");
174 grub_printf("ventoy_left: %s\n", value
);
177 value
= vtoy_json_get_string_ex(json
->pstChild
, "ventoy_top");
180 grub_printf("ventoy_top: %s\n", value
);
183 value
= vtoy_json_get_string_ex(json
->pstChild
, "ventoy_color");
186 grub_printf("ventoy_color: %s\n", value
);
189 node
= vtoy_json_find_item(json
->pstChild
, JSON_TYPE_ARRAY
, "fonts");
192 for (node
= node
->pstChild
; node
; node
= node
->pstNext
)
194 if (node
->enDataType
== JSON_TYPE_STRING
)
196 if (ventoy_check_file_exist("%s%s", isodisk
, node
->unData
.pcStrVal
))
198 grub_printf("%s [OK]\n", node
->unData
.pcStrVal
);
202 grub_printf("%s [NOT EXIST]\n", node
->unData
.pcStrVal
);
209 grub_printf("fonts NOT found\n");
215 static int ventoy_plugin_theme_entry(VTOY_JSON
*json
, const char *isodisk
)
221 value
= vtoy_json_get_string_ex(json
->pstChild
, "file");
226 grub_snprintf(filepath
, sizeof(filepath
), "%s%s", isodisk
, value
);
230 grub_snprintf(filepath
, sizeof(filepath
), "%s/ventoy/%s", isodisk
, value
);
233 if (ventoy_is_file_exist(filepath
) == 0)
235 debug("Theme file %s does not exist\n", filepath
);
239 debug("vtoy_theme %s\n", filepath
);
240 grub_env_set("vtoy_theme", filepath
);
243 value
= vtoy_json_get_string_ex(json
->pstChild
, "gfxmode");
246 debug("vtoy_gfxmode %s\n", value
);
247 grub_env_set("vtoy_gfxmode", value
);
250 value
= vtoy_json_get_string_ex(json
->pstChild
, "display_mode");
253 debug("display_mode %s\n", value
);
254 grub_env_set("vtoy_display_mode", value
);
257 value
= vtoy_json_get_string_ex(json
->pstChild
, "serial_param");
260 debug("serial_param %s\n", value
);
261 grub_env_set("vtoy_serial_param", value
);
264 value
= vtoy_json_get_string_ex(json
->pstChild
, "ventoy_left");
267 grub_env_set("VTLE_LFT", value
);
270 value
= vtoy_json_get_string_ex(json
->pstChild
, "ventoy_top");
273 grub_env_set("VTLE_TOP", value
);
276 value
= vtoy_json_get_string_ex(json
->pstChild
, "ventoy_color");
279 grub_env_set("VTLE_CLR", value
);
282 node
= vtoy_json_find_item(json
->pstChild
, JSON_TYPE_ARRAY
, "fonts");
285 for (node
= node
->pstChild
; node
; node
= node
->pstNext
)
287 if (node
->enDataType
== JSON_TYPE_STRING
&&
288 ventoy_check_file_exist("%s%s", isodisk
, node
->unData
.pcStrVal
))
290 grub_snprintf(filepath
, sizeof(filepath
), "%s%s", isodisk
, node
->unData
.pcStrVal
);
291 grub_font_load(filepath
);
299 static int ventoy_plugin_check_path(const char *path
, const char *file
)
303 grub_printf("%s is NOT begin with '/' \n", file
);
307 if (grub_strchr(file
, '\\'))
309 grub_printf("%s contains invalid '\\' \n", file
);
313 if (grub_strstr(file
, "//"))
315 grub_printf("%s contains invalid double slash\n", file
);
319 if (grub_strstr(file
, "../"))
321 grub_printf("%s contains invalid '../' \n", file
);
325 if (!ventoy_is_file_exist("%s%s", path
, file
))
327 grub_printf("%s%s does NOT exist\n", path
, file
);
334 static int ventoy_plugin_check_fullpath
345 VTOY_JSON
*node
= json
;
346 VTOY_JSON
*child
= NULL
;
350 if (0 == grub_strcmp(key
, node
->pcName
))
354 node
= node
->pstNext
;
362 if (JSON_TYPE_STRING
== node
->enDataType
)
365 ret
= ventoy_plugin_check_path(isodisk
, node
->unData
.pcStrVal
);
366 grub_printf("%s: %s [%s]\n", key
, node
->unData
.pcStrVal
, ret
? "FAIL" : "OK");
368 else if (JSON_TYPE_ARRAY
== node
->enDataType
)
370 for (child
= node
->pstChild
; child
; child
= child
->pstNext
)
372 if (JSON_TYPE_STRING
!= child
->enDataType
)
374 grub_printf("Non string json type\n");
378 rc
= ventoy_plugin_check_path(isodisk
, child
->unData
.pcStrVal
);
379 grub_printf("%s: %s [%s]\n", key
, child
->unData
.pcStrVal
, rc
? "FAIL" : "OK");
390 static int ventoy_plugin_parse_fullpath
395 file_fullpath
**fullpath
,
401 VTOY_JSON
*node
= json
;
402 VTOY_JSON
*child
= NULL
;
403 file_fullpath
*path
= NULL
;
407 if (0 == grub_strcmp(key
, node
->pcName
))
411 node
= node
->pstNext
;
419 if (JSON_TYPE_STRING
== node
->enDataType
)
421 debug("%s is string type data\n", node
->pcName
);
423 if ((node
->unData
.pcStrVal
[0] != '/') || (!ventoy_is_file_exist("%s%s", isodisk
, node
->unData
.pcStrVal
)))
425 debug("%s%s file not found\n", isodisk
, node
->unData
.pcStrVal
);
429 path
= (file_fullpath
*)grub_zalloc(sizeof(file_fullpath
));
432 grub_snprintf(path
->path
, sizeof(path
->path
), "%s", node
->unData
.pcStrVal
);
438 else if (JSON_TYPE_ARRAY
== node
->enDataType
)
440 for (child
= node
->pstChild
; child
; child
= child
->pstNext
)
442 if ((JSON_TYPE_STRING
!= child
->enDataType
) || (child
->unData
.pcStrVal
[0] != '/'))
444 debug("Invalid data type:%d\n", child
->enDataType
);
449 debug("%s is array type data, count=%d\n", node
->pcName
, count
);
451 path
= (file_fullpath
*)grub_zalloc(sizeof(file_fullpath
) * count
);
456 for (count
= 0, child
= node
->pstChild
; child
; child
= child
->pstNext
)
458 if (ventoy_is_file_exist("%s%s", isodisk
, child
->unData
.pcStrVal
))
460 grub_snprintf(path
->path
, sizeof(path
->path
), "%s", child
->unData
.pcStrVal
);
474 static int ventoy_plugin_auto_install_check(VTOY_JSON
*json
, const char *isodisk
)
478 const char *iso
= NULL
;
479 VTOY_JSON
*pNode
= NULL
;
481 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
483 grub_printf("Not array type %d\n", json
->enDataType
);
487 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
489 if (pNode
->enDataType
!= JSON_TYPE_OBJECT
)
491 grub_printf("NOT object type\n");
494 iso
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
497 if (0 == ventoy_plugin_check_path(isodisk
, iso
))
499 grub_printf("image: %s [OK]\n", iso
);
500 ventoy_plugin_check_fullpath(pNode
->pstChild
, isodisk
, "template", &pathnum
);
502 if (JSON_SUCCESS
== vtoy_json_get_int(pNode
->pstChild
, "autosel", &autosel
))
504 if (autosel
>= 0 && autosel
<= pathnum
)
506 grub_printf("autosel: %d [OK]\n", autosel
);
510 grub_printf("autosel: %d [FAIL]\n", autosel
);
516 grub_printf("image: %s [FAIL]\n", iso
);
521 grub_printf("image not found\n");
528 static int ventoy_plugin_auto_install_entry(VTOY_JSON
*json
, const char *isodisk
)
532 const char *iso
= NULL
;
533 VTOY_JSON
*pNode
= NULL
;
534 install_template
*node
= NULL
;
535 install_template
*next
= NULL
;
536 file_fullpath
*templatepath
= NULL
;
538 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
540 debug("Not array %d\n", json
->enDataType
);
544 if (g_install_template_head
)
546 for (node
= g_install_template_head
; node
; node
= next
)
549 grub_check_free(node
->templatepath
);
553 g_install_template_head
= NULL
;
556 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
558 iso
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
559 if (iso
&& iso
[0] == '/')
561 if (0 == ventoy_plugin_parse_fullpath(pNode
->pstChild
, isodisk
, "template", &templatepath
, &pathnum
))
563 node
= grub_zalloc(sizeof(install_template
));
566 node
->pathlen
= grub_snprintf(node
->isopath
, sizeof(node
->isopath
), "%s", iso
);
567 node
->templatepath
= templatepath
;
568 node
->templatenum
= pathnum
;
571 if (JSON_SUCCESS
== vtoy_json_get_int(pNode
->pstChild
, "autosel", &autosel
))
573 if (autosel
>= 0 && autosel
<= pathnum
)
575 node
->autosel
= autosel
;
579 if (g_install_template_head
)
581 node
->next
= g_install_template_head
;
584 g_install_template_head
= node
;
593 static int ventoy_plugin_persistence_check(VTOY_JSON
*json
, const char *isodisk
)
597 const char *iso
= NULL
;
598 VTOY_JSON
*pNode
= NULL
;
600 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
602 grub_printf("Not array type %d\n", json
->enDataType
);
606 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
608 if (pNode
->enDataType
!= JSON_TYPE_OBJECT
)
610 grub_printf("NOT object type\n");
613 iso
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
616 if (0 == ventoy_plugin_check_path(isodisk
, iso
))
618 grub_printf("image: %s [OK]\n", iso
);
619 ventoy_plugin_check_fullpath(pNode
->pstChild
, isodisk
, "backend", &pathnum
);
621 if (JSON_SUCCESS
== vtoy_json_get_int(pNode
->pstChild
, "autosel", &autosel
))
623 if (autosel
>= 0 && autosel
<= pathnum
)
625 grub_printf("autosel: %d [OK]\n", autosel
);
629 grub_printf("autosel: %d [FAIL]\n", autosel
);
635 grub_printf("image: %s [FAIL]\n", iso
);
640 grub_printf("image not found\n");
647 static int ventoy_plugin_persistence_entry(VTOY_JSON
*json
, const char *isodisk
)
651 const char *iso
= NULL
;
652 VTOY_JSON
*pNode
= NULL
;
653 persistence_config
*node
= NULL
;
654 persistence_config
*next
= NULL
;
655 file_fullpath
*backendpath
= NULL
;
659 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
661 debug("Not array %d\n", json
->enDataType
);
665 if (g_persistence_head
)
667 for (node
= g_persistence_head
; node
; node
= next
)
670 grub_check_free(node
->backendpath
);
674 g_persistence_head
= NULL
;
677 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
679 iso
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
680 if (iso
&& iso
[0] == '/')
682 if (0 == ventoy_plugin_parse_fullpath(pNode
->pstChild
, isodisk
, "backend", &backendpath
, &pathnum
))
684 node
= grub_zalloc(sizeof(persistence_config
));
687 node
->pathlen
= grub_snprintf(node
->isopath
, sizeof(node
->isopath
), "%s", iso
);
688 node
->backendpath
= backendpath
;
689 node
->backendnum
= pathnum
;
692 if (JSON_SUCCESS
== vtoy_json_get_int(pNode
->pstChild
, "autosel", &autosel
))
694 if (autosel
>= 0 && autosel
<= pathnum
)
696 node
->autosel
= autosel
;
700 if (g_persistence_head
)
702 node
->next
= g_persistence_head
;
705 g_persistence_head
= node
;
714 static int ventoy_plugin_menualias_check(VTOY_JSON
*json
, const char *isodisk
)
717 const char *path
= NULL
;
718 const char *alias
= NULL
;
719 VTOY_JSON
*pNode
= NULL
;
723 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
725 grub_printf("Not array %d\n", json
->enDataType
);
729 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
731 type
= vtoy_alias_image_file
;
732 path
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
735 path
= vtoy_json_get_string_ex(pNode
->pstChild
, "dir");
736 type
= vtoy_alias_directory
;
739 alias
= vtoy_json_get_string_ex(pNode
->pstChild
, "alias");
740 if (path
&& path
[0] == '/' && alias
)
742 if (vtoy_alias_image_file
== type
)
744 if (ventoy_is_file_exist("%s%s", isodisk
, path
))
746 grub_printf("image: <%s> [ OK ]\n", path
);
750 grub_printf("image: <%s> [ NOT EXIST ]\n", path
);
755 if (ventoy_is_dir_exist("%s%s", isodisk
, path
))
757 grub_printf("dir: <%s> [ OK ]\n", path
);
761 grub_printf("dir: <%s> [ NOT EXIST ]\n", path
);
765 grub_printf("alias: <%s>\n\n", alias
);
772 static int ventoy_plugin_menualias_entry(VTOY_JSON
*json
, const char *isodisk
)
775 const char *path
= NULL
;
776 const char *alias
= NULL
;
777 VTOY_JSON
*pNode
= NULL
;
778 menu_alias
*node
= NULL
;
779 menu_alias
*next
= NULL
;
783 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
785 debug("Not array %d\n", json
->enDataType
);
789 if (g_menu_alias_head
)
791 for (node
= g_menu_alias_head
; node
; node
= next
)
797 g_menu_alias_head
= NULL
;
800 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
802 type
= vtoy_alias_image_file
;
803 path
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
806 path
= vtoy_json_get_string_ex(pNode
->pstChild
, "dir");
807 type
= vtoy_alias_directory
;
810 alias
= vtoy_json_get_string_ex(pNode
->pstChild
, "alias");
811 if (path
&& path
[0] == '/' && alias
)
813 node
= grub_zalloc(sizeof(menu_alias
));
817 node
->pathlen
= grub_snprintf(node
->isopath
, sizeof(node
->isopath
), "%s", path
);
818 grub_snprintf(node
->alias
, sizeof(node
->alias
), "%s", alias
);
820 if (g_menu_alias_head
)
822 node
->next
= g_menu_alias_head
;
825 g_menu_alias_head
= node
;
834 static int ventoy_plugin_injection_check(VTOY_JSON
*json
, const char *isodisk
)
836 const char *path
= NULL
;
837 const char *archive
= NULL
;
838 VTOY_JSON
*pNode
= NULL
;
842 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
844 grub_printf("Not array %d\n", json
->enDataType
);
848 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
850 path
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
853 grub_printf("image not found\n");
857 archive
= vtoy_json_get_string_ex(pNode
->pstChild
, "archive");
860 grub_printf("archive not found\n");
864 grub_printf("image: <%s> [%s]\n", path
, ventoy_check_file_exist("%s%s", isodisk
, path
) ? "OK" : "NOT EXIST");
865 grub_printf("archive: <%s> [%s]\n\n", archive
, ventoy_check_file_exist("%s%s", isodisk
, archive
) ? "OK" : "NOT EXIST");
871 static int ventoy_plugin_injection_entry(VTOY_JSON
*json
, const char *isodisk
)
873 const char *path
= NULL
;
874 const char *archive
= NULL
;
875 VTOY_JSON
*pNode
= NULL
;
876 injection_config
*node
= NULL
;
877 injection_config
*next
= NULL
;
881 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
883 debug("Not array %d\n", json
->enDataType
);
887 if (g_injection_head
)
889 for (node
= g_injection_head
; node
; node
= next
)
895 g_injection_head
= NULL
;
898 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
900 path
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
901 archive
= vtoy_json_get_string_ex(pNode
->pstChild
, "archive");
902 if (path
&& path
[0] == '/' && archive
&& archive
[0] == '/')
904 node
= grub_zalloc(sizeof(injection_config
));
907 node
->pathlen
= grub_snprintf(node
->isopath
, sizeof(node
->isopath
), "%s", path
);
908 grub_snprintf(node
->archive
, sizeof(node
->archive
), "%s", archive
);
910 if (g_injection_head
)
912 node
->next
= g_injection_head
;
915 g_injection_head
= node
;
923 static int ventoy_plugin_menuclass_entry(VTOY_JSON
*json
, const char *isodisk
)
926 const char *key
= NULL
;
927 const char *class = NULL
;
928 VTOY_JSON
*pNode
= NULL
;
929 menu_class
*tail
= NULL
;
930 menu_class
*node
= NULL
;
931 menu_class
*next
= NULL
;
935 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
937 debug("Not array %d\n", json
->enDataType
);
941 if (g_menu_class_head
)
943 for (node
= g_menu_class_head
; node
; node
= next
)
949 g_menu_class_head
= NULL
;
952 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
954 type
= vtoy_class_image_file
;
955 key
= vtoy_json_get_string_ex(pNode
->pstChild
, "key");
958 key
= vtoy_json_get_string_ex(pNode
->pstChild
, "dir");
959 type
= vtoy_class_directory
;
962 class = vtoy_json_get_string_ex(pNode
->pstChild
, "class");
965 node
= grub_zalloc(sizeof(menu_class
));
969 node
->patlen
= grub_snprintf(node
->pattern
, sizeof(node
->pattern
), "%s", key
);
970 grub_snprintf(node
->class, sizeof(node
->class), "%s", class);
972 if (g_menu_class_head
)
978 g_menu_class_head
= node
;
988 static int ventoy_plugin_menuclass_check(VTOY_JSON
*json
, const char *isodisk
)
991 const char *key
= NULL
;
992 const char *class = NULL
;
993 VTOY_JSON
*pNode
= NULL
;
997 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
999 grub_printf("Not array %d\n", json
->enDataType
);
1003 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
1005 type
= vtoy_class_image_file
;
1006 key
= vtoy_json_get_string_ex(pNode
->pstChild
, "key");
1009 key
= vtoy_json_get_string_ex(pNode
->pstChild
, "dir");
1010 type
= vtoy_class_directory
;
1013 class = vtoy_json_get_string_ex(pNode
->pstChild
, "class");
1016 grub_printf("%s: <%s>\n", (type
== vtoy_class_directory
) ? "dir" : "key", key
);
1017 grub_printf("class: <%s>\n\n", class);
1024 static int ventoy_plugin_conf_replace_entry(VTOY_JSON
*json
, const char *isodisk
)
1026 const char *isof
= NULL
;
1027 const char *orgf
= NULL
;
1028 const char *newf
= NULL
;
1029 VTOY_JSON
*pNode
= NULL
;
1030 conf_replace
*tail
= NULL
;
1031 conf_replace
*node
= NULL
;
1032 conf_replace
*next
= NULL
;
1036 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
1038 debug("Not array %d\n", json
->enDataType
);
1042 if (g_conf_replace_head
)
1044 for (node
= g_conf_replace_head
; node
; node
= next
)
1050 g_conf_replace_head
= NULL
;
1053 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
1055 isof
= vtoy_json_get_string_ex(pNode
->pstChild
, "iso");
1056 orgf
= vtoy_json_get_string_ex(pNode
->pstChild
, "org");
1057 newf
= vtoy_json_get_string_ex(pNode
->pstChild
, "new");
1058 if (isof
&& orgf
&& newf
&& isof
[0] == '/' && orgf
[0] == '/' && newf
[0] == '/')
1060 node
= grub_zalloc(sizeof(conf_replace
));
1063 node
->pathlen
= grub_snprintf(node
->isopath
, sizeof(node
->isopath
), "%s", isof
);
1064 grub_snprintf(node
->orgconf
, sizeof(node
->orgconf
), "%s", orgf
);
1065 grub_snprintf(node
->newconf
, sizeof(node
->newconf
), "%s", newf
);
1067 if (g_conf_replace_head
)
1073 g_conf_replace_head
= node
;
1083 static int ventoy_plugin_conf_replace_check(VTOY_JSON
*json
, const char *isodisk
)
1085 const char *isof
= NULL
;
1086 const char *orgf
= NULL
;
1087 const char *newf
= NULL
;
1088 VTOY_JSON
*pNode
= NULL
;
1089 grub_file_t file
= NULL
;
1094 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
1096 grub_printf("Not array %d\n", json
->enDataType
);
1100 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
1102 isof
= vtoy_json_get_string_ex(pNode
->pstChild
, "iso");
1103 orgf
= vtoy_json_get_string_ex(pNode
->pstChild
, "org");
1104 newf
= vtoy_json_get_string_ex(pNode
->pstChild
, "new");
1105 if (isof
&& orgf
&& newf
&& isof
[0] == '/' && orgf
[0] == '/' && newf
[0] == '/')
1107 if (ventoy_check_file_exist("%s%s", isodisk
, isof
))
1109 grub_printf("iso:<%s> [OK]\n", isof
);
1111 grub_snprintf(cmd
, sizeof(cmd
), "loopback vtisocheck %s%s", isodisk
, isof
);
1112 grub_script_execute_sourcecode(cmd
);
1114 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(vtisocheck)/%s", orgf
);
1117 if (grub_strcmp(file
->fs
->name
, "iso9660") == 0)
1119 grub_printf("org:<%s> [OK]\n", orgf
);
1123 grub_printf("org:<%s> [Exist But NOT ISO9660]\n", orgf
);
1125 grub_file_close(file
);
1129 grub_printf("org:<%s> [NOT Exist]\n", orgf
);
1132 grub_script_execute_sourcecode("loopback -d vtisocheck");
1136 grub_printf("iso:<%s> [NOT Exist]\n", isof
);
1137 grub_printf("org:<%s>\n", orgf
);
1140 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", isodisk
, newf
);
1143 if (file
->size
> vtoy_max_replace_file_size
)
1145 grub_printf("new:<%s> [Too Big %lu] \n", newf
, (ulong
)file
->size
);
1149 grub_printf("new:<%s> [OK]\n", newf
);
1151 grub_file_close(file
);
1155 grub_printf("new:<%s> [NOT Exist]\n", newf
);
1164 static int ventoy_plugin_auto_memdisk_entry(VTOY_JSON
*json
, const char *isodisk
)
1166 VTOY_JSON
*pNode
= NULL
;
1167 auto_memdisk
*node
= NULL
;
1168 auto_memdisk
*next
= NULL
;
1172 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
1174 debug("Not array %d\n", json
->enDataType
);
1178 if (g_auto_memdisk_head
)
1180 for (node
= g_auto_memdisk_head
; node
; node
= next
)
1186 g_auto_memdisk_head
= NULL
;
1189 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
1191 if (pNode
->enDataType
== JSON_TYPE_STRING
)
1193 node
= grub_zalloc(sizeof(auto_memdisk
));
1196 node
->pathlen
= grub_snprintf(node
->isopath
, sizeof(node
->isopath
), "%s", pNode
->unData
.pcStrVal
);
1198 if (g_auto_memdisk_head
)
1200 node
->next
= g_auto_memdisk_head
;
1203 g_auto_memdisk_head
= node
;
1211 static int ventoy_plugin_auto_memdisk_check(VTOY_JSON
*json
, const char *isodisk
)
1213 VTOY_JSON
*pNode
= NULL
;
1215 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
1217 grub_printf("Not array %d\n", json
->enDataType
);
1221 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
1223 if (pNode
->enDataType
== JSON_TYPE_STRING
)
1225 grub_printf("<%s> ", pNode
->unData
.pcStrVal
);
1227 if (ventoy_check_file_exist("%s%s", isodisk
, pNode
->unData
.pcStrVal
))
1229 grub_printf(" [OK]\n");
1233 grub_printf(" [NOT EXIST]\n");
1241 static int ventoy_plugin_image_list_entry(VTOY_JSON
*json
, const char *isodisk
)
1243 VTOY_JSON
*pNode
= NULL
;
1244 image_list
*node
= NULL
;
1245 image_list
*next
= NULL
;
1246 image_list
*tail
= NULL
;
1250 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
1252 debug("Not array %d\n", json
->enDataType
);
1256 if (g_image_list_head
)
1258 for (node
= g_image_list_head
; node
; node
= next
)
1264 g_image_list_head
= NULL
;
1267 g_plugin_image_list
= 1;
1269 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
1271 if (pNode
->enDataType
== JSON_TYPE_STRING
)
1273 node
= grub_zalloc(sizeof(image_list
));
1276 node
->pathlen
= grub_snprintf(node
->isopath
, sizeof(node
->isopath
), "%s", pNode
->unData
.pcStrVal
);
1278 if (g_image_list_head
)
1284 g_image_list_head
= node
;
1294 static int ventoy_plugin_image_list_check(VTOY_JSON
*json
, const char *isodisk
)
1296 VTOY_JSON
*pNode
= NULL
;
1298 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
1300 grub_printf("Not array %d\n", json
->enDataType
);
1304 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
1306 if (pNode
->enDataType
== JSON_TYPE_STRING
)
1308 grub_printf("<%s> ", pNode
->unData
.pcStrVal
);
1310 if (ventoy_check_file_exist("%s%s", isodisk
, pNode
->unData
.pcStrVal
))
1312 grub_printf(" [OK]\n");
1316 grub_printf(" [NOT EXIST]\n");
1324 static plugin_entry g_plugin_entries
[] =
1326 { "control", ventoy_plugin_control_entry
, ventoy_plugin_control_check
},
1327 { "theme", ventoy_plugin_theme_entry
, ventoy_plugin_theme_check
},
1328 { "auto_install", ventoy_plugin_auto_install_entry
, ventoy_plugin_auto_install_check
},
1329 { "persistence", ventoy_plugin_persistence_entry
, ventoy_plugin_persistence_check
},
1330 { "menu_alias", ventoy_plugin_menualias_entry
, ventoy_plugin_menualias_check
},
1331 { "menu_class", ventoy_plugin_menuclass_entry
, ventoy_plugin_menuclass_check
},
1332 { "injection", ventoy_plugin_injection_entry
, ventoy_plugin_injection_check
},
1333 { "auto_memdisk", ventoy_plugin_auto_memdisk_entry
, ventoy_plugin_auto_memdisk_check
},
1334 { "image_list", ventoy_plugin_image_list_entry
, ventoy_plugin_image_list_check
},
1335 { "conf_replace", ventoy_plugin_conf_replace_entry
, ventoy_plugin_conf_replace_check
},
1338 static int ventoy_parse_plugin_config(VTOY_JSON
*json
, const char *isodisk
)
1342 VTOY_JSON
*cur
= json
;
1344 grub_snprintf(g_iso_disk_name
, sizeof(g_iso_disk_name
), "%s", isodisk
);
1348 for (i
= 0; i
< (int)ARRAY_SIZE(g_plugin_entries
); i
++)
1350 grub_snprintf(key
, sizeof(key
), "%s_%s", g_plugin_entries
[i
].key
, VTOY_DUAL_MODE_SUFFIX
);
1351 if (grub_strcmp(g_plugin_entries
[i
].key
, cur
->pcName
) == 0 || grub_strcmp(key
, cur
->pcName
) == 0)
1353 debug("Plugin entry for %s\n", g_plugin_entries
[i
].key
);
1354 g_plugin_entries
[i
].entryfunc(cur
, isodisk
);
1365 grub_err_t
ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1370 VTOY_JSON
*json
= NULL
;
1375 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/ventoy/ventoy.json", args
[0]);
1378 return GRUB_ERR_NONE
;
1381 debug("json configuration file size %d\n", (int)file
->size
);
1383 buf
= grub_malloc(file
->size
+ 1);
1386 grub_file_close(file
);
1390 buf
[file
->size
] = 0;
1391 grub_file_read(file
, buf
, file
->size
);
1392 grub_file_close(file
);
1394 json
= vtoy_json_create();
1402 ret
= vtoy_json_parse(json
, buf
);
1405 grub_env_set("VTOY_PLUGIN_SYNTAX_ERROR", "1");
1406 grub_env_export("VTOY_PLUGIN_SYNTAX_ERROR");
1408 debug("Failed to parse json string %d\n", ret
);
1413 ventoy_parse_plugin_config(json
->pstChild
, args
[0]);
1415 vtoy_json_destroy(json
);
1419 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1422 void ventoy_plugin_dump_injection(void)
1424 injection_config
*node
= NULL
;
1426 for (node
= g_injection_head
; node
; node
= node
->next
)
1428 grub_printf("\nIMAGE:<%s>\n", node
->isopath
);
1429 grub_printf("ARCHIVE:<%s>\n", node
->archive
);
1436 void ventoy_plugin_dump_auto_install(void)
1439 install_template
*node
= NULL
;
1441 for (node
= g_install_template_head
; node
; node
= node
->next
)
1443 grub_printf("\nIMAGE:<%s> <%d>\n", node
->isopath
, node
->templatenum
);
1444 for (i
= 0; i
< node
->templatenum
; i
++)
1446 grub_printf("SCRIPT %d:<%s>\n", i
, node
->templatepath
[i
].path
);
1453 void ventoy_plugin_dump_persistence(void)
1457 persistence_config
*node
= NULL
;
1458 ventoy_img_chunk_list chunk_list
;
1460 for (node
= g_persistence_head
; node
; node
= node
->next
)
1462 grub_printf("\nIMAGE:<%s> <%d>\n", node
->isopath
, node
->backendnum
);
1464 for (i
= 0; i
< node
->backendnum
; i
++)
1466 grub_printf("PERSIST %d:<%s>", i
, node
->backendpath
[i
].path
);
1467 rc
= ventoy_plugin_get_persistent_chunklist(node
->isopath
, i
, &chunk_list
);
1470 grub_printf(" [ SUCCESS ]\n");
1471 grub_free(chunk_list
.chunk
);
1475 grub_printf(" [ FAILED ]\n");
1483 install_template
* ventoy_plugin_find_install_template(const char *isopath
)
1486 install_template
*node
= NULL
;
1488 if (!g_install_template_head
)
1493 len
= (int)grub_strlen(isopath
);
1494 for (node
= g_install_template_head
; node
; node
= node
->next
)
1496 if (node
->pathlen
== len
&& grub_strcmp(node
->isopath
, isopath
) == 0)
1505 char * ventoy_plugin_get_cur_install_template(const char *isopath
)
1507 install_template
*node
= NULL
;
1509 node
= ventoy_plugin_find_install_template(isopath
);
1510 if ((!node
) || (!node
->templatepath
))
1515 if (node
->cursel
< 0 || node
->cursel
>= node
->templatenum
)
1520 return node
->templatepath
[node
->cursel
].path
;
1523 persistence_config
* ventoy_plugin_find_persistent(const char *isopath
)
1526 persistence_config
*node
= NULL
;
1528 if (!g_persistence_head
)
1533 len
= (int)grub_strlen(isopath
);
1534 for (node
= g_persistence_head
; node
; node
= node
->next
)
1536 if ((len
== node
->pathlen
) && (grub_strcmp(node
->isopath
, isopath
) == 0))
1545 int ventoy_plugin_get_persistent_chunklist(const char *isopath
, int index
, ventoy_img_chunk_list
*chunk_list
)
1548 grub_uint64_t start
= 0;
1549 grub_file_t file
= NULL
;
1550 persistence_config
*node
= NULL
;
1552 node
= ventoy_plugin_find_persistent(isopath
);
1553 if ((!node
) || (!node
->backendpath
))
1560 index
= node
->cursel
;
1563 if (index
< 0 || index
>= node
->backendnum
)
1568 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", g_iso_disk_name
, node
->backendpath
[index
].path
);
1571 debug("Failed to open file %s%s\n", g_iso_disk_name
, node
->backendpath
[index
].path
);
1575 grub_memset(chunk_list
, 0, sizeof(ventoy_img_chunk_list
));
1576 chunk_list
->chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1577 if (NULL
== chunk_list
->chunk
)
1582 chunk_list
->max_chunk
= DEFAULT_CHUNK_NUM
;
1583 chunk_list
->cur_chunk
= 0;
1585 start
= file
->device
->disk
->partition
->start
;
1586 ventoy_get_block_list(file
, chunk_list
, start
);
1588 if (0 != ventoy_check_block_list(file
, chunk_list
, start
))
1590 grub_free(chunk_list
->chunk
);
1591 chunk_list
->chunk
= NULL
;
1599 grub_file_close(file
);
1604 const char * ventoy_plugin_get_injection(const char *isopath
)
1607 injection_config
*node
= NULL
;
1609 if (!g_injection_head
)
1614 len
= (int)grub_strlen(isopath
);
1615 for (node
= g_injection_head
; node
; node
= node
->next
)
1617 if (node
->pathlen
== len
&& grub_strcmp(node
->isopath
, isopath
) == 0)
1619 return node
->archive
;
1626 const char * ventoy_plugin_get_menu_alias(int type
, const char *isopath
)
1629 menu_alias
*node
= NULL
;
1631 if (!g_menu_alias_head
)
1636 len
= (int)grub_strlen(isopath
);
1637 for (node
= g_menu_alias_head
; node
; node
= node
->next
)
1639 if (node
->type
== type
&& node
->pathlen
&&
1640 node
->pathlen
== len
&& grub_strcmp(node
->isopath
, isopath
) == 0)
1649 const char * ventoy_plugin_get_menu_class(int type
, const char *name
)
1652 menu_class
*node
= NULL
;
1654 if (!g_menu_class_head
)
1659 len
= (int)grub_strlen(name
);
1661 if (vtoy_class_image_file
== type
)
1663 for (node
= g_menu_class_head
; node
; node
= node
->next
)
1665 if (node
->type
== type
&& node
->patlen
<= len
&& grub_strstr(name
, node
->pattern
))
1673 for (node
= g_menu_class_head
; node
; node
= node
->next
)
1675 if (node
->type
== type
&& node
->patlen
== len
&& grub_strncmp(name
, node
->pattern
, len
) == 0)
1685 int ventoy_plugin_check_memdisk(const char *isopath
)
1688 auto_memdisk
*node
= NULL
;
1690 if (!g_auto_memdisk_head
)
1695 len
= (int)grub_strlen(isopath
);
1696 for (node
= g_auto_memdisk_head
; node
; node
= node
->next
)
1698 if (node
->pathlen
== len
&& grub_strncmp(isopath
, node
->isopath
, len
) == 0)
1707 int ventoy_plugin_get_image_list_index(int type
, const char *name
)
1711 image_list
*node
= NULL
;
1713 if (!g_image_list_head
)
1718 len
= (int)grub_strlen(name
);
1720 for (node
= g_image_list_head
; node
; node
= node
->next
, index
++)
1722 if (vtoy_class_directory
== type
)
1724 if (len
< node
->pathlen
&& grub_strncmp(name
, node
->isopath
, len
) == 0)
1731 if (len
== node
->pathlen
&& grub_strncmp(name
, node
->isopath
, len
) == 0)
1741 conf_replace
* ventoy_plugin_find_conf_replace(const char *iso
)
1746 if (!g_conf_replace_head
)
1751 len
= (int)grub_strlen(iso
);
1753 for (node
= g_conf_replace_head
; node
; node
= node
->next
)
1755 if (node
->pathlen
== len
&& grub_strncmp(iso
, node
->isopath
, len
) == 0)
1764 grub_err_t
ventoy_cmd_plugin_check_json(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1771 VTOY_JSON
*node
= NULL
;
1772 VTOY_JSON
*json
= NULL
;
1781 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/ventoy/ventoy.json", args
[0]);
1784 grub_printf("Plugin json file /ventoy/ventoy.json does NOT exist.\n");
1788 buf
= grub_malloc(file
->size
+ 1);
1791 grub_printf("Failed to malloc memory %lu.\n", (ulong
)(file
->size
+ 1));
1795 buf
[file
->size
] = 0;
1796 grub_file_read(file
, buf
, file
->size
);
1798 json
= vtoy_json_create();
1801 grub_printf("Failed to create json\n");
1805 ret
= vtoy_json_parse(json
, buf
);
1808 grub_printf("Syntax error detected in ventoy.json, please check it.\n");
1812 grub_snprintf(key
, sizeof(key
), "%s_%s", args
[1], VTOY_DUAL_MODE_SUFFIX
);
1813 for (node
= json
->pstChild
; node
; node
= node
->pstNext
)
1815 if (grub_strcmp(node
->pcName
, args
[1]) == 0 || grub_strcmp(node
->pcName
, key
) == 0)
1823 grub_printf("%s is NOT found in ventoy.json\n", args
[1]);
1827 for (i
= 0; i
< (int)ARRAY_SIZE(g_plugin_entries
); i
++)
1829 if (grub_strcmp(g_plugin_entries
[i
].key
, args
[1]) == 0)
1831 if (g_plugin_entries
[i
].checkfunc
)
1833 ret
= g_plugin_entries
[i
].checkfunc(node
, args
[2]);
1840 check_free(file
, grub_file_close
);
1841 check_free(json
, vtoy_json_destroy
);
1842 grub_check_free(buf
);