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 dud
*g_dud_head
= NULL
;
45 static persistence_config
*g_persistence_head
= NULL
;
46 static menu_alias
*g_menu_alias_head
= NULL
;
47 static menu_class
*g_menu_class_head
= NULL
;
48 static injection_config
*g_injection_head
= NULL
;
49 static auto_memdisk
*g_auto_memdisk_head
= NULL
;
50 static image_list
*g_image_list_head
= NULL
;
51 static conf_replace
*g_conf_replace_head
= NULL
;
53 static int ventoy_plugin_control_check(VTOY_JSON
*json
, const char *isodisk
)
56 VTOY_JSON
*pNode
= NULL
;
57 VTOY_JSON
*pChild
= NULL
;
61 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
63 grub_printf("Not array type %d\n", json
->enDataType
);
67 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
69 if (pNode
->enDataType
== JSON_TYPE_OBJECT
)
71 pChild
= pNode
->pstChild
;
72 if (pChild
->enDataType
== JSON_TYPE_STRING
)
74 if (grub_strcmp(pChild
->pcName
, "VTOY_DEFAULT_IMAGE") == 0)
76 grub_printf("%s: %s [%s]\n", pChild
->pcName
, pChild
->unData
.pcStrVal
,
77 ventoy_check_file_exist("%s%s", isodisk
, pChild
->unData
.pcStrVal
) ? "OK" : "NOT EXIST");
81 grub_printf("%s: %s\n", pChild
->pcName
, pChild
->unData
.pcStrVal
);
86 grub_printf("%s is NOT string type\n", pChild
->pcName
);
92 grub_printf("%s is not an object\n", pNode
->pcName
);
100 static int ventoy_plugin_control_entry(VTOY_JSON
*json
, const char *isodisk
)
102 VTOY_JSON
*pNode
= NULL
;
103 VTOY_JSON
*pChild
= NULL
;
107 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
109 debug("Not array %d\n", json
->enDataType
);
113 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
115 if (pNode
->enDataType
== JSON_TYPE_OBJECT
)
117 pChild
= pNode
->pstChild
;
118 if (pChild
->enDataType
== JSON_TYPE_STRING
&& pChild
->pcName
&& pChild
->unData
.pcStrVal
)
120 ventoy_set_env(pChild
->pcName
, pChild
->unData
.pcStrVal
);
128 static int ventoy_plugin_theme_check(VTOY_JSON
*json
, const char *isodisk
)
134 value
= vtoy_json_get_string_ex(json
->pstChild
, "file");
137 grub_printf("file: %s\n", value
);
140 exist
= ventoy_is_file_exist("%s%s", isodisk
, value
);
144 exist
= ventoy_is_file_exist("%s/ventoy/%s", isodisk
, value
);
149 grub_printf("Theme file %s does NOT exist\n", value
);
154 value
= vtoy_json_get_string_ex(json
->pstChild
, "gfxmode");
157 grub_printf("gfxmode: %s\n", value
);
160 value
= vtoy_json_get_string_ex(json
->pstChild
, "display_mode");
163 grub_printf("display_mode: %s\n", value
);
166 value
= vtoy_json_get_string_ex(json
->pstChild
, "serial_param");
169 grub_printf("serial_param %s\n", value
);
172 value
= vtoy_json_get_string_ex(json
->pstChild
, "ventoy_left");
175 grub_printf("ventoy_left: %s\n", value
);
178 value
= vtoy_json_get_string_ex(json
->pstChild
, "ventoy_top");
181 grub_printf("ventoy_top: %s\n", value
);
184 value
= vtoy_json_get_string_ex(json
->pstChild
, "ventoy_color");
187 grub_printf("ventoy_color: %s\n", value
);
190 node
= vtoy_json_find_item(json
->pstChild
, JSON_TYPE_ARRAY
, "fonts");
193 for (node
= node
->pstChild
; node
; node
= node
->pstNext
)
195 if (node
->enDataType
== JSON_TYPE_STRING
)
197 if (ventoy_check_file_exist("%s%s", isodisk
, node
->unData
.pcStrVal
))
199 grub_printf("%s [OK]\n", node
->unData
.pcStrVal
);
203 grub_printf("%s [NOT EXIST]\n", node
->unData
.pcStrVal
);
210 grub_printf("fonts NOT found\n");
216 static int ventoy_plugin_theme_entry(VTOY_JSON
*json
, const char *isodisk
)
222 value
= vtoy_json_get_string_ex(json
->pstChild
, "file");
227 grub_snprintf(filepath
, sizeof(filepath
), "%s%s", isodisk
, value
);
231 grub_snprintf(filepath
, sizeof(filepath
), "%s/ventoy/%s", isodisk
, value
);
234 if (ventoy_is_file_exist(filepath
) == 0)
236 debug("Theme file %s does not exist\n", filepath
);
240 debug("vtoy_theme %s\n", filepath
);
241 grub_env_set("vtoy_theme", filepath
);
244 value
= vtoy_json_get_string_ex(json
->pstChild
, "gfxmode");
247 debug("vtoy_gfxmode %s\n", value
);
248 grub_env_set("vtoy_gfxmode", value
);
251 value
= vtoy_json_get_string_ex(json
->pstChild
, "display_mode");
254 debug("display_mode %s\n", value
);
255 grub_env_set("vtoy_display_mode", value
);
258 value
= vtoy_json_get_string_ex(json
->pstChild
, "serial_param");
261 debug("serial_param %s\n", value
);
262 grub_env_set("vtoy_serial_param", value
);
265 value
= vtoy_json_get_string_ex(json
->pstChild
, "ventoy_left");
268 grub_env_set("VTLE_LFT", value
);
271 value
= vtoy_json_get_string_ex(json
->pstChild
, "ventoy_top");
274 grub_env_set("VTLE_TOP", value
);
277 value
= vtoy_json_get_string_ex(json
->pstChild
, "ventoy_color");
280 grub_env_set("VTLE_CLR", value
);
283 node
= vtoy_json_find_item(json
->pstChild
, JSON_TYPE_ARRAY
, "fonts");
286 for (node
= node
->pstChild
; node
; node
= node
->pstNext
)
288 if (node
->enDataType
== JSON_TYPE_STRING
&&
289 ventoy_check_file_exist("%s%s", isodisk
, node
->unData
.pcStrVal
))
291 grub_snprintf(filepath
, sizeof(filepath
), "%s%s", isodisk
, node
->unData
.pcStrVal
);
292 grub_font_load(filepath
);
300 static int ventoy_plugin_check_path(const char *path
, const char *file
)
304 grub_printf("%s is NOT begin with '/' \n", file
);
308 if (grub_strchr(file
, '\\'))
310 grub_printf("%s contains invalid '\\' \n", file
);
314 if (grub_strstr(file
, "//"))
316 grub_printf("%s contains invalid double slash\n", file
);
320 if (grub_strstr(file
, "../"))
322 grub_printf("%s contains invalid '../' \n", file
);
326 if (!ventoy_is_file_exist("%s%s", path
, file
))
328 grub_printf("%s%s does NOT exist\n", path
, file
);
335 static int ventoy_plugin_check_fullpath
346 VTOY_JSON
*node
= json
;
347 VTOY_JSON
*child
= NULL
;
351 if (0 == grub_strcmp(key
, node
->pcName
))
355 node
= node
->pstNext
;
363 if (JSON_TYPE_STRING
== node
->enDataType
)
366 ret
= ventoy_plugin_check_path(isodisk
, node
->unData
.pcStrVal
);
367 grub_printf("%s: %s [%s]\n", key
, node
->unData
.pcStrVal
, ret
? "FAIL" : "OK");
369 else if (JSON_TYPE_ARRAY
== node
->enDataType
)
371 for (child
= node
->pstChild
; child
; child
= child
->pstNext
)
373 if (JSON_TYPE_STRING
!= child
->enDataType
)
375 grub_printf("Non string json type\n");
379 rc
= ventoy_plugin_check_path(isodisk
, child
->unData
.pcStrVal
);
380 grub_printf("%s: %s [%s]\n", key
, child
->unData
.pcStrVal
, rc
? "FAIL" : "OK");
391 static int ventoy_plugin_parse_fullpath
396 file_fullpath
**fullpath
,
402 VTOY_JSON
*node
= json
;
403 VTOY_JSON
*child
= NULL
;
404 file_fullpath
*path
= NULL
;
408 if (0 == grub_strcmp(key
, node
->pcName
))
412 node
= node
->pstNext
;
420 if (JSON_TYPE_STRING
== node
->enDataType
)
422 debug("%s is string type data\n", node
->pcName
);
424 if ((node
->unData
.pcStrVal
[0] != '/') || (!ventoy_is_file_exist("%s%s", isodisk
, node
->unData
.pcStrVal
)))
426 debug("%s%s file not found\n", isodisk
, node
->unData
.pcStrVal
);
430 path
= (file_fullpath
*)grub_zalloc(sizeof(file_fullpath
));
433 grub_snprintf(path
->path
, sizeof(path
->path
), "%s", node
->unData
.pcStrVal
);
439 else if (JSON_TYPE_ARRAY
== node
->enDataType
)
441 for (child
= node
->pstChild
; child
; child
= child
->pstNext
)
443 if ((JSON_TYPE_STRING
!= child
->enDataType
) || (child
->unData
.pcStrVal
[0] != '/'))
445 debug("Invalid data type:%d\n", child
->enDataType
);
450 debug("%s is array type data, count=%d\n", node
->pcName
, count
);
452 path
= (file_fullpath
*)grub_zalloc(sizeof(file_fullpath
) * count
);
457 for (count
= 0, child
= node
->pstChild
; child
; child
= child
->pstNext
)
459 if (ventoy_is_file_exist("%s%s", isodisk
, child
->unData
.pcStrVal
))
461 grub_snprintf(path
->path
, sizeof(path
->path
), "%s", child
->unData
.pcStrVal
);
475 static int ventoy_plugin_auto_install_check(VTOY_JSON
*json
, const char *isodisk
)
479 const char *iso
= NULL
;
480 VTOY_JSON
*pNode
= NULL
;
482 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
484 grub_printf("Not array type %d\n", json
->enDataType
);
488 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
490 if (pNode
->enDataType
!= JSON_TYPE_OBJECT
)
492 grub_printf("NOT object type\n");
495 iso
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
498 if (0 == ventoy_plugin_check_path(isodisk
, iso
))
500 grub_printf("image: %s [OK]\n", iso
);
501 ventoy_plugin_check_fullpath(pNode
->pstChild
, isodisk
, "template", &pathnum
);
503 if (JSON_SUCCESS
== vtoy_json_get_int(pNode
->pstChild
, "autosel", &autosel
))
505 if (autosel
>= 0 && autosel
<= pathnum
)
507 grub_printf("autosel: %d [OK]\n", autosel
);
511 grub_printf("autosel: %d [FAIL]\n", autosel
);
517 grub_printf("image: %s [FAIL]\n", iso
);
522 grub_printf("image not found\n");
529 static int ventoy_plugin_auto_install_entry(VTOY_JSON
*json
, const char *isodisk
)
533 const char *iso
= NULL
;
534 VTOY_JSON
*pNode
= NULL
;
535 install_template
*node
= NULL
;
536 install_template
*next
= NULL
;
537 file_fullpath
*templatepath
= NULL
;
539 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
541 debug("Not array %d\n", json
->enDataType
);
545 if (g_install_template_head
)
547 for (node
= g_install_template_head
; node
; node
= next
)
550 grub_check_free(node
->templatepath
);
554 g_install_template_head
= NULL
;
557 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
559 iso
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
560 if (iso
&& iso
[0] == '/')
562 if (0 == ventoy_plugin_parse_fullpath(pNode
->pstChild
, isodisk
, "template", &templatepath
, &pathnum
))
564 node
= grub_zalloc(sizeof(install_template
));
567 node
->pathlen
= grub_snprintf(node
->isopath
, sizeof(node
->isopath
), "%s", iso
);
568 node
->templatepath
= templatepath
;
569 node
->templatenum
= pathnum
;
572 if (JSON_SUCCESS
== vtoy_json_get_int(pNode
->pstChild
, "autosel", &autosel
))
574 if (autosel
>= 0 && autosel
<= pathnum
)
576 node
->autosel
= autosel
;
580 if (g_install_template_head
)
582 node
->next
= g_install_template_head
;
585 g_install_template_head
= node
;
594 static int ventoy_plugin_dud_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
, "dud", &pathnum
);
623 grub_printf("image: %s [FAIL]\n", iso
);
628 grub_printf("image not found\n");
635 static int ventoy_plugin_dud_entry(VTOY_JSON
*json
, const char *isodisk
)
638 const char *iso
= NULL
;
639 VTOY_JSON
*pNode
= NULL
;
642 file_fullpath
*dudpath
= NULL
;
644 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
646 debug("Not array %d\n", json
->enDataType
);
652 for (node
= g_dud_head
; node
; node
= next
)
655 grub_check_free(node
->dudpath
);
662 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
664 iso
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
665 if (iso
&& iso
[0] == '/')
667 if (0 == ventoy_plugin_parse_fullpath(pNode
->pstChild
, isodisk
, "dud", &dudpath
, &pathnum
))
669 node
= grub_zalloc(sizeof(dud
));
672 node
->pathlen
= grub_snprintf(node
->isopath
, sizeof(node
->isopath
), "%s", iso
);
673 node
->dudpath
= dudpath
;
674 node
->dudnum
= pathnum
;
675 node
->files
= grub_zalloc(sizeof(dudfile
) * pathnum
);
681 node
->next
= g_dud_head
;
698 static int ventoy_plugin_persistence_check(VTOY_JSON
*json
, const char *isodisk
)
702 const char *iso
= NULL
;
703 VTOY_JSON
*pNode
= NULL
;
705 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
707 grub_printf("Not array type %d\n", json
->enDataType
);
711 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
713 if (pNode
->enDataType
!= JSON_TYPE_OBJECT
)
715 grub_printf("NOT object type\n");
718 iso
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
721 if (0 == ventoy_plugin_check_path(isodisk
, iso
))
723 grub_printf("image: %s [OK]\n", iso
);
724 ventoy_plugin_check_fullpath(pNode
->pstChild
, isodisk
, "backend", &pathnum
);
726 if (JSON_SUCCESS
== vtoy_json_get_int(pNode
->pstChild
, "autosel", &autosel
))
728 if (autosel
>= 0 && autosel
<= pathnum
)
730 grub_printf("autosel: %d [OK]\n", autosel
);
734 grub_printf("autosel: %d [FAIL]\n", autosel
);
740 grub_printf("image: %s [FAIL]\n", iso
);
745 grub_printf("image not found\n");
752 static int ventoy_plugin_persistence_entry(VTOY_JSON
*json
, const char *isodisk
)
756 const char *iso
= NULL
;
757 VTOY_JSON
*pNode
= NULL
;
758 persistence_config
*node
= NULL
;
759 persistence_config
*next
= NULL
;
760 file_fullpath
*backendpath
= NULL
;
764 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
766 debug("Not array %d\n", json
->enDataType
);
770 if (g_persistence_head
)
772 for (node
= g_persistence_head
; node
; node
= next
)
775 grub_check_free(node
->backendpath
);
779 g_persistence_head
= NULL
;
782 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
784 iso
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
785 if (iso
&& iso
[0] == '/')
787 if (0 == ventoy_plugin_parse_fullpath(pNode
->pstChild
, isodisk
, "backend", &backendpath
, &pathnum
))
789 node
= grub_zalloc(sizeof(persistence_config
));
792 node
->pathlen
= grub_snprintf(node
->isopath
, sizeof(node
->isopath
), "%s", iso
);
793 node
->backendpath
= backendpath
;
794 node
->backendnum
= pathnum
;
797 if (JSON_SUCCESS
== vtoy_json_get_int(pNode
->pstChild
, "autosel", &autosel
))
799 if (autosel
>= 0 && autosel
<= pathnum
)
801 node
->autosel
= autosel
;
805 if (g_persistence_head
)
807 node
->next
= g_persistence_head
;
810 g_persistence_head
= node
;
819 static int ventoy_plugin_menualias_check(VTOY_JSON
*json
, const char *isodisk
)
822 const char *path
= NULL
;
823 const char *alias
= NULL
;
824 VTOY_JSON
*pNode
= NULL
;
828 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
830 grub_printf("Not array %d\n", json
->enDataType
);
834 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
836 type
= vtoy_alias_image_file
;
837 path
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
840 path
= vtoy_json_get_string_ex(pNode
->pstChild
, "dir");
841 type
= vtoy_alias_directory
;
844 alias
= vtoy_json_get_string_ex(pNode
->pstChild
, "alias");
845 if (path
&& path
[0] == '/' && alias
)
847 if (vtoy_alias_image_file
== type
)
849 if (ventoy_is_file_exist("%s%s", isodisk
, path
))
851 grub_printf("image: <%s> [ OK ]\n", path
);
855 grub_printf("image: <%s> [ NOT EXIST ]\n", path
);
860 if (ventoy_is_dir_exist("%s%s", isodisk
, path
))
862 grub_printf("dir: <%s> [ OK ]\n", path
);
866 grub_printf("dir: <%s> [ NOT EXIST ]\n", path
);
870 grub_printf("alias: <%s>\n\n", alias
);
877 static int ventoy_plugin_menualias_entry(VTOY_JSON
*json
, const char *isodisk
)
880 const char *path
= NULL
;
881 const char *alias
= NULL
;
882 VTOY_JSON
*pNode
= NULL
;
883 menu_alias
*node
= NULL
;
884 menu_alias
*next
= NULL
;
888 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
890 debug("Not array %d\n", json
->enDataType
);
894 if (g_menu_alias_head
)
896 for (node
= g_menu_alias_head
; node
; node
= next
)
902 g_menu_alias_head
= NULL
;
905 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
907 type
= vtoy_alias_image_file
;
908 path
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
911 path
= vtoy_json_get_string_ex(pNode
->pstChild
, "dir");
912 type
= vtoy_alias_directory
;
915 alias
= vtoy_json_get_string_ex(pNode
->pstChild
, "alias");
916 if (path
&& path
[0] == '/' && alias
)
918 node
= grub_zalloc(sizeof(menu_alias
));
922 node
->pathlen
= grub_snprintf(node
->isopath
, sizeof(node
->isopath
), "%s", path
);
923 grub_snprintf(node
->alias
, sizeof(node
->alias
), "%s", alias
);
925 if (g_menu_alias_head
)
927 node
->next
= g_menu_alias_head
;
930 g_menu_alias_head
= node
;
939 static int ventoy_plugin_injection_check(VTOY_JSON
*json
, const char *isodisk
)
941 const char *path
= NULL
;
942 const char *archive
= NULL
;
943 VTOY_JSON
*pNode
= NULL
;
947 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
949 grub_printf("Not array %d\n", json
->enDataType
);
953 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
955 path
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
958 grub_printf("image not found\n");
962 archive
= vtoy_json_get_string_ex(pNode
->pstChild
, "archive");
965 grub_printf("archive not found\n");
969 grub_printf("image: <%s> [%s]\n", path
, ventoy_check_file_exist("%s%s", isodisk
, path
) ? "OK" : "NOT EXIST");
970 grub_printf("archive: <%s> [%s]\n\n", archive
, ventoy_check_file_exist("%s%s", isodisk
, archive
) ? "OK" : "NOT EXIST");
976 static int ventoy_plugin_injection_entry(VTOY_JSON
*json
, const char *isodisk
)
978 const char *path
= NULL
;
979 const char *archive
= NULL
;
980 VTOY_JSON
*pNode
= NULL
;
981 injection_config
*node
= NULL
;
982 injection_config
*next
= NULL
;
986 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
988 debug("Not array %d\n", json
->enDataType
);
992 if (g_injection_head
)
994 for (node
= g_injection_head
; node
; node
= next
)
1000 g_injection_head
= NULL
;
1003 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
1005 path
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
1006 archive
= vtoy_json_get_string_ex(pNode
->pstChild
, "archive");
1007 if (path
&& path
[0] == '/' && archive
&& archive
[0] == '/')
1009 node
= grub_zalloc(sizeof(injection_config
));
1012 node
->pathlen
= grub_snprintf(node
->isopath
, sizeof(node
->isopath
), "%s", path
);
1013 grub_snprintf(node
->archive
, sizeof(node
->archive
), "%s", archive
);
1015 if (g_injection_head
)
1017 node
->next
= g_injection_head
;
1020 g_injection_head
= node
;
1028 static int ventoy_plugin_menuclass_entry(VTOY_JSON
*json
, const char *isodisk
)
1031 const char *key
= NULL
;
1032 const char *class = NULL
;
1033 VTOY_JSON
*pNode
= NULL
;
1034 menu_class
*tail
= NULL
;
1035 menu_class
*node
= NULL
;
1036 menu_class
*next
= NULL
;
1040 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
1042 debug("Not array %d\n", json
->enDataType
);
1046 if (g_menu_class_head
)
1048 for (node
= g_menu_class_head
; node
; node
= next
)
1054 g_menu_class_head
= NULL
;
1057 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
1059 type
= vtoy_class_image_file
;
1060 key
= vtoy_json_get_string_ex(pNode
->pstChild
, "key");
1063 key
= vtoy_json_get_string_ex(pNode
->pstChild
, "dir");
1064 type
= vtoy_class_directory
;
1067 class = vtoy_json_get_string_ex(pNode
->pstChild
, "class");
1070 node
= grub_zalloc(sizeof(menu_class
));
1074 node
->patlen
= grub_snprintf(node
->pattern
, sizeof(node
->pattern
), "%s", key
);
1075 grub_snprintf(node
->class, sizeof(node
->class), "%s", class);
1077 if (g_menu_class_head
)
1083 g_menu_class_head
= node
;
1093 static int ventoy_plugin_menuclass_check(VTOY_JSON
*json
, const char *isodisk
)
1096 const char *key
= NULL
;
1097 const char *class = NULL
;
1098 VTOY_JSON
*pNode
= NULL
;
1102 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
1104 grub_printf("Not array %d\n", json
->enDataType
);
1108 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
1110 type
= vtoy_class_image_file
;
1111 key
= vtoy_json_get_string_ex(pNode
->pstChild
, "key");
1114 key
= vtoy_json_get_string_ex(pNode
->pstChild
, "dir");
1115 type
= vtoy_class_directory
;
1118 class = vtoy_json_get_string_ex(pNode
->pstChild
, "class");
1121 grub_printf("%s: <%s>\n", (type
== vtoy_class_directory
) ? "dir" : "key", key
);
1122 grub_printf("class: <%s>\n\n", class);
1129 static int ventoy_plugin_conf_replace_entry(VTOY_JSON
*json
, const char *isodisk
)
1131 const char *isof
= NULL
;
1132 const char *orgf
= NULL
;
1133 const char *newf
= NULL
;
1134 VTOY_JSON
*pNode
= NULL
;
1135 conf_replace
*tail
= NULL
;
1136 conf_replace
*node
= NULL
;
1137 conf_replace
*next
= NULL
;
1141 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
1143 debug("Not array %d\n", json
->enDataType
);
1147 if (g_conf_replace_head
)
1149 for (node
= g_conf_replace_head
; node
; node
= next
)
1155 g_conf_replace_head
= NULL
;
1158 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
1160 isof
= vtoy_json_get_string_ex(pNode
->pstChild
, "iso");
1161 orgf
= vtoy_json_get_string_ex(pNode
->pstChild
, "org");
1162 newf
= vtoy_json_get_string_ex(pNode
->pstChild
, "new");
1163 if (isof
&& orgf
&& newf
&& isof
[0] == '/' && orgf
[0] == '/' && newf
[0] == '/')
1165 node
= grub_zalloc(sizeof(conf_replace
));
1168 node
->pathlen
= grub_snprintf(node
->isopath
, sizeof(node
->isopath
), "%s", isof
);
1169 grub_snprintf(node
->orgconf
, sizeof(node
->orgconf
), "%s", orgf
);
1170 grub_snprintf(node
->newconf
, sizeof(node
->newconf
), "%s", newf
);
1172 if (g_conf_replace_head
)
1178 g_conf_replace_head
= node
;
1188 static int ventoy_plugin_conf_replace_check(VTOY_JSON
*json
, const char *isodisk
)
1190 const char *isof
= NULL
;
1191 const char *orgf
= NULL
;
1192 const char *newf
= NULL
;
1193 VTOY_JSON
*pNode
= NULL
;
1194 grub_file_t file
= NULL
;
1199 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
1201 grub_printf("Not array %d\n", json
->enDataType
);
1205 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
1207 isof
= vtoy_json_get_string_ex(pNode
->pstChild
, "iso");
1208 orgf
= vtoy_json_get_string_ex(pNode
->pstChild
, "org");
1209 newf
= vtoy_json_get_string_ex(pNode
->pstChild
, "new");
1210 if (isof
&& orgf
&& newf
&& isof
[0] == '/' && orgf
[0] == '/' && newf
[0] == '/')
1212 if (ventoy_check_file_exist("%s%s", isodisk
, isof
))
1214 grub_printf("iso:<%s> [OK]\n", isof
);
1216 grub_snprintf(cmd
, sizeof(cmd
), "loopback vtisocheck %s%s", isodisk
, isof
);
1217 grub_script_execute_sourcecode(cmd
);
1219 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(vtisocheck)/%s", orgf
);
1222 if (grub_strcmp(file
->fs
->name
, "iso9660") == 0)
1224 grub_printf("org:<%s> [OK]\n", orgf
);
1228 grub_printf("org:<%s> [Exist But NOT ISO9660]\n", orgf
);
1230 grub_file_close(file
);
1234 grub_printf("org:<%s> [NOT Exist]\n", orgf
);
1237 grub_script_execute_sourcecode("loopback -d vtisocheck");
1241 grub_printf("iso:<%s> [NOT Exist]\n", isof
);
1242 grub_printf("org:<%s>\n", orgf
);
1245 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", isodisk
, newf
);
1248 if (file
->size
> vtoy_max_replace_file_size
)
1250 grub_printf("new:<%s> [Too Big %lu] \n", newf
, (ulong
)file
->size
);
1254 grub_printf("new:<%s> [OK]\n", newf
);
1256 grub_file_close(file
);
1260 grub_printf("new:<%s> [NOT Exist]\n", newf
);
1269 static int ventoy_plugin_auto_memdisk_entry(VTOY_JSON
*json
, const char *isodisk
)
1271 VTOY_JSON
*pNode
= NULL
;
1272 auto_memdisk
*node
= NULL
;
1273 auto_memdisk
*next
= NULL
;
1277 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
1279 debug("Not array %d\n", json
->enDataType
);
1283 if (g_auto_memdisk_head
)
1285 for (node
= g_auto_memdisk_head
; node
; node
= next
)
1291 g_auto_memdisk_head
= NULL
;
1294 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
1296 if (pNode
->enDataType
== JSON_TYPE_STRING
)
1298 node
= grub_zalloc(sizeof(auto_memdisk
));
1301 node
->pathlen
= grub_snprintf(node
->isopath
, sizeof(node
->isopath
), "%s", pNode
->unData
.pcStrVal
);
1303 if (g_auto_memdisk_head
)
1305 node
->next
= g_auto_memdisk_head
;
1308 g_auto_memdisk_head
= node
;
1316 static int ventoy_plugin_auto_memdisk_check(VTOY_JSON
*json
, const char *isodisk
)
1318 VTOY_JSON
*pNode
= NULL
;
1320 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
1322 grub_printf("Not array %d\n", json
->enDataType
);
1326 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
1328 if (pNode
->enDataType
== JSON_TYPE_STRING
)
1330 grub_printf("<%s> ", pNode
->unData
.pcStrVal
);
1332 if (ventoy_check_file_exist("%s%s", isodisk
, pNode
->unData
.pcStrVal
))
1334 grub_printf(" [OK]\n");
1338 grub_printf(" [NOT EXIST]\n");
1346 static int ventoy_plugin_image_list_entry(VTOY_JSON
*json
, const char *isodisk
)
1348 VTOY_JSON
*pNode
= NULL
;
1349 image_list
*node
= NULL
;
1350 image_list
*next
= NULL
;
1351 image_list
*tail
= NULL
;
1355 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
1357 debug("Not array %d\n", json
->enDataType
);
1361 if (g_image_list_head
)
1363 for (node
= g_image_list_head
; node
; node
= next
)
1369 g_image_list_head
= NULL
;
1372 g_plugin_image_list
= 1;
1374 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
1376 if (pNode
->enDataType
== JSON_TYPE_STRING
)
1378 node
= grub_zalloc(sizeof(image_list
));
1381 node
->pathlen
= grub_snprintf(node
->isopath
, sizeof(node
->isopath
), "%s", pNode
->unData
.pcStrVal
);
1383 if (g_image_list_head
)
1389 g_image_list_head
= node
;
1399 static int ventoy_plugin_image_list_check(VTOY_JSON
*json
, const char *isodisk
)
1401 VTOY_JSON
*pNode
= NULL
;
1403 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
1405 grub_printf("Not array %d\n", json
->enDataType
);
1409 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
1411 if (pNode
->enDataType
== JSON_TYPE_STRING
)
1413 grub_printf("<%s> ", pNode
->unData
.pcStrVal
);
1415 if (ventoy_check_file_exist("%s%s", isodisk
, pNode
->unData
.pcStrVal
))
1417 grub_printf(" [OK]\n");
1421 grub_printf(" [NOT EXIST]\n");
1429 static plugin_entry g_plugin_entries
[] =
1431 { "control", ventoy_plugin_control_entry
, ventoy_plugin_control_check
},
1432 { "theme", ventoy_plugin_theme_entry
, ventoy_plugin_theme_check
},
1433 { "auto_install", ventoy_plugin_auto_install_entry
, ventoy_plugin_auto_install_check
},
1434 { "persistence", ventoy_plugin_persistence_entry
, ventoy_plugin_persistence_check
},
1435 { "menu_alias", ventoy_plugin_menualias_entry
, ventoy_plugin_menualias_check
},
1436 { "menu_class", ventoy_plugin_menuclass_entry
, ventoy_plugin_menuclass_check
},
1437 { "injection", ventoy_plugin_injection_entry
, ventoy_plugin_injection_check
},
1438 { "auto_memdisk", ventoy_plugin_auto_memdisk_entry
, ventoy_plugin_auto_memdisk_check
},
1439 { "image_list", ventoy_plugin_image_list_entry
, ventoy_plugin_image_list_check
},
1440 { "conf_replace", ventoy_plugin_conf_replace_entry
, ventoy_plugin_conf_replace_check
},
1441 { "dud", ventoy_plugin_dud_entry
, ventoy_plugin_dud_check
},
1444 static int ventoy_parse_plugin_config(VTOY_JSON
*json
, const char *isodisk
)
1448 VTOY_JSON
*cur
= json
;
1450 grub_snprintf(g_iso_disk_name
, sizeof(g_iso_disk_name
), "%s", isodisk
);
1454 for (i
= 0; i
< (int)ARRAY_SIZE(g_plugin_entries
); i
++)
1456 grub_snprintf(key
, sizeof(key
), "%s_%s", g_plugin_entries
[i
].key
, VTOY_DUAL_MODE_SUFFIX
);
1457 if (grub_strcmp(g_plugin_entries
[i
].key
, cur
->pcName
) == 0 || grub_strcmp(key
, cur
->pcName
) == 0)
1459 debug("Plugin entry for %s\n", g_plugin_entries
[i
].key
);
1460 g_plugin_entries
[i
].entryfunc(cur
, isodisk
);
1471 grub_err_t
ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1476 VTOY_JSON
*json
= NULL
;
1481 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/ventoy/ventoy.json", args
[0]);
1484 return GRUB_ERR_NONE
;
1487 debug("json configuration file size %d\n", (int)file
->size
);
1489 buf
= grub_malloc(file
->size
+ 1);
1492 grub_file_close(file
);
1496 buf
[file
->size
] = 0;
1497 grub_file_read(file
, buf
, file
->size
);
1498 grub_file_close(file
);
1500 json
= vtoy_json_create();
1508 ret
= vtoy_json_parse(json
, buf
);
1511 grub_env_set("VTOY_PLUGIN_SYNTAX_ERROR", "1");
1512 grub_env_export("VTOY_PLUGIN_SYNTAX_ERROR");
1514 debug("Failed to parse json string %d\n", ret
);
1519 ventoy_parse_plugin_config(json
->pstChild
, args
[0]);
1521 vtoy_json_destroy(json
);
1525 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1528 void ventoy_plugin_dump_injection(void)
1530 injection_config
*node
= NULL
;
1532 for (node
= g_injection_head
; node
; node
= node
->next
)
1534 grub_printf("\nIMAGE:<%s>\n", node
->isopath
);
1535 grub_printf("ARCHIVE:<%s>\n", node
->archive
);
1542 void ventoy_plugin_dump_auto_install(void)
1545 install_template
*node
= NULL
;
1547 for (node
= g_install_template_head
; node
; node
= node
->next
)
1549 grub_printf("\nIMAGE:<%s> <%d>\n", node
->isopath
, node
->templatenum
);
1550 for (i
= 0; i
< node
->templatenum
; i
++)
1552 grub_printf("SCRIPT %d:<%s>\n", i
, node
->templatepath
[i
].path
);
1559 void ventoy_plugin_dump_persistence(void)
1563 persistence_config
*node
= NULL
;
1564 ventoy_img_chunk_list chunk_list
;
1566 for (node
= g_persistence_head
; node
; node
= node
->next
)
1568 grub_printf("\nIMAGE:<%s> <%d>\n", node
->isopath
, node
->backendnum
);
1570 for (i
= 0; i
< node
->backendnum
; i
++)
1572 grub_printf("PERSIST %d:<%s>", i
, node
->backendpath
[i
].path
);
1573 rc
= ventoy_plugin_get_persistent_chunklist(node
->isopath
, i
, &chunk_list
);
1576 grub_printf(" [ SUCCESS ]\n");
1577 grub_free(chunk_list
.chunk
);
1581 grub_printf(" [ FAILED ]\n");
1589 install_template
* ventoy_plugin_find_install_template(const char *isopath
)
1592 install_template
*node
= NULL
;
1594 if (!g_install_template_head
)
1599 len
= (int)grub_strlen(isopath
);
1600 for (node
= g_install_template_head
; node
; node
= node
->next
)
1602 if (node
->pathlen
== len
&& grub_strcmp(node
->isopath
, isopath
) == 0)
1611 char * ventoy_plugin_get_cur_install_template(const char *isopath
)
1613 install_template
*node
= NULL
;
1615 node
= ventoy_plugin_find_install_template(isopath
);
1616 if ((!node
) || (!node
->templatepath
))
1621 if (node
->cursel
< 0 || node
->cursel
>= node
->templatenum
)
1626 return node
->templatepath
[node
->cursel
].path
;
1629 persistence_config
* ventoy_plugin_find_persistent(const char *isopath
)
1632 persistence_config
*node
= NULL
;
1634 if (!g_persistence_head
)
1639 len
= (int)grub_strlen(isopath
);
1640 for (node
= g_persistence_head
; node
; node
= node
->next
)
1642 if ((len
== node
->pathlen
) && (grub_strcmp(node
->isopath
, isopath
) == 0))
1651 int ventoy_plugin_get_persistent_chunklist(const char *isopath
, int index
, ventoy_img_chunk_list
*chunk_list
)
1654 grub_uint64_t start
= 0;
1655 grub_file_t file
= NULL
;
1656 persistence_config
*node
= NULL
;
1658 node
= ventoy_plugin_find_persistent(isopath
);
1659 if ((!node
) || (!node
->backendpath
))
1666 index
= node
->cursel
;
1669 if (index
< 0 || index
>= node
->backendnum
)
1674 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", g_iso_disk_name
, node
->backendpath
[index
].path
);
1677 debug("Failed to open file %s%s\n", g_iso_disk_name
, node
->backendpath
[index
].path
);
1681 grub_memset(chunk_list
, 0, sizeof(ventoy_img_chunk_list
));
1682 chunk_list
->chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1683 if (NULL
== chunk_list
->chunk
)
1688 chunk_list
->max_chunk
= DEFAULT_CHUNK_NUM
;
1689 chunk_list
->cur_chunk
= 0;
1691 start
= file
->device
->disk
->partition
->start
;
1692 ventoy_get_block_list(file
, chunk_list
, start
);
1694 if (0 != ventoy_check_block_list(file
, chunk_list
, start
))
1696 grub_free(chunk_list
->chunk
);
1697 chunk_list
->chunk
= NULL
;
1705 grub_file_close(file
);
1710 const char * ventoy_plugin_get_injection(const char *isopath
)
1713 injection_config
*node
= NULL
;
1715 if (!g_injection_head
)
1720 len
= (int)grub_strlen(isopath
);
1721 for (node
= g_injection_head
; node
; node
= node
->next
)
1723 if (node
->pathlen
== len
&& grub_strcmp(node
->isopath
, isopath
) == 0)
1725 return node
->archive
;
1732 const char * ventoy_plugin_get_menu_alias(int type
, const char *isopath
)
1735 menu_alias
*node
= NULL
;
1737 if (!g_menu_alias_head
)
1742 len
= (int)grub_strlen(isopath
);
1743 for (node
= g_menu_alias_head
; node
; node
= node
->next
)
1745 if (node
->type
== type
&& node
->pathlen
&&
1746 node
->pathlen
== len
&& grub_strcmp(node
->isopath
, isopath
) == 0)
1755 const char * ventoy_plugin_get_menu_class(int type
, const char *name
)
1758 menu_class
*node
= NULL
;
1760 if (!g_menu_class_head
)
1765 len
= (int)grub_strlen(name
);
1767 if (vtoy_class_image_file
== type
)
1769 for (node
= g_menu_class_head
; node
; node
= node
->next
)
1771 if (node
->type
== type
&& node
->patlen
<= len
&& grub_strstr(name
, node
->pattern
))
1779 for (node
= g_menu_class_head
; node
; node
= node
->next
)
1781 if (node
->type
== type
&& node
->patlen
== len
&& grub_strncmp(name
, node
->pattern
, len
) == 0)
1791 int ventoy_plugin_check_memdisk(const char *isopath
)
1794 auto_memdisk
*node
= NULL
;
1796 if (!g_auto_memdisk_head
)
1801 len
= (int)grub_strlen(isopath
);
1802 for (node
= g_auto_memdisk_head
; node
; node
= node
->next
)
1804 if (node
->pathlen
== len
&& grub_strncmp(isopath
, node
->isopath
, len
) == 0)
1813 int ventoy_plugin_get_image_list_index(int type
, const char *name
)
1817 image_list
*node
= NULL
;
1819 if (!g_image_list_head
)
1824 len
= (int)grub_strlen(name
);
1826 for (node
= g_image_list_head
; node
; node
= node
->next
, index
++)
1828 if (vtoy_class_directory
== type
)
1830 if (len
< node
->pathlen
&& grub_strncmp(name
, node
->isopath
, len
) == 0)
1837 if (len
== node
->pathlen
&& grub_strncmp(name
, node
->isopath
, len
) == 0)
1847 conf_replace
* ventoy_plugin_find_conf_replace(const char *iso
)
1852 if (!g_conf_replace_head
)
1857 len
= (int)grub_strlen(iso
);
1859 for (node
= g_conf_replace_head
; node
; node
= node
->next
)
1861 if (node
->pathlen
== len
&& grub_strncmp(iso
, node
->isopath
, len
) == 0)
1870 dud
* ventoy_plugin_find_dud(const char *iso
)
1880 len
= (int)grub_strlen(iso
);
1881 for (node
= g_dud_head
; node
; node
= node
->next
)
1883 if (node
->pathlen
== len
&& grub_strncmp(iso
, node
->isopath
, len
) == 0)
1892 int ventoy_plugin_load_dud(dud
*node
, const char *isopart
)
1898 for (i
= 0; i
< node
->dudnum
; i
++)
1900 if (node
->files
[i
].size
> 0)
1902 debug("file %d has been loaded\n", i
);
1906 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", isopart
, node
->dudpath
[i
].path
);
1909 buf
= grub_malloc(file
->size
);
1912 grub_file_read(file
, buf
, file
->size
);
1913 node
->files
[i
].size
= (int)file
->size
;
1914 node
->files
[i
].buf
= buf
;
1916 grub_file_close(file
);
1923 grub_err_t
ventoy_cmd_plugin_check_json(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1930 VTOY_JSON
*node
= NULL
;
1931 VTOY_JSON
*json
= NULL
;
1940 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/ventoy/ventoy.json", args
[0]);
1943 grub_printf("Plugin json file /ventoy/ventoy.json does NOT exist.\n");
1944 grub_printf("Attention: directory name and filename are both case-sensitive.\n");
1948 buf
= grub_malloc(file
->size
+ 1);
1951 grub_printf("Failed to malloc memory %lu.\n", (ulong
)(file
->size
+ 1));
1955 buf
[file
->size
] = 0;
1956 grub_file_read(file
, buf
, file
->size
);
1958 json
= vtoy_json_create();
1961 grub_printf("Failed to create json\n");
1965 ret
= vtoy_json_parse(json
, buf
);
1968 grub_printf("Syntax error detected in ventoy.json, please check it.\n");
1972 grub_snprintf(key
, sizeof(key
), "%s_%s", args
[1], VTOY_DUAL_MODE_SUFFIX
);
1973 for (node
= json
->pstChild
; node
; node
= node
->pstNext
)
1975 if (grub_strcmp(node
->pcName
, args
[1]) == 0 || grub_strcmp(node
->pcName
, key
) == 0)
1983 grub_printf("%s is NOT found in ventoy.json\n", args
[1]);
1987 for (i
= 0; i
< (int)ARRAY_SIZE(g_plugin_entries
); i
++)
1989 if (grub_strcmp(g_plugin_entries
[i
].key
, args
[1]) == 0)
1991 if (g_plugin_entries
[i
].checkfunc
)
1993 ret
= g_plugin_entries
[i
].checkfunc(node
, args
[2]);
2000 check_free(file
, grub_file_close
);
2001 check_free(json
, vtoy_json_destroy
);
2002 grub_check_free(buf
);