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