]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c
65d57799220e1908fd810868b3dfec7a0e2924a9
[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 int type;
1482 const char *path = NULL;
1483 const char *tip = NULL;
1484 VTOY_JSON *pNode = NULL;
1485
1486 (void)isodisk;
1487
1488 if (json->enDataType != JSON_TYPE_OBJECT)
1489 {
1490 grub_printf("Not object %d\n", json->enDataType);
1491 return 1;
1492 }
1493
1494 tip = vtoy_json_get_string_ex(json->pstChild, "left");
1495 if (tip)
1496 {
1497 grub_printf("left: <%s>\n", tip);
1498 }
1499
1500 tip = vtoy_json_get_string_ex(json->pstChild, "top");
1501 if (tip)
1502 {
1503 grub_printf("top: <%s>\n", tip);
1504 }
1505
1506 tip = vtoy_json_get_string_ex(json->pstChild, "color");
1507 if (tip)
1508 {
1509 grub_printf("color: <%s>\n", tip);
1510 }
1511
1512 pNode = vtoy_json_find_item(json->pstChild, JSON_TYPE_ARRAY, "tips");
1513 for (pNode = pNode->pstChild; pNode; pNode = pNode->pstNext)
1514 {
1515 type = vtoy_tip_image_file;
1516 path = vtoy_json_get_string_ex(pNode->pstChild, "image");
1517 if (!path)
1518 {
1519 path = vtoy_json_get_string_ex(pNode->pstChild, "dir");
1520 type = vtoy_tip_directory;
1521 }
1522
1523 if (path && path[0] == '/')
1524 {
1525 if (vtoy_tip_image_file == type)
1526 {
1527 if (grub_strchr(path, '*'))
1528 {
1529 grub_printf("image: <%s> [ * ]\n", path);
1530 }
1531 else if (ventoy_is_file_exist("%s%s", isodisk, path))
1532 {
1533 grub_printf("image: <%s> [ OK ]\n", path);
1534 }
1535 else
1536 {
1537 grub_printf("image: <%s> [ NOT EXIST ]\n", path);
1538 }
1539 }
1540 else
1541 {
1542 if (ventoy_is_dir_exist("%s%s", isodisk, path))
1543 {
1544 grub_printf("dir: <%s> [ OK ]\n", path);
1545 }
1546 else
1547 {
1548 grub_printf("dir: <%s> [ NOT EXIST ]\n", path);
1549 }
1550 }
1551
1552 tip = vtoy_json_get_string_ex(pNode->pstChild, "tip");
1553 if (tip)
1554 {
1555 grub_printf("tip: <%s>\n", tip);
1556 }
1557 else
1558 {
1559 tip = vtoy_json_get_string_ex(pNode->pstChild, "tip1");
1560 if (tip)
1561 grub_printf("tip1: <%s>\n", tip);
1562 else
1563 grub_printf("tip1: <NULL>\n");
1564
1565 tip = vtoy_json_get_string_ex(pNode->pstChild, "tip2");
1566 if (tip)
1567 grub_printf("tip2: <%s>\n", tip);
1568 else
1569 grub_printf("tip2: <NULL>\n");
1570 }
1571 }
1572 else
1573 {
1574 grub_printf("image: <%s> [ INVALID ]\n", path);
1575 }
1576 }
1577
1578 return 0;
1579 }
1580
1581 static int ventoy_plugin_menutip_entry(VTOY_JSON *json, const char *isodisk)
1582 {
1583 int type;
1584 const char *path = NULL;
1585 const char *tip = NULL;
1586 VTOY_JSON *pNode = NULL;
1587 menu_tip *node = NULL;
1588 menu_tip *next = NULL;
1589
1590 (void)isodisk;
1591
1592 if (json->enDataType != JSON_TYPE_OBJECT)
1593 {
1594 debug("Not object %d\n", json->enDataType);
1595 return 0;
1596 }
1597
1598 pNode = vtoy_json_find_item(json->pstChild, JSON_TYPE_ARRAY, "tips");
1599 if (pNode == NULL)
1600 {
1601 debug("Not tips found\n");
1602 return 0;
1603 }
1604
1605 if (g_menu_tip_head)
1606 {
1607 for (node = g_menu_tip_head; node; node = next)
1608 {
1609 next = node->next;
1610 grub_free(node);
1611 }
1612
1613 g_menu_tip_head = NULL;
1614 }
1615
1616 tip = vtoy_json_get_string_ex(json->pstChild, "left");
1617 if (tip)
1618 {
1619 grub_env_set("VTOY_TIP_LEFT", tip);
1620 }
1621
1622 tip = vtoy_json_get_string_ex(json->pstChild, "top");
1623 if (tip)
1624 {
1625 grub_env_set("VTOY_TIP_TOP", tip);
1626 }
1627
1628 tip = vtoy_json_get_string_ex(json->pstChild, "color");
1629 if (tip)
1630 {
1631 grub_env_set("VTOY_TIP_COLOR", tip);
1632 }
1633
1634 for (pNode = pNode->pstChild; pNode; pNode = pNode->pstNext)
1635 {
1636 type = vtoy_tip_image_file;
1637 path = vtoy_json_get_string_ex(pNode->pstChild, "image");
1638 if (!path)
1639 {
1640 path = vtoy_json_get_string_ex(pNode->pstChild, "dir");
1641 type = vtoy_tip_directory;
1642 }
1643
1644 if (path && path[0] == '/')
1645 {
1646 node = grub_zalloc(sizeof(menu_tip));
1647 if (node)
1648 {
1649 node->type = type;
1650 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", path);
1651
1652 tip = vtoy_json_get_string_ex(pNode->pstChild, "tip");
1653 if (tip)
1654 {
1655 grub_snprintf(node->tip1, 1000, "%s", tip);
1656 }
1657 else
1658 {
1659 tip = vtoy_json_get_string_ex(pNode->pstChild, "tip1");
1660 if (tip)
1661 grub_snprintf(node->tip1, 1000, "%s", tip);
1662
1663 tip = vtoy_json_get_string_ex(pNode->pstChild, "tip2");
1664 if (tip)
1665 grub_snprintf(node->tip2, 1000, "%s", tip);
1666 }
1667
1668 if (g_menu_tip_head)
1669 {
1670 node->next = g_menu_tip_head;
1671 }
1672
1673 g_menu_tip_head = node;
1674 }
1675 }
1676 }
1677
1678 return 0;
1679 }
1680
1681 static int ventoy_plugin_injection_check(VTOY_JSON *json, const char *isodisk)
1682 {
1683 int type = 0;
1684 const char *path = NULL;
1685 const char *archive = NULL;
1686 VTOY_JSON *pNode = NULL;
1687
1688 (void)isodisk;
1689
1690 if (json->enDataType != JSON_TYPE_ARRAY)
1691 {
1692 grub_printf("Not array %d\n", json->enDataType);
1693 return 0;
1694 }
1695
1696 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1697 {
1698 type = injection_type_file;
1699 path = vtoy_json_get_string_ex(pNode->pstChild, "image");
1700 if (!path)
1701 {
1702 type = injection_type_parent;
1703 path = vtoy_json_get_string_ex(pNode->pstChild, "parent");
1704 if (!path)
1705 {
1706 grub_printf("image/parent not found\n");
1707 continue;
1708 }
1709 }
1710
1711 archive = vtoy_json_get_string_ex(pNode->pstChild, "archive");
1712 if (!archive)
1713 {
1714 grub_printf("archive not found\n");
1715 continue;
1716 }
1717
1718 if (type == injection_type_file)
1719 {
1720 if (grub_strchr(path, '*'))
1721 {
1722 grub_printf("image: <%s> [*]\n", path);
1723 }
1724 else
1725 {
1726 grub_printf("image: <%s> [%s]\n", path, ventoy_check_file_exist("%s%s", isodisk, path) ? "OK" : "NOT EXIST");
1727 }
1728 }
1729 else
1730 {
1731 grub_printf("parent: <%s> [%s]\n", path,
1732 ventoy_is_dir_exist("%s%s", isodisk, path) ? "OK" : "NOT EXIST");
1733 }
1734
1735 grub_printf("archive: <%s> [%s]\n\n", archive, ventoy_check_file_exist("%s%s", isodisk, archive) ? "OK" : "NOT EXIST");
1736 }
1737
1738 return 0;
1739 }
1740
1741 static int ventoy_plugin_injection_entry(VTOY_JSON *json, const char *isodisk)
1742 {
1743 int type = 0;
1744 const char *path = NULL;
1745 const char *archive = NULL;
1746 VTOY_JSON *pNode = NULL;
1747 injection_config *node = NULL;
1748 injection_config *next = NULL;
1749
1750 (void)isodisk;
1751
1752 if (json->enDataType != JSON_TYPE_ARRAY)
1753 {
1754 debug("Not array %d\n", json->enDataType);
1755 return 0;
1756 }
1757
1758 if (g_injection_head)
1759 {
1760 for (node = g_injection_head; node; node = next)
1761 {
1762 next = node->next;
1763 grub_free(node);
1764 }
1765
1766 g_injection_head = NULL;
1767 }
1768
1769 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1770 {
1771 type = injection_type_file;
1772 path = vtoy_json_get_string_ex(pNode->pstChild, "image");
1773 if (!path)
1774 {
1775 type = injection_type_parent;
1776 path = vtoy_json_get_string_ex(pNode->pstChild, "parent");
1777 }
1778
1779 archive = vtoy_json_get_string_ex(pNode->pstChild, "archive");
1780 if (path && path[0] == '/' && archive && archive[0] == '/')
1781 {
1782 node = grub_zalloc(sizeof(injection_config));
1783 if (node)
1784 {
1785 node->type = type;
1786 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", path);
1787 grub_snprintf(node->archive, sizeof(node->archive), "%s", archive);
1788
1789 if (g_injection_head)
1790 {
1791 node->next = g_injection_head;
1792 }
1793
1794 g_injection_head = node;
1795 }
1796 }
1797 }
1798
1799 return 0;
1800 }
1801
1802 static int ventoy_plugin_menuclass_entry(VTOY_JSON *json, const char *isodisk)
1803 {
1804 int type;
1805 int parent = 0;
1806 const char *key = NULL;
1807 const char *class = NULL;
1808 VTOY_JSON *pNode = NULL;
1809 menu_class *tail = NULL;
1810 menu_class *node = NULL;
1811 menu_class *next = NULL;
1812
1813 (void)isodisk;
1814
1815 if (json->enDataType != JSON_TYPE_ARRAY)
1816 {
1817 debug("Not array %d\n", json->enDataType);
1818 return 0;
1819 }
1820
1821 if (g_menu_class_head)
1822 {
1823 for (node = g_menu_class_head; node; node = next)
1824 {
1825 next = node->next;
1826 grub_free(node);
1827 }
1828
1829 g_menu_class_head = NULL;
1830 }
1831
1832 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1833 {
1834 parent = 0;
1835 type = vtoy_class_image_file;
1836 key = vtoy_json_get_string_ex(pNode->pstChild, "key");
1837 if (!key)
1838 {
1839 key = vtoy_json_get_string_ex(pNode->pstChild, "parent");
1840 if (key)
1841 {
1842 parent = 1;
1843 }
1844 else
1845 {
1846 key = vtoy_json_get_string_ex(pNode->pstChild, "dir");
1847 type = vtoy_class_directory;
1848 }
1849 }
1850
1851 class = vtoy_json_get_string_ex(pNode->pstChild, "class");
1852 if (key && class)
1853 {
1854 node = grub_zalloc(sizeof(menu_class));
1855 if (node)
1856 {
1857 node->type = type;
1858 node->parent = parent;
1859 node->patlen = grub_snprintf(node->pattern, sizeof(node->pattern), "%s", key);
1860 grub_snprintf(node->class, sizeof(node->class), "%s", class);
1861
1862 if (g_menu_class_head)
1863 {
1864 tail->next = node;
1865 }
1866 else
1867 {
1868 g_menu_class_head = node;
1869 }
1870 tail = node;
1871 }
1872 }
1873 }
1874
1875 return 0;
1876 }
1877
1878 static int ventoy_plugin_menuclass_check(VTOY_JSON *json, const char *isodisk)
1879 {
1880 const char *name = NULL;
1881 const char *key = NULL;
1882 const char *class = NULL;
1883 VTOY_JSON *pNode = NULL;
1884
1885 (void)isodisk;
1886
1887 if (json->enDataType != JSON_TYPE_ARRAY)
1888 {
1889 grub_printf("Not array %d\n", json->enDataType);
1890 return 1;
1891 }
1892
1893 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1894 {
1895 name = "key";
1896 key = vtoy_json_get_string_ex(pNode->pstChild, "key");
1897 if (!key)
1898 {
1899 name = "parent";
1900 key = vtoy_json_get_string_ex(pNode->pstChild, "parent");
1901 if (!key)
1902 {
1903 name = "dir";
1904 key = vtoy_json_get_string_ex(pNode->pstChild, "dir");
1905 }
1906 }
1907
1908 class = vtoy_json_get_string_ex(pNode->pstChild, "class");
1909 if (key && class)
1910 {
1911 grub_printf("%s: <%s>\n", name, key);
1912 grub_printf("class: <%s>\n\n", class);
1913 }
1914 }
1915
1916 return 0;
1917 }
1918
1919 static int ventoy_plugin_custom_boot_entry(VTOY_JSON *json, const char *isodisk)
1920 {
1921 int type;
1922 int len;
1923 const char *key = NULL;
1924 const char *cfg = NULL;
1925 VTOY_JSON *pNode = NULL;
1926 custom_boot *tail = NULL;
1927 custom_boot *node = NULL;
1928 custom_boot *next = NULL;
1929
1930 (void)isodisk;
1931
1932 if (json->enDataType != JSON_TYPE_ARRAY)
1933 {
1934 debug("Not array %d\n", json->enDataType);
1935 return 0;
1936 }
1937
1938 if (g_custom_boot_head)
1939 {
1940 for (node = g_custom_boot_head; node; node = next)
1941 {
1942 next = node->next;
1943 grub_free(node);
1944 }
1945
1946 g_custom_boot_head = NULL;
1947 }
1948
1949 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1950 {
1951 type = vtoy_custom_boot_image_file;
1952 key = vtoy_json_get_string_ex(pNode->pstChild, "file");
1953 if (!key)
1954 {
1955 key = vtoy_json_get_string_ex(pNode->pstChild, "dir");
1956 type = vtoy_custom_boot_directory;
1957 }
1958
1959 cfg = vtoy_json_get_string_ex(pNode->pstChild, "vcfg");
1960 if (key && cfg)
1961 {
1962 node = grub_zalloc(sizeof(custom_boot));
1963 if (node)
1964 {
1965 node->type = type;
1966 node->pathlen = grub_snprintf(node->path, sizeof(node->path), "%s", key);
1967 len = (int)grub_snprintf(node->cfg, sizeof(node->cfg), "%s", cfg);
1968
1969 if (len >= 5 && grub_strncmp(node->cfg + len - 5, ".vcfg", 5) == 0)
1970 {
1971 if (g_custom_boot_head)
1972 {
1973 tail->next = node;
1974 }
1975 else
1976 {
1977 g_custom_boot_head = node;
1978 }
1979 tail = node;
1980 }
1981 else
1982 {
1983 grub_free(node);
1984 }
1985 }
1986 }
1987 }
1988
1989 return 0;
1990 }
1991
1992 static int ventoy_plugin_custom_boot_check(VTOY_JSON *json, const char *isodisk)
1993 {
1994 int type;
1995 int len;
1996 const char *key = NULL;
1997 const char *cfg = NULL;
1998 VTOY_JSON *pNode = NULL;
1999
2000 (void)isodisk;
2001
2002 if (json->enDataType != JSON_TYPE_ARRAY)
2003 {
2004 grub_printf("Not array %d\n", json->enDataType);
2005 return 1;
2006 }
2007
2008 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
2009 {
2010 type = vtoy_custom_boot_image_file;
2011 key = vtoy_json_get_string_ex(pNode->pstChild, "file");
2012 if (!key)
2013 {
2014 key = vtoy_json_get_string_ex(pNode->pstChild, "dir");
2015 type = vtoy_custom_boot_directory;
2016 }
2017
2018 cfg = vtoy_json_get_string_ex(pNode->pstChild, "vcfg");
2019 len = (int)grub_strlen(cfg);
2020 if (key && cfg)
2021 {
2022 if (len < 5 || grub_strncmp(cfg + len - 5, ".vcfg", 5))
2023 {
2024 grub_printf("<%s> does not have \".vcfg\" suffix\n\n", cfg);
2025 }
2026 else
2027 {
2028 grub_printf("%s: <%s>\n", (type == vtoy_custom_boot_directory) ? "dir" : "file", key);
2029 grub_printf("vcfg: <%s>\n\n", cfg);
2030 }
2031 }
2032 }
2033
2034 return 0;
2035 }
2036
2037 static int ventoy_plugin_conf_replace_entry(VTOY_JSON *json, const char *isodisk)
2038 {
2039 int img = 0;
2040 const char *isof = NULL;
2041 const char *orgf = NULL;
2042 const char *newf = NULL;
2043 VTOY_JSON *pNode = NULL;
2044 conf_replace *tail = NULL;
2045 conf_replace *node = NULL;
2046 conf_replace *next = NULL;
2047
2048 (void)isodisk;
2049
2050 if (json->enDataType != JSON_TYPE_ARRAY)
2051 {
2052 debug("Not array %d\n", json->enDataType);
2053 return 0;
2054 }
2055
2056 if (g_conf_replace_head)
2057 {
2058 for (node = g_conf_replace_head; node; node = next)
2059 {
2060 next = node->next;
2061 grub_free(node);
2062 }
2063
2064 g_conf_replace_head = NULL;
2065 }
2066
2067 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
2068 {
2069 isof = vtoy_json_get_string_ex(pNode->pstChild, "iso");
2070 orgf = vtoy_json_get_string_ex(pNode->pstChild, "org");
2071 newf = vtoy_json_get_string_ex(pNode->pstChild, "new");
2072 if (isof && orgf && newf && isof[0] == '/' && orgf[0] == '/' && newf[0] == '/')
2073 {
2074 node = grub_zalloc(sizeof(conf_replace));
2075 if (node)
2076 {
2077 if (JSON_SUCCESS == vtoy_json_get_int(pNode->pstChild, "img", &img))
2078 {
2079 node->img = img;
2080 }
2081
2082 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", isof);
2083 grub_snprintf(node->orgconf, sizeof(node->orgconf), "%s", orgf);
2084 grub_snprintf(node->newconf, sizeof(node->newconf), "%s", newf);
2085
2086 if (g_conf_replace_head)
2087 {
2088 tail->next = node;
2089 }
2090 else
2091 {
2092 g_conf_replace_head = node;
2093 }
2094 tail = node;
2095 }
2096 }
2097 }
2098
2099 return 0;
2100 }
2101
2102 static int ventoy_plugin_conf_replace_check(VTOY_JSON *json, const char *isodisk)
2103 {
2104 int img = 0;
2105 const char *isof = NULL;
2106 const char *orgf = NULL;
2107 const char *newf = NULL;
2108 VTOY_JSON *pNode = NULL;
2109 grub_file_t file = NULL;
2110 char cmd[256];
2111
2112 (void)isodisk;
2113
2114 if (json->enDataType != JSON_TYPE_ARRAY)
2115 {
2116 grub_printf("Not array %d\n", json->enDataType);
2117 return 1;
2118 }
2119
2120 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
2121 {
2122 isof = vtoy_json_get_string_ex(pNode->pstChild, "iso");
2123 orgf = vtoy_json_get_string_ex(pNode->pstChild, "org");
2124 newf = vtoy_json_get_string_ex(pNode->pstChild, "new");
2125 if (isof && orgf && newf && isof[0] == '/' && orgf[0] == '/' && newf[0] == '/')
2126 {
2127 if (ventoy_check_file_exist("%s%s", isodisk, isof))
2128 {
2129 grub_printf("iso:<%s> [OK]\n", isof);
2130
2131 grub_snprintf(cmd, sizeof(cmd), "loopback vtisocheck \"%s%s\"", isodisk, isof);
2132 grub_script_execute_sourcecode(cmd);
2133
2134 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(vtisocheck)/%s", orgf);
2135 if (file)
2136 {
2137 if (grub_strcmp(file->fs->name, "iso9660") == 0)
2138 {
2139 grub_printf("org:<%s> [OK]\n", orgf);
2140 }
2141 else
2142 {
2143 grub_printf("org:<%s> [Exist But NOT ISO9660]\n", orgf);
2144 }
2145 grub_file_close(file);
2146 }
2147 else
2148 {
2149 grub_printf("org:<%s> [NOT Exist]\n", orgf);
2150 }
2151
2152 grub_script_execute_sourcecode("loopback -d vtisocheck");
2153 }
2154 else if (grub_strchr(isof, '*'))
2155 {
2156 grub_printf("iso:<%s> [*]\n", isof);
2157 grub_printf("org:<%s>\n", orgf);
2158 }
2159 else
2160 {
2161 grub_printf("iso:<%s> [NOT Exist]\n", isof);
2162 grub_printf("org:<%s>\n", orgf);
2163 }
2164
2165 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", isodisk, newf);
2166 if (file)
2167 {
2168 if (file->size > vtoy_max_replace_file_size)
2169 {
2170 grub_printf("new:<%s> [Too Big %lu] \n", newf, (ulong)file->size);
2171 }
2172 else
2173 {
2174 grub_printf("new1:<%s> [OK]\n", newf);
2175 }
2176 grub_file_close(file);
2177 }
2178 else
2179 {
2180 grub_printf("new:<%s> [NOT Exist]\n", newf);
2181 }
2182
2183 if (JSON_SUCCESS == vtoy_json_get_int(pNode->pstChild, "img", &img))
2184 {
2185 grub_printf("img:<%d>\n", img);
2186 }
2187
2188 grub_printf("\n");
2189 }
2190 }
2191
2192 return 0;
2193 }
2194
2195 static int ventoy_plugin_auto_memdisk_entry(VTOY_JSON *json, const char *isodisk)
2196 {
2197 VTOY_JSON *pNode = NULL;
2198 auto_memdisk *node = NULL;
2199 auto_memdisk *next = NULL;
2200
2201 (void)isodisk;
2202
2203 if (json->enDataType != JSON_TYPE_ARRAY)
2204 {
2205 debug("Not array %d\n", json->enDataType);
2206 return 0;
2207 }
2208
2209 if (g_auto_memdisk_head)
2210 {
2211 for (node = g_auto_memdisk_head; node; node = next)
2212 {
2213 next = node->next;
2214 grub_free(node);
2215 }
2216
2217 g_auto_memdisk_head = NULL;
2218 }
2219
2220 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
2221 {
2222 if (pNode->enDataType == JSON_TYPE_STRING)
2223 {
2224 node = grub_zalloc(sizeof(auto_memdisk));
2225 if (node)
2226 {
2227 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", pNode->unData.pcStrVal);
2228
2229 if (g_auto_memdisk_head)
2230 {
2231 node->next = g_auto_memdisk_head;
2232 }
2233
2234 g_auto_memdisk_head = node;
2235 }
2236 }
2237 }
2238
2239 return 0;
2240 }
2241
2242 static int ventoy_plugin_auto_memdisk_check(VTOY_JSON *json, const char *isodisk)
2243 {
2244 VTOY_JSON *pNode = NULL;
2245
2246 if (json->enDataType != JSON_TYPE_ARRAY)
2247 {
2248 grub_printf("Not array %d\n", json->enDataType);
2249 return 1;
2250 }
2251
2252 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
2253 {
2254 if (pNode->enDataType == JSON_TYPE_STRING)
2255 {
2256 grub_printf("<%s> ", pNode->unData.pcStrVal);
2257
2258 if (grub_strchr(pNode->unData.pcStrVal, '*'))
2259 {
2260 grub_printf(" [*]\n");
2261 }
2262 else if (ventoy_check_file_exist("%s%s", isodisk, pNode->unData.pcStrVal))
2263 {
2264 grub_printf(" [OK]\n");
2265 }
2266 else
2267 {
2268 grub_printf(" [NOT EXIST]\n");
2269 }
2270 }
2271 }
2272
2273 return 0;
2274 }
2275
2276 static int ventoy_plugin_image_list_entry(VTOY_JSON *json, const char *isodisk)
2277 {
2278 VTOY_JSON *pNode = NULL;
2279 image_list *node = NULL;
2280 image_list *next = NULL;
2281 image_list *tail = NULL;
2282
2283 (void)isodisk;
2284
2285 if (json->enDataType != JSON_TYPE_ARRAY)
2286 {
2287 debug("Not array %d\n", json->enDataType);
2288 return 0;
2289 }
2290
2291 if (g_image_list_head)
2292 {
2293 for (node = g_image_list_head; node; node = next)
2294 {
2295 next = node->next;
2296 grub_free(node);
2297 }
2298
2299 g_image_list_head = NULL;
2300 }
2301
2302 if (grub_strncmp(json->pcName, "image_blacklist", 15) == 0)
2303 {
2304 g_plugin_image_list = VENTOY_IMG_BLACK_LIST;
2305 }
2306 else
2307 {
2308 g_plugin_image_list = VENTOY_IMG_WHITE_LIST;
2309 }
2310
2311 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
2312 {
2313 if (pNode->enDataType == JSON_TYPE_STRING)
2314 {
2315 node = grub_zalloc(sizeof(image_list));
2316 if (node)
2317 {
2318 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", pNode->unData.pcStrVal);
2319
2320 if (g_image_list_head)
2321 {
2322 tail->next = node;
2323 }
2324 else
2325 {
2326 g_image_list_head = node;
2327 }
2328 tail = node;
2329 }
2330 }
2331 }
2332
2333 return 0;
2334 }
2335
2336 static int ventoy_plugin_image_list_check(VTOY_JSON *json, const char *isodisk)
2337 {
2338 VTOY_JSON *pNode = NULL;
2339
2340 if (json->enDataType != JSON_TYPE_ARRAY)
2341 {
2342 grub_printf("Not array %d\n", json->enDataType);
2343 return 1;
2344 }
2345
2346 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
2347 {
2348 if (pNode->enDataType == JSON_TYPE_STRING)
2349 {
2350 grub_printf("<%s> ", pNode->unData.pcStrVal);
2351
2352 if (grub_strchr(pNode->unData.pcStrVal, '*'))
2353 {
2354 grub_printf(" [*]\n");
2355 }
2356 else if (ventoy_check_file_exist("%s%s", isodisk, pNode->unData.pcStrVal))
2357 {
2358 grub_printf(" [OK]\n");
2359 }
2360 else
2361 {
2362 grub_printf(" [NOT EXIST]\n");
2363 }
2364 }
2365 }
2366
2367 return 0;
2368 }
2369
2370 static plugin_entry g_plugin_entries[] =
2371 {
2372 { "control", ventoy_plugin_control_entry, ventoy_plugin_control_check, 0 },
2373 { "theme", ventoy_plugin_theme_entry, ventoy_plugin_theme_check, 0 },
2374 { "auto_install", ventoy_plugin_auto_install_entry, ventoy_plugin_auto_install_check, 0 },
2375 { "persistence", ventoy_plugin_persistence_entry, ventoy_plugin_persistence_check, 0 },
2376 { "menu_alias", ventoy_plugin_menualias_entry, ventoy_plugin_menualias_check, 0 },
2377 { "menu_tip", ventoy_plugin_menutip_entry, ventoy_plugin_menutip_check, 0 },
2378 { "menu_class", ventoy_plugin_menuclass_entry, ventoy_plugin_menuclass_check, 0 },
2379 { "injection", ventoy_plugin_injection_entry, ventoy_plugin_injection_check, 0 },
2380 { "auto_memdisk", ventoy_plugin_auto_memdisk_entry, ventoy_plugin_auto_memdisk_check, 0 },
2381 { "image_list", ventoy_plugin_image_list_entry, ventoy_plugin_image_list_check, 0 },
2382 { "image_blacklist", ventoy_plugin_image_list_entry, ventoy_plugin_image_list_check, 0 },
2383 { "conf_replace", ventoy_plugin_conf_replace_entry, ventoy_plugin_conf_replace_check, 0 },
2384 { "dud", ventoy_plugin_dud_entry, ventoy_plugin_dud_check, 0 },
2385 { "password", ventoy_plugin_pwd_entry, ventoy_plugin_pwd_check, 0 },
2386 { "custom_boot", ventoy_plugin_custom_boot_entry, ventoy_plugin_custom_boot_check, 0 },
2387 };
2388
2389 static int ventoy_parse_plugin_config(VTOY_JSON *json, const char *isodisk)
2390 {
2391 int i;
2392 char key[128];
2393 VTOY_JSON *cur = NULL;
2394
2395 grub_snprintf(g_iso_disk_name, sizeof(g_iso_disk_name), "%s", isodisk);
2396
2397 for (cur = json; cur; cur = cur->pstNext)
2398 {
2399 for (i = 0; i < (int)ARRAY_SIZE(g_plugin_entries); i++)
2400 {
2401 grub_snprintf(key, sizeof(key), "%s_%s", g_plugin_entries[i].key, g_arch_mode_suffix);
2402 if (g_plugin_entries[i].flag == 0 && grub_strcmp(key, cur->pcName) == 0)
2403 {
2404 debug("Plugin entry for %s\n", g_plugin_entries[i].key);
2405 g_plugin_entries[i].entryfunc(cur, isodisk);
2406 g_plugin_entries[i].flag = 1;
2407 break;
2408 }
2409 }
2410 }
2411
2412
2413 for (cur = json; cur; cur = cur->pstNext)
2414 {
2415 for (i = 0; i < (int)ARRAY_SIZE(g_plugin_entries); i++)
2416 {
2417 if (g_plugin_entries[i].flag == 0 && grub_strcmp(g_plugin_entries[i].key, cur->pcName) == 0)
2418 {
2419 debug("Plugin entry for %s\n", g_plugin_entries[i].key);
2420 g_plugin_entries[i].entryfunc(cur, isodisk);
2421 g_plugin_entries[i].flag = 1;
2422 break;
2423 }
2424 }
2425 }
2426
2427 return 0;
2428 }
2429
2430 grub_err_t ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **args)
2431 {
2432 int ret = 0;
2433 int offset = 0;
2434 char *buf = NULL;
2435 grub_uint8_t *code = NULL;
2436 grub_file_t file;
2437 VTOY_JSON *json = NULL;
2438
2439 (void)ctxt;
2440 (void)argc;
2441
2442 grub_env_set("VTOY_TIP_LEFT", "10%");
2443 grub_env_set("VTOY_TIP_TOP", "80%+5");
2444 grub_env_set("VTOY_TIP_COLOR", "blue");
2445 grub_env_set("VTOY_TIP_ALIGN", "left");
2446
2447 file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s/ventoy/ventoy.json", args[0]);
2448 if (!file)
2449 {
2450 return GRUB_ERR_NONE;
2451 }
2452
2453 debug("json configuration file size %d\n", (int)file->size);
2454
2455 buf = grub_malloc(file->size + 1);
2456 if (!buf)
2457 {
2458 grub_file_close(file);
2459 return 1;
2460 }
2461
2462 buf[file->size] = 0;
2463 grub_file_read(file, buf, file->size);
2464 grub_file_close(file);
2465
2466 json = vtoy_json_create();
2467 if (!json)
2468 {
2469 return 1;
2470 }
2471
2472 code = (grub_uint8_t *)buf;
2473 if (code[0] == 0xef && code[1] == 0xbb && code[2] == 0xbf)
2474 {
2475 offset = 3; /* Skip UTF-8 BOM */
2476 }
2477 else if ((code[0] == 0xff && code[1] == 0xfe) || (code[0] == 0xfe && code[1] == 0xff))
2478 {
2479 grub_env_set("VTOY_PLUGIN_SYNTAX_ERROR", "1");
2480 grub_env_export("VTOY_PLUGIN_SYNTAX_ERROR");
2481
2482 grub_env_set("VTOY_PLUGIN_ENCODE_ERROR", "1");
2483 grub_env_export("VTOY_PLUGIN_ENCODE_ERROR");
2484
2485 debug("Failed to parse json string %d\n", ret);
2486 grub_free(buf);
2487 return 1;
2488 }
2489
2490 ret = vtoy_json_parse(json, buf + offset);
2491 if (ret)
2492 {
2493 grub_env_set("VTOY_PLUGIN_SYNTAX_ERROR", "1");
2494 grub_env_export("VTOY_PLUGIN_SYNTAX_ERROR");
2495
2496 debug("Failed to parse json string %d\n", ret);
2497 grub_free(buf);
2498 return 1;
2499 }
2500
2501 ventoy_parse_plugin_config(json->pstChild, args[0]);
2502
2503 vtoy_json_destroy(json);
2504
2505 grub_free(buf);
2506
2507 if (g_boot_pwd.type)
2508 {
2509 grub_printf("\n\n======= %s ======\n\n", grub_env_get("VTOY_TEXT_MENU_VER"));
2510 if (ventoy_check_password(&g_boot_pwd, 3))
2511 {
2512 grub_printf("\n!!! Password check failed, will exit after 5 seconds. !!!\n");
2513 grub_refresh();
2514 grub_sleep(5);
2515 grub_exit();
2516 }
2517 }
2518
2519 if (g_menu_tip_head)
2520 {
2521 grub_env_set("VTOY_MENU_TIP_ENABLE", "1");
2522 }
2523 else
2524 {
2525 grub_env_unset("VTOY_MENU_TIP_ENABLE");
2526 }
2527
2528 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2529 }
2530
2531 void ventoy_plugin_dump_injection(void)
2532 {
2533 injection_config *node = NULL;
2534
2535 for (node = g_injection_head; node; node = node->next)
2536 {
2537 grub_printf("\n%s:<%s>\n", (node->type == injection_type_file) ? "IMAGE" : "PARENT", node->isopath);
2538 grub_printf("ARCHIVE:<%s>\n", node->archive);
2539 }
2540
2541 return;
2542 }
2543
2544
2545 void ventoy_plugin_dump_auto_install(void)
2546 {
2547 int i;
2548 install_template *node = NULL;
2549
2550 for (node = g_install_template_head; node; node = node->next)
2551 {
2552 grub_printf("\n%s:<%s> <%d>\n",
2553 (node->type == auto_install_type_file) ? "IMAGE" : "PARENT",
2554 node->isopath, node->templatenum);
2555 for (i = 0; i < node->templatenum; i++)
2556 {
2557 grub_printf("SCRIPT %d:<%s>\n", i, node->templatepath[i].path);
2558 }
2559 }
2560
2561 return;
2562 }
2563
2564 void ventoy_plugin_dump_persistence(void)
2565 {
2566 int rc;
2567 int i = 0;
2568 persistence_config *node = NULL;
2569 ventoy_img_chunk_list chunk_list;
2570
2571 for (node = g_persistence_head; node; node = node->next)
2572 {
2573 grub_printf("\nIMAGE:<%s> <%d>\n", node->isopath, node->backendnum);
2574
2575 for (i = 0; i < node->backendnum; i++)
2576 {
2577 grub_printf("PERSIST %d:<%s>", i, node->backendpath[i].path);
2578 rc = ventoy_plugin_get_persistent_chunklist(node->isopath, i, &chunk_list);
2579 if (rc == 0)
2580 {
2581 grub_printf(" [ SUCCESS ]\n");
2582 grub_free(chunk_list.chunk);
2583 }
2584 else
2585 {
2586 grub_printf(" [ FAILED ]\n");
2587 }
2588 }
2589 }
2590
2591 return;
2592 }
2593
2594 install_template * ventoy_plugin_find_install_template(const char *isopath)
2595 {
2596 int len;
2597 install_template *node = NULL;
2598
2599 if (!g_install_template_head)
2600 {
2601 return NULL;
2602 }
2603
2604 len = (int)grub_strlen(isopath);
2605 for (node = g_install_template_head; node; node = node->next)
2606 {
2607 if (node->type == auto_install_type_file)
2608 {
2609 if (node->pathlen == len && ventoy_strcmp(node->isopath, isopath) == 0)
2610 {
2611 return node;
2612 }
2613 }
2614 }
2615
2616 for (node = g_install_template_head; node; node = node->next)
2617 {
2618 if (node->type == auto_install_type_parent)
2619 {
2620 if (node->pathlen < len && ventoy_plugin_is_parent(node->isopath, node->pathlen, isopath))
2621 {
2622 return node;
2623 }
2624 }
2625 }
2626
2627 return NULL;
2628 }
2629
2630 char * ventoy_plugin_get_cur_install_template(const char *isopath)
2631 {
2632 install_template *node = NULL;
2633
2634 node = ventoy_plugin_find_install_template(isopath);
2635 if ((!node) || (!node->templatepath))
2636 {
2637 return NULL;
2638 }
2639
2640 if (node->cursel < 0 || node->cursel >= node->templatenum)
2641 {
2642 return NULL;
2643 }
2644
2645 return node->templatepath[node->cursel].path;
2646 }
2647
2648 persistence_config * ventoy_plugin_find_persistent(const char *isopath)
2649 {
2650 int len;
2651 persistence_config *node = NULL;
2652
2653 if (!g_persistence_head)
2654 {
2655 return NULL;
2656 }
2657
2658 len = (int)grub_strlen(isopath);
2659 for (node = g_persistence_head; node; node = node->next)
2660 {
2661 if ((len == node->pathlen) && (ventoy_strcmp(node->isopath, isopath) == 0))
2662 {
2663 return node;
2664 }
2665 }
2666
2667 return NULL;
2668 }
2669
2670 int ventoy_plugin_get_persistent_chunklist(const char *isopath, int index, ventoy_img_chunk_list *chunk_list)
2671 {
2672 int rc = 1;
2673 grub_uint64_t start = 0;
2674 grub_file_t file = NULL;
2675 persistence_config *node = NULL;
2676
2677 node = ventoy_plugin_find_persistent(isopath);
2678 if ((!node) || (!node->backendpath))
2679 {
2680 return 1;
2681 }
2682
2683 if (index < 0)
2684 {
2685 index = node->cursel;
2686 }
2687
2688 if (index < 0 || index >= node->backendnum)
2689 {
2690 return 1;
2691 }
2692
2693 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", g_iso_disk_name, node->backendpath[index].path);
2694 if (!file)
2695 {
2696 debug("Failed to open file %s%s\n", g_iso_disk_name, node->backendpath[index].path);
2697 goto end;
2698 }
2699
2700 grub_memset(chunk_list, 0, sizeof(ventoy_img_chunk_list));
2701 chunk_list->chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
2702 if (NULL == chunk_list->chunk)
2703 {
2704 goto end;
2705 }
2706
2707 chunk_list->max_chunk = DEFAULT_CHUNK_NUM;
2708 chunk_list->cur_chunk = 0;
2709
2710 start = file->device->disk->partition->start;
2711 ventoy_get_block_list(file, chunk_list, start);
2712
2713 if (0 != ventoy_check_block_list(file, chunk_list, start))
2714 {
2715 grub_free(chunk_list->chunk);
2716 chunk_list->chunk = NULL;
2717 goto end;
2718 }
2719
2720 rc = 0;
2721
2722 end:
2723 if (file)
2724 grub_file_close(file);
2725
2726 return rc;
2727 }
2728
2729 const char * ventoy_plugin_get_injection(const char *isopath)
2730 {
2731 int len;
2732 injection_config *node = NULL;
2733
2734 if (!g_injection_head)
2735 {
2736 return NULL;
2737 }
2738
2739 len = (int)grub_strlen(isopath);
2740 for (node = g_injection_head; node; node = node->next)
2741 {
2742 if (node->type == injection_type_file)
2743 {
2744 if (node->pathlen == len && ventoy_strcmp(node->isopath, isopath) == 0)
2745 {
2746 return node->archive;
2747 }
2748 }
2749 }
2750
2751 for (node = g_injection_head; node; node = node->next)
2752 {
2753 if (node->type == injection_type_parent)
2754 {
2755 if (node->pathlen < len && ventoy_plugin_is_parent(node->isopath, node->pathlen, isopath))
2756 {
2757 return node->archive;
2758 }
2759 }
2760 }
2761
2762 return NULL;
2763 }
2764
2765 const char * ventoy_plugin_get_menu_alias(int type, const char *isopath)
2766 {
2767 int len;
2768 menu_alias *node = NULL;
2769
2770 if (!g_menu_alias_head)
2771 {
2772 return NULL;
2773 }
2774
2775 len = (int)grub_strlen(isopath);
2776 for (node = g_menu_alias_head; node; node = node->next)
2777 {
2778 if (node->type == type && node->pathlen &&
2779 node->pathlen == len && ventoy_strcmp(node->isopath, isopath) == 0)
2780 {
2781 return node->alias;
2782 }
2783 }
2784
2785 return NULL;
2786 }
2787
2788 const menu_tip * ventoy_plugin_get_menu_tip(int type, const char *isopath)
2789 {
2790 int len;
2791 menu_tip *node = NULL;
2792
2793 if (!g_menu_tip_head)
2794 {
2795 return NULL;
2796 }
2797
2798 len = (int)grub_strlen(isopath);
2799 for (node = g_menu_tip_head; node; node = node->next)
2800 {
2801 if (node->type == type && node->pathlen &&
2802 node->pathlen == len && ventoy_strcmp(node->isopath, isopath) == 0)
2803 {
2804 return node;
2805 }
2806 }
2807
2808 return NULL;
2809 }
2810
2811 const char * ventoy_plugin_get_menu_class(int type, const char *name, const char *path)
2812 {
2813 int namelen;
2814 int pathlen;
2815 menu_class *node = NULL;
2816
2817 if (!g_menu_class_head)
2818 {
2819 return NULL;
2820 }
2821
2822 namelen = (int)grub_strlen(name);
2823 pathlen = (int)grub_strlen(path);
2824
2825 if (vtoy_class_image_file == type)
2826 {
2827 for (node = g_menu_class_head; node; node = node->next)
2828 {
2829 if (node->type != type)
2830 {
2831 continue;
2832 }
2833
2834 if (node->parent == 0)
2835 {
2836 if ((node->patlen < namelen) && grub_strstr(name, node->pattern))
2837 {
2838 return node->class;
2839 }
2840 }
2841 }
2842
2843 for (node = g_menu_class_head; node; node = node->next)
2844 {
2845 if (node->type != type)
2846 {
2847 continue;
2848 }
2849
2850 if (node->parent)
2851 {
2852 if ((node->patlen < pathlen) && ventoy_plugin_is_parent(node->pattern, node->patlen, path))
2853 {
2854 return node->class;
2855 }
2856 }
2857 }
2858 }
2859 else
2860 {
2861 for (node = g_menu_class_head; node; node = node->next)
2862 {
2863 if (node->type == type && node->patlen == namelen && grub_strncmp(name, node->pattern, namelen) == 0)
2864 {
2865 return node->class;
2866 }
2867 }
2868 }
2869
2870 return NULL;
2871 }
2872
2873 int ventoy_plugin_add_custom_boot(const char *vcfgpath)
2874 {
2875 int len;
2876 custom_boot *node = NULL;
2877
2878 node = grub_zalloc(sizeof(custom_boot));
2879 if (node)
2880 {
2881 node->type = vtoy_custom_boot_image_file;
2882 node->pathlen = grub_snprintf(node->path, sizeof(node->path), "%s", vcfgpath);
2883 grub_snprintf(node->cfg, sizeof(node->cfg), "%s", vcfgpath);
2884
2885 /* .vcfg */
2886 len = node->pathlen - 5;
2887 node->path[len] = 0;
2888 node->pathlen = len;
2889
2890 if (g_custom_boot_head)
2891 {
2892 node->next = g_custom_boot_head;
2893 }
2894 g_custom_boot_head = node;
2895 }
2896
2897 return 0;
2898 }
2899
2900 const char * ventoy_plugin_get_custom_boot(const char *isopath)
2901 {
2902 int i;
2903 int len;
2904 custom_boot *node = NULL;
2905
2906 if (!g_custom_boot_head)
2907 {
2908 return NULL;
2909 }
2910
2911 len = (int)grub_strlen(isopath);
2912
2913 for (node = g_custom_boot_head; node; node = node->next)
2914 {
2915 if (node->type == vtoy_custom_boot_image_file)
2916 {
2917 if (node->pathlen == len && grub_strncmp(isopath, node->path, len) == 0)
2918 {
2919 return node->cfg;
2920 }
2921 }
2922 else
2923 {
2924 if (node->pathlen < len && isopath[node->pathlen] == '/' &&
2925 grub_strncmp(isopath, node->path, node->pathlen) == 0)
2926 {
2927 for (i = node->pathlen + 1; i < len; i++)
2928 {
2929 if (isopath[i] == '/')
2930 {
2931 break;
2932 }
2933 }
2934
2935 if (i >= len)
2936 {
2937 return node->cfg;
2938 }
2939 }
2940 }
2941 }
2942
2943 return NULL;
2944 }
2945
2946 grub_err_t ventoy_cmd_dump_custom_boot(grub_extcmd_context_t ctxt, int argc, char **args)
2947 {
2948 custom_boot *node = NULL;
2949
2950 (void)argc;
2951 (void)ctxt;
2952 (void)args;
2953
2954 for (node = g_custom_boot_head; node; node = node->next)
2955 {
2956 grub_printf("[%s] <%s>:<%s>\n", (node->type == vtoy_custom_boot_directory) ? "dir" : "file",
2957 node->path, node->cfg);
2958 }
2959
2960 return 0;
2961 }
2962
2963 int ventoy_plugin_check_memdisk(const char *isopath)
2964 {
2965 int len;
2966 auto_memdisk *node = NULL;
2967
2968 if (!g_auto_memdisk_head)
2969 {
2970 return 0;
2971 }
2972
2973 len = (int)grub_strlen(isopath);
2974 for (node = g_auto_memdisk_head; node; node = node->next)
2975 {
2976 if (node->pathlen == len && ventoy_strncmp(node->isopath, isopath, len) == 0)
2977 {
2978 return 1;
2979 }
2980 }
2981
2982 return 0;
2983 }
2984
2985 int ventoy_plugin_get_image_list_index(int type, const char *name)
2986 {
2987 int len;
2988 int index = 1;
2989 image_list *node = NULL;
2990
2991 if (!g_image_list_head)
2992 {
2993 return 0;
2994 }
2995
2996 len = (int)grub_strlen(name);
2997
2998 for (node = g_image_list_head; node; node = node->next, index++)
2999 {
3000 if (vtoy_class_directory == type)
3001 {
3002 if (len < node->pathlen && ventoy_strncmp(node->isopath, name, len) == 0)
3003 {
3004 return index;
3005 }
3006 }
3007 else
3008 {
3009 if (len == node->pathlen && ventoy_strncmp(node->isopath, name, len) == 0)
3010 {
3011 return index;
3012 }
3013 }
3014 }
3015
3016 return 0;
3017 }
3018
3019 conf_replace * ventoy_plugin_find_conf_replace(const char *iso)
3020 {
3021 int len;
3022 conf_replace *node;
3023
3024 if (!g_conf_replace_head)
3025 {
3026 return NULL;
3027 }
3028
3029 len = (int)grub_strlen(iso);
3030
3031 for (node = g_conf_replace_head; node; node = node->next)
3032 {
3033 if (node->pathlen == len && ventoy_strncmp(node->isopath, iso, len) == 0)
3034 {
3035 return node;
3036 }
3037 }
3038
3039 return NULL;
3040 }
3041
3042 dud * ventoy_plugin_find_dud(const char *iso)
3043 {
3044 int len;
3045 dud *node;
3046
3047 if (!g_dud_head)
3048 {
3049 return NULL;
3050 }
3051
3052 len = (int)grub_strlen(iso);
3053 for (node = g_dud_head; node; node = node->next)
3054 {
3055 if (node->pathlen == len && ventoy_strncmp(node->isopath, iso, len) == 0)
3056 {
3057 return node;
3058 }
3059 }
3060
3061 return NULL;
3062 }
3063
3064 int ventoy_plugin_load_dud(dud *node, const char *isopart)
3065 {
3066 int i;
3067 char *buf;
3068 grub_file_t file;
3069
3070 for (i = 0; i < node->dudnum; i++)
3071 {
3072 if (node->files[i].size > 0)
3073 {
3074 debug("file %d has been loaded\n", i);
3075 continue;
3076 }
3077
3078 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", isopart, node->dudpath[i].path);
3079 if (file)
3080 {
3081 buf = grub_malloc(file->size);
3082 if (buf)
3083 {
3084 grub_file_read(file, buf, file->size);
3085 node->files[i].size = (int)file->size;
3086 node->files[i].buf = buf;
3087 }
3088 grub_file_close(file);
3089 }
3090 }
3091
3092 return 0;
3093 }
3094
3095 static const vtoy_password * ventoy_plugin_get_password(const char *isopath)
3096 {
3097 int i;
3098 int len;
3099 const char *pos = NULL;
3100 menu_password *node = NULL;
3101
3102 if (!isopath)
3103 {
3104 return NULL;
3105 }
3106
3107 if (g_pwd_head)
3108 {
3109 len = (int)grub_strlen(isopath);
3110 for (node = g_pwd_head; node; node = node->next)
3111 {
3112 if (node->type == vtoy_menu_pwd_file)
3113 {
3114 if (node->pathlen == len && ventoy_strncmp(node->isopath, isopath, len) == 0)
3115 {
3116 return &(node->password);
3117 }
3118 }
3119 }
3120
3121 for (node = g_pwd_head; node; node = node->next)
3122 {
3123 if (node->type == vtoy_menu_pwd_parent)
3124 {
3125 if (node->pathlen < len && ventoy_plugin_is_parent(node->isopath, node->pathlen, isopath))
3126 {
3127 return &(node->password);
3128 }
3129 }
3130 }
3131 }
3132
3133 while (*isopath)
3134 {
3135 if (*isopath == '.')
3136 {
3137 pos = isopath;
3138 }
3139 isopath++;
3140 }
3141
3142 if (pos)
3143 {
3144 for (i = 0; i < (int)ARRAY_SIZE(g_menu_prefix); i++)
3145 {
3146 if (g_file_type_pwd[i].type && 0 == grub_strcasecmp(pos + 1, g_menu_prefix[i]))
3147 {
3148 return g_file_type_pwd + i;
3149 }
3150 }
3151 }
3152
3153 return NULL;
3154 }
3155
3156 grub_err_t ventoy_cmd_check_password(grub_extcmd_context_t ctxt, int argc, char **args)
3157 {
3158 int ret;
3159 const vtoy_password *pwd = NULL;
3160
3161 (void)ctxt;
3162 (void)argc;
3163
3164 pwd = ventoy_plugin_get_password(args[0]);
3165 if (pwd)
3166 {
3167 if (0 == ventoy_check_password(pwd, 1))
3168 {
3169 ret = 1;
3170 }
3171 else
3172 {
3173 ret = 0;
3174 }
3175 }
3176 else
3177 {
3178 ret = 1;
3179 }
3180
3181 grub_errno = 0;
3182 return ret;
3183 }
3184
3185 grub_err_t ventoy_cmd_plugin_check_json(grub_extcmd_context_t ctxt, int argc, char **args)
3186 {
3187 int i = 0;
3188 int ret = 0;
3189 char *buf = NULL;
3190 char key[128];
3191 grub_file_t file;
3192 VTOY_JSON *node = NULL;
3193 VTOY_JSON *json = NULL;
3194
3195 (void)ctxt;
3196
3197 if (argc != 3)
3198 {
3199 return 0;
3200 }
3201
3202 file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s/ventoy/ventoy.json", args[0]);
3203 if (!file)
3204 {
3205 grub_printf("Plugin json file /ventoy/ventoy.json does NOT exist.\n");
3206 grub_printf("Attention: directory name and filename are both case-sensitive.\n");
3207 goto end;
3208 }
3209
3210 buf = grub_malloc(file->size + 1);
3211 if (!buf)
3212 {
3213 grub_printf("Failed to malloc memory %lu.\n", (ulong)(file->size + 1));
3214 goto end;
3215 }
3216
3217 buf[file->size] = 0;
3218 grub_file_read(file, buf, file->size);
3219
3220 json = vtoy_json_create();
3221 if (!json)
3222 {
3223 grub_printf("Failed to create json\n");
3224 goto end;
3225 }
3226
3227 ret = vtoy_json_parse(json, buf);
3228 if (ret)
3229 {
3230 grub_printf("Syntax error detected in ventoy.json, please check it.\n");
3231 goto end;
3232 }
3233
3234 grub_snprintf(key, sizeof(key), "%s_%s", args[1], g_arch_mode_suffix);
3235 for (node = json->pstChild; node; node = node->pstNext)
3236 {
3237 if (grub_strcmp(node->pcName, key) == 0)
3238 {
3239 break;
3240 }
3241 }
3242
3243 if (!node)
3244 {
3245 for (node = json->pstChild; node; node = node->pstNext)
3246 {
3247 if (grub_strcmp(node->pcName, args[1]) == 0)
3248 {
3249 break;
3250 }
3251 }
3252
3253 if (!node)
3254 {
3255 grub_printf("%s is NOT found in ventoy.json\n", args[1]);
3256 goto end;
3257 }
3258 }
3259
3260 for (i = 0; i < (int)ARRAY_SIZE(g_plugin_entries); i++)
3261 {
3262 if (grub_strcmp(g_plugin_entries[i].key, args[1]) == 0)
3263 {
3264 if (g_plugin_entries[i].checkfunc)
3265 {
3266 ret = g_plugin_entries[i].checkfunc(node, args[2]);
3267 }
3268 break;
3269 }
3270 }
3271
3272 end:
3273 check_free(file, grub_file_close);
3274 check_free(json, vtoy_json_destroy);
3275 grub_check_free(buf);
3276
3277 return 0;
3278 }
3279
3280 grub_err_t ventoy_cmd_set_theme(grub_extcmd_context_t ctxt, int argc, char **args)
3281 {
3282 grub_uint32_t i = 0;
3283 grub_uint32_t mod = 0;
3284 theme_list *node = g_theme_head;
3285 struct grub_datetime datetime;
3286
3287 (void)argc;
3288 (void)args;
3289 (void)ctxt;
3290
3291 if (g_theme_single_file[0])
3292 {
3293 debug("single theme %s\n", g_theme_single_file);
3294 grub_env_set("theme", g_theme_single_file);
3295 goto end;
3296 }
3297
3298 debug("g_theme_num = %d\n", g_theme_num);
3299
3300 if (g_theme_num == 0)
3301 {
3302 goto end;
3303 }
3304
3305 grub_memset(&datetime, 0, sizeof(datetime));
3306 grub_get_datetime(&datetime);
3307
3308 if (g_theme_random == vtoy_theme_random_boot_second)
3309 {
3310 grub_divmod32((grub_uint32_t)datetime.second, (grub_uint32_t)g_theme_num, &mod);
3311 }
3312 else if (g_theme_random == vtoy_theme_random_boot_day)
3313 {
3314 grub_divmod32((grub_uint32_t)datetime.day, (grub_uint32_t)g_theme_num, &mod);
3315 }
3316 else if (g_theme_random == vtoy_theme_random_boot_month)
3317 {
3318 grub_divmod32((grub_uint32_t)datetime.month, (grub_uint32_t)g_theme_num, &mod);
3319 }
3320
3321 debug("%04d/%02d/%02d %02d:%02d:%02d radom:%d mod:%d\n",
3322 datetime.year, datetime.month, datetime.day,
3323 datetime.hour, datetime.minute, datetime.second,
3324 g_theme_random, mod);
3325
3326 for (i = 0; i < mod && node; i++)
3327 {
3328 node = node->next;
3329 }
3330
3331 debug("random theme %s\n", node->theme.path);
3332 grub_env_set("theme", node->theme.path);
3333
3334 end:
3335 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3336 }
3337
3338