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