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