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