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
;
51 static int ventoy_plugin_control_check(VTOY_JSON
*json
, const char *isodisk
)
54 VTOY_JSON
*pNode
= NULL
;
55 VTOY_JSON
*pChild
= NULL
;
59 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
61 grub_printf("Not array type %d\n", json
->enDataType
);
65 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
67 if (pNode
->enDataType
== JSON_TYPE_OBJECT
)
69 pChild
= pNode
->pstChild
;
70 if (pChild
->enDataType
== JSON_TYPE_STRING
)
72 if (grub_strcmp(pChild
->pcName
, "VTOY_DEFAULT_IMAGE") == 0)
74 grub_printf("%s: %s [%s]\n", pChild
->pcName
, pChild
->unData
.pcStrVal
,
75 ventoy_check_file_exist("%s%s", isodisk
, pChild
->unData
.pcStrVal
) ? "OK" : "NOT EXIST");
79 grub_printf("%s: %s\n", pChild
->pcName
, pChild
->unData
.pcStrVal
);
84 grub_printf("%s is NOT string type\n", pChild
->pcName
);
90 grub_printf("%s is not an object\n", pNode
->pcName
);
98 static int ventoy_plugin_control_entry(VTOY_JSON
*json
, const char *isodisk
)
100 VTOY_JSON
*pNode
= NULL
;
101 VTOY_JSON
*pChild
= NULL
;
105 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
107 debug("Not array %d\n", json
->enDataType
);
111 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
113 if (pNode
->enDataType
== JSON_TYPE_OBJECT
)
115 pChild
= pNode
->pstChild
;
116 if (pChild
->enDataType
== JSON_TYPE_STRING
&& pChild
->pcName
&& pChild
->unData
.pcStrVal
)
118 ventoy_set_env(pChild
->pcName
, pChild
->unData
.pcStrVal
);
126 static int ventoy_plugin_theme_check(VTOY_JSON
*json
, const char *isodisk
)
132 value
= vtoy_json_get_string_ex(json
->pstChild
, "file");
135 grub_printf("file: %s\n", value
);
138 exist
= ventoy_is_file_exist("%s%s", isodisk
, value
);
142 exist
= ventoy_is_file_exist("%s/ventoy/%s", isodisk
, value
);
147 grub_printf("Theme file %s does NOT exist\n", value
);
152 value
= vtoy_json_get_string_ex(json
->pstChild
, "gfxmode");
155 grub_printf("gfxmode: %s\n", value
);
158 value
= vtoy_json_get_string_ex(json
->pstChild
, "display_mode");
161 grub_printf("display_mode: %s\n", value
);
164 value
= vtoy_json_get_string_ex(json
->pstChild
, "serial_param");
167 grub_printf("serial_param %s\n", value
);
170 value
= vtoy_json_get_string_ex(json
->pstChild
, "ventoy_left");
173 grub_printf("ventoy_left: %s\n", value
);
176 value
= vtoy_json_get_string_ex(json
->pstChild
, "ventoy_top");
179 grub_printf("ventoy_top: %s\n", value
);
182 value
= vtoy_json_get_string_ex(json
->pstChild
, "ventoy_color");
185 grub_printf("ventoy_color: %s\n", value
);
188 node
= vtoy_json_find_item(json
->pstChild
, JSON_TYPE_ARRAY
, "fonts");
191 for (node
= node
->pstChild
; node
; node
= node
->pstNext
)
193 if (node
->enDataType
== JSON_TYPE_STRING
)
195 if (ventoy_check_file_exist("%s%s", isodisk
, node
->unData
.pcStrVal
))
197 grub_printf("%s [OK]\n", node
->unData
.pcStrVal
);
201 grub_printf("%s [NOT EXIST]\n", node
->unData
.pcStrVal
);
208 grub_printf("fonts NOT found\n");
214 static int ventoy_plugin_theme_entry(VTOY_JSON
*json
, const char *isodisk
)
220 value
= vtoy_json_get_string_ex(json
->pstChild
, "file");
225 grub_snprintf(filepath
, sizeof(filepath
), "%s%s", isodisk
, value
);
229 grub_snprintf(filepath
, sizeof(filepath
), "%s/ventoy/%s", isodisk
, value
);
232 if (ventoy_is_file_exist(filepath
) == 0)
234 debug("Theme file %s does not exist\n", filepath
);
238 debug("vtoy_theme %s\n", filepath
);
239 grub_env_set("vtoy_theme", filepath
);
242 value
= vtoy_json_get_string_ex(json
->pstChild
, "gfxmode");
245 debug("vtoy_gfxmode %s\n", value
);
246 grub_env_set("vtoy_gfxmode", value
);
249 value
= vtoy_json_get_string_ex(json
->pstChild
, "display_mode");
252 debug("display_mode %s\n", value
);
253 grub_env_set("vtoy_display_mode", value
);
256 value
= vtoy_json_get_string_ex(json
->pstChild
, "serial_param");
259 debug("serial_param %s\n", value
);
260 grub_env_set("vtoy_serial_param", value
);
263 value
= vtoy_json_get_string_ex(json
->pstChild
, "ventoy_left");
266 grub_env_set("VTLE_LFT", value
);
269 value
= vtoy_json_get_string_ex(json
->pstChild
, "ventoy_top");
272 grub_env_set("VTLE_TOP", value
);
275 value
= vtoy_json_get_string_ex(json
->pstChild
, "ventoy_color");
278 grub_env_set("VTLE_CLR", value
);
281 node
= vtoy_json_find_item(json
->pstChild
, JSON_TYPE_ARRAY
, "fonts");
284 for (node
= node
->pstChild
; node
; node
= node
->pstNext
)
286 if (node
->enDataType
== JSON_TYPE_STRING
&&
287 ventoy_check_file_exist("%s%s", isodisk
, node
->unData
.pcStrVal
))
289 grub_snprintf(filepath
, sizeof(filepath
), "%s%s", isodisk
, node
->unData
.pcStrVal
);
290 grub_font_load(filepath
);
298 static int ventoy_plugin_check_path(const char *path
, const char *file
)
302 grub_printf("%s is NOT begin with '/' \n", file
);
306 if (grub_strchr(file
, '\\'))
308 grub_printf("%s contains invalid '\\' \n", file
);
312 if (grub_strstr(file
, "//"))
314 grub_printf("%s contains invalid double slash\n", file
);
318 if (grub_strstr(file
, "../"))
320 grub_printf("%s contains invalid '../' \n", file
);
324 if (!ventoy_is_file_exist("%s%s", path
, file
))
326 grub_printf("%s%s does NOT exist\n", path
, file
);
333 static int ventoy_plugin_check_fullpath
344 VTOY_JSON
*node
= json
;
345 VTOY_JSON
*child
= NULL
;
349 if (0 == grub_strcmp(key
, node
->pcName
))
353 node
= node
->pstNext
;
361 if (JSON_TYPE_STRING
== node
->enDataType
)
364 ret
= ventoy_plugin_check_path(isodisk
, node
->unData
.pcStrVal
);
365 grub_printf("%s: %s [%s]\n", key
, node
->unData
.pcStrVal
, ret
? "FAIL" : "OK");
367 else if (JSON_TYPE_ARRAY
== node
->enDataType
)
369 for (child
= node
->pstChild
; child
; child
= child
->pstNext
)
371 if (JSON_TYPE_STRING
!= child
->enDataType
)
373 grub_printf("Non string json type\n");
377 rc
= ventoy_plugin_check_path(isodisk
, child
->unData
.pcStrVal
);
378 grub_printf("%s: %s [%s]\n", key
, child
->unData
.pcStrVal
, rc
? "FAIL" : "OK");
389 static int ventoy_plugin_parse_fullpath
394 file_fullpath
**fullpath
,
400 VTOY_JSON
*node
= json
;
401 VTOY_JSON
*child
= NULL
;
402 file_fullpath
*path
= NULL
;
406 if (0 == grub_strcmp(key
, node
->pcName
))
410 node
= node
->pstNext
;
418 if (JSON_TYPE_STRING
== node
->enDataType
)
420 debug("%s is string type data\n", node
->pcName
);
422 if ((node
->unData
.pcStrVal
[0] != '/') || (!ventoy_is_file_exist("%s%s", isodisk
, node
->unData
.pcStrVal
)))
424 debug("%s%s file not found\n", isodisk
, node
->unData
.pcStrVal
);
428 path
= (file_fullpath
*)grub_zalloc(sizeof(file_fullpath
));
431 grub_snprintf(path
->path
, sizeof(path
->path
), "%s", node
->unData
.pcStrVal
);
437 else if (JSON_TYPE_ARRAY
== node
->enDataType
)
439 for (child
= node
->pstChild
; child
; child
= child
->pstNext
)
441 if ((JSON_TYPE_STRING
!= child
->enDataType
) || (child
->unData
.pcStrVal
[0] != '/'))
443 debug("Invalid data type:%d\n", child
->enDataType
);
448 debug("%s is array type data, count=%d\n", node
->pcName
, count
);
450 path
= (file_fullpath
*)grub_zalloc(sizeof(file_fullpath
) * count
);
455 for (count
= 0, child
= node
->pstChild
; child
; child
= child
->pstNext
)
457 if (ventoy_is_file_exist("%s%s", isodisk
, child
->unData
.pcStrVal
))
459 grub_snprintf(path
->path
, sizeof(path
->path
), "%s", child
->unData
.pcStrVal
);
473 static int ventoy_plugin_auto_install_check(VTOY_JSON
*json
, const char *isodisk
)
477 const char *iso
= NULL
;
478 VTOY_JSON
*pNode
= NULL
;
480 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
482 grub_printf("Not array type %d\n", json
->enDataType
);
486 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
488 if (pNode
->enDataType
!= JSON_TYPE_OBJECT
)
490 grub_printf("NOT object type\n");
493 iso
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
496 if (0 == ventoy_plugin_check_path(isodisk
, iso
))
498 grub_printf("image: %s [OK]\n", iso
);
499 ventoy_plugin_check_fullpath(pNode
->pstChild
, isodisk
, "template", &pathnum
);
501 if (JSON_SUCCESS
== vtoy_json_get_int(pNode
->pstChild
, "autosel", &autosel
))
503 if (autosel
>= 0 && autosel
<= pathnum
)
505 grub_printf("autosel: %d [OK]\n", autosel
);
509 grub_printf("autosel: %d [FAIL]\n", autosel
);
515 grub_printf("image: %s [FAIL]\n", iso
);
520 grub_printf("image not found\n");
527 static int ventoy_plugin_auto_install_entry(VTOY_JSON
*json
, const char *isodisk
)
531 const char *iso
= NULL
;
532 VTOY_JSON
*pNode
= NULL
;
533 install_template
*node
= NULL
;
534 install_template
*next
= NULL
;
535 file_fullpath
*templatepath
= NULL
;
537 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
539 debug("Not array %d\n", json
->enDataType
);
543 if (g_install_template_head
)
545 for (node
= g_install_template_head
; node
; node
= next
)
548 grub_check_free(node
->templatepath
);
552 g_install_template_head
= NULL
;
555 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
557 iso
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
558 if (iso
&& iso
[0] == '/')
560 if (0 == ventoy_plugin_parse_fullpath(pNode
->pstChild
, isodisk
, "template", &templatepath
, &pathnum
))
562 node
= grub_zalloc(sizeof(install_template
));
565 node
->pathlen
= grub_snprintf(node
->isopath
, sizeof(node
->isopath
), "%s", iso
);
566 node
->templatepath
= templatepath
;
567 node
->templatenum
= pathnum
;
570 if (JSON_SUCCESS
== vtoy_json_get_int(pNode
->pstChild
, "autosel", &autosel
))
572 if (autosel
>= 0 && autosel
<= pathnum
)
574 node
->autosel
= autosel
;
578 if (g_install_template_head
)
580 node
->next
= g_install_template_head
;
583 g_install_template_head
= node
;
592 static int ventoy_plugin_persistence_check(VTOY_JSON
*json
, const char *isodisk
)
596 const char *iso
= NULL
;
597 VTOY_JSON
*pNode
= NULL
;
599 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
601 grub_printf("Not array type %d\n", json
->enDataType
);
605 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
607 if (pNode
->enDataType
!= JSON_TYPE_OBJECT
)
609 grub_printf("NOT object type\n");
612 iso
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
615 if (0 == ventoy_plugin_check_path(isodisk
, iso
))
617 grub_printf("image: %s [OK]\n", iso
);
618 ventoy_plugin_check_fullpath(pNode
->pstChild
, isodisk
, "backend", &pathnum
);
620 if (JSON_SUCCESS
== vtoy_json_get_int(pNode
->pstChild
, "autosel", &autosel
))
622 if (autosel
>= 0 && autosel
<= pathnum
)
624 grub_printf("autosel: %d [OK]\n", autosel
);
628 grub_printf("autosel: %d [FAIL]\n", autosel
);
634 grub_printf("image: %s [FAIL]\n", iso
);
639 grub_printf("image not found\n");
646 static int ventoy_plugin_persistence_entry(VTOY_JSON
*json
, const char *isodisk
)
650 const char *iso
= NULL
;
651 VTOY_JSON
*pNode
= NULL
;
652 persistence_config
*node
= NULL
;
653 persistence_config
*next
= NULL
;
654 file_fullpath
*backendpath
= NULL
;
658 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
660 debug("Not array %d\n", json
->enDataType
);
664 if (g_persistence_head
)
666 for (node
= g_persistence_head
; node
; node
= next
)
669 grub_check_free(node
->backendpath
);
673 g_persistence_head
= NULL
;
676 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
678 iso
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
679 if (iso
&& iso
[0] == '/')
681 if (0 == ventoy_plugin_parse_fullpath(pNode
->pstChild
, isodisk
, "backend", &backendpath
, &pathnum
))
683 node
= grub_zalloc(sizeof(persistence_config
));
686 node
->pathlen
= grub_snprintf(node
->isopath
, sizeof(node
->isopath
), "%s", iso
);
687 node
->backendpath
= backendpath
;
688 node
->backendnum
= pathnum
;
691 if (JSON_SUCCESS
== vtoy_json_get_int(pNode
->pstChild
, "autosel", &autosel
))
693 if (autosel
>= 0 && autosel
<= pathnum
)
695 node
->autosel
= autosel
;
699 if (g_persistence_head
)
701 node
->next
= g_persistence_head
;
704 g_persistence_head
= node
;
713 static int ventoy_plugin_menualias_check(VTOY_JSON
*json
, const char *isodisk
)
716 const char *path
= NULL
;
717 const char *alias
= NULL
;
718 VTOY_JSON
*pNode
= NULL
;
722 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
724 grub_printf("Not array %d\n", json
->enDataType
);
728 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
730 type
= vtoy_alias_image_file
;
731 path
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
734 path
= vtoy_json_get_string_ex(pNode
->pstChild
, "dir");
735 type
= vtoy_alias_directory
;
738 alias
= vtoy_json_get_string_ex(pNode
->pstChild
, "alias");
739 if (path
&& path
[0] == '/' && alias
)
741 if (vtoy_alias_image_file
== type
)
743 if (ventoy_is_file_exist("%s%s", isodisk
, path
))
745 grub_printf("image: <%s> [ OK ]\n", path
);
749 grub_printf("image: <%s> [ NOT EXIST ]\n", path
);
754 if (ventoy_is_dir_exist("%s%s", isodisk
, path
))
756 grub_printf("dir: <%s> [ OK ]\n", path
);
760 grub_printf("dir: <%s> [ NOT EXIST ]\n", path
);
764 grub_printf("alias: <%s>\n\n", alias
);
771 static int ventoy_plugin_menualias_entry(VTOY_JSON
*json
, const char *isodisk
)
774 const char *path
= NULL
;
775 const char *alias
= NULL
;
776 VTOY_JSON
*pNode
= NULL
;
777 menu_alias
*node
= NULL
;
778 menu_alias
*next
= NULL
;
782 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
784 debug("Not array %d\n", json
->enDataType
);
788 if (g_menu_alias_head
)
790 for (node
= g_menu_alias_head
; node
; node
= next
)
796 g_menu_alias_head
= NULL
;
799 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
801 type
= vtoy_alias_image_file
;
802 path
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
805 path
= vtoy_json_get_string_ex(pNode
->pstChild
, "dir");
806 type
= vtoy_alias_directory
;
809 alias
= vtoy_json_get_string_ex(pNode
->pstChild
, "alias");
810 if (path
&& path
[0] == '/' && alias
)
812 node
= grub_zalloc(sizeof(menu_alias
));
816 node
->pathlen
= grub_snprintf(node
->isopath
, sizeof(node
->isopath
), "%s", path
);
817 grub_snprintf(node
->alias
, sizeof(node
->alias
), "%s", alias
);
819 if (g_menu_alias_head
)
821 node
->next
= g_menu_alias_head
;
824 g_menu_alias_head
= node
;
833 static int ventoy_plugin_injection_check(VTOY_JSON
*json
, const char *isodisk
)
835 const char *path
= NULL
;
836 const char *archive
= NULL
;
837 VTOY_JSON
*pNode
= NULL
;
841 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
843 grub_printf("Not array %d\n", json
->enDataType
);
847 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
849 path
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
852 grub_printf("image not found\n");
856 archive
= vtoy_json_get_string_ex(pNode
->pstChild
, "archive");
859 grub_printf("archive not found\n");
863 grub_printf("image: <%s> [%s]\n", path
, ventoy_check_file_exist("%s%s", isodisk
, path
) ? "OK" : "NOT EXIST");
864 grub_printf("archive: <%s> [%s]\n\n", archive
, ventoy_check_file_exist("%s%s", isodisk
, archive
) ? "OK" : "NOT EXIST");
870 static int ventoy_plugin_injection_entry(VTOY_JSON
*json
, const char *isodisk
)
872 const char *path
= NULL
;
873 const char *archive
= NULL
;
874 VTOY_JSON
*pNode
= NULL
;
875 injection_config
*node
= NULL
;
876 injection_config
*next
= NULL
;
880 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
882 debug("Not array %d\n", json
->enDataType
);
886 if (g_injection_head
)
888 for (node
= g_injection_head
; node
; node
= next
)
894 g_injection_head
= NULL
;
897 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
899 path
= vtoy_json_get_string_ex(pNode
->pstChild
, "image");
900 archive
= vtoy_json_get_string_ex(pNode
->pstChild
, "archive");
901 if (path
&& path
[0] == '/' && archive
&& archive
[0] == '/')
903 node
= grub_zalloc(sizeof(injection_config
));
906 node
->pathlen
= grub_snprintf(node
->isopath
, sizeof(node
->isopath
), "%s", path
);
907 grub_snprintf(node
->archive
, sizeof(node
->archive
), "%s", archive
);
909 if (g_injection_head
)
911 node
->next
= g_injection_head
;
914 g_injection_head
= node
;
922 static int ventoy_plugin_menuclass_entry(VTOY_JSON
*json
, const char *isodisk
)
925 const char *key
= NULL
;
926 const char *class = NULL
;
927 VTOY_JSON
*pNode
= NULL
;
928 menu_class
*tail
= NULL
;
929 menu_class
*node
= NULL
;
930 menu_class
*next
= NULL
;
934 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
936 debug("Not array %d\n", json
->enDataType
);
940 if (g_menu_class_head
)
942 for (node
= g_menu_class_head
; node
; node
= next
)
948 g_menu_class_head
= NULL
;
951 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
953 type
= vtoy_class_image_file
;
954 key
= vtoy_json_get_string_ex(pNode
->pstChild
, "key");
957 key
= vtoy_json_get_string_ex(pNode
->pstChild
, "dir");
958 type
= vtoy_class_directory
;
961 class = vtoy_json_get_string_ex(pNode
->pstChild
, "class");
964 node
= grub_zalloc(sizeof(menu_class
));
968 node
->patlen
= grub_snprintf(node
->pattern
, sizeof(node
->pattern
), "%s", key
);
969 grub_snprintf(node
->class, sizeof(node
->class), "%s", class);
971 if (g_menu_class_head
)
977 g_menu_class_head
= node
;
987 static int ventoy_plugin_menuclass_check(VTOY_JSON
*json
, const char *isodisk
)
990 const char *key
= NULL
;
991 const char *class = NULL
;
992 VTOY_JSON
*pNode
= NULL
;
996 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
998 grub_printf("Not array %d\n", json
->enDataType
);
1002 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
1004 type
= vtoy_class_image_file
;
1005 key
= vtoy_json_get_string_ex(pNode
->pstChild
, "key");
1008 key
= vtoy_json_get_string_ex(pNode
->pstChild
, "dir");
1009 type
= vtoy_class_directory
;
1012 class = vtoy_json_get_string_ex(pNode
->pstChild
, "class");
1015 grub_printf("%s: <%s>\n", (type
== vtoy_class_directory
) ? "dir" : "key", key
);
1016 grub_printf("class: <%s>\n\n", class);
1023 static int ventoy_plugin_auto_memdisk_entry(VTOY_JSON
*json
, const char *isodisk
)
1025 VTOY_JSON
*pNode
= NULL
;
1026 auto_memdisk
*node
= NULL
;
1027 auto_memdisk
*next
= NULL
;
1031 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
1033 debug("Not array %d\n", json
->enDataType
);
1037 if (g_auto_memdisk_head
)
1039 for (node
= g_auto_memdisk_head
; node
; node
= next
)
1045 g_auto_memdisk_head
= NULL
;
1048 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
1050 if (pNode
->enDataType
== JSON_TYPE_STRING
)
1052 node
= grub_zalloc(sizeof(auto_memdisk
));
1055 node
->pathlen
= grub_snprintf(node
->isopath
, sizeof(node
->isopath
), "%s", pNode
->unData
.pcStrVal
);
1057 if (g_auto_memdisk_head
)
1059 node
->next
= g_auto_memdisk_head
;
1062 g_auto_memdisk_head
= node
;
1070 static int ventoy_plugin_auto_memdisk_check(VTOY_JSON
*json
, const char *isodisk
)
1072 VTOY_JSON
*pNode
= NULL
;
1074 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
1076 grub_printf("Not array %d\n", json
->enDataType
);
1080 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
1082 if (pNode
->enDataType
== JSON_TYPE_STRING
)
1084 grub_printf("<%s> ", pNode
->unData
.pcStrVal
);
1086 if (ventoy_check_file_exist("%s%s", isodisk
, pNode
->unData
.pcStrVal
))
1088 grub_printf(" [OK]\n");
1092 grub_printf(" [NOT EXIST]\n");
1100 static int ventoy_plugin_image_list_entry(VTOY_JSON
*json
, const char *isodisk
)
1102 VTOY_JSON
*pNode
= NULL
;
1103 image_list
*node
= NULL
;
1104 image_list
*next
= NULL
;
1105 image_list
*tail
= NULL
;
1109 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
1111 debug("Not array %d\n", json
->enDataType
);
1115 if (g_image_list_head
)
1117 for (node
= g_image_list_head
; node
; node
= next
)
1123 g_image_list_head
= NULL
;
1126 g_plugin_image_list
= 1;
1128 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
1130 if (pNode
->enDataType
== JSON_TYPE_STRING
)
1132 node
= grub_zalloc(sizeof(image_list
));
1135 node
->pathlen
= grub_snprintf(node
->isopath
, sizeof(node
->isopath
), "%s", pNode
->unData
.pcStrVal
);
1137 if (g_image_list_head
)
1143 g_image_list_head
= node
;
1153 static int ventoy_plugin_image_list_check(VTOY_JSON
*json
, const char *isodisk
)
1155 VTOY_JSON
*pNode
= NULL
;
1157 if (json
->enDataType
!= JSON_TYPE_ARRAY
)
1159 grub_printf("Not array %d\n", json
->enDataType
);
1163 for (pNode
= json
->pstChild
; pNode
; pNode
= pNode
->pstNext
)
1165 if (pNode
->enDataType
== JSON_TYPE_STRING
)
1167 grub_printf("<%s> ", pNode
->unData
.pcStrVal
);
1169 if (ventoy_check_file_exist("%s%s", isodisk
, pNode
->unData
.pcStrVal
))
1171 grub_printf(" [OK]\n");
1175 grub_printf(" [NOT EXIST]\n");
1183 static plugin_entry g_plugin_entries
[] =
1185 { "control", ventoy_plugin_control_entry
, ventoy_plugin_control_check
},
1186 { "theme", ventoy_plugin_theme_entry
, ventoy_plugin_theme_check
},
1187 #ifdef GRUB_MACHINE_EFI
1188 { "theme_uefi", ventoy_plugin_theme_entry
, ventoy_plugin_theme_check
},
1190 { "theme_legacy", ventoy_plugin_theme_entry
, ventoy_plugin_theme_check
},
1192 { "auto_install", ventoy_plugin_auto_install_entry
, ventoy_plugin_auto_install_check
},
1193 { "persistence", ventoy_plugin_persistence_entry
, ventoy_plugin_persistence_check
},
1194 { "menu_alias", ventoy_plugin_menualias_entry
, ventoy_plugin_menualias_check
},
1195 { "menu_class", ventoy_plugin_menuclass_entry
, ventoy_plugin_menuclass_check
},
1196 { "injection", ventoy_plugin_injection_entry
, ventoy_plugin_injection_check
},
1197 { "auto_memdisk", ventoy_plugin_auto_memdisk_entry
, ventoy_plugin_auto_memdisk_check
},
1198 { "image_list", ventoy_plugin_image_list_entry
, ventoy_plugin_image_list_check
},
1201 static int ventoy_parse_plugin_config(VTOY_JSON
*json
, const char *isodisk
)
1204 VTOY_JSON
*cur
= json
;
1206 grub_snprintf(g_iso_disk_name
, sizeof(g_iso_disk_name
), "%s", isodisk
);
1210 for (i
= 0; i
< (int)ARRAY_SIZE(g_plugin_entries
); i
++)
1212 if (grub_strcmp(g_plugin_entries
[i
].key
, cur
->pcName
) == 0)
1214 debug("Plugin entry for %s\n", g_plugin_entries
[i
].key
);
1215 g_plugin_entries
[i
].entryfunc(cur
, isodisk
);
1226 grub_err_t
ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1231 VTOY_JSON
*json
= NULL
;
1236 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/ventoy/ventoy.json", args
[0]);
1239 return GRUB_ERR_NONE
;
1242 debug("json configuration file size %d\n", (int)file
->size
);
1244 buf
= grub_malloc(file
->size
+ 1);
1247 grub_file_close(file
);
1251 buf
[file
->size
] = 0;
1252 grub_file_read(file
, buf
, file
->size
);
1253 grub_file_close(file
);
1255 json
= vtoy_json_create();
1263 ret
= vtoy_json_parse(json
, buf
);
1266 debug("Failed to parse json string %d\n", ret
);
1271 ventoy_parse_plugin_config(json
->pstChild
, args
[0]);
1273 vtoy_json_destroy(json
);
1277 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1280 void ventoy_plugin_dump_injection(void)
1282 injection_config
*node
= NULL
;
1284 for (node
= g_injection_head
; node
; node
= node
->next
)
1286 grub_printf("\nIMAGE:<%s>\n", node
->isopath
);
1287 grub_printf("ARCHIVE:<%s>\n", node
->archive
);
1294 void ventoy_plugin_dump_auto_install(void)
1297 install_template
*node
= NULL
;
1299 for (node
= g_install_template_head
; node
; node
= node
->next
)
1301 grub_printf("\nIMAGE:<%s> <%d>\n", node
->isopath
, node
->templatenum
);
1302 for (i
= 0; i
< node
->templatenum
; i
++)
1304 grub_printf("SCRIPT %d:<%s>\n", i
, node
->templatepath
[i
].path
);
1311 void ventoy_plugin_dump_persistence(void)
1315 persistence_config
*node
= NULL
;
1316 ventoy_img_chunk_list chunk_list
;
1318 for (node
= g_persistence_head
; node
; node
= node
->next
)
1320 grub_printf("\nIMAGE:<%s> <%d>\n", node
->isopath
, node
->backendnum
);
1322 for (i
= 0; i
< node
->backendnum
; i
++)
1324 grub_printf("PERSIST %d:<%s>", i
, node
->backendpath
[i
].path
);
1325 rc
= ventoy_plugin_get_persistent_chunklist(node
->isopath
, i
, &chunk_list
);
1328 grub_printf(" [ SUCCESS ]\n");
1329 grub_free(chunk_list
.chunk
);
1333 grub_printf(" [ FAILED ]\n");
1341 install_template
* ventoy_plugin_find_install_template(const char *isopath
)
1344 install_template
*node
= NULL
;
1346 if (!g_install_template_head
)
1351 len
= (int)grub_strlen(isopath
);
1352 for (node
= g_install_template_head
; node
; node
= node
->next
)
1354 if (node
->pathlen
== len
&& grub_strcmp(node
->isopath
, isopath
) == 0)
1363 char * ventoy_plugin_get_cur_install_template(const char *isopath
)
1365 install_template
*node
= NULL
;
1367 node
= ventoy_plugin_find_install_template(isopath
);
1368 if ((!node
) || (!node
->templatepath
))
1373 if (node
->cursel
< 0 || node
->cursel
>= node
->templatenum
)
1378 return node
->templatepath
[node
->cursel
].path
;
1381 persistence_config
* ventoy_plugin_find_persistent(const char *isopath
)
1384 persistence_config
*node
= NULL
;
1386 if (!g_persistence_head
)
1391 len
= (int)grub_strlen(isopath
);
1392 for (node
= g_persistence_head
; node
; node
= node
->next
)
1394 if ((len
== node
->pathlen
) && (grub_strcmp(node
->isopath
, isopath
) == 0))
1403 int ventoy_plugin_get_persistent_chunklist(const char *isopath
, int index
, ventoy_img_chunk_list
*chunk_list
)
1406 grub_uint64_t start
= 0;
1407 grub_file_t file
= NULL
;
1408 persistence_config
*node
= NULL
;
1410 node
= ventoy_plugin_find_persistent(isopath
);
1411 if ((!node
) || (!node
->backendpath
))
1418 index
= node
->cursel
;
1421 if (index
< 0 || index
>= node
->backendnum
)
1426 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", g_iso_disk_name
, node
->backendpath
[index
].path
);
1429 debug("Failed to open file %s%s\n", g_iso_disk_name
, node
->backendpath
[index
].path
);
1433 grub_memset(chunk_list
, 0, sizeof(ventoy_img_chunk_list
));
1434 chunk_list
->chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1435 if (NULL
== chunk_list
->chunk
)
1440 chunk_list
->max_chunk
= DEFAULT_CHUNK_NUM
;
1441 chunk_list
->cur_chunk
= 0;
1443 start
= file
->device
->disk
->partition
->start
;
1444 ventoy_get_block_list(file
, chunk_list
, start
);
1446 if (0 != ventoy_check_block_list(file
, chunk_list
, start
))
1448 grub_free(chunk_list
->chunk
);
1449 chunk_list
->chunk
= NULL
;
1457 grub_file_close(file
);
1462 const char * ventoy_plugin_get_injection(const char *isopath
)
1465 injection_config
*node
= NULL
;
1467 if (!g_injection_head
)
1472 len
= (int)grub_strlen(isopath
);
1473 for (node
= g_injection_head
; node
; node
= node
->next
)
1475 if (node
->pathlen
== len
&& grub_strcmp(node
->isopath
, isopath
) == 0)
1477 return node
->archive
;
1484 const char * ventoy_plugin_get_menu_alias(int type
, const char *isopath
)
1487 menu_alias
*node
= NULL
;
1489 if (!g_menu_alias_head
)
1494 len
= (int)grub_strlen(isopath
);
1495 for (node
= g_menu_alias_head
; node
; node
= node
->next
)
1497 if (node
->type
== type
&& node
->pathlen
&&
1498 node
->pathlen
== len
&& grub_strcmp(node
->isopath
, isopath
) == 0)
1507 const char * ventoy_plugin_get_menu_class(int type
, const char *name
)
1510 menu_class
*node
= NULL
;
1512 if (!g_menu_class_head
)
1517 len
= (int)grub_strlen(name
);
1519 if (vtoy_class_image_file
== type
)
1521 for (node
= g_menu_class_head
; node
; node
= node
->next
)
1523 if (node
->type
== type
&& node
->patlen
<= len
&& grub_strstr(name
, node
->pattern
))
1531 for (node
= g_menu_class_head
; node
; node
= node
->next
)
1533 if (node
->type
== type
&& node
->patlen
== len
&& grub_strncmp(name
, node
->pattern
, len
) == 0)
1543 int ventoy_plugin_check_memdisk(const char *isopath
)
1546 auto_memdisk
*node
= NULL
;
1548 if (!g_auto_memdisk_head
)
1553 len
= (int)grub_strlen(isopath
);
1554 for (node
= g_auto_memdisk_head
; node
; node
= node
->next
)
1556 if (node
->pathlen
== len
&& grub_strncmp(isopath
, node
->isopath
, len
) == 0)
1565 int ventoy_plugin_get_image_list_index(int type
, const char *name
)
1569 image_list
*node
= NULL
;
1571 if (!g_image_list_head
)
1576 len
= (int)grub_strlen(name
);
1578 for (node
= g_image_list_head
; node
; node
= node
->next
, index
++)
1580 if (vtoy_class_directory
== type
)
1582 if (len
< node
->pathlen
&& grub_strncmp(name
, node
->isopath
, len
) == 0)
1589 if (len
== node
->pathlen
&& grub_strncmp(name
, node
->isopath
, len
) == 0)
1599 grub_err_t
ventoy_cmd_plugin_check_json(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1605 VTOY_JSON
*node
= NULL
;
1606 VTOY_JSON
*json
= NULL
;
1615 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/ventoy/ventoy.json", args
[0]);
1618 grub_printf("Plugin json file /ventoy/ventoy.json does NOT exist.\n");
1622 buf
= grub_malloc(file
->size
+ 1);
1625 grub_printf("Failed to malloc memory %lu.\n", (ulong
)(file
->size
+ 1));
1629 buf
[file
->size
] = 0;
1630 grub_file_read(file
, buf
, file
->size
);
1632 json
= vtoy_json_create();
1635 grub_printf("Failed to create json\n");
1639 ret
= vtoy_json_parse(json
, buf
);
1642 grub_printf("Syntax error detected in ventoy.json, please check it.\n");
1646 for (node
= json
->pstChild
; node
; node
= node
->pstNext
)
1648 if (grub_strcmp(node
->pcName
, args
[1]) == 0)
1656 grub_printf("%s is NOT found in ventoy.json\n", args
[1]);
1660 for (i
= 0; i
< (int)ARRAY_SIZE(g_plugin_entries
); i
++)
1662 if (grub_strcmp(g_plugin_entries
[i
].key
, args
[1]) == 0)
1664 if (g_plugin_entries
[i
].checkfunc
)
1666 ret
= g_plugin_entries
[i
].checkfunc(node
, args
[2]);
1673 check_free(file
, grub_file_close
);
1674 check_free(json
, vtoy_json_destroy
);
1675 grub_check_free(buf
);