]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c
3c2ae77ee4c5cd4104ee30dc8b54c801e34b364a
[Ventoy.git] / GRUB2 / MOD_SRC / grub-2.04 / grub-core / ventoy / ventoy_plugin.c
1 /******************************************************************************
2 * ventoy_plugin.c
3 *
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20 #include <grub/types.h>
21 #include <grub/misc.h>
22 #include <grub/mm.h>
23 #include <grub/err.h>
24 #include <grub/dl.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>
34 #include <grub/net.h>
35 #include <grub/crypto.h>
36 #include <grub/time.h>
37 #include <grub/font.h>
38 #include <grub/ventoy.h>
39 #include "ventoy_def.h"
40
41 GRUB_MOD_LICENSE ("GPLv3+");
42
43 char g_arch_mode_suffix[64];
44 static char g_iso_disk_name[128];
45 static vtoy_password g_boot_pwd;
46 static vtoy_password g_file_type_pwd[img_type_max];
47 static install_template *g_install_template_head = NULL;
48 static dud *g_dud_head = NULL;
49 static menu_password *g_pwd_head = NULL;
50 static persistence_config *g_persistence_head = NULL;
51 static menu_tip *g_menu_tip_head = NULL;
52 static menu_alias *g_menu_alias_head = NULL;
53 static menu_class *g_menu_class_head = NULL;
54 static custom_boot *g_custom_boot_head = NULL;
55 static injection_config *g_injection_head = NULL;
56 static auto_memdisk *g_auto_memdisk_head = NULL;
57 static image_list *g_image_list_head = NULL;
58 static conf_replace *g_conf_replace_head = NULL;
59 static VTOY_JSON *g_menu_lang_json = NULL;
60
61 static int g_theme_id = 0;
62 static int g_theme_num = 0;
63 static theme_list *g_theme_head = NULL;
64 static int g_theme_random = vtoy_theme_random_boot_second;
65 static char g_theme_single_file[256];
66 static char g_cur_menu_language[32] = {0};
67
68 static int ventoy_plugin_is_parent(const char *pat, int patlen, const char *isopath)
69 {
70 if (patlen > 1)
71 {
72 if (isopath[patlen] == '/' && ventoy_strncmp(pat, isopath, patlen) == 0 &&
73 grub_strchr(isopath + patlen + 1, '/') == NULL)
74 {
75 return 1;
76 }
77 }
78 else
79 {
80 if (pat[0] == '/' && grub_strchr(isopath + 1, '/') == NULL)
81 {
82 return 1;
83 }
84 }
85
86 return 0;
87 }
88
89 static int ventoy_plugin_control_check(VTOY_JSON *json, const char *isodisk)
90 {
91 int rc = 0;
92 VTOY_JSON *pNode = NULL;
93 VTOY_JSON *pChild = NULL;
94
95 (void)isodisk;
96
97 if (json->enDataType != JSON_TYPE_ARRAY)
98 {
99 grub_printf("Not array type %d\n", json->enDataType);
100 return 1;
101 }
102
103 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
104 {
105 if (pNode->enDataType == JSON_TYPE_OBJECT)
106 {
107 pChild = pNode->pstChild;
108 if (pChild->enDataType == JSON_TYPE_STRING)
109 {
110 if (grub_strcmp(pChild->pcName, "VTOY_DEFAULT_IMAGE") == 0)
111 {
112 grub_printf("%s: %s [%s]\n", pChild->pcName, pChild->unData.pcStrVal,
113 ventoy_check_file_exist("%s%s", isodisk, pChild->unData.pcStrVal) ? "OK" : "NOT EXIST");
114 }
115 else
116 {
117 grub_printf("%s: %s\n", pChild->pcName, pChild->unData.pcStrVal);
118 }
119 }
120 else
121 {
122 grub_printf("%s is NOT string type\n", pChild->pcName);
123 rc = 1;
124 }
125 }
126 else
127 {
128 grub_printf("%s is not an object\n", pNode->pcName);
129 rc = 1;
130 }
131 }
132
133 return rc;
134 }
135
136 static int ventoy_plugin_control_entry(VTOY_JSON *json, const char *isodisk)
137 {
138 VTOY_JSON *pNode = NULL;
139 VTOY_JSON *pChild = NULL;
140
141 (void)isodisk;
142
143 if (json->enDataType != JSON_TYPE_ARRAY)
144 {
145 debug("Not array %d\n", json->enDataType);
146 return 0;
147 }
148
149 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
150 {
151 if (pNode->enDataType == JSON_TYPE_OBJECT)
152 {
153 pChild = pNode->pstChild;
154 if (pChild->enDataType == JSON_TYPE_STRING && pChild->pcName && pChild->unData.pcStrVal)
155 {
156 ventoy_set_env(pChild->pcName, pChild->unData.pcStrVal);
157 }
158 }
159 }
160
161 return 0;
162 }
163
164 static int ventoy_plugin_theme_check(VTOY_JSON *json, const char *isodisk)
165 {
166 int exist = 0;
167 const char *value;
168 VTOY_JSON *node;
169
170 value = vtoy_json_get_string_ex(json->pstChild, "file");
171 if (value)
172 {
173 grub_printf("file: %s\n", value);
174 if (value[0] == '/')
175 {
176 exist = ventoy_check_file_exist("%s%s", isodisk, value);
177 }
178 else
179 {
180 exist = ventoy_check_file_exist("%s/ventoy/%s", isodisk, value);
181 }
182
183 if (exist == 0)
184 {
185 grub_printf("Theme file %s does NOT exist\n", value);
186 return 1;
187 }
188 }
189 else
190 {
191 node = vtoy_json_find_item(json->pstChild, JSON_TYPE_ARRAY, "file");
192 if (node)
193 {
194 for (node = node->pstChild; node; node = node->pstNext)
195 {
196 value = node->unData.pcStrVal;
197 grub_printf("file: %s\n", value);
198 if (value[0] == '/')
199 {
200 exist = ventoy_check_file_exist("%s%s", isodisk, value);
201 }
202 else
203 {
204 exist = ventoy_check_file_exist("%s/ventoy/%s", isodisk, value);
205 }
206
207 if (exist == 0)
208 {
209 grub_printf("Theme file %s does NOT exist\n", value);
210 return 1;
211 }
212 }
213
214 value = vtoy_json_get_string_ex(json->pstChild, "random");
215 if (value)
216 {
217 grub_printf("random: %s\n", value);
218 }
219 }
220 }
221
222 value = vtoy_json_get_string_ex(json->pstChild, "gfxmode");
223 if (value)
224 {
225 grub_printf("gfxmode: %s\n", value);
226 }
227
228 value = vtoy_json_get_string_ex(json->pstChild, "display_mode");
229 if (value)
230 {
231 grub_printf("display_mode: %s\n", value);
232 }
233
234 value = vtoy_json_get_string_ex(json->pstChild, "serial_param");
235 if (value)
236 {
237 grub_printf("serial_param %s\n", value);
238 }
239
240 value = vtoy_json_get_string_ex(json->pstChild, "ventoy_left");
241 if (value)
242 {
243 grub_printf("ventoy_left: %s\n", value);
244 }
245
246 value = vtoy_json_get_string_ex(json->pstChild, "ventoy_top");
247 if (value)
248 {
249 grub_printf("ventoy_top: %s\n", value);
250 }
251
252 value = vtoy_json_get_string_ex(json->pstChild, "ventoy_color");
253 if (value)
254 {
255 grub_printf("ventoy_color: %s\n", value);
256 }
257
258 node = vtoy_json_find_item(json->pstChild, JSON_TYPE_ARRAY, "fonts");
259 if (node)
260 {
261 for (node = node->pstChild; node; node = node->pstNext)
262 {
263 if (node->enDataType == JSON_TYPE_STRING)
264 {
265 if (ventoy_check_file_exist("%s%s", isodisk, node->unData.pcStrVal))
266 {
267 grub_printf("%s [OK]\n", node->unData.pcStrVal);
268 }
269 else
270 {
271 grub_printf("%s [NOT EXIST]\n", node->unData.pcStrVal);
272 }
273 }
274 }
275 }
276 else
277 {
278 grub_printf("fonts NOT found\n");
279 }
280
281 return 0;
282 }
283
284 static int ventoy_plugin_theme_entry(VTOY_JSON *json, const char *isodisk)
285 {
286 const char *value;
287 char val[64];
288 char filepath[256];
289 VTOY_JSON *node = NULL;
290 theme_list *tail = NULL;
291 theme_list *themenode = NULL;
292
293 value = vtoy_json_get_string_ex(json->pstChild, "file");
294 if (value)
295 {
296 if (value[0] == '/')
297 {
298 grub_snprintf(filepath, sizeof(filepath), "%s%s", isodisk, value);
299 }
300 else
301 {
302 grub_snprintf(filepath, sizeof(filepath), "%s/ventoy/%s", isodisk, value);
303 }
304
305 if (ventoy_check_file_exist(filepath) == 0)
306 {
307 debug("Theme file %s does not exist\n", filepath);
308 return 0;
309 }
310
311 debug("vtoy_theme %s\n", filepath);
312 ventoy_env_export("vtoy_theme", filepath);
313 grub_snprintf(g_theme_single_file, sizeof(g_theme_single_file), "%s", filepath);
314 }
315 else
316 {
317 node = vtoy_json_find_item(json->pstChild, JSON_TYPE_ARRAY, "file");
318 if (node)
319 {
320 for (node = node->pstChild; node; node = node->pstNext)
321 {
322 value = node->unData.pcStrVal;
323 if (value[0] == '/')
324 {
325 grub_snprintf(filepath, sizeof(filepath), "%s%s", isodisk, value);
326 }
327 else
328 {
329 grub_snprintf(filepath, sizeof(filepath), "%s/ventoy/%s", isodisk, value);
330 }
331
332 if (ventoy_check_file_exist(filepath) == 0)
333 {
334 continue;
335 }
336
337 themenode = grub_zalloc(sizeof(theme_list));
338 if (themenode)
339 {
340 grub_snprintf(themenode->theme.path, sizeof(themenode->theme.path), "%s", filepath);
341 if (g_theme_head)
342 {
343 tail->next = themenode;
344 }
345 else
346 {
347 g_theme_head = themenode;
348 }
349 tail = themenode;
350 g_theme_num++;
351 }
352 }
353
354 ventoy_env_export("vtoy_theme", "random");
355 value = vtoy_json_get_string_ex(json->pstChild, "random");
356 if (value)
357 {
358 if (grub_strcmp(value, "boot_second") == 0)
359 {
360 g_theme_random = vtoy_theme_random_boot_second;
361 }
362 else if (grub_strcmp(value, "boot_day") == 0)
363 {
364 g_theme_random = vtoy_theme_random_boot_day;
365 }
366 else if (grub_strcmp(value, "boot_month") == 0)
367 {
368 g_theme_random = vtoy_theme_random_boot_month;
369 }
370 }
371 }
372 }
373
374 grub_snprintf(val, sizeof(val), "%d", g_theme_num);
375 grub_env_set("VTOY_THEME_COUNT", val);
376 grub_env_export("VTOY_THEME_COUNT");
377 if (g_theme_num > 0)
378 {
379 vtoy_json_get_int(json->pstChild, "default_file", &g_theme_id);
380 if (g_theme_id > g_theme_num || g_theme_id < 0)
381 {
382 g_theme_id = 0;
383 }
384 }
385
386 value = vtoy_json_get_string_ex(json->pstChild, "gfxmode");
387 if (value)
388 {
389 debug("vtoy_gfxmode %s\n", value);
390 ventoy_env_export("vtoy_gfxmode", value);
391 }
392
393 value = vtoy_json_get_string_ex(json->pstChild, "display_mode");
394 if (value)
395 {
396 debug("display_mode %s\n", value);
397 ventoy_env_export("vtoy_display_mode", value);
398 }
399
400 value = vtoy_json_get_string_ex(json->pstChild, "serial_param");
401 if (value)
402 {
403 debug("serial_param %s\n", value);
404 ventoy_env_export("vtoy_serial_param", value);
405 }
406
407 value = vtoy_json_get_string_ex(json->pstChild, "ventoy_left");
408 if (value)
409 {
410 ventoy_env_export("VTLE_LFT", value);
411 }
412
413 value = vtoy_json_get_string_ex(json->pstChild, "ventoy_top");
414 if (value)
415 {
416 ventoy_env_export("VTLE_TOP", value);
417 }
418
419 value = vtoy_json_get_string_ex(json->pstChild, "ventoy_color");
420 if (value)
421 {
422 ventoy_env_export("VTLE_CLR", value);
423 }
424
425 node = vtoy_json_find_item(json->pstChild, JSON_TYPE_ARRAY, "fonts");
426 if (node)
427 {
428 for (node = node->pstChild; node; node = node->pstNext)
429 {
430 if (node->enDataType == JSON_TYPE_STRING &&
431 ventoy_check_file_exist("%s%s", isodisk, node->unData.pcStrVal))
432 {
433 grub_snprintf(filepath, sizeof(filepath), "%s%s", isodisk, node->unData.pcStrVal);
434 grub_font_load(filepath);
435 }
436 }
437 }
438
439 return 0;
440 }
441
442 static int ventoy_plugin_check_path(const char *path, const char *file)
443 {
444 if (file[0] != '/')
445 {
446 grub_printf("%s is NOT begin with '/' \n", file);
447 return 1;
448 }
449
450 if (grub_strchr(file, '\\'))
451 {
452 grub_printf("%s contains invalid '\\' \n", file);
453 return 1;
454 }
455
456 if (grub_strstr(file, "//"))
457 {
458 grub_printf("%s contains invalid double slash\n", file);
459 return 1;
460 }
461
462 if (grub_strstr(file, "../"))
463 {
464 grub_printf("%s contains invalid '../' \n", file);
465 return 1;
466 }
467
468 if (!ventoy_check_file_exist("%s%s", path, file))
469 {
470 grub_printf("%s%s does NOT exist\n", path, file);
471 return 1;
472 }
473
474 return 0;
475 }
476
477 static int ventoy_plugin_check_fullpath
478 (
479 VTOY_JSON *json,
480 const char *isodisk,
481 const char *key,
482 int *pathnum
483 )
484 {
485 int rc = 0;
486 int ret = 0;
487 int cnt = 0;
488 VTOY_JSON *node = json;
489 VTOY_JSON *child = NULL;
490
491 while (node)
492 {
493 if (0 == grub_strcmp(key, node->pcName))
494 {
495 break;
496 }
497 node = node->pstNext;
498 }
499
500 if (!node)
501 {
502 return 1;
503 }
504
505 if (JSON_TYPE_STRING == node->enDataType)
506 {
507 cnt = 1;
508 ret = ventoy_plugin_check_path(isodisk, node->unData.pcStrVal);
509 grub_printf("%s: %s [%s]\n", key, node->unData.pcStrVal, ret ? "FAIL" : "OK");
510 }
511 else if (JSON_TYPE_ARRAY == node->enDataType)
512 {
513 for (child = node->pstChild; child; child = child->pstNext)
514 {
515 if (JSON_TYPE_STRING != child->enDataType)
516 {
517 grub_printf("Non string json type\n");
518 }
519 else
520 {
521 rc = ventoy_plugin_check_path(isodisk, child->unData.pcStrVal);
522 grub_printf("%s: %s [%s]\n", key, child->unData.pcStrVal, rc ? "FAIL" : "OK");
523 ret += rc;
524 cnt++;
525 }
526 }
527 }
528
529 *pathnum = cnt;
530 return ret;
531 }
532
533 static int ventoy_plugin_parse_fullpath
534 (
535 VTOY_JSON *json,
536 const char *isodisk,
537 const char *key,
538 file_fullpath **fullpath,
539 int *pathnum
540 )
541 {
542 int rc = 1;
543 int count = 0;
544 VTOY_JSON *node = json;
545 VTOY_JSON *child = NULL;
546 file_fullpath *path = NULL;
547
548 while (node)
549 {
550 if (0 == grub_strcmp(key, node->pcName))
551 {
552 break;
553 }
554 node = node->pstNext;
555 }
556
557 if (!node)
558 {
559 return 1;
560 }
561
562 if (JSON_TYPE_STRING == node->enDataType)
563 {
564 debug("%s is string type data\n", node->pcName);
565
566 if ((node->unData.pcStrVal[0] != '/') || (!ventoy_check_file_exist("%s%s", isodisk, node->unData.pcStrVal)))
567 {
568 debug("%s%s file not found\n", isodisk, node->unData.pcStrVal);
569 return 1;
570 }
571
572 path = (file_fullpath *)grub_zalloc(sizeof(file_fullpath));
573 if (path)
574 {
575 grub_snprintf(path->path, sizeof(path->path), "%s", node->unData.pcStrVal);
576 *fullpath = path;
577 *pathnum = 1;
578 rc = 0;
579 }
580 }
581 else if (JSON_TYPE_ARRAY == node->enDataType)
582 {
583 for (child = node->pstChild; child; child = child->pstNext)
584 {
585 if ((JSON_TYPE_STRING != child->enDataType) || (child->unData.pcStrVal[0] != '/'))
586 {
587 debug("Invalid data type:%d\n", child->enDataType);
588 return 1;
589 }
590 count++;
591 }
592 debug("%s is array type data, count=%d\n", node->pcName, count);
593
594 path = (file_fullpath *)grub_zalloc(sizeof(file_fullpath) * count);
595 if (path)
596 {
597 *fullpath = path;
598
599 for (count = 0, child = node->pstChild; child; child = child->pstNext)
600 {
601 if (ventoy_check_file_exist("%s%s", isodisk, child->unData.pcStrVal))
602 {
603 grub_snprintf(path->path, sizeof(path->path), "%s", child->unData.pcStrVal);
604 path++;
605 count++;
606 }
607 }
608
609 *pathnum = count;
610 rc = 0;
611 }
612 }
613
614 return rc;
615 }
616
617 static int ventoy_plugin_auto_install_check(VTOY_JSON *json, const char *isodisk)
618 {
619 int pathnum = 0;
620 int autosel = 0;
621 int timeout = 0;
622 char *pos = NULL;
623 const char *iso = NULL;
624 VTOY_JSON *pNode = NULL;
625
626 if (json->enDataType != JSON_TYPE_ARRAY)
627 {
628 grub_printf("Not array type %d\n", json->enDataType);
629 return 1;
630 }
631
632 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
633 {
634 if (pNode->enDataType != JSON_TYPE_OBJECT)
635 {
636 grub_printf("NOT object type\n");
637 }
638
639 if ((iso = vtoy_json_get_string_ex(pNode->pstChild, "image")) != NULL)
640 {
641 pos = grub_strchr(iso, '*');
642 if (pos || 0 == ventoy_plugin_check_path(isodisk, iso))
643 {
644 grub_printf("image: %s [%s]\n", iso, (pos ? "*" : "OK"));
645 ventoy_plugin_check_fullpath(pNode->pstChild, isodisk, "template", &pathnum);
646
647 if (JSON_SUCCESS == vtoy_json_get_int(pNode->pstChild, "autosel", &autosel))
648 {
649 if (autosel >= 0 && autosel <= pathnum)
650 {
651 grub_printf("autosel: %d [OK]\n", autosel);
652 }
653 else
654 {
655 grub_printf("autosel: %d [FAIL]\n", autosel);
656 }
657 }
658
659 if (JSON_SUCCESS == vtoy_json_get_int(pNode->pstChild, "timeout", &timeout))
660 {
661 if (timeout >= 0)
662 {
663 grub_printf("timeout: %d [OK]\n", timeout);
664 }
665 else
666 {
667 grub_printf("timeout: %d [FAIL]\n", timeout);
668 }
669 }
670 }
671 else
672 {
673 grub_printf("image: %s [FAIL]\n", iso);
674 }
675 }
676 else if ((iso = vtoy_json_get_string_ex(pNode->pstChild, "parent")) != NULL)
677 {
678 if (ventoy_is_dir_exist("%s%s", isodisk, iso))
679 {
680 grub_printf("parent: %s [OK]\n", iso);
681 ventoy_plugin_check_fullpath(pNode->pstChild, isodisk, "template", &pathnum);
682
683 if (JSON_SUCCESS == vtoy_json_get_int(pNode->pstChild, "autosel", &autosel))
684 {
685 if (autosel >= 0 && autosel <= pathnum)
686 {
687 grub_printf("autosel: %d [OK]\n", autosel);
688 }
689 else
690 {
691 grub_printf("autosel: %d [FAIL]\n", autosel);
692 }
693 }
694
695 if (JSON_SUCCESS == vtoy_json_get_int(pNode->pstChild, "timeout", &timeout))
696 {
697 if (timeout >= 0)
698 {
699 grub_printf("timeout: %d [OK]\n", timeout);
700 }
701 else
702 {
703 grub_printf("timeout: %d [FAIL]\n", timeout);
704 }
705 }
706 }
707 else
708 {
709 grub_printf("parent: %s [FAIL]\n", iso);
710 }
711 }
712 else
713 {
714 grub_printf("image not found\n");
715 }
716 }
717
718 return 0;
719 }
720
721 static int ventoy_plugin_auto_install_entry(VTOY_JSON *json, const char *isodisk)
722 {
723 int type = 0;
724 int pathnum = 0;
725 int autosel = 0;
726 int timeout = 0;
727 const char *iso = NULL;
728 VTOY_JSON *pNode = NULL;
729 install_template *node = NULL;
730 install_template *next = NULL;
731 file_fullpath *templatepath = NULL;
732
733 if (json->enDataType != JSON_TYPE_ARRAY)
734 {
735 debug("Not array %d\n", json->enDataType);
736 return 0;
737 }
738
739 if (g_install_template_head)
740 {
741 for (node = g_install_template_head; node; node = next)
742 {
743 next = node->next;
744 grub_check_free(node->templatepath);
745 grub_free(node);
746 }
747
748 g_install_template_head = NULL;
749 }
750
751 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
752 {
753 type = auto_install_type_file;
754 iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
755 if (!iso)
756 {
757 type = auto_install_type_parent;
758 iso = vtoy_json_get_string_ex(pNode->pstChild, "parent");
759 }
760
761 if (iso && iso[0] == '/')
762 {
763 if (0 == ventoy_plugin_parse_fullpath(pNode->pstChild, isodisk, "template", &templatepath, &pathnum))
764 {
765 node = grub_zalloc(sizeof(install_template));
766 if (node)
767 {
768 node->type = type;
769 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", iso);
770 node->templatepath = templatepath;
771 node->templatenum = pathnum;
772
773 node->autosel = -1;
774 node->timeout = -1;
775 if (JSON_SUCCESS == vtoy_json_get_int(pNode->pstChild, "autosel", &autosel))
776 {
777 if (autosel >= 0 && autosel <= pathnum)
778 {
779 node->autosel = autosel;
780 }
781 }
782
783 if (JSON_SUCCESS == vtoy_json_get_int(pNode->pstChild, "timeout", &timeout))
784 {
785 if (timeout >= 0)
786 {
787 node->timeout = timeout;
788 }
789 }
790
791 if (g_install_template_head)
792 {
793 node->next = g_install_template_head;
794 }
795
796 g_install_template_head = node;
797 }
798 }
799 }
800 }
801
802 return 0;
803 }
804
805 static int ventoy_plugin_dud_check(VTOY_JSON *json, const char *isodisk)
806 {
807 int pathnum = 0;
808 char *pos = NULL;
809 const char *iso = NULL;
810 VTOY_JSON *pNode = NULL;
811
812 if (json->enDataType != JSON_TYPE_ARRAY)
813 {
814 grub_printf("Not array type %d\n", json->enDataType);
815 return 1;
816 }
817
818 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
819 {
820 if (pNode->enDataType != JSON_TYPE_OBJECT)
821 {
822 grub_printf("NOT object type\n");
823 }
824
825 iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
826 if (iso)
827 {
828 pos = grub_strchr(iso, '*');
829 if (pos || 0 == ventoy_plugin_check_path(isodisk, iso))
830 {
831 grub_printf("image: %s [%s]\n", iso, (pos ? "*" : "OK"));
832 ventoy_plugin_check_fullpath(pNode->pstChild, isodisk, "dud", &pathnum);
833 }
834 else
835 {
836 grub_printf("image: %s [FAIL]\n", iso);
837 }
838 }
839 else
840 {
841 grub_printf("image not found\n");
842 }
843 }
844
845 return 0;
846 }
847
848 static int ventoy_plugin_dud_entry(VTOY_JSON *json, const char *isodisk)
849 {
850 int pathnum = 0;
851 const char *iso = NULL;
852 VTOY_JSON *pNode = NULL;
853 dud *node = NULL;
854 dud *next = NULL;
855 file_fullpath *dudpath = NULL;
856
857 if (json->enDataType != JSON_TYPE_ARRAY)
858 {
859 debug("Not array %d\n", json->enDataType);
860 return 0;
861 }
862
863 if (g_dud_head)
864 {
865 for (node = g_dud_head; node; node = next)
866 {
867 next = node->next;
868 grub_check_free(node->dudpath);
869 grub_free(node);
870 }
871
872 g_dud_head = NULL;
873 }
874
875 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
876 {
877 iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
878 if (iso && iso[0] == '/')
879 {
880 if (0 == ventoy_plugin_parse_fullpath(pNode->pstChild, isodisk, "dud", &dudpath, &pathnum))
881 {
882 node = grub_zalloc(sizeof(dud));
883 if (node)
884 {
885 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", iso);
886 node->dudpath = dudpath;
887 node->dudnum = pathnum;
888 node->files = grub_zalloc(sizeof(dudfile) * pathnum);
889
890 if (node->files)
891 {
892 if (g_dud_head)
893 {
894 node->next = g_dud_head;
895 }
896
897 g_dud_head = node;
898 }
899 else
900 {
901 grub_free(node);
902 }
903 }
904 }
905 }
906 }
907
908 return 0;
909 }
910
911 static int ventoy_plugin_parse_pwdstr(char *pwdstr, vtoy_password *pwd)
912 {
913 int i;
914 int len;
915 char ch;
916 char *pos;
917 char bytes[3];
918 vtoy_password tmpPwd;
919
920 len = (int)grub_strlen(pwdstr);
921 if (len > 64)
922 {
923 if (NULL == pwd) grub_printf("Password too long %d\n", len);
924 return 1;
925 }
926
927 grub_memset(&tmpPwd, 0, sizeof(tmpPwd));
928
929 if (grub_strncmp(pwdstr, "txt#", 4) == 0)
930 {
931 tmpPwd.type = VTOY_PASSWORD_TXT;
932 grub_snprintf(tmpPwd.text, sizeof(tmpPwd.text), "%s", pwdstr + 4);
933 }
934 else if (grub_strncmp(pwdstr, "md5#", 4) == 0)
935 {
936 if ((len - 4) == 32)
937 {
938 for (i = 0; i < 16; i++)
939 {
940 bytes[0] = pwdstr[4 + i * 2];
941 bytes[1] = pwdstr[4 + i * 2 + 1];
942 bytes[2] = 0;
943
944 if (grub_isxdigit(bytes[0]) && grub_isxdigit(bytes[1]))
945 {
946 tmpPwd.md5[i] = (grub_uint8_t)grub_strtoul(bytes, NULL, 16);
947 }
948 else
949 {
950 if (NULL == pwd) grub_printf("Invalid md5 hex format %s %d\n", pwdstr, i);
951 return 1;
952 }
953 }
954 tmpPwd.type = VTOY_PASSWORD_MD5;
955 }
956 else if ((len - 4) > 32)
957 {
958 pos = grub_strchr(pwdstr + 4, '#');
959 if (!pos)
960 {
961 if (NULL == pwd) grub_printf("Invalid md5 password format %s\n", pwdstr);
962 return 1;
963 }
964
965 if (len - 1 - ((long)pos - (long)pwdstr) != 32)
966 {
967 if (NULL == pwd) grub_printf("Invalid md5 salt password format %s\n", pwdstr);
968 return 1;
969 }
970
971 ch = *pos;
972 *pos = 0;
973 grub_snprintf(tmpPwd.salt, sizeof(tmpPwd.salt), "%s", pwdstr + 4);
974 *pos = ch;
975
976 pos++;
977 for (i = 0; i < 16; i++)
978 {
979 bytes[0] = pos[i * 2];
980 bytes[1] = pos[i * 2 + 1];
981 bytes[2] = 0;
982
983 if (grub_isxdigit(bytes[0]) && grub_isxdigit(bytes[1]))
984 {
985 tmpPwd.md5[i] = (grub_uint8_t)grub_strtoul(bytes, NULL, 16);
986 }
987 else
988 {
989 if (NULL == pwd) grub_printf("Invalid md5 hex format %s %d\n", pwdstr, i);
990 return 1;
991 }
992 }
993
994 tmpPwd.type = VTOY_PASSWORD_SALT_MD5;
995 }
996 else
997 {
998 if (NULL == pwd) grub_printf("Invalid md5 password format %s\n", pwdstr);
999 return 1;
1000 }
1001 }
1002 else
1003 {
1004 if (NULL == pwd) grub_printf("Invalid password format %s\n", pwdstr);
1005 return 1;
1006 }
1007
1008 if (pwd)
1009 {
1010 grub_memcpy(pwd, &tmpPwd, sizeof(tmpPwd));
1011 }
1012
1013 return 0;
1014 }
1015
1016 static int ventoy_plugin_get_pwd_type(const char *pwd)
1017 {
1018 int i;
1019 char pwdtype[64];
1020
1021 for (i = 0; pwd && i < (int)ARRAY_SIZE(g_menu_prefix); i++)
1022 {
1023 grub_snprintf(pwdtype, sizeof(pwdtype), "%spwd", g_menu_prefix[i]);
1024 if (grub_strcmp(pwdtype, pwd) == 0)
1025 {
1026 return img_type_start + i;
1027 }
1028 }
1029
1030 return -1;
1031 }
1032
1033 static int ventoy_plugin_pwd_entry(VTOY_JSON *json, const char *isodisk)
1034 {
1035 int type = -1;
1036 const char *iso = NULL;
1037 const char *pwd = NULL;
1038 VTOY_JSON *pNode = NULL;
1039 VTOY_JSON *pCNode = NULL;
1040 menu_password *node = NULL;
1041 menu_password *tail = NULL;
1042 menu_password *next = NULL;
1043
1044 (void)isodisk;
1045
1046 if (json->enDataType != JSON_TYPE_OBJECT)
1047 {
1048 debug("Not object %d\n", json->enDataType);
1049 return 0;
1050 }
1051
1052 if (g_pwd_head)
1053 {
1054 for (node = g_pwd_head; node; node = next)
1055 {
1056 next = node->next;
1057 grub_free(node);
1058 }
1059
1060 g_pwd_head = NULL;
1061 }
1062
1063 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1064 {
1065 if (pNode->pcName && grub_strcmp("bootpwd", pNode->pcName) == 0)
1066 {
1067 ventoy_plugin_parse_pwdstr(pNode->unData.pcStrVal, &g_boot_pwd);
1068 }
1069 else if ((type = ventoy_plugin_get_pwd_type(pNode->pcName)) >= 0)
1070 {
1071 ventoy_plugin_parse_pwdstr(pNode->unData.pcStrVal, g_file_type_pwd + type);
1072 }
1073 else if (pNode->pcName && grub_strcmp("menupwd", pNode->pcName) == 0)
1074 {
1075 for (pCNode = pNode->pstChild; pCNode; pCNode = pCNode->pstNext)
1076 {
1077 if (pCNode->enDataType != JSON_TYPE_OBJECT)
1078 {
1079 continue;
1080 }
1081
1082 type = vtoy_menu_pwd_file;
1083 iso = vtoy_json_get_string_ex(pCNode->pstChild, "file");
1084 if (!iso)
1085 {
1086 type = vtoy_menu_pwd_parent;
1087 iso = vtoy_json_get_string_ex(pCNode->pstChild, "parent");
1088 }
1089
1090 pwd = vtoy_json_get_string_ex(pCNode->pstChild, "pwd");
1091 if (iso && pwd && iso[0] == '/')
1092 {
1093 node = grub_zalloc(sizeof(menu_password));
1094 if (node)
1095 {
1096 node->type = type;
1097 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", iso);
1098
1099 if (ventoy_plugin_parse_pwdstr((char *)pwd, &(node->password)))
1100 {
1101 grub_free(node);
1102 continue;
1103 }
1104
1105 if (g_pwd_head)
1106 {
1107 tail->next = node;
1108 }
1109 else
1110 {
1111 g_pwd_head = node;
1112 }
1113 tail = node;
1114 }
1115 }
1116 }
1117 }
1118 }
1119
1120 return 0;
1121 }
1122
1123 static int ventoy_plugin_pwd_check(VTOY_JSON *json, const char *isodisk)
1124 {
1125 int type = -1;
1126 char *pos = NULL;
1127 const char *iso = NULL;
1128 const char *pwd = NULL;
1129 VTOY_JSON *pNode = NULL;
1130 VTOY_JSON *pCNode = NULL;
1131
1132 if (json->enDataType != JSON_TYPE_OBJECT)
1133 {
1134 grub_printf("Not object %d\n", json->enDataType);
1135 return 0;
1136 }
1137
1138 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1139 {
1140 if (pNode->pcName && grub_strcmp("bootpwd", pNode->pcName) == 0)
1141 {
1142 if (0 == ventoy_plugin_parse_pwdstr(pNode->unData.pcStrVal, NULL))
1143 {
1144 grub_printf("bootpwd:<%s>\n", pNode->unData.pcStrVal);
1145 }
1146 else
1147 {
1148 grub_printf("Invalid bootpwd.\n");
1149 }
1150 }
1151 else if ((type = ventoy_plugin_get_pwd_type(pNode->pcName)) >= 0)
1152 {
1153 if (0 == ventoy_plugin_parse_pwdstr(pNode->unData.pcStrVal, NULL))
1154 {
1155 grub_printf("%s:<%s>\n", pNode->pcName, pNode->unData.pcStrVal);
1156 }
1157 else
1158 {
1159 grub_printf("Invalid pwd <%s>\n", pNode->unData.pcStrVal);
1160 }
1161 }
1162 else if (pNode->pcName && grub_strcmp("menupwd", pNode->pcName) == 0)
1163 {
1164 grub_printf("\n");
1165 for (pCNode = pNode->pstChild; pCNode; pCNode = pCNode->pstNext)
1166 {
1167 if (pCNode->enDataType != JSON_TYPE_OBJECT)
1168 {
1169 grub_printf("Not object %d\n", pCNode->enDataType);
1170 continue;
1171 }
1172
1173 if ((iso = vtoy_json_get_string_ex(pCNode->pstChild, "file")) != NULL)
1174 {
1175 pos = grub_strchr(iso, '*');
1176 if (pos || 0 == ventoy_plugin_check_path(isodisk, iso))
1177 {
1178 pwd = vtoy_json_get_string_ex(pCNode->pstChild, "pwd");
1179
1180 if (0 == ventoy_plugin_parse_pwdstr((char *)pwd, NULL))
1181 {
1182 grub_printf("file:<%s> [%s]\n", iso, (pos ? "*" : "OK"));
1183 grub_printf("pwd:<%s>\n\n", pwd);
1184 }
1185 else
1186 {
1187 grub_printf("Invalid password for <%s>\n", iso);
1188 }
1189 }
1190 else
1191 {
1192 grub_printf("<%s%s> not found\n", isodisk, iso);
1193 }
1194 }
1195 else if ((iso = vtoy_json_get_string_ex(pCNode->pstChild, "parent")) != NULL)
1196 {
1197 if (ventoy_is_dir_exist("%s%s", isodisk, iso))
1198 {
1199 pwd = vtoy_json_get_string_ex(pCNode->pstChild, "pwd");
1200 if (0 == ventoy_plugin_parse_pwdstr((char *)pwd, NULL))
1201 {
1202 grub_printf("dir:<%s> [%s]\n", iso, (pos ? "*" : "OK"));
1203 grub_printf("pwd:<%s>\n\n", pwd);
1204 }
1205 else
1206 {
1207 grub_printf("Invalid password for <%s>\n", iso);
1208 }
1209 }
1210 else
1211 {
1212 grub_printf("<%s%s> not found\n", isodisk, iso);
1213 }
1214 }
1215 else
1216 {
1217 grub_printf("No file item found in json.\n");
1218 }
1219 }
1220 }
1221 }
1222
1223 return 0;
1224 }
1225
1226 static int ventoy_plugin_persistence_check(VTOY_JSON *json, const char *isodisk)
1227 {
1228 int autosel = 0;
1229 int timeout = 0;
1230 int pathnum = 0;
1231 char *pos = NULL;
1232 const char *iso = NULL;
1233 VTOY_JSON *pNode = NULL;
1234
1235 if (json->enDataType != JSON_TYPE_ARRAY)
1236 {
1237 grub_printf("Not array type %d\n", json->enDataType);
1238 return 1;
1239 }
1240
1241 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1242 {
1243 if (pNode->enDataType != JSON_TYPE_OBJECT)
1244 {
1245 grub_printf("NOT object type\n");
1246 }
1247
1248 iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
1249 if (iso)
1250 {
1251 pos = grub_strchr(iso, '*');
1252 if (pos || 0 == ventoy_plugin_check_path(isodisk, iso))
1253 {
1254 grub_printf("image: %s [%s]\n", iso, (pos ? "*" : "OK"));
1255 ventoy_plugin_check_fullpath(pNode->pstChild, isodisk, "backend", &pathnum);
1256
1257 if (JSON_SUCCESS == vtoy_json_get_int(pNode->pstChild, "autosel", &autosel))
1258 {
1259 if (autosel >= 0 && autosel <= pathnum)
1260 {
1261 grub_printf("autosel: %d [OK]\n", autosel);
1262 }
1263 else
1264 {
1265 grub_printf("autosel: %d [FAIL]\n", autosel);
1266 }
1267 }
1268
1269 if (JSON_SUCCESS == vtoy_json_get_int(pNode->pstChild, "timeout", &timeout))
1270 {
1271 if (timeout >= 0)
1272 {
1273 grub_printf("timeout: %d [OK]\n", timeout);
1274 }
1275 else
1276 {
1277 grub_printf("timeout: %d [FAIL]\n", timeout);
1278 }
1279 }
1280 }
1281 else
1282 {
1283 grub_printf("image: %s [FAIL]\n", iso);
1284 }
1285 }
1286 else
1287 {
1288 grub_printf("image not found\n");
1289 }
1290 }
1291
1292 return 0;
1293 }
1294
1295 static int ventoy_plugin_persistence_entry(VTOY_JSON *json, const char *isodisk)
1296 {
1297 int autosel = 0;
1298 int timeout = 0;
1299 int pathnum = 0;
1300 const char *iso = NULL;
1301 VTOY_JSON *pNode = NULL;
1302 persistence_config *node = NULL;
1303 persistence_config *next = NULL;
1304 file_fullpath *backendpath = NULL;
1305
1306 (void)isodisk;
1307
1308 if (json->enDataType != JSON_TYPE_ARRAY)
1309 {
1310 debug("Not array %d\n", json->enDataType);
1311 return 0;
1312 }
1313
1314 if (g_persistence_head)
1315 {
1316 for (node = g_persistence_head; node; node = next)
1317 {
1318 next = node->next;
1319 grub_check_free(node->backendpath);
1320 grub_free(node);
1321 }
1322
1323 g_persistence_head = NULL;
1324 }
1325
1326 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1327 {
1328 iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
1329 if (iso && iso[0] == '/')
1330 {
1331 if (0 == ventoy_plugin_parse_fullpath(pNode->pstChild, isodisk, "backend", &backendpath, &pathnum))
1332 {
1333 node = grub_zalloc(sizeof(persistence_config));
1334 if (node)
1335 {
1336 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", iso);
1337 node->backendpath = backendpath;
1338 node->backendnum = pathnum;
1339
1340 node->autosel = -1;
1341 node->timeout = -1;
1342 if (JSON_SUCCESS == vtoy_json_get_int(pNode->pstChild, "autosel", &autosel))
1343 {
1344 if (autosel >= 0 && autosel <= pathnum)
1345 {
1346 node->autosel = autosel;
1347 }
1348 }
1349
1350 if (JSON_SUCCESS == vtoy_json_get_int(pNode->pstChild, "timeout", &timeout))
1351 {
1352 if (timeout >= 0)
1353 {
1354 node->timeout = timeout;
1355 }
1356 }
1357
1358 if (g_persistence_head)
1359 {
1360 node->next = g_persistence_head;
1361 }
1362
1363 g_persistence_head = node;
1364 }
1365 }
1366 }
1367 }
1368
1369 return 0;
1370 }
1371
1372 static int ventoy_plugin_menualias_check(VTOY_JSON *json, const char *isodisk)
1373 {
1374 int type;
1375 const char *path = NULL;
1376 const char *alias = NULL;
1377 VTOY_JSON *pNode = NULL;
1378
1379 (void)isodisk;
1380
1381 if (json->enDataType != JSON_TYPE_ARRAY)
1382 {
1383 grub_printf("Not array %d\n", json->enDataType);
1384 return 1;
1385 }
1386
1387 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1388 {
1389 type = vtoy_alias_image_file;
1390 path = vtoy_json_get_string_ex(pNode->pstChild, "image");
1391 if (!path)
1392 {
1393 path = vtoy_json_get_string_ex(pNode->pstChild, "dir");
1394 type = vtoy_alias_directory;
1395 }
1396
1397 alias = vtoy_json_get_string_ex(pNode->pstChild, "alias");
1398 if (path && path[0] == '/' && alias)
1399 {
1400 if (vtoy_alias_image_file == type)
1401 {
1402 if (grub_strchr(path, '*'))
1403 {
1404 grub_printf("image: <%s> [ * ]\n", path);
1405 }
1406 else if (ventoy_check_file_exist("%s%s", isodisk, path))
1407 {
1408 grub_printf("image: <%s> [ OK ]\n", path);
1409 }
1410 else
1411 {
1412 grub_printf("image: <%s> [ NOT EXIST ]\n", path);
1413 }
1414 }
1415 else
1416 {
1417 if (ventoy_is_dir_exist("%s%s", isodisk, path))
1418 {
1419 grub_printf("dir: <%s> [ OK ]\n", path);
1420 }
1421 else
1422 {
1423 grub_printf("dir: <%s> [ NOT EXIST ]\n", path);
1424 }
1425 }
1426
1427 grub_printf("alias: <%s>\n\n", alias);
1428 }
1429 }
1430
1431 return 0;
1432 }
1433
1434 static int ventoy_plugin_menualias_entry(VTOY_JSON *json, const char *isodisk)
1435 {
1436 int type;
1437 const char *path = NULL;
1438 const char *alias = NULL;
1439 VTOY_JSON *pNode = NULL;
1440 menu_alias *node = NULL;
1441 menu_alias *next = NULL;
1442
1443 (void)isodisk;
1444
1445 if (json->enDataType != JSON_TYPE_ARRAY)
1446 {
1447 debug("Not array %d\n", json->enDataType);
1448 return 0;
1449 }
1450
1451 if (g_menu_alias_head)
1452 {
1453 for (node = g_menu_alias_head; node; node = next)
1454 {
1455 next = node->next;
1456 grub_free(node);
1457 }
1458
1459 g_menu_alias_head = NULL;
1460 }
1461
1462 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1463 {
1464 type = vtoy_alias_image_file;
1465 path = vtoy_json_get_string_ex(pNode->pstChild, "image");
1466 if (!path)
1467 {
1468 path = vtoy_json_get_string_ex(pNode->pstChild, "dir");
1469 type = vtoy_alias_directory;
1470 }
1471
1472 alias = vtoy_json_get_string_ex(pNode->pstChild, "alias");
1473 if (path && path[0] == '/' && alias)
1474 {
1475 node = grub_zalloc(sizeof(menu_alias));
1476 if (node)
1477 {
1478 node->type = type;
1479 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", path);
1480 grub_snprintf(node->alias, sizeof(node->alias), "%s", alias);
1481
1482 if (g_menu_alias_head)
1483 {
1484 node->next = g_menu_alias_head;
1485 }
1486
1487 g_menu_alias_head = node;
1488 }
1489 }
1490 }
1491
1492 return 0;
1493 }
1494
1495 static int ventoy_plugin_menutip_check(VTOY_JSON *json, const char *isodisk)
1496 {
1497 int type;
1498 const char *path = NULL;
1499 const char *tip = NULL;
1500 VTOY_JSON *pNode = NULL;
1501
1502 (void)isodisk;
1503
1504 if (json->enDataType != JSON_TYPE_OBJECT)
1505 {
1506 grub_printf("Not object %d\n", json->enDataType);
1507 return 1;
1508 }
1509
1510 tip = vtoy_json_get_string_ex(json->pstChild, "left");
1511 if (tip)
1512 {
1513 grub_printf("left: <%s>\n", tip);
1514 }
1515
1516 tip = vtoy_json_get_string_ex(json->pstChild, "top");
1517 if (tip)
1518 {
1519 grub_printf("top: <%s>\n", tip);
1520 }
1521
1522 tip = vtoy_json_get_string_ex(json->pstChild, "color");
1523 if (tip)
1524 {
1525 grub_printf("color: <%s>\n", tip);
1526 }
1527
1528 pNode = vtoy_json_find_item(json->pstChild, JSON_TYPE_ARRAY, "tips");
1529 for (pNode = pNode->pstChild; pNode; pNode = pNode->pstNext)
1530 {
1531 type = vtoy_tip_image_file;
1532 path = vtoy_json_get_string_ex(pNode->pstChild, "image");
1533 if (!path)
1534 {
1535 path = vtoy_json_get_string_ex(pNode->pstChild, "dir");
1536 type = vtoy_tip_directory;
1537 }
1538
1539 if (path && path[0] == '/')
1540 {
1541 if (vtoy_tip_image_file == type)
1542 {
1543 if (grub_strchr(path, '*'))
1544 {
1545 grub_printf("image: <%s> [ * ]\n", path);
1546 }
1547 else if (ventoy_check_file_exist("%s%s", isodisk, path))
1548 {
1549 grub_printf("image: <%s> [ OK ]\n", path);
1550 }
1551 else
1552 {
1553 grub_printf("image: <%s> [ NOT EXIST ]\n", path);
1554 }
1555 }
1556 else
1557 {
1558 if (ventoy_is_dir_exist("%s%s", isodisk, path))
1559 {
1560 grub_printf("dir: <%s> [ OK ]\n", path);
1561 }
1562 else
1563 {
1564 grub_printf("dir: <%s> [ NOT EXIST ]\n", path);
1565 }
1566 }
1567
1568 tip = vtoy_json_get_string_ex(pNode->pstChild, "tip");
1569 if (tip)
1570 {
1571 grub_printf("tip: <%s>\n", tip);
1572 }
1573 else
1574 {
1575 tip = vtoy_json_get_string_ex(pNode->pstChild, "tip1");
1576 if (tip)
1577 grub_printf("tip1: <%s>\n", tip);
1578 else
1579 grub_printf("tip1: <NULL>\n");
1580
1581 tip = vtoy_json_get_string_ex(pNode->pstChild, "tip2");
1582 if (tip)
1583 grub_printf("tip2: <%s>\n", tip);
1584 else
1585 grub_printf("tip2: <NULL>\n");
1586 }
1587 }
1588 else
1589 {
1590 grub_printf("image: <%s> [ INVALID ]\n", path);
1591 }
1592 }
1593
1594 return 0;
1595 }
1596
1597 static int ventoy_plugin_menutip_entry(VTOY_JSON *json, const char *isodisk)
1598 {
1599 int type;
1600 const char *path = NULL;
1601 const char *tip = NULL;
1602 VTOY_JSON *pNode = NULL;
1603 menu_tip *node = NULL;
1604 menu_tip *next = NULL;
1605
1606 (void)isodisk;
1607
1608 if (json->enDataType != JSON_TYPE_OBJECT)
1609 {
1610 debug("Not object %d\n", json->enDataType);
1611 return 0;
1612 }
1613
1614 pNode = vtoy_json_find_item(json->pstChild, JSON_TYPE_ARRAY, "tips");
1615 if (pNode == NULL)
1616 {
1617 debug("Not tips found\n");
1618 return 0;
1619 }
1620
1621 if (g_menu_tip_head)
1622 {
1623 for (node = g_menu_tip_head; node; node = next)
1624 {
1625 next = node->next;
1626 grub_free(node);
1627 }
1628
1629 g_menu_tip_head = NULL;
1630 }
1631
1632 tip = vtoy_json_get_string_ex(json->pstChild, "left");
1633 if (tip)
1634 {
1635 grub_env_set("VTOY_TIP_LEFT", tip);
1636 }
1637
1638 tip = vtoy_json_get_string_ex(json->pstChild, "top");
1639 if (tip)
1640 {
1641 grub_env_set("VTOY_TIP_TOP", tip);
1642 }
1643
1644 tip = vtoy_json_get_string_ex(json->pstChild, "color");
1645 if (tip)
1646 {
1647 grub_env_set("VTOY_TIP_COLOR", tip);
1648 }
1649
1650 for (pNode = pNode->pstChild; pNode; pNode = pNode->pstNext)
1651 {
1652 type = vtoy_tip_image_file;
1653 path = vtoy_json_get_string_ex(pNode->pstChild, "image");
1654 if (!path)
1655 {
1656 path = vtoy_json_get_string_ex(pNode->pstChild, "dir");
1657 type = vtoy_tip_directory;
1658 }
1659
1660 if (path && path[0] == '/')
1661 {
1662 node = grub_zalloc(sizeof(menu_tip));
1663 if (node)
1664 {
1665 node->type = type;
1666 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", path);
1667
1668 tip = vtoy_json_get_string_ex(pNode->pstChild, "tip");
1669 if (tip)
1670 {
1671 grub_snprintf(node->tip1, 1000, "%s", tip);
1672 }
1673 else
1674 {
1675 tip = vtoy_json_get_string_ex(pNode->pstChild, "tip1");
1676 if (tip)
1677 grub_snprintf(node->tip1, 1000, "%s", tip);
1678
1679 tip = vtoy_json_get_string_ex(pNode->pstChild, "tip2");
1680 if (tip)
1681 grub_snprintf(node->tip2, 1000, "%s", tip);
1682 }
1683
1684 if (g_menu_tip_head)
1685 {
1686 node->next = g_menu_tip_head;
1687 }
1688
1689 g_menu_tip_head = node;
1690 }
1691 }
1692 }
1693
1694 return 0;
1695 }
1696
1697 static int ventoy_plugin_injection_check(VTOY_JSON *json, const char *isodisk)
1698 {
1699 int type = 0;
1700 const char *path = NULL;
1701 const char *archive = NULL;
1702 VTOY_JSON *pNode = NULL;
1703
1704 (void)isodisk;
1705
1706 if (json->enDataType != JSON_TYPE_ARRAY)
1707 {
1708 grub_printf("Not array %d\n", json->enDataType);
1709 return 0;
1710 }
1711
1712 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1713 {
1714 type = injection_type_file;
1715 path = vtoy_json_get_string_ex(pNode->pstChild, "image");
1716 if (!path)
1717 {
1718 type = injection_type_parent;
1719 path = vtoy_json_get_string_ex(pNode->pstChild, "parent");
1720 if (!path)
1721 {
1722 grub_printf("image/parent not found\n");
1723 continue;
1724 }
1725 }
1726
1727 archive = vtoy_json_get_string_ex(pNode->pstChild, "archive");
1728 if (!archive)
1729 {
1730 grub_printf("archive not found\n");
1731 continue;
1732 }
1733
1734 if (type == injection_type_file)
1735 {
1736 if (grub_strchr(path, '*'))
1737 {
1738 grub_printf("image: <%s> [*]\n", path);
1739 }
1740 else
1741 {
1742 grub_printf("image: <%s> [%s]\n", path, ventoy_check_file_exist("%s%s", isodisk, path) ? "OK" : "NOT EXIST");
1743 }
1744 }
1745 else
1746 {
1747 grub_printf("parent: <%s> [%s]\n", path,
1748 ventoy_is_dir_exist("%s%s", isodisk, path) ? "OK" : "NOT EXIST");
1749 }
1750
1751 grub_printf("archive: <%s> [%s]\n\n", archive, ventoy_check_file_exist("%s%s", isodisk, archive) ? "OK" : "NOT EXIST");
1752 }
1753
1754 return 0;
1755 }
1756
1757 static int ventoy_plugin_injection_entry(VTOY_JSON *json, const char *isodisk)
1758 {
1759 int type = 0;
1760 const char *path = NULL;
1761 const char *archive = NULL;
1762 VTOY_JSON *pNode = NULL;
1763 injection_config *node = NULL;
1764 injection_config *next = NULL;
1765
1766 (void)isodisk;
1767
1768 if (json->enDataType != JSON_TYPE_ARRAY)
1769 {
1770 debug("Not array %d\n", json->enDataType);
1771 return 0;
1772 }
1773
1774 if (g_injection_head)
1775 {
1776 for (node = g_injection_head; node; node = next)
1777 {
1778 next = node->next;
1779 grub_free(node);
1780 }
1781
1782 g_injection_head = NULL;
1783 }
1784
1785 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1786 {
1787 type = injection_type_file;
1788 path = vtoy_json_get_string_ex(pNode->pstChild, "image");
1789 if (!path)
1790 {
1791 type = injection_type_parent;
1792 path = vtoy_json_get_string_ex(pNode->pstChild, "parent");
1793 }
1794
1795 archive = vtoy_json_get_string_ex(pNode->pstChild, "archive");
1796 if (path && path[0] == '/' && archive && archive[0] == '/')
1797 {
1798 node = grub_zalloc(sizeof(injection_config));
1799 if (node)
1800 {
1801 node->type = type;
1802 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", path);
1803 grub_snprintf(node->archive, sizeof(node->archive), "%s", archive);
1804
1805 if (g_injection_head)
1806 {
1807 node->next = g_injection_head;
1808 }
1809
1810 g_injection_head = node;
1811 }
1812 }
1813 }
1814
1815 return 0;
1816 }
1817
1818 static int ventoy_plugin_menuclass_entry(VTOY_JSON *json, const char *isodisk)
1819 {
1820 int type;
1821 int parent = 0;
1822 const char *key = NULL;
1823 const char *class = NULL;
1824 VTOY_JSON *pNode = NULL;
1825 menu_class *tail = NULL;
1826 menu_class *node = NULL;
1827 menu_class *next = NULL;
1828
1829 (void)isodisk;
1830
1831 if (json->enDataType != JSON_TYPE_ARRAY)
1832 {
1833 debug("Not array %d\n", json->enDataType);
1834 return 0;
1835 }
1836
1837 if (g_menu_class_head)
1838 {
1839 for (node = g_menu_class_head; node; node = next)
1840 {
1841 next = node->next;
1842 grub_free(node);
1843 }
1844
1845 g_menu_class_head = NULL;
1846 }
1847
1848 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1849 {
1850 parent = 0;
1851 type = vtoy_class_image_file;
1852 key = vtoy_json_get_string_ex(pNode->pstChild, "key");
1853 if (!key)
1854 {
1855 key = vtoy_json_get_string_ex(pNode->pstChild, "parent");
1856 if (key)
1857 {
1858 parent = 1;
1859 }
1860 else
1861 {
1862 key = vtoy_json_get_string_ex(pNode->pstChild, "dir");
1863 type = vtoy_class_directory;
1864 }
1865 }
1866
1867 class = vtoy_json_get_string_ex(pNode->pstChild, "class");
1868 if (key && class)
1869 {
1870 node = grub_zalloc(sizeof(menu_class));
1871 if (node)
1872 {
1873 node->type = type;
1874 node->parent = parent;
1875 node->patlen = grub_snprintf(node->pattern, sizeof(node->pattern), "%s", key);
1876 grub_snprintf(node->class, sizeof(node->class), "%s", class);
1877
1878 if (g_menu_class_head)
1879 {
1880 tail->next = node;
1881 }
1882 else
1883 {
1884 g_menu_class_head = node;
1885 }
1886 tail = node;
1887 }
1888 }
1889 }
1890
1891 return 0;
1892 }
1893
1894 static int ventoy_plugin_menuclass_check(VTOY_JSON *json, const char *isodisk)
1895 {
1896 const char *name = NULL;
1897 const char *key = NULL;
1898 const char *class = NULL;
1899 VTOY_JSON *pNode = NULL;
1900
1901 (void)isodisk;
1902
1903 if (json->enDataType != JSON_TYPE_ARRAY)
1904 {
1905 grub_printf("Not array %d\n", json->enDataType);
1906 return 1;
1907 }
1908
1909 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1910 {
1911 name = "key";
1912 key = vtoy_json_get_string_ex(pNode->pstChild, "key");
1913 if (!key)
1914 {
1915 name = "parent";
1916 key = vtoy_json_get_string_ex(pNode->pstChild, "parent");
1917 if (!key)
1918 {
1919 name = "dir";
1920 key = vtoy_json_get_string_ex(pNode->pstChild, "dir");
1921 }
1922 }
1923
1924 class = vtoy_json_get_string_ex(pNode->pstChild, "class");
1925 if (key && class)
1926 {
1927 grub_printf("%s: <%s>\n", name, key);
1928 grub_printf("class: <%s>\n\n", class);
1929 }
1930 }
1931
1932 return 0;
1933 }
1934
1935 static int ventoy_plugin_custom_boot_entry(VTOY_JSON *json, const char *isodisk)
1936 {
1937 int type;
1938 int len;
1939 const char *key = NULL;
1940 const char *cfg = NULL;
1941 VTOY_JSON *pNode = NULL;
1942 custom_boot *tail = NULL;
1943 custom_boot *node = NULL;
1944 custom_boot *next = NULL;
1945
1946 (void)isodisk;
1947
1948 if (json->enDataType != JSON_TYPE_ARRAY)
1949 {
1950 debug("Not array %d\n", json->enDataType);
1951 return 0;
1952 }
1953
1954 if (g_custom_boot_head)
1955 {
1956 for (node = g_custom_boot_head; node; node = next)
1957 {
1958 next = node->next;
1959 grub_free(node);
1960 }
1961
1962 g_custom_boot_head = NULL;
1963 }
1964
1965 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1966 {
1967 type = vtoy_custom_boot_image_file;
1968 key = vtoy_json_get_string_ex(pNode->pstChild, "file");
1969 if (!key)
1970 {
1971 key = vtoy_json_get_string_ex(pNode->pstChild, "dir");
1972 type = vtoy_custom_boot_directory;
1973 }
1974
1975 cfg = vtoy_json_get_string_ex(pNode->pstChild, "vcfg");
1976 if (key && cfg)
1977 {
1978 node = grub_zalloc(sizeof(custom_boot));
1979 if (node)
1980 {
1981 node->type = type;
1982 node->pathlen = grub_snprintf(node->path, sizeof(node->path), "%s", key);
1983 len = (int)grub_snprintf(node->cfg, sizeof(node->cfg), "%s", cfg);
1984
1985 if (len >= 5 && grub_strncmp(node->cfg + len - 5, ".vcfg", 5) == 0)
1986 {
1987 if (g_custom_boot_head)
1988 {
1989 tail->next = node;
1990 }
1991 else
1992 {
1993 g_custom_boot_head = node;
1994 }
1995 tail = node;
1996 }
1997 else
1998 {
1999 grub_free(node);
2000 }
2001 }
2002 }
2003 }
2004
2005 return 0;
2006 }
2007
2008 static int ventoy_plugin_custom_boot_check(VTOY_JSON *json, const char *isodisk)
2009 {
2010 int type;
2011 int len;
2012 const char *key = NULL;
2013 const char *cfg = NULL;
2014 VTOY_JSON *pNode = NULL;
2015
2016 (void)isodisk;
2017
2018 if (json->enDataType != JSON_TYPE_ARRAY)
2019 {
2020 grub_printf("Not array %d\n", json->enDataType);
2021 return 1;
2022 }
2023
2024 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
2025 {
2026 type = vtoy_custom_boot_image_file;
2027 key = vtoy_json_get_string_ex(pNode->pstChild, "file");
2028 if (!key)
2029 {
2030 key = vtoy_json_get_string_ex(pNode->pstChild, "dir");
2031 type = vtoy_custom_boot_directory;
2032 }
2033
2034 cfg = vtoy_json_get_string_ex(pNode->pstChild, "vcfg");
2035 len = (int)grub_strlen(cfg);
2036 if (key && cfg)
2037 {
2038 if (len < 5 || grub_strncmp(cfg + len - 5, ".vcfg", 5))
2039 {
2040 grub_printf("<%s> does not have \".vcfg\" suffix\n\n", cfg);
2041 }
2042 else
2043 {
2044 grub_printf("%s: <%s>\n", (type == vtoy_custom_boot_directory) ? "dir" : "file", key);
2045 grub_printf("vcfg: <%s>\n\n", cfg);
2046 }
2047 }
2048 }
2049
2050 return 0;
2051 }
2052
2053 static int ventoy_plugin_conf_replace_entry(VTOY_JSON *json, const char *isodisk)
2054 {
2055 int img = 0;
2056 const char *isof = NULL;
2057 const char *orgf = NULL;
2058 const char *newf = NULL;
2059 VTOY_JSON *pNode = NULL;
2060 conf_replace *tail = NULL;
2061 conf_replace *node = NULL;
2062 conf_replace *next = NULL;
2063
2064 (void)isodisk;
2065
2066 if (json->enDataType != JSON_TYPE_ARRAY)
2067 {
2068 debug("Not array %d\n", json->enDataType);
2069 return 0;
2070 }
2071
2072 if (g_conf_replace_head)
2073 {
2074 for (node = g_conf_replace_head; node; node = next)
2075 {
2076 next = node->next;
2077 grub_free(node);
2078 }
2079
2080 g_conf_replace_head = NULL;
2081 }
2082
2083 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
2084 {
2085 isof = vtoy_json_get_string_ex(pNode->pstChild, "iso");
2086 orgf = vtoy_json_get_string_ex(pNode->pstChild, "org");
2087 newf = vtoy_json_get_string_ex(pNode->pstChild, "new");
2088 if (isof && orgf && newf && isof[0] == '/' && orgf[0] == '/' && newf[0] == '/')
2089 {
2090 node = grub_zalloc(sizeof(conf_replace));
2091 if (node)
2092 {
2093 if (JSON_SUCCESS == vtoy_json_get_int(pNode->pstChild, "img", &img))
2094 {
2095 node->img = img;
2096 }
2097
2098 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", isof);
2099 grub_snprintf(node->orgconf, sizeof(node->orgconf), "%s", orgf);
2100 grub_snprintf(node->newconf, sizeof(node->newconf), "%s", newf);
2101
2102 if (g_conf_replace_head)
2103 {
2104 tail->next = node;
2105 }
2106 else
2107 {
2108 g_conf_replace_head = node;
2109 }
2110 tail = node;
2111 }
2112 }
2113 }
2114
2115 return 0;
2116 }
2117
2118 static int ventoy_plugin_conf_replace_check(VTOY_JSON *json, const char *isodisk)
2119 {
2120 int img = 0;
2121 const char *isof = NULL;
2122 const char *orgf = NULL;
2123 const char *newf = NULL;
2124 VTOY_JSON *pNode = NULL;
2125 grub_file_t file = NULL;
2126 char cmd[256];
2127
2128 (void)isodisk;
2129
2130 if (json->enDataType != JSON_TYPE_ARRAY)
2131 {
2132 grub_printf("Not array %d\n", json->enDataType);
2133 return 1;
2134 }
2135
2136 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
2137 {
2138 isof = vtoy_json_get_string_ex(pNode->pstChild, "iso");
2139 orgf = vtoy_json_get_string_ex(pNode->pstChild, "org");
2140 newf = vtoy_json_get_string_ex(pNode->pstChild, "new");
2141 if (isof && orgf && newf && isof[0] == '/' && orgf[0] == '/' && newf[0] == '/')
2142 {
2143 if (ventoy_check_file_exist("%s%s", isodisk, isof))
2144 {
2145 grub_printf("iso:<%s> [OK]\n", isof);
2146
2147 grub_snprintf(cmd, sizeof(cmd), "loopback vtisocheck \"%s%s\"", isodisk, isof);
2148 grub_script_execute_sourcecode(cmd);
2149
2150 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(vtisocheck)/%s", orgf);
2151 if (file)
2152 {
2153 if (grub_strcmp(file->fs->name, "iso9660") == 0)
2154 {
2155 grub_printf("org:<%s> [OK]\n", orgf);
2156 }
2157 else
2158 {
2159 grub_printf("org:<%s> [Exist But NOT ISO9660]\n", orgf);
2160 }
2161 grub_file_close(file);
2162 }
2163 else
2164 {
2165 grub_printf("org:<%s> [NOT Exist]\n", orgf);
2166 }
2167
2168 grub_script_execute_sourcecode("loopback -d vtisocheck");
2169 }
2170 else if (grub_strchr(isof, '*'))
2171 {
2172 grub_printf("iso:<%s> [*]\n", isof);
2173 grub_printf("org:<%s>\n", orgf);
2174 }
2175 else
2176 {
2177 grub_printf("iso:<%s> [NOT Exist]\n", isof);
2178 grub_printf("org:<%s>\n", orgf);
2179 }
2180
2181 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", isodisk, newf);
2182 if (file)
2183 {
2184 if (file->size > vtoy_max_replace_file_size)
2185 {
2186 grub_printf("new:<%s> [Too Big %lu] \n", newf, (ulong)file->size);
2187 }
2188 else
2189 {
2190 grub_printf("new1:<%s> [OK]\n", newf);
2191 }
2192 grub_file_close(file);
2193 }
2194 else
2195 {
2196 grub_printf("new:<%s> [NOT Exist]\n", newf);
2197 }
2198
2199 if (JSON_SUCCESS == vtoy_json_get_int(pNode->pstChild, "img", &img))
2200 {
2201 grub_printf("img:<%d>\n", img);
2202 }
2203
2204 grub_printf("\n");
2205 }
2206 }
2207
2208 return 0;
2209 }
2210
2211 static int ventoy_plugin_auto_memdisk_entry(VTOY_JSON *json, const char *isodisk)
2212 {
2213 VTOY_JSON *pNode = NULL;
2214 auto_memdisk *node = NULL;
2215 auto_memdisk *next = NULL;
2216
2217 (void)isodisk;
2218
2219 if (json->enDataType != JSON_TYPE_ARRAY)
2220 {
2221 debug("Not array %d\n", json->enDataType);
2222 return 0;
2223 }
2224
2225 if (g_auto_memdisk_head)
2226 {
2227 for (node = g_auto_memdisk_head; node; node = next)
2228 {
2229 next = node->next;
2230 grub_free(node);
2231 }
2232
2233 g_auto_memdisk_head = NULL;
2234 }
2235
2236 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
2237 {
2238 if (pNode->enDataType == JSON_TYPE_STRING)
2239 {
2240 node = grub_zalloc(sizeof(auto_memdisk));
2241 if (node)
2242 {
2243 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", pNode->unData.pcStrVal);
2244
2245 if (g_auto_memdisk_head)
2246 {
2247 node->next = g_auto_memdisk_head;
2248 }
2249
2250 g_auto_memdisk_head = node;
2251 }
2252 }
2253 }
2254
2255 return 0;
2256 }
2257
2258 static int ventoy_plugin_auto_memdisk_check(VTOY_JSON *json, const char *isodisk)
2259 {
2260 VTOY_JSON *pNode = NULL;
2261
2262 if (json->enDataType != JSON_TYPE_ARRAY)
2263 {
2264 grub_printf("Not array %d\n", json->enDataType);
2265 return 1;
2266 }
2267
2268 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
2269 {
2270 if (pNode->enDataType == JSON_TYPE_STRING)
2271 {
2272 grub_printf("<%s> ", pNode->unData.pcStrVal);
2273
2274 if (grub_strchr(pNode->unData.pcStrVal, '*'))
2275 {
2276 grub_printf(" [*]\n");
2277 }
2278 else if (ventoy_check_file_exist("%s%s", isodisk, pNode->unData.pcStrVal))
2279 {
2280 grub_printf(" [OK]\n");
2281 }
2282 else
2283 {
2284 grub_printf(" [NOT EXIST]\n");
2285 }
2286 }
2287 }
2288
2289 return 0;
2290 }
2291
2292 static int ventoy_plugin_image_list_entry(VTOY_JSON *json, const char *isodisk)
2293 {
2294 VTOY_JSON *pNode = NULL;
2295 image_list *node = NULL;
2296 image_list *next = NULL;
2297 image_list *tail = NULL;
2298
2299 (void)isodisk;
2300
2301 if (json->enDataType != JSON_TYPE_ARRAY)
2302 {
2303 debug("Not array %d\n", json->enDataType);
2304 return 0;
2305 }
2306
2307 if (g_image_list_head)
2308 {
2309 for (node = g_image_list_head; node; node = next)
2310 {
2311 next = node->next;
2312 grub_free(node);
2313 }
2314
2315 g_image_list_head = NULL;
2316 }
2317
2318 if (grub_strncmp(json->pcName, "image_blacklist", 15) == 0)
2319 {
2320 g_plugin_image_list = VENTOY_IMG_BLACK_LIST;
2321 }
2322 else
2323 {
2324 g_plugin_image_list = VENTOY_IMG_WHITE_LIST;
2325 }
2326
2327 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
2328 {
2329 if (pNode->enDataType == JSON_TYPE_STRING)
2330 {
2331 node = grub_zalloc(sizeof(image_list));
2332 if (node)
2333 {
2334 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", pNode->unData.pcStrVal);
2335
2336 if (g_image_list_head)
2337 {
2338 tail->next = node;
2339 }
2340 else
2341 {
2342 g_image_list_head = node;
2343 }
2344 tail = node;
2345 }
2346 }
2347 }
2348
2349 return 0;
2350 }
2351
2352 static int ventoy_plugin_image_list_check(VTOY_JSON *json, const char *isodisk)
2353 {
2354 VTOY_JSON *pNode = NULL;
2355
2356 if (json->enDataType != JSON_TYPE_ARRAY)
2357 {
2358 grub_printf("Not array %d\n", json->enDataType);
2359 return 1;
2360 }
2361
2362 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
2363 {
2364 if (pNode->enDataType == JSON_TYPE_STRING)
2365 {
2366 grub_printf("<%s> ", pNode->unData.pcStrVal);
2367
2368 if (grub_strchr(pNode->unData.pcStrVal, '*'))
2369 {
2370 grub_printf(" [*]\n");
2371 }
2372 else if (ventoy_check_file_exist("%s%s", isodisk, pNode->unData.pcStrVal))
2373 {
2374 grub_printf(" [OK]\n");
2375 }
2376 else
2377 {
2378 grub_printf(" [NOT EXIST]\n");
2379 }
2380 }
2381 }
2382
2383 return 0;
2384 }
2385
2386 static plugin_entry g_plugin_entries[] =
2387 {
2388 { "control", ventoy_plugin_control_entry, ventoy_plugin_control_check, 0 },
2389 { "theme", ventoy_plugin_theme_entry, ventoy_plugin_theme_check, 0 },
2390 { "auto_install", ventoy_plugin_auto_install_entry, ventoy_plugin_auto_install_check, 0 },
2391 { "persistence", ventoy_plugin_persistence_entry, ventoy_plugin_persistence_check, 0 },
2392 { "menu_alias", ventoy_plugin_menualias_entry, ventoy_plugin_menualias_check, 0 },
2393 { "menu_tip", ventoy_plugin_menutip_entry, ventoy_plugin_menutip_check, 0 },
2394 { "menu_class", ventoy_plugin_menuclass_entry, ventoy_plugin_menuclass_check, 0 },
2395 { "injection", ventoy_plugin_injection_entry, ventoy_plugin_injection_check, 0 },
2396 { "auto_memdisk", ventoy_plugin_auto_memdisk_entry, ventoy_plugin_auto_memdisk_check, 0 },
2397 { "image_list", ventoy_plugin_image_list_entry, ventoy_plugin_image_list_check, 0 },
2398 { "image_blacklist", ventoy_plugin_image_list_entry, ventoy_plugin_image_list_check, 0 },
2399 { "conf_replace", ventoy_plugin_conf_replace_entry, ventoy_plugin_conf_replace_check, 0 },
2400 { "dud", ventoy_plugin_dud_entry, ventoy_plugin_dud_check, 0 },
2401 { "password", ventoy_plugin_pwd_entry, ventoy_plugin_pwd_check, 0 },
2402 { "custom_boot", ventoy_plugin_custom_boot_entry, ventoy_plugin_custom_boot_check, 0 },
2403 };
2404
2405 static int ventoy_parse_plugin_config(VTOY_JSON *json, const char *isodisk)
2406 {
2407 int i;
2408 char key[128];
2409 VTOY_JSON *cur = NULL;
2410
2411 grub_snprintf(g_iso_disk_name, sizeof(g_iso_disk_name), "%s", isodisk);
2412
2413 for (cur = json; cur; cur = cur->pstNext)
2414 {
2415 for (i = 0; i < (int)ARRAY_SIZE(g_plugin_entries); i++)
2416 {
2417 grub_snprintf(key, sizeof(key), "%s_%s", g_plugin_entries[i].key, g_arch_mode_suffix);
2418 if (g_plugin_entries[i].flag == 0 && grub_strcmp(key, cur->pcName) == 0)
2419 {
2420 debug("Plugin entry for %s\n", g_plugin_entries[i].key);
2421 g_plugin_entries[i].entryfunc(cur, isodisk);
2422 g_plugin_entries[i].flag = 1;
2423 break;
2424 }
2425 }
2426 }
2427
2428
2429 for (cur = json; cur; cur = cur->pstNext)
2430 {
2431 for (i = 0; i < (int)ARRAY_SIZE(g_plugin_entries); i++)
2432 {
2433 if (g_plugin_entries[i].flag == 0 && grub_strcmp(g_plugin_entries[i].key, cur->pcName) == 0)
2434 {
2435 debug("Plugin entry for %s\n", g_plugin_entries[i].key);
2436 g_plugin_entries[i].entryfunc(cur, isodisk);
2437 g_plugin_entries[i].flag = 1;
2438 break;
2439 }
2440 }
2441 }
2442
2443 return 0;
2444 }
2445
2446 grub_err_t ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **args)
2447 {
2448 int ret = 0;
2449 int offset = 0;
2450 char *buf = NULL;
2451 grub_uint8_t *code = NULL;
2452 grub_file_t file;
2453 VTOY_JSON *json = NULL;
2454
2455 (void)ctxt;
2456 (void)argc;
2457
2458 grub_env_set("VTOY_TIP_LEFT", "10%");
2459 grub_env_set("VTOY_TIP_TOP", "80%+5");
2460 grub_env_set("VTOY_TIP_COLOR", "blue");
2461 grub_env_set("VTOY_TIP_ALIGN", "left");
2462
2463 file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s/ventoy/ventoy.json", args[0]);
2464 if (!file)
2465 {
2466 return GRUB_ERR_NONE;
2467 }
2468
2469 debug("json configuration file size %d\n", (int)file->size);
2470
2471 buf = grub_malloc(file->size + 1);
2472 if (!buf)
2473 {
2474 grub_file_close(file);
2475 return 1;
2476 }
2477
2478 buf[file->size] = 0;
2479 grub_file_read(file, buf, file->size);
2480 grub_file_close(file);
2481
2482 json = vtoy_json_create();
2483 if (!json)
2484 {
2485 return 1;
2486 }
2487
2488 code = (grub_uint8_t *)buf;
2489 if (code[0] == 0xef && code[1] == 0xbb && code[2] == 0xbf)
2490 {
2491 offset = 3; /* Skip UTF-8 BOM */
2492 }
2493 else if ((code[0] == 0xff && code[1] == 0xfe) || (code[0] == 0xfe && code[1] == 0xff))
2494 {
2495 grub_env_set("VTOY_PLUGIN_SYNTAX_ERROR", "1");
2496 grub_env_export("VTOY_PLUGIN_SYNTAX_ERROR");
2497
2498 grub_env_set("VTOY_PLUGIN_ENCODE_ERROR", "1");
2499 grub_env_export("VTOY_PLUGIN_ENCODE_ERROR");
2500
2501 debug("Failed to parse json string %d\n", ret);
2502 grub_free(buf);
2503 return 1;
2504 }
2505
2506 ret = vtoy_json_parse(json, buf + offset);
2507 if (ret)
2508 {
2509 grub_env_set("VTOY_PLUGIN_SYNTAX_ERROR", "1");
2510 grub_env_export("VTOY_PLUGIN_SYNTAX_ERROR");
2511
2512 debug("Failed to parse json string %d\n", ret);
2513 grub_free(buf);
2514 return 1;
2515 }
2516
2517 ventoy_parse_plugin_config(json->pstChild, args[0]);
2518
2519 vtoy_json_destroy(json);
2520
2521 grub_free(buf);
2522
2523 if (g_boot_pwd.type)
2524 {
2525 grub_printf("\n\n======= %s ======\n\n", grub_env_get("VTOY_TEXT_MENU_VER"));
2526 if (ventoy_check_password(&g_boot_pwd, 3))
2527 {
2528 grub_printf("\n!!! Password check failed, will exit after 5 seconds. !!!\n");
2529 grub_refresh();
2530 grub_sleep(5);
2531 grub_exit();
2532 }
2533 }
2534
2535 if (g_menu_tip_head)
2536 {
2537 grub_env_set("VTOY_MENU_TIP_ENABLE", "1");
2538 }
2539 else
2540 {
2541 grub_env_unset("VTOY_MENU_TIP_ENABLE");
2542 }
2543
2544 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2545 }
2546
2547 void ventoy_plugin_dump_injection(void)
2548 {
2549 injection_config *node = NULL;
2550
2551 for (node = g_injection_head; node; node = node->next)
2552 {
2553 grub_printf("\n%s:<%s>\n", (node->type == injection_type_file) ? "IMAGE" : "PARENT", node->isopath);
2554 grub_printf("ARCHIVE:<%s>\n", node->archive);
2555 }
2556
2557 return;
2558 }
2559
2560
2561 void ventoy_plugin_dump_auto_install(void)
2562 {
2563 int i;
2564 install_template *node = NULL;
2565
2566 for (node = g_install_template_head; node; node = node->next)
2567 {
2568 grub_printf("\n%s:<%s> <%d>\n",
2569 (node->type == auto_install_type_file) ? "IMAGE" : "PARENT",
2570 node->isopath, node->templatenum);
2571 for (i = 0; i < node->templatenum; i++)
2572 {
2573 grub_printf("SCRIPT %d:<%s>\n", i, node->templatepath[i].path);
2574 }
2575 }
2576
2577 return;
2578 }
2579
2580 void ventoy_plugin_dump_persistence(void)
2581 {
2582 int rc;
2583 int i = 0;
2584 persistence_config *node = NULL;
2585 ventoy_img_chunk_list chunk_list;
2586
2587 for (node = g_persistence_head; node; node = node->next)
2588 {
2589 grub_printf("\nIMAGE:<%s> <%d>\n", node->isopath, node->backendnum);
2590
2591 for (i = 0; i < node->backendnum; i++)
2592 {
2593 grub_printf("PERSIST %d:<%s>", i, node->backendpath[i].path);
2594 rc = ventoy_plugin_get_persistent_chunklist(node->isopath, i, &chunk_list);
2595 if (rc == 0)
2596 {
2597 grub_printf(" [ SUCCESS ]\n");
2598 grub_free(chunk_list.chunk);
2599 }
2600 else
2601 {
2602 grub_printf(" [ FAILED ]\n");
2603 }
2604 }
2605 }
2606
2607 return;
2608 }
2609
2610 install_template * ventoy_plugin_find_install_template(const char *isopath)
2611 {
2612 int len;
2613 install_template *node = NULL;
2614
2615 if (!g_install_template_head)
2616 {
2617 return NULL;
2618 }
2619
2620 len = (int)grub_strlen(isopath);
2621 for (node = g_install_template_head; node; node = node->next)
2622 {
2623 if (node->type == auto_install_type_file)
2624 {
2625 if (node->pathlen == len && ventoy_strcmp(node->isopath, isopath) == 0)
2626 {
2627 return node;
2628 }
2629 }
2630 }
2631
2632 for (node = g_install_template_head; node; node = node->next)
2633 {
2634 if (node->type == auto_install_type_parent)
2635 {
2636 if (node->pathlen < len && ventoy_plugin_is_parent(node->isopath, node->pathlen, isopath))
2637 {
2638 return node;
2639 }
2640 }
2641 }
2642
2643 return NULL;
2644 }
2645
2646 char * ventoy_plugin_get_cur_install_template(const char *isopath, install_template **cur)
2647 {
2648 install_template *node = NULL;
2649
2650 if (cur)
2651 {
2652 *cur = NULL;
2653 }
2654
2655 node = ventoy_plugin_find_install_template(isopath);
2656 if ((!node) || (!node->templatepath))
2657 {
2658 return NULL;
2659 }
2660
2661 if (node->cursel < 0 || node->cursel >= node->templatenum)
2662 {
2663 return NULL;
2664 }
2665
2666 if (cur)
2667 {
2668 *cur = node;
2669 }
2670
2671 return node->templatepath[node->cursel].path;
2672 }
2673
2674 persistence_config * ventoy_plugin_find_persistent(const char *isopath)
2675 {
2676 int len;
2677 persistence_config *node = NULL;
2678
2679 if (!g_persistence_head)
2680 {
2681 return NULL;
2682 }
2683
2684 len = (int)grub_strlen(isopath);
2685 for (node = g_persistence_head; node; node = node->next)
2686 {
2687 if ((len == node->pathlen) && (ventoy_strcmp(node->isopath, isopath) == 0))
2688 {
2689 return node;
2690 }
2691 }
2692
2693 return NULL;
2694 }
2695
2696 int ventoy_plugin_get_persistent_chunklist(const char *isopath, int index, ventoy_img_chunk_list *chunk_list)
2697 {
2698 int rc = 1;
2699 int len = 0;
2700 char *path = NULL;
2701 grub_uint64_t start = 0;
2702 grub_file_t file = NULL;
2703 persistence_config *node = NULL;
2704
2705 node = ventoy_plugin_find_persistent(isopath);
2706 if ((!node) || (!node->backendpath))
2707 {
2708 return 1;
2709 }
2710
2711 if (index < 0)
2712 {
2713 index = node->cursel;
2714 }
2715
2716 if (index < 0 || index >= node->backendnum)
2717 {
2718 return 1;
2719 }
2720
2721 path = node->backendpath[index].path;
2722
2723 if (node->backendpath[index].vlnk_add == 0)
2724 {
2725 len = grub_strlen(path);
2726 if (len > 9 && grub_strncmp(path + len - 9, ".vlnk.dat", 9) == 0)
2727 {
2728 ventoy_add_vlnk_file(NULL, path);
2729 node->backendpath[index].vlnk_add = 1;
2730 }
2731 }
2732
2733 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", g_iso_disk_name, path);
2734 if (!file)
2735 {
2736 debug("Failed to open file %s%s\n", g_iso_disk_name, path);
2737 goto end;
2738 }
2739
2740 grub_memset(chunk_list, 0, sizeof(ventoy_img_chunk_list));
2741 chunk_list->chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
2742 if (NULL == chunk_list->chunk)
2743 {
2744 goto end;
2745 }
2746
2747 chunk_list->max_chunk = DEFAULT_CHUNK_NUM;
2748 chunk_list->cur_chunk = 0;
2749
2750 start = file->device->disk->partition->start;
2751 ventoy_get_block_list(file, chunk_list, start);
2752
2753 if (0 != ventoy_check_block_list(file, chunk_list, start))
2754 {
2755 grub_free(chunk_list->chunk);
2756 chunk_list->chunk = NULL;
2757 goto end;
2758 }
2759
2760 rc = 0;
2761
2762 end:
2763 if (file)
2764 grub_file_close(file);
2765
2766 return rc;
2767 }
2768
2769 const char * ventoy_plugin_get_injection(const char *isopath)
2770 {
2771 int len;
2772 injection_config *node = NULL;
2773
2774 if (!g_injection_head)
2775 {
2776 return NULL;
2777 }
2778
2779 len = (int)grub_strlen(isopath);
2780 for (node = g_injection_head; node; node = node->next)
2781 {
2782 if (node->type == injection_type_file)
2783 {
2784 if (node->pathlen == len && ventoy_strcmp(node->isopath, isopath) == 0)
2785 {
2786 return node->archive;
2787 }
2788 }
2789 }
2790
2791 for (node = g_injection_head; node; node = node->next)
2792 {
2793 if (node->type == injection_type_parent)
2794 {
2795 if (node->pathlen < len && ventoy_plugin_is_parent(node->isopath, node->pathlen, isopath))
2796 {
2797 return node->archive;
2798 }
2799 }
2800 }
2801
2802 return NULL;
2803 }
2804
2805 const char * ventoy_plugin_get_menu_alias(int type, const char *isopath)
2806 {
2807 int len;
2808 menu_alias *node = NULL;
2809
2810 if (!g_menu_alias_head)
2811 {
2812 return NULL;
2813 }
2814
2815 len = (int)grub_strlen(isopath);
2816 for (node = g_menu_alias_head; node; node = node->next)
2817 {
2818 if (node->type == type && node->pathlen &&
2819 node->pathlen == len && ventoy_strcmp(node->isopath, isopath) == 0)
2820 {
2821 return node->alias;
2822 }
2823 }
2824
2825 return NULL;
2826 }
2827
2828 const menu_tip * ventoy_plugin_get_menu_tip(int type, const char *isopath)
2829 {
2830 int len;
2831 menu_tip *node = NULL;
2832
2833 if (!g_menu_tip_head)
2834 {
2835 return NULL;
2836 }
2837
2838 len = (int)grub_strlen(isopath);
2839 for (node = g_menu_tip_head; node; node = node->next)
2840 {
2841 if (node->type == type && node->pathlen &&
2842 node->pathlen == len && ventoy_strcmp(node->isopath, isopath) == 0)
2843 {
2844 return node;
2845 }
2846 }
2847
2848 return NULL;
2849 }
2850
2851 const char * ventoy_plugin_get_menu_class(int type, const char *name, const char *path)
2852 {
2853 int namelen;
2854 int pathlen;
2855 menu_class *node = NULL;
2856
2857 if (!g_menu_class_head)
2858 {
2859 return NULL;
2860 }
2861
2862 namelen = (int)grub_strlen(name);
2863 pathlen = (int)grub_strlen(path);
2864
2865 if (vtoy_class_image_file == type)
2866 {
2867 for (node = g_menu_class_head; node; node = node->next)
2868 {
2869 if (node->type != type)
2870 {
2871 continue;
2872 }
2873
2874 if (node->parent == 0)
2875 {
2876 if ((node->patlen < namelen) && grub_strstr(name, node->pattern))
2877 {
2878 return node->class;
2879 }
2880 }
2881 }
2882
2883 for (node = g_menu_class_head; node; node = node->next)
2884 {
2885 if (node->type != type)
2886 {
2887 continue;
2888 }
2889
2890 if (node->parent)
2891 {
2892 if ((node->patlen < pathlen) && ventoy_plugin_is_parent(node->pattern, node->patlen, path))
2893 {
2894 return node->class;
2895 }
2896 }
2897 }
2898 }
2899 else
2900 {
2901 for (node = g_menu_class_head; node; node = node->next)
2902 {
2903 if (node->type == type && node->patlen == namelen && grub_strncmp(name, node->pattern, namelen) == 0)
2904 {
2905 return node->class;
2906 }
2907 }
2908 }
2909
2910 return NULL;
2911 }
2912
2913 int ventoy_plugin_add_custom_boot(const char *vcfgpath)
2914 {
2915 int len;
2916 custom_boot *node = NULL;
2917
2918 node = grub_zalloc(sizeof(custom_boot));
2919 if (node)
2920 {
2921 node->type = vtoy_custom_boot_image_file;
2922 node->pathlen = grub_snprintf(node->path, sizeof(node->path), "%s", vcfgpath);
2923 grub_snprintf(node->cfg, sizeof(node->cfg), "%s", vcfgpath);
2924
2925 /* .vcfg */
2926 len = node->pathlen - 5;
2927 node->path[len] = 0;
2928 node->pathlen = len;
2929
2930 if (g_custom_boot_head)
2931 {
2932 node->next = g_custom_boot_head;
2933 }
2934 g_custom_boot_head = node;
2935 }
2936
2937 return 0;
2938 }
2939
2940 const char * ventoy_plugin_get_custom_boot(const char *isopath)
2941 {
2942 int i;
2943 int len;
2944 custom_boot *node = NULL;
2945
2946 if (!g_custom_boot_head)
2947 {
2948 return NULL;
2949 }
2950
2951 len = (int)grub_strlen(isopath);
2952
2953 for (node = g_custom_boot_head; node; node = node->next)
2954 {
2955 if (node->type == vtoy_custom_boot_image_file)
2956 {
2957 if (node->pathlen == len && grub_strncmp(isopath, node->path, len) == 0)
2958 {
2959 return node->cfg;
2960 }
2961 }
2962 else
2963 {
2964 if (node->pathlen < len && isopath[node->pathlen] == '/' &&
2965 grub_strncmp(isopath, node->path, node->pathlen) == 0)
2966 {
2967 for (i = node->pathlen + 1; i < len; i++)
2968 {
2969 if (isopath[i] == '/')
2970 {
2971 break;
2972 }
2973 }
2974
2975 if (i >= len)
2976 {
2977 return node->cfg;
2978 }
2979 }
2980 }
2981 }
2982
2983 return NULL;
2984 }
2985
2986 grub_err_t ventoy_cmd_dump_custom_boot(grub_extcmd_context_t ctxt, int argc, char **args)
2987 {
2988 custom_boot *node = NULL;
2989
2990 (void)argc;
2991 (void)ctxt;
2992 (void)args;
2993
2994 for (node = g_custom_boot_head; node; node = node->next)
2995 {
2996 grub_printf("[%s] <%s>:<%s>\n", (node->type == vtoy_custom_boot_directory) ? "dir" : "file",
2997 node->path, node->cfg);
2998 }
2999
3000 return 0;
3001 }
3002
3003 int ventoy_plugin_check_memdisk(const char *isopath)
3004 {
3005 int len;
3006 auto_memdisk *node = NULL;
3007
3008 if (!g_auto_memdisk_head)
3009 {
3010 return 0;
3011 }
3012
3013 len = (int)grub_strlen(isopath);
3014 for (node = g_auto_memdisk_head; node; node = node->next)
3015 {
3016 if (node->pathlen == len && ventoy_strncmp(node->isopath, isopath, len) == 0)
3017 {
3018 return 1;
3019 }
3020 }
3021
3022 return 0;
3023 }
3024
3025 int ventoy_plugin_get_image_list_index(int type, const char *name)
3026 {
3027 int len;
3028 int index = 1;
3029 image_list *node = NULL;
3030
3031 if (!g_image_list_head)
3032 {
3033 return 0;
3034 }
3035
3036 len = (int)grub_strlen(name);
3037
3038 for (node = g_image_list_head; node; node = node->next, index++)
3039 {
3040 if (vtoy_class_directory == type)
3041 {
3042 if (len < node->pathlen && ventoy_strncmp(node->isopath, name, len) == 0)
3043 {
3044 return index;
3045 }
3046 }
3047 else
3048 {
3049 if (len == node->pathlen && ventoy_strncmp(node->isopath, name, len) == 0)
3050 {
3051 return index;
3052 }
3053 }
3054 }
3055
3056 return 0;
3057 }
3058
3059 int ventoy_plugin_find_conf_replace(const char *iso, conf_replace *nodes[VTOY_MAX_CONF_REPLACE])
3060 {
3061 int n = 0;
3062 int len;
3063 conf_replace *node;
3064
3065 if (!g_conf_replace_head)
3066 {
3067 return 0;
3068 }
3069
3070 len = (int)grub_strlen(iso);
3071
3072 for (node = g_conf_replace_head; node; node = node->next)
3073 {
3074 if (node->pathlen == len && ventoy_strncmp(node->isopath, iso, len) == 0)
3075 {
3076 nodes[n++] = node;
3077 if (n >= VTOY_MAX_CONF_REPLACE)
3078 {
3079 return n;
3080 }
3081 }
3082 }
3083
3084 return n;
3085 }
3086
3087 dud * ventoy_plugin_find_dud(const char *iso)
3088 {
3089 int len;
3090 dud *node;
3091
3092 if (!g_dud_head)
3093 {
3094 return NULL;
3095 }
3096
3097 len = (int)grub_strlen(iso);
3098 for (node = g_dud_head; node; node = node->next)
3099 {
3100 if (node->pathlen == len && ventoy_strncmp(node->isopath, iso, len) == 0)
3101 {
3102 return node;
3103 }
3104 }
3105
3106 return NULL;
3107 }
3108
3109 int ventoy_plugin_load_dud(dud *node, const char *isopart)
3110 {
3111 int i;
3112 char *buf;
3113 grub_file_t file;
3114
3115 for (i = 0; i < node->dudnum; i++)
3116 {
3117 if (node->files[i].size > 0)
3118 {
3119 debug("file %d has been loaded\n", i);
3120 continue;
3121 }
3122
3123 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", isopart, node->dudpath[i].path);
3124 if (file)
3125 {
3126 buf = grub_malloc(file->size);
3127 if (buf)
3128 {
3129 grub_file_read(file, buf, file->size);
3130 node->files[i].size = (int)file->size;
3131 node->files[i].buf = buf;
3132 }
3133 grub_file_close(file);
3134 }
3135 }
3136
3137 return 0;
3138 }
3139
3140 static const vtoy_password * ventoy_plugin_get_password(const char *isopath)
3141 {
3142 int i;
3143 int len;
3144 const char *pos = NULL;
3145 menu_password *node = NULL;
3146
3147 if (!isopath)
3148 {
3149 return NULL;
3150 }
3151
3152 if (g_pwd_head)
3153 {
3154 len = (int)grub_strlen(isopath);
3155 for (node = g_pwd_head; node; node = node->next)
3156 {
3157 if (node->type == vtoy_menu_pwd_file)
3158 {
3159 if (node->pathlen == len && ventoy_strncmp(node->isopath, isopath, len) == 0)
3160 {
3161 return &(node->password);
3162 }
3163 }
3164 }
3165
3166 for (node = g_pwd_head; node; node = node->next)
3167 {
3168 if (node->type == vtoy_menu_pwd_parent)
3169 {
3170 if (node->pathlen < len && ventoy_plugin_is_parent(node->isopath, node->pathlen, isopath))
3171 {
3172 return &(node->password);
3173 }
3174 }
3175 }
3176 }
3177
3178 while (*isopath)
3179 {
3180 if (*isopath == '.')
3181 {
3182 pos = isopath;
3183 }
3184 isopath++;
3185 }
3186
3187 if (pos)
3188 {
3189 for (i = 0; i < (int)ARRAY_SIZE(g_menu_prefix); i++)
3190 {
3191 if (g_file_type_pwd[i].type && 0 == grub_strcasecmp(pos + 1, g_menu_prefix[i]))
3192 {
3193 return g_file_type_pwd + i;
3194 }
3195 }
3196 }
3197
3198 return NULL;
3199 }
3200
3201 grub_err_t ventoy_cmd_check_password(grub_extcmd_context_t ctxt, int argc, char **args)
3202 {
3203 int ret;
3204 const vtoy_password *pwd = NULL;
3205
3206 (void)ctxt;
3207 (void)argc;
3208
3209 pwd = ventoy_plugin_get_password(args[0]);
3210 if (pwd)
3211 {
3212 if (0 == ventoy_check_password(pwd, 1))
3213 {
3214 ret = 1;
3215 }
3216 else
3217 {
3218 ret = 0;
3219 }
3220 }
3221 else
3222 {
3223 ret = 1;
3224 }
3225
3226 grub_errno = 0;
3227 return ret;
3228 }
3229
3230 grub_err_t ventoy_cmd_plugin_check_json(grub_extcmd_context_t ctxt, int argc, char **args)
3231 {
3232 int i = 0;
3233 int ret = 0;
3234 char *buf = NULL;
3235 char key[128];
3236 grub_file_t file;
3237 VTOY_JSON *node = NULL;
3238 VTOY_JSON *json = NULL;
3239
3240 (void)ctxt;
3241
3242 if (argc != 3)
3243 {
3244 return 0;
3245 }
3246
3247 file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s/ventoy/ventoy.json", args[0]);
3248 if (!file)
3249 {
3250 grub_printf("Plugin json file /ventoy/ventoy.json does NOT exist.\n");
3251 grub_printf("Attention: directory name and filename are both case-sensitive.\n");
3252 goto end;
3253 }
3254
3255 buf = grub_malloc(file->size + 1);
3256 if (!buf)
3257 {
3258 grub_printf("Failed to malloc memory %lu.\n", (ulong)(file->size + 1));
3259 goto end;
3260 }
3261
3262 buf[file->size] = 0;
3263 grub_file_read(file, buf, file->size);
3264
3265 json = vtoy_json_create();
3266 if (!json)
3267 {
3268 grub_printf("Failed to create json\n");
3269 goto end;
3270 }
3271
3272 ret = vtoy_json_parse(json, buf);
3273 if (ret)
3274 {
3275 grub_printf("Syntax error detected in ventoy.json, please check it.\n");
3276 goto end;
3277 }
3278
3279 grub_snprintf(key, sizeof(key), "%s_%s", args[1], g_arch_mode_suffix);
3280 for (node = json->pstChild; node; node = node->pstNext)
3281 {
3282 if (grub_strcmp(node->pcName, key) == 0)
3283 {
3284 break;
3285 }
3286 }
3287
3288 if (!node)
3289 {
3290 for (node = json->pstChild; node; node = node->pstNext)
3291 {
3292 if (grub_strcmp(node->pcName, args[1]) == 0)
3293 {
3294 break;
3295 }
3296 }
3297
3298 if (!node)
3299 {
3300 grub_printf("%s is NOT found in ventoy.json\n", args[1]);
3301 goto end;
3302 }
3303 }
3304
3305 for (i = 0; i < (int)ARRAY_SIZE(g_plugin_entries); i++)
3306 {
3307 if (grub_strcmp(g_plugin_entries[i].key, args[1]) == 0)
3308 {
3309 if (g_plugin_entries[i].checkfunc)
3310 {
3311 ret = g_plugin_entries[i].checkfunc(node, args[2]);
3312 }
3313 break;
3314 }
3315 }
3316
3317 end:
3318 check_free(file, grub_file_close);
3319 check_free(json, vtoy_json_destroy);
3320 grub_check_free(buf);
3321
3322 return 0;
3323 }
3324
3325 grub_err_t ventoy_cmd_select_theme_cfg(grub_extcmd_context_t ctxt, int argc, char **args)
3326 {
3327 int pos = 0;
3328 int bufsize = 0;
3329 char *name = NULL;
3330 char *buf = NULL;
3331 theme_list *node = NULL;
3332
3333 (void)argc;
3334 (void)args;
3335 (void)ctxt;
3336
3337 if (g_theme_single_file[0])
3338 {
3339 return 0;
3340 }
3341
3342 if (g_theme_num < 2)
3343 {
3344 return 0;
3345 }
3346
3347 bufsize = (g_theme_num + 1) * 1024;
3348 buf = grub_malloc(bufsize);
3349 if (!buf)
3350 {
3351 return 0;
3352 }
3353
3354 for (node = g_theme_head; node; node = node->next)
3355 {
3356 name = grub_strstr(node->theme.path, ")/");
3357 if (name)
3358 {
3359 name++;
3360 }
3361 else
3362 {
3363 name = node->theme.path;
3364 }
3365
3366 pos += grub_snprintf(buf + pos, bufsize - pos,
3367 "menuentry \"%s\" --class=debug_theme_item --class=debug_theme_select --class=F5tool {\n"
3368 "vt_set_theme_path \"%s\"\n"
3369 "}\n",
3370 name, node->theme.path);
3371 }
3372
3373 pos += grub_snprintf(buf + pos, bufsize - pos,
3374 "menuentry '@VTMENU_RETURN_PREVIOUS' --class=vtoyret VTOY_RET {\n"
3375 "echo 'Return ...'\n"
3376 "}\n");
3377
3378 grub_script_execute_sourcecode(buf);
3379 grub_free(buf);
3380
3381 return 0;
3382 }
3383
3384 grub_err_t ventoy_cmd_set_theme(grub_extcmd_context_t ctxt, int argc, char **args)
3385 {
3386 grub_uint32_t i = 0;
3387 grub_uint32_t mod = 0;
3388 theme_list *node = g_theme_head;
3389 struct grub_datetime datetime;
3390
3391 (void)argc;
3392 (void)args;
3393 (void)ctxt;
3394
3395 if (g_theme_single_file[0])
3396 {
3397 debug("single theme %s\n", g_theme_single_file);
3398 grub_env_set("theme", g_theme_single_file);
3399 goto end;
3400 }
3401
3402 debug("g_theme_num = %d\n", g_theme_num);
3403
3404 if (g_theme_num == 0)
3405 {
3406 goto end;
3407 }
3408
3409 if (g_theme_id > 0 && g_theme_id <= g_theme_num)
3410 {
3411 for (i = 0; i < (grub_uint32_t)(g_theme_id - 1) && node; i++)
3412 {
3413 node = node->next;
3414 }
3415
3416 grub_env_set("theme", node->theme.path);
3417 goto end;
3418 }
3419
3420 grub_memset(&datetime, 0, sizeof(datetime));
3421 grub_get_datetime(&datetime);
3422
3423 if (g_theme_random == vtoy_theme_random_boot_second)
3424 {
3425 grub_divmod32((grub_uint32_t)datetime.second, (grub_uint32_t)g_theme_num, &mod);
3426 }
3427 else if (g_theme_random == vtoy_theme_random_boot_day)
3428 {
3429 grub_divmod32((grub_uint32_t)datetime.day, (grub_uint32_t)g_theme_num, &mod);
3430 }
3431 else if (g_theme_random == vtoy_theme_random_boot_month)
3432 {
3433 grub_divmod32((grub_uint32_t)datetime.month, (grub_uint32_t)g_theme_num, &mod);
3434 }
3435
3436 debug("%04d/%02d/%02d %02d:%02d:%02d radom:%d mod:%d\n",
3437 datetime.year, datetime.month, datetime.day,
3438 datetime.hour, datetime.minute, datetime.second,
3439 g_theme_random, mod);
3440
3441 for (i = 0; i < mod && node; i++)
3442 {
3443 node = node->next;
3444 }
3445
3446 debug("random theme %s\n", node->theme.path);
3447 grub_env_set("theme", node->theme.path);
3448
3449 end:
3450
3451 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3452 }
3453
3454 extern char g_ventoy_theme_path[256];
3455 grub_err_t ventoy_cmd_set_theme_path(grub_extcmd_context_t ctxt, int argc, char **args)
3456 {
3457 (void)argc;
3458 (void)ctxt;
3459
3460 if (argc == 0)
3461 {
3462 g_ventoy_theme_path[0] = 0;
3463 }
3464 else
3465 {
3466 grub_snprintf(g_ventoy_theme_path, sizeof(g_ventoy_theme_path), "%s", args[0]);
3467 }
3468
3469 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3470 }
3471
3472 const char *ventoy_get_vmenu_title(const char *vMenu)
3473 {
3474 return vtoy_json_get_string_ex(g_menu_lang_json->pstChild, vMenu);
3475 }
3476
3477 int ventoy_plugin_load_menu_lang(const char *lang)
3478 {
3479 int ret = 1;
3480 grub_file_t file = NULL;
3481 char *buf = NULL;
3482
3483 if (grub_strcmp(lang, g_cur_menu_language) == 0)
3484 {
3485 debug("Same menu lang %s\n", lang);
3486 return 0;
3487 }
3488 grub_snprintf(g_cur_menu_language, sizeof(g_cur_menu_language), "%s", lang);
3489
3490 debug("Load menu lang %s\n", g_cur_menu_language);
3491
3492 if (g_menu_lang_json)
3493 {
3494 vtoy_json_destroy(g_menu_lang_json);
3495 g_menu_lang_json = NULL;
3496 }
3497
3498 g_menu_lang_json = vtoy_json_create();
3499 if (!g_menu_lang_json)
3500 {
3501 goto end;
3502 }
3503
3504 file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "(vt_menu_tarfs)/menu/%s.json", lang);
3505 if (!file)
3506 {
3507 goto end;
3508 }
3509
3510 buf = grub_malloc(file->size + 1);
3511 if (!buf)
3512 {
3513 grub_printf("Failed to malloc memory %lu.\n", (ulong)(file->size + 1));
3514 goto end;
3515 }
3516
3517 buf[file->size] = 0;
3518 grub_file_read(file, buf, file->size);
3519
3520 vtoy_json_parse(g_menu_lang_json, buf);
3521
3522 if (g_default_menu_mode == 0)
3523 {
3524 grub_snprintf(g_ventoy_hotkey_tip, sizeof(g_ventoy_hotkey_tip), "%s", ventoy_get_vmenu_title("VTMENU_STR_HOTKEY_TREE"));
3525 }
3526 else
3527 {
3528 grub_snprintf(g_ventoy_hotkey_tip, sizeof(g_ventoy_hotkey_tip), "%s", ventoy_get_vmenu_title("VTMENU_STR_HOTKEY_LIST"));
3529 }
3530
3531 ventoy_menu_push_key(GRUB_TERM_ESC);
3532 ventoy_menu_push_key(GRUB_TERM_ESC);
3533 g_ventoy_menu_refresh = 1;
3534 ret = 0;
3535
3536 end:
3537
3538 check_free(file, grub_file_close);
3539 grub_check_free(buf);
3540
3541 return ret;
3542 }
3543
3544 grub_err_t ventoy_cmd_cur_menu_lang(grub_extcmd_context_t ctxt, int argc, char **args)
3545 {
3546 (void)ctxt;
3547 (void)argc;
3548
3549 if (argc > 0)
3550 {
3551 grub_env_set(args[0], g_cur_menu_language);
3552 }
3553 else
3554 {
3555 grub_printf("%s\n", g_cur_menu_language);
3556 grub_printf("%s\n", g_ventoy_hotkey_tip);
3557 grub_refresh();
3558 }
3559
3560 VENTOY_CMD_RETURN(0);
3561 }
3562