]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c
abecbb9e10e1e257fe87bc7f36e96817ecd46dd8
[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 const char *env = NULL;
2452 grub_uint8_t *code = NULL;
2453 grub_file_t file;
2454 VTOY_JSON *json = NULL;
2455
2456 (void)ctxt;
2457 (void)argc;
2458
2459 grub_env_set("VTOY_TIP_LEFT", "10%");
2460 grub_env_set("VTOY_TIP_TOP", "80%+5");
2461 grub_env_set("VTOY_TIP_COLOR", "blue");
2462 grub_env_set("VTOY_TIP_ALIGN", "left");
2463
2464 file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s/ventoy/ventoy.json", args[0]);
2465 if (!file)
2466 {
2467 return GRUB_ERR_NONE;
2468 }
2469
2470 debug("json configuration file size %d\n", (int)file->size);
2471
2472 buf = grub_malloc(file->size + 1);
2473 if (!buf)
2474 {
2475 grub_file_close(file);
2476 return 1;
2477 }
2478
2479 buf[file->size] = 0;
2480 grub_file_read(file, buf, file->size);
2481 grub_file_close(file);
2482
2483 json = vtoy_json_create();
2484 if (!json)
2485 {
2486 return 1;
2487 }
2488
2489 code = (grub_uint8_t *)buf;
2490 if (code[0] == 0xef && code[1] == 0xbb && code[2] == 0xbf)
2491 {
2492 offset = 3; /* Skip UTF-8 BOM */
2493 }
2494 else if ((code[0] == 0xff && code[1] == 0xfe) || (code[0] == 0xfe && code[1] == 0xff))
2495 {
2496 grub_env_set("VTOY_PLUGIN_SYNTAX_ERROR", "1");
2497 grub_env_export("VTOY_PLUGIN_SYNTAX_ERROR");
2498
2499 grub_env_set("VTOY_PLUGIN_ENCODE_ERROR", "1");
2500 grub_env_export("VTOY_PLUGIN_ENCODE_ERROR");
2501
2502 debug("Failed to parse json string %d\n", ret);
2503 grub_free(buf);
2504 return 1;
2505 }
2506
2507 ret = vtoy_json_parse(json, buf + offset);
2508 if (ret)
2509 {
2510 grub_env_set("VTOY_PLUGIN_SYNTAX_ERROR", "1");
2511 grub_env_export("VTOY_PLUGIN_SYNTAX_ERROR");
2512
2513 debug("Failed to parse json string %d\n", ret);
2514 grub_free(buf);
2515 return 1;
2516 }
2517
2518 ventoy_parse_plugin_config(json->pstChild, args[0]);
2519
2520 vtoy_json_destroy(json);
2521
2522 grub_free(buf);
2523
2524 if (g_boot_pwd.type)
2525 {
2526 grub_printf("\n\n======= %s ======\n\n", grub_env_get("VTOY_TEXT_MENU_VER"));
2527 if (ventoy_check_password(&g_boot_pwd, 3))
2528 {
2529 grub_printf("\n!!! Password check failed, will exit after 5 seconds. !!!\n");
2530 grub_refresh();
2531 grub_sleep(5);
2532 grub_exit();
2533 }
2534 }
2535
2536 if (g_menu_tip_head)
2537 {
2538 grub_env_set("VTOY_MENU_TIP_ENABLE", "1");
2539 }
2540 else
2541 {
2542 grub_env_unset("VTOY_MENU_TIP_ENABLE");
2543 }
2544
2545 env = grub_env_get("VTOY_MENU_LANGUAGE");
2546 ventoy_plugin_load_menu_lang(env ? env : "en_US");
2547
2548 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2549 }
2550
2551 void ventoy_plugin_dump_injection(void)
2552 {
2553 injection_config *node = NULL;
2554
2555 for (node = g_injection_head; node; node = node->next)
2556 {
2557 grub_printf("\n%s:<%s>\n", (node->type == injection_type_file) ? "IMAGE" : "PARENT", node->isopath);
2558 grub_printf("ARCHIVE:<%s>\n", node->archive);
2559 }
2560
2561 return;
2562 }
2563
2564
2565 void ventoy_plugin_dump_auto_install(void)
2566 {
2567 int i;
2568 install_template *node = NULL;
2569
2570 for (node = g_install_template_head; node; node = node->next)
2571 {
2572 grub_printf("\n%s:<%s> <%d>\n",
2573 (node->type == auto_install_type_file) ? "IMAGE" : "PARENT",
2574 node->isopath, node->templatenum);
2575 for (i = 0; i < node->templatenum; i++)
2576 {
2577 grub_printf("SCRIPT %d:<%s>\n", i, node->templatepath[i].path);
2578 }
2579 }
2580
2581 return;
2582 }
2583
2584 void ventoy_plugin_dump_persistence(void)
2585 {
2586 int rc;
2587 int i = 0;
2588 persistence_config *node = NULL;
2589 ventoy_img_chunk_list chunk_list;
2590
2591 for (node = g_persistence_head; node; node = node->next)
2592 {
2593 grub_printf("\nIMAGE:<%s> <%d>\n", node->isopath, node->backendnum);
2594
2595 for (i = 0; i < node->backendnum; i++)
2596 {
2597 grub_printf("PERSIST %d:<%s>", i, node->backendpath[i].path);
2598 rc = ventoy_plugin_get_persistent_chunklist(node->isopath, i, &chunk_list);
2599 if (rc == 0)
2600 {
2601 grub_printf(" [ SUCCESS ]\n");
2602 grub_free(chunk_list.chunk);
2603 }
2604 else
2605 {
2606 grub_printf(" [ FAILED ]\n");
2607 }
2608 }
2609 }
2610
2611 return;
2612 }
2613
2614 install_template * ventoy_plugin_find_install_template(const char *isopath)
2615 {
2616 int len;
2617 install_template *node = NULL;
2618
2619 if (!g_install_template_head)
2620 {
2621 return NULL;
2622 }
2623
2624 len = (int)grub_strlen(isopath);
2625 for (node = g_install_template_head; node; node = node->next)
2626 {
2627 if (node->type == auto_install_type_file)
2628 {
2629 if (node->pathlen == len && ventoy_strcmp(node->isopath, isopath) == 0)
2630 {
2631 return node;
2632 }
2633 }
2634 }
2635
2636 for (node = g_install_template_head; node; node = node->next)
2637 {
2638 if (node->type == auto_install_type_parent)
2639 {
2640 if (node->pathlen < len && ventoy_plugin_is_parent(node->isopath, node->pathlen, isopath))
2641 {
2642 return node;
2643 }
2644 }
2645 }
2646
2647 return NULL;
2648 }
2649
2650 char * ventoy_plugin_get_cur_install_template(const char *isopath, install_template **cur)
2651 {
2652 install_template *node = NULL;
2653
2654 if (cur)
2655 {
2656 *cur = NULL;
2657 }
2658
2659 node = ventoy_plugin_find_install_template(isopath);
2660 if ((!node) || (!node->templatepath))
2661 {
2662 return NULL;
2663 }
2664
2665 if (node->cursel < 0 || node->cursel >= node->templatenum)
2666 {
2667 return NULL;
2668 }
2669
2670 if (cur)
2671 {
2672 *cur = node;
2673 }
2674
2675 return node->templatepath[node->cursel].path;
2676 }
2677
2678 persistence_config * ventoy_plugin_find_persistent(const char *isopath)
2679 {
2680 int len;
2681 persistence_config *node = NULL;
2682
2683 if (!g_persistence_head)
2684 {
2685 return NULL;
2686 }
2687
2688 len = (int)grub_strlen(isopath);
2689 for (node = g_persistence_head; node; node = node->next)
2690 {
2691 if ((len == node->pathlen) && (ventoy_strcmp(node->isopath, isopath) == 0))
2692 {
2693 return node;
2694 }
2695 }
2696
2697 return NULL;
2698 }
2699
2700 int ventoy_plugin_get_persistent_chunklist(const char *isopath, int index, ventoy_img_chunk_list *chunk_list)
2701 {
2702 int rc = 1;
2703 int len = 0;
2704 char *path = NULL;
2705 grub_uint64_t start = 0;
2706 grub_file_t file = NULL;
2707 persistence_config *node = NULL;
2708
2709 node = ventoy_plugin_find_persistent(isopath);
2710 if ((!node) || (!node->backendpath))
2711 {
2712 return 1;
2713 }
2714
2715 if (index < 0)
2716 {
2717 index = node->cursel;
2718 }
2719
2720 if (index < 0 || index >= node->backendnum)
2721 {
2722 return 1;
2723 }
2724
2725 path = node->backendpath[index].path;
2726
2727 if (node->backendpath[index].vlnk_add == 0)
2728 {
2729 len = grub_strlen(path);
2730 if (len > 9 && grub_strncmp(path + len - 9, ".vlnk.dat", 9) == 0)
2731 {
2732 ventoy_add_vlnk_file(NULL, path);
2733 node->backendpath[index].vlnk_add = 1;
2734 }
2735 }
2736
2737 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", g_iso_disk_name, path);
2738 if (!file)
2739 {
2740 debug("Failed to open file %s%s\n", g_iso_disk_name, path);
2741 goto end;
2742 }
2743
2744 grub_memset(chunk_list, 0, sizeof(ventoy_img_chunk_list));
2745 chunk_list->chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
2746 if (NULL == chunk_list->chunk)
2747 {
2748 goto end;
2749 }
2750
2751 chunk_list->max_chunk = DEFAULT_CHUNK_NUM;
2752 chunk_list->cur_chunk = 0;
2753
2754 start = file->device->disk->partition->start;
2755 ventoy_get_block_list(file, chunk_list, start);
2756
2757 if (0 != ventoy_check_block_list(file, chunk_list, start))
2758 {
2759 grub_free(chunk_list->chunk);
2760 chunk_list->chunk = NULL;
2761 goto end;
2762 }
2763
2764 rc = 0;
2765
2766 end:
2767 if (file)
2768 grub_file_close(file);
2769
2770 return rc;
2771 }
2772
2773 const char * ventoy_plugin_get_injection(const char *isopath)
2774 {
2775 int len;
2776 injection_config *node = NULL;
2777
2778 if (!g_injection_head)
2779 {
2780 return NULL;
2781 }
2782
2783 len = (int)grub_strlen(isopath);
2784 for (node = g_injection_head; node; node = node->next)
2785 {
2786 if (node->type == injection_type_file)
2787 {
2788 if (node->pathlen == len && ventoy_strcmp(node->isopath, isopath) == 0)
2789 {
2790 return node->archive;
2791 }
2792 }
2793 }
2794
2795 for (node = g_injection_head; node; node = node->next)
2796 {
2797 if (node->type == injection_type_parent)
2798 {
2799 if (node->pathlen < len && ventoy_plugin_is_parent(node->isopath, node->pathlen, isopath))
2800 {
2801 return node->archive;
2802 }
2803 }
2804 }
2805
2806 return NULL;
2807 }
2808
2809 const char * ventoy_plugin_get_menu_alias(int type, const char *isopath)
2810 {
2811 int len;
2812 menu_alias *node = NULL;
2813
2814 if (!g_menu_alias_head)
2815 {
2816 return NULL;
2817 }
2818
2819 len = (int)grub_strlen(isopath);
2820 for (node = g_menu_alias_head; node; node = node->next)
2821 {
2822 if (node->type == type && node->pathlen &&
2823 node->pathlen == len && ventoy_strcmp(node->isopath, isopath) == 0)
2824 {
2825 return node->alias;
2826 }
2827 }
2828
2829 return NULL;
2830 }
2831
2832 const menu_tip * ventoy_plugin_get_menu_tip(int type, const char *isopath)
2833 {
2834 int len;
2835 menu_tip *node = NULL;
2836
2837 if (!g_menu_tip_head)
2838 {
2839 return NULL;
2840 }
2841
2842 len = (int)grub_strlen(isopath);
2843 for (node = g_menu_tip_head; node; node = node->next)
2844 {
2845 if (node->type == type && node->pathlen &&
2846 node->pathlen == len && ventoy_strcmp(node->isopath, isopath) == 0)
2847 {
2848 return node;
2849 }
2850 }
2851
2852 return NULL;
2853 }
2854
2855 const char * ventoy_plugin_get_menu_class(int type, const char *name, const char *path)
2856 {
2857 int namelen;
2858 int pathlen;
2859 menu_class *node = NULL;
2860
2861 if (!g_menu_class_head)
2862 {
2863 return NULL;
2864 }
2865
2866 namelen = (int)grub_strlen(name);
2867 pathlen = (int)grub_strlen(path);
2868
2869 if (vtoy_class_image_file == type)
2870 {
2871 for (node = g_menu_class_head; node; node = node->next)
2872 {
2873 if (node->type != type)
2874 {
2875 continue;
2876 }
2877
2878 if (node->parent == 0)
2879 {
2880 if ((node->patlen < namelen) && grub_strstr(name, node->pattern))
2881 {
2882 return node->class;
2883 }
2884 }
2885 }
2886
2887 for (node = g_menu_class_head; node; node = node->next)
2888 {
2889 if (node->type != type)
2890 {
2891 continue;
2892 }
2893
2894 if (node->parent)
2895 {
2896 if ((node->patlen < pathlen) && ventoy_plugin_is_parent(node->pattern, node->patlen, path))
2897 {
2898 return node->class;
2899 }
2900 }
2901 }
2902 }
2903 else
2904 {
2905 for (node = g_menu_class_head; node; node = node->next)
2906 {
2907 if (node->type == type && node->patlen == namelen && grub_strncmp(name, node->pattern, namelen) == 0)
2908 {
2909 return node->class;
2910 }
2911 }
2912 }
2913
2914 return NULL;
2915 }
2916
2917 int ventoy_plugin_add_custom_boot(const char *vcfgpath)
2918 {
2919 int len;
2920 custom_boot *node = NULL;
2921
2922 node = grub_zalloc(sizeof(custom_boot));
2923 if (node)
2924 {
2925 node->type = vtoy_custom_boot_image_file;
2926 node->pathlen = grub_snprintf(node->path, sizeof(node->path), "%s", vcfgpath);
2927 grub_snprintf(node->cfg, sizeof(node->cfg), "%s", vcfgpath);
2928
2929 /* .vcfg */
2930 len = node->pathlen - 5;
2931 node->path[len] = 0;
2932 node->pathlen = len;
2933
2934 if (g_custom_boot_head)
2935 {
2936 node->next = g_custom_boot_head;
2937 }
2938 g_custom_boot_head = node;
2939 }
2940
2941 return 0;
2942 }
2943
2944 const char * ventoy_plugin_get_custom_boot(const char *isopath)
2945 {
2946 int i;
2947 int len;
2948 custom_boot *node = NULL;
2949
2950 if (!g_custom_boot_head)
2951 {
2952 return NULL;
2953 }
2954
2955 len = (int)grub_strlen(isopath);
2956
2957 for (node = g_custom_boot_head; node; node = node->next)
2958 {
2959 if (node->type == vtoy_custom_boot_image_file)
2960 {
2961 if (node->pathlen == len && grub_strncmp(isopath, node->path, len) == 0)
2962 {
2963 return node->cfg;
2964 }
2965 }
2966 else
2967 {
2968 if (node->pathlen < len && isopath[node->pathlen] == '/' &&
2969 grub_strncmp(isopath, node->path, node->pathlen) == 0)
2970 {
2971 for (i = node->pathlen + 1; i < len; i++)
2972 {
2973 if (isopath[i] == '/')
2974 {
2975 break;
2976 }
2977 }
2978
2979 if (i >= len)
2980 {
2981 return node->cfg;
2982 }
2983 }
2984 }
2985 }
2986
2987 return NULL;
2988 }
2989
2990 grub_err_t ventoy_cmd_dump_custom_boot(grub_extcmd_context_t ctxt, int argc, char **args)
2991 {
2992 custom_boot *node = NULL;
2993
2994 (void)argc;
2995 (void)ctxt;
2996 (void)args;
2997
2998 for (node = g_custom_boot_head; node; node = node->next)
2999 {
3000 grub_printf("[%s] <%s>:<%s>\n", (node->type == vtoy_custom_boot_directory) ? "dir" : "file",
3001 node->path, node->cfg);
3002 }
3003
3004 return 0;
3005 }
3006
3007 int ventoy_plugin_check_memdisk(const char *isopath)
3008 {
3009 int len;
3010 auto_memdisk *node = NULL;
3011
3012 if (!g_auto_memdisk_head)
3013 {
3014 return 0;
3015 }
3016
3017 len = (int)grub_strlen(isopath);
3018 for (node = g_auto_memdisk_head; node; node = node->next)
3019 {
3020 if (node->pathlen == len && ventoy_strncmp(node->isopath, isopath, len) == 0)
3021 {
3022 return 1;
3023 }
3024 }
3025
3026 return 0;
3027 }
3028
3029 int ventoy_plugin_get_image_list_index(int type, const char *name)
3030 {
3031 int len;
3032 int index = 1;
3033 image_list *node = NULL;
3034
3035 if (!g_image_list_head)
3036 {
3037 return 0;
3038 }
3039
3040 len = (int)grub_strlen(name);
3041
3042 for (node = g_image_list_head; node; node = node->next, index++)
3043 {
3044 if (vtoy_class_directory == type)
3045 {
3046 if (len < node->pathlen && ventoy_strncmp(node->isopath, name, len) == 0)
3047 {
3048 return index;
3049 }
3050 }
3051 else
3052 {
3053 if (len == node->pathlen && ventoy_strncmp(node->isopath, name, len) == 0)
3054 {
3055 return index;
3056 }
3057 }
3058 }
3059
3060 return 0;
3061 }
3062
3063 int ventoy_plugin_find_conf_replace(const char *iso, conf_replace *nodes[VTOY_MAX_CONF_REPLACE])
3064 {
3065 int n = 0;
3066 int len;
3067 conf_replace *node;
3068
3069 if (!g_conf_replace_head)
3070 {
3071 return 0;
3072 }
3073
3074 len = (int)grub_strlen(iso);
3075
3076 for (node = g_conf_replace_head; node; node = node->next)
3077 {
3078 if (node->pathlen == len && ventoy_strncmp(node->isopath, iso, len) == 0)
3079 {
3080 nodes[n++] = node;
3081 if (n >= VTOY_MAX_CONF_REPLACE)
3082 {
3083 return n;
3084 }
3085 }
3086 }
3087
3088 return n;
3089 }
3090
3091 dud * ventoy_plugin_find_dud(const char *iso)
3092 {
3093 int len;
3094 dud *node;
3095
3096 if (!g_dud_head)
3097 {
3098 return NULL;
3099 }
3100
3101 len = (int)grub_strlen(iso);
3102 for (node = g_dud_head; node; node = node->next)
3103 {
3104 if (node->pathlen == len && ventoy_strncmp(node->isopath, iso, len) == 0)
3105 {
3106 return node;
3107 }
3108 }
3109
3110 return NULL;
3111 }
3112
3113 int ventoy_plugin_load_dud(dud *node, const char *isopart)
3114 {
3115 int i;
3116 char *buf;
3117 grub_file_t file;
3118
3119 for (i = 0; i < node->dudnum; i++)
3120 {
3121 if (node->files[i].size > 0)
3122 {
3123 debug("file %d has been loaded\n", i);
3124 continue;
3125 }
3126
3127 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", isopart, node->dudpath[i].path);
3128 if (file)
3129 {
3130 buf = grub_malloc(file->size);
3131 if (buf)
3132 {
3133 grub_file_read(file, buf, file->size);
3134 node->files[i].size = (int)file->size;
3135 node->files[i].buf = buf;
3136 }
3137 grub_file_close(file);
3138 }
3139 }
3140
3141 return 0;
3142 }
3143
3144 static const vtoy_password * ventoy_plugin_get_password(const char *isopath)
3145 {
3146 int i;
3147 int len;
3148 const char *pos = NULL;
3149 menu_password *node = NULL;
3150
3151 if (!isopath)
3152 {
3153 return NULL;
3154 }
3155
3156 if (g_pwd_head)
3157 {
3158 len = (int)grub_strlen(isopath);
3159 for (node = g_pwd_head; node; node = node->next)
3160 {
3161 if (node->type == vtoy_menu_pwd_file)
3162 {
3163 if (node->pathlen == len && ventoy_strncmp(node->isopath, isopath, len) == 0)
3164 {
3165 return &(node->password);
3166 }
3167 }
3168 }
3169
3170 for (node = g_pwd_head; node; node = node->next)
3171 {
3172 if (node->type == vtoy_menu_pwd_parent)
3173 {
3174 if (node->pathlen < len && ventoy_plugin_is_parent(node->isopath, node->pathlen, isopath))
3175 {
3176 return &(node->password);
3177 }
3178 }
3179 }
3180 }
3181
3182 while (*isopath)
3183 {
3184 if (*isopath == '.')
3185 {
3186 pos = isopath;
3187 }
3188 isopath++;
3189 }
3190
3191 if (pos)
3192 {
3193 for (i = 0; i < (int)ARRAY_SIZE(g_menu_prefix); i++)
3194 {
3195 if (g_file_type_pwd[i].type && 0 == grub_strcasecmp(pos + 1, g_menu_prefix[i]))
3196 {
3197 return g_file_type_pwd + i;
3198 }
3199 }
3200 }
3201
3202 return NULL;
3203 }
3204
3205 grub_err_t ventoy_cmd_check_password(grub_extcmd_context_t ctxt, int argc, char **args)
3206 {
3207 int ret;
3208 const vtoy_password *pwd = NULL;
3209
3210 (void)ctxt;
3211 (void)argc;
3212
3213 pwd = ventoy_plugin_get_password(args[0]);
3214 if (pwd)
3215 {
3216 if (0 == ventoy_check_password(pwd, 1))
3217 {
3218 ret = 1;
3219 }
3220 else
3221 {
3222 ret = 0;
3223 }
3224 }
3225 else
3226 {
3227 ret = 1;
3228 }
3229
3230 grub_errno = 0;
3231 return ret;
3232 }
3233
3234 grub_err_t ventoy_cmd_plugin_check_json(grub_extcmd_context_t ctxt, int argc, char **args)
3235 {
3236 int i = 0;
3237 int ret = 0;
3238 char *buf = NULL;
3239 char key[128];
3240 grub_file_t file;
3241 VTOY_JSON *node = NULL;
3242 VTOY_JSON *json = NULL;
3243
3244 (void)ctxt;
3245
3246 if (argc != 3)
3247 {
3248 return 0;
3249 }
3250
3251 file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s/ventoy/ventoy.json", args[0]);
3252 if (!file)
3253 {
3254 grub_printf("Plugin json file /ventoy/ventoy.json does NOT exist.\n");
3255 grub_printf("Attention: directory name and filename are both case-sensitive.\n");
3256 goto end;
3257 }
3258
3259 buf = grub_malloc(file->size + 1);
3260 if (!buf)
3261 {
3262 grub_printf("Failed to malloc memory %lu.\n", (ulong)(file->size + 1));
3263 goto end;
3264 }
3265
3266 buf[file->size] = 0;
3267 grub_file_read(file, buf, file->size);
3268
3269 json = vtoy_json_create();
3270 if (!json)
3271 {
3272 grub_printf("Failed to create json\n");
3273 goto end;
3274 }
3275
3276 ret = vtoy_json_parse(json, buf);
3277 if (ret)
3278 {
3279 grub_printf("Syntax error detected in ventoy.json, please check it.\n");
3280 goto end;
3281 }
3282
3283 grub_snprintf(key, sizeof(key), "%s_%s", args[1], g_arch_mode_suffix);
3284 for (node = json->pstChild; node; node = node->pstNext)
3285 {
3286 if (grub_strcmp(node->pcName, key) == 0)
3287 {
3288 break;
3289 }
3290 }
3291
3292 if (!node)
3293 {
3294 for (node = json->pstChild; node; node = node->pstNext)
3295 {
3296 if (grub_strcmp(node->pcName, args[1]) == 0)
3297 {
3298 break;
3299 }
3300 }
3301
3302 if (!node)
3303 {
3304 grub_printf("%s is NOT found in ventoy.json\n", args[1]);
3305 goto end;
3306 }
3307 }
3308
3309 for (i = 0; i < (int)ARRAY_SIZE(g_plugin_entries); i++)
3310 {
3311 if (grub_strcmp(g_plugin_entries[i].key, args[1]) == 0)
3312 {
3313 if (g_plugin_entries[i].checkfunc)
3314 {
3315 ret = g_plugin_entries[i].checkfunc(node, args[2]);
3316 }
3317 break;
3318 }
3319 }
3320
3321 end:
3322 check_free(file, grub_file_close);
3323 check_free(json, vtoy_json_destroy);
3324 grub_check_free(buf);
3325
3326 return 0;
3327 }
3328
3329 grub_err_t ventoy_cmd_select_theme_cfg(grub_extcmd_context_t ctxt, int argc, char **args)
3330 {
3331 int pos = 0;
3332 int bufsize = 0;
3333 char *name = NULL;
3334 char *buf = NULL;
3335 theme_list *node = NULL;
3336
3337 (void)argc;
3338 (void)args;
3339 (void)ctxt;
3340
3341 if (g_theme_single_file[0])
3342 {
3343 return 0;
3344 }
3345
3346 if (g_theme_num < 2)
3347 {
3348 return 0;
3349 }
3350
3351 bufsize = (g_theme_num + 1) * 1024;
3352 buf = grub_malloc(bufsize);
3353 if (!buf)
3354 {
3355 return 0;
3356 }
3357
3358 for (node = g_theme_head; node; node = node->next)
3359 {
3360 name = grub_strstr(node->theme.path, ")/");
3361 if (name)
3362 {
3363 name++;
3364 }
3365 else
3366 {
3367 name = node->theme.path;
3368 }
3369
3370 pos += grub_snprintf(buf + pos, bufsize - pos,
3371 "menuentry \"%s\" --class=debug_theme_item --class=debug_theme_select --class=F5tool {\n"
3372 "vt_set_theme_path \"%s\"\n"
3373 "}\n",
3374 name, node->theme.path);
3375 }
3376
3377 pos += grub_snprintf(buf + pos, bufsize - pos,
3378 "menuentry '@VTMENU_RETURN_PREVIOUS' --class=vtoyret VTOY_RET {\n"
3379 "echo 'Return ...'\n"
3380 "}\n");
3381
3382 grub_script_execute_sourcecode(buf);
3383 grub_free(buf);
3384
3385 return 0;
3386 }
3387
3388 grub_err_t ventoy_cmd_set_theme(grub_extcmd_context_t ctxt, int argc, char **args)
3389 {
3390 grub_uint32_t i = 0;
3391 grub_uint32_t mod = 0;
3392 theme_list *node = g_theme_head;
3393 struct grub_datetime datetime;
3394
3395 (void)argc;
3396 (void)args;
3397 (void)ctxt;
3398
3399 if (g_theme_single_file[0])
3400 {
3401 debug("single theme %s\n", g_theme_single_file);
3402 grub_env_set("theme", g_theme_single_file);
3403 goto end;
3404 }
3405
3406 debug("g_theme_num = %d\n", g_theme_num);
3407
3408 if (g_theme_num == 0)
3409 {
3410 goto end;
3411 }
3412
3413 if (g_theme_id > 0 && g_theme_id <= g_theme_num)
3414 {
3415 for (i = 0; i < (grub_uint32_t)(g_theme_id - 1) && node; i++)
3416 {
3417 node = node->next;
3418 }
3419
3420 grub_env_set("theme", node->theme.path);
3421 goto end;
3422 }
3423
3424 grub_memset(&datetime, 0, sizeof(datetime));
3425 grub_get_datetime(&datetime);
3426
3427 if (g_theme_random == vtoy_theme_random_boot_second)
3428 {
3429 grub_divmod32((grub_uint32_t)datetime.second, (grub_uint32_t)g_theme_num, &mod);
3430 }
3431 else if (g_theme_random == vtoy_theme_random_boot_day)
3432 {
3433 grub_divmod32((grub_uint32_t)datetime.day, (grub_uint32_t)g_theme_num, &mod);
3434 }
3435 else if (g_theme_random == vtoy_theme_random_boot_month)
3436 {
3437 grub_divmod32((grub_uint32_t)datetime.month, (grub_uint32_t)g_theme_num, &mod);
3438 }
3439
3440 debug("%04d/%02d/%02d %02d:%02d:%02d radom:%d mod:%d\n",
3441 datetime.year, datetime.month, datetime.day,
3442 datetime.hour, datetime.minute, datetime.second,
3443 g_theme_random, mod);
3444
3445 for (i = 0; i < mod && node; i++)
3446 {
3447 node = node->next;
3448 }
3449
3450 debug("random theme %s\n", node->theme.path);
3451 grub_env_set("theme", node->theme.path);
3452
3453 end:
3454
3455 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3456 }
3457
3458 extern char g_ventoy_theme_path[256];
3459 grub_err_t ventoy_cmd_set_theme_path(grub_extcmd_context_t ctxt, int argc, char **args)
3460 {
3461 (void)argc;
3462 (void)ctxt;
3463
3464 if (argc == 0)
3465 {
3466 g_ventoy_theme_path[0] = 0;
3467 }
3468 else
3469 {
3470 grub_snprintf(g_ventoy_theme_path, sizeof(g_ventoy_theme_path), "%s", args[0]);
3471 }
3472
3473 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3474 }
3475
3476 const char *ventoy_get_vmenu_title(const char *vMenu)
3477 {
3478 return vtoy_json_get_string_ex(g_menu_lang_json->pstChild, vMenu);
3479 }
3480
3481 int ventoy_plugin_load_menu_lang(const char *lang)
3482 {
3483 int ret = 1;
3484 grub_file_t file = NULL;
3485 char *buf = NULL;
3486
3487 if (grub_strcmp(lang, g_cur_menu_language) == 0)
3488 {
3489 debug("Same menu lang %s\n", lang);
3490 return 0;
3491 }
3492 grub_snprintf(g_cur_menu_language, sizeof(g_cur_menu_language), "%s", lang);
3493
3494 debug("Load menu lang %s\n", g_cur_menu_language);
3495
3496 if (g_menu_lang_json)
3497 {
3498 vtoy_json_destroy(g_menu_lang_json);
3499 g_menu_lang_json = NULL;
3500 }
3501
3502 g_menu_lang_json = vtoy_json_create();
3503 if (!g_menu_lang_json)
3504 {
3505 goto end;
3506 }
3507
3508 file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "(vt_menu_tarfs)/menu/%s.json", lang);
3509 if (!file)
3510 {
3511 goto end;
3512 }
3513
3514 buf = grub_malloc(file->size + 1);
3515 if (!buf)
3516 {
3517 grub_printf("Failed to malloc memory %lu.\n", (ulong)(file->size + 1));
3518 goto end;
3519 }
3520
3521 buf[file->size] = 0;
3522 grub_file_read(file, buf, file->size);
3523
3524 vtoy_json_parse(g_menu_lang_json, buf);
3525
3526 if (g_default_menu_mode == 0)
3527 {
3528 grub_snprintf(g_ventoy_hotkey_tip, sizeof(g_ventoy_hotkey_tip), "%s", ventoy_get_vmenu_title("VTMENU_STR_HOTKEY_TREE"));
3529 }
3530 else
3531 {
3532 grub_snprintf(g_ventoy_hotkey_tip, sizeof(g_ventoy_hotkey_tip), "%s", ventoy_get_vmenu_title("VTMENU_STR_HOTKEY_LIST"));
3533 }
3534
3535 ventoy_menu_push_key(GRUB_TERM_ESC);
3536 ventoy_menu_push_key(GRUB_TERM_ESC);
3537 g_ventoy_menu_refresh = 1;
3538 ret = 0;
3539
3540 end:
3541
3542 check_free(file, grub_file_close);
3543 grub_check_free(buf);
3544
3545 return ret;
3546 }
3547
3548 grub_err_t ventoy_cmd_cur_menu_lang(grub_extcmd_context_t ctxt, int argc, char **args)
3549 {
3550 (void)ctxt;
3551 (void)argc;
3552 (void)args;
3553
3554 grub_printf("%s\n", g_cur_menu_language);
3555 grub_printf("%s\n", g_ventoy_hotkey_tip);
3556 grub_refresh();
3557
3558 VENTOY_CMD_RETURN(0);
3559 }
3560