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