]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c
fc56936f53c5947f7bfd28db559bdb13100ab3a8
[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)
2492 {
2493 if ((node->patlen < pathlen) && ventoy_plugin_is_parent(node->pattern, node->patlen, path))
2494 {
2495 return node->class;
2496 }
2497 }
2498 else
2499 {
2500 if ((node->patlen < namelen) && grub_strstr(name, node->pattern))
2501 {
2502 return node->class;
2503 }
2504 }
2505 }
2506 }
2507 else
2508 {
2509 for (node = g_menu_class_head; node; node = node->next)
2510 {
2511 if (node->type == type && node->patlen == namelen && grub_strncmp(name, node->pattern, namelen) == 0)
2512 {
2513 return node->class;
2514 }
2515 }
2516 }
2517
2518 return NULL;
2519 }
2520
2521 int ventoy_plugin_add_custom_boot(const char *vcfgpath)
2522 {
2523 int len;
2524 custom_boot *node = NULL;
2525
2526 node = grub_zalloc(sizeof(custom_boot));
2527 if (node)
2528 {
2529 node->type = vtoy_custom_boot_image_file;
2530 node->pathlen = grub_snprintf(node->path, sizeof(node->path), "%s", vcfgpath);
2531 grub_snprintf(node->cfg, sizeof(node->cfg), "%s", vcfgpath);
2532
2533 /* .vcfg */
2534 len = node->pathlen - 5;
2535 node->path[len] = 0;
2536 node->pathlen = len;
2537
2538 if (g_custom_boot_head)
2539 {
2540 node->next = g_custom_boot_head;
2541 }
2542 g_custom_boot_head = node;
2543 }
2544
2545 return 0;
2546 }
2547
2548 const char * ventoy_plugin_get_custom_boot(const char *isopath)
2549 {
2550 int i;
2551 int len;
2552 custom_boot *node = NULL;
2553
2554 if (!g_custom_boot_head)
2555 {
2556 return NULL;
2557 }
2558
2559 len = (int)grub_strlen(isopath);
2560
2561 for (node = g_custom_boot_head; node; node = node->next)
2562 {
2563 if (node->type == vtoy_custom_boot_image_file)
2564 {
2565 if (node->pathlen == len && grub_strncmp(isopath, node->path, len) == 0)
2566 {
2567 return node->cfg;
2568 }
2569 }
2570 else
2571 {
2572 if (node->pathlen < len && isopath[node->pathlen] == '/' &&
2573 grub_strncmp(isopath, node->path, node->pathlen) == 0)
2574 {
2575 for (i = node->pathlen + 1; i < len; i++)
2576 {
2577 if (isopath[i] == '/')
2578 {
2579 break;
2580 }
2581 }
2582
2583 if (i >= len)
2584 {
2585 return node->cfg;
2586 }
2587 }
2588 }
2589 }
2590
2591 return NULL;
2592 }
2593
2594 grub_err_t ventoy_cmd_dump_custom_boot(grub_extcmd_context_t ctxt, int argc, char **args)
2595 {
2596 custom_boot *node = NULL;
2597
2598 (void)argc;
2599 (void)ctxt;
2600 (void)args;
2601
2602 for (node = g_custom_boot_head; node; node = node->next)
2603 {
2604 grub_printf("[%s] <%s>:<%s>\n", (node->type == vtoy_custom_boot_directory) ? "dir" : "file",
2605 node->path, node->cfg);
2606 }
2607
2608 return 0;
2609 }
2610
2611 int ventoy_plugin_check_memdisk(const char *isopath)
2612 {
2613 int len;
2614 auto_memdisk *node = NULL;
2615
2616 if (!g_auto_memdisk_head)
2617 {
2618 return 0;
2619 }
2620
2621 len = (int)grub_strlen(isopath);
2622 for (node = g_auto_memdisk_head; node; node = node->next)
2623 {
2624 if (node->pathlen == len && ventoy_strncmp(node->isopath, isopath, len) == 0)
2625 {
2626 return 1;
2627 }
2628 }
2629
2630 return 0;
2631 }
2632
2633 int ventoy_plugin_get_image_list_index(int type, const char *name)
2634 {
2635 int len;
2636 int index = 1;
2637 image_list *node = NULL;
2638
2639 if (!g_image_list_head)
2640 {
2641 return 0;
2642 }
2643
2644 len = (int)grub_strlen(name);
2645
2646 for (node = g_image_list_head; node; node = node->next, index++)
2647 {
2648 if (vtoy_class_directory == type)
2649 {
2650 if (len < node->pathlen && ventoy_strncmp(node->isopath, name, len) == 0)
2651 {
2652 return index;
2653 }
2654 }
2655 else
2656 {
2657 if (len == node->pathlen && ventoy_strncmp(node->isopath, name, len) == 0)
2658 {
2659 return index;
2660 }
2661 }
2662 }
2663
2664 return 0;
2665 }
2666
2667 conf_replace * ventoy_plugin_find_conf_replace(const char *iso)
2668 {
2669 int len;
2670 conf_replace *node;
2671
2672 if (!g_conf_replace_head)
2673 {
2674 return NULL;
2675 }
2676
2677 len = (int)grub_strlen(iso);
2678
2679 for (node = g_conf_replace_head; node; node = node->next)
2680 {
2681 if (node->pathlen == len && ventoy_strncmp(node->isopath, iso, len) == 0)
2682 {
2683 return node;
2684 }
2685 }
2686
2687 return NULL;
2688 }
2689
2690 dud * ventoy_plugin_find_dud(const char *iso)
2691 {
2692 int len;
2693 dud *node;
2694
2695 if (!g_dud_head)
2696 {
2697 return NULL;
2698 }
2699
2700 len = (int)grub_strlen(iso);
2701 for (node = g_dud_head; node; node = node->next)
2702 {
2703 if (node->pathlen == len && ventoy_strncmp(node->isopath, iso, len) == 0)
2704 {
2705 return node;
2706 }
2707 }
2708
2709 return NULL;
2710 }
2711
2712 int ventoy_plugin_load_dud(dud *node, const char *isopart)
2713 {
2714 int i;
2715 char *buf;
2716 grub_file_t file;
2717
2718 for (i = 0; i < node->dudnum; i++)
2719 {
2720 if (node->files[i].size > 0)
2721 {
2722 debug("file %d has been loaded\n", i);
2723 continue;
2724 }
2725
2726 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", isopart, node->dudpath[i].path);
2727 if (file)
2728 {
2729 buf = grub_malloc(file->size);
2730 if (buf)
2731 {
2732 grub_file_read(file, buf, file->size);
2733 node->files[i].size = (int)file->size;
2734 node->files[i].buf = buf;
2735 }
2736 grub_file_close(file);
2737 }
2738 }
2739
2740 return 0;
2741 }
2742
2743 static const vtoy_password * ventoy_plugin_get_password(const char *isopath)
2744 {
2745 int i;
2746 int len;
2747 const char *pos = NULL;
2748 menu_password *node = NULL;
2749
2750 if (!isopath)
2751 {
2752 return NULL;
2753 }
2754
2755 if (g_pwd_head)
2756 {
2757 len = (int)grub_strlen(isopath);
2758 for (node = g_pwd_head; node; node = node->next)
2759 {
2760 if (node->type == vtoy_menu_pwd_file)
2761 {
2762 if (node->pathlen == len && ventoy_strncmp(node->isopath, isopath, len) == 0)
2763 {
2764 return &(node->password);
2765 }
2766 }
2767 }
2768
2769 for (node = g_pwd_head; node; node = node->next)
2770 {
2771 if (node->type == vtoy_menu_pwd_parent)
2772 {
2773 if (node->pathlen < len && ventoy_plugin_is_parent(node->isopath, node->pathlen, isopath))
2774 {
2775 return &(node->password);
2776 }
2777 }
2778 }
2779 }
2780
2781 while (*isopath)
2782 {
2783 if (*isopath == '.')
2784 {
2785 pos = isopath;
2786 }
2787 isopath++;
2788 }
2789
2790 if (pos)
2791 {
2792 for (i = 0; i < (int)ARRAY_SIZE(g_menu_prefix); i++)
2793 {
2794 if (g_file_type_pwd[i].type && 0 == grub_strcasecmp(pos + 1, g_menu_prefix[i]))
2795 {
2796 return g_file_type_pwd + i;
2797 }
2798 }
2799 }
2800
2801 return NULL;
2802 }
2803
2804 grub_err_t ventoy_cmd_check_password(grub_extcmd_context_t ctxt, int argc, char **args)
2805 {
2806 int ret;
2807 const vtoy_password *pwd = NULL;
2808
2809 (void)ctxt;
2810 (void)argc;
2811
2812 pwd = ventoy_plugin_get_password(args[0]);
2813 if (pwd)
2814 {
2815 if (0 == ventoy_check_password(pwd, 1))
2816 {
2817 ret = 1;
2818 }
2819 else
2820 {
2821 ret = 0;
2822 }
2823 }
2824 else
2825 {
2826 ret = 1;
2827 }
2828
2829 grub_errno = 0;
2830 return ret;
2831 }
2832
2833 grub_err_t ventoy_cmd_plugin_check_json(grub_extcmd_context_t ctxt, int argc, char **args)
2834 {
2835 int i = 0;
2836 int ret = 0;
2837 char *buf = NULL;
2838 char key[128];
2839 grub_file_t file;
2840 VTOY_JSON *node = NULL;
2841 VTOY_JSON *json = NULL;
2842
2843 (void)ctxt;
2844
2845 if (argc != 3)
2846 {
2847 return 0;
2848 }
2849
2850 file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s/ventoy/ventoy.json", args[0]);
2851 if (!file)
2852 {
2853 grub_printf("Plugin json file /ventoy/ventoy.json does NOT exist.\n");
2854 grub_printf("Attention: directory name and filename are both case-sensitive.\n");
2855 goto end;
2856 }
2857
2858 buf = grub_malloc(file->size + 1);
2859 if (!buf)
2860 {
2861 grub_printf("Failed to malloc memory %lu.\n", (ulong)(file->size + 1));
2862 goto end;
2863 }
2864
2865 buf[file->size] = 0;
2866 grub_file_read(file, buf, file->size);
2867
2868 json = vtoy_json_create();
2869 if (!json)
2870 {
2871 grub_printf("Failed to create json\n");
2872 goto end;
2873 }
2874
2875 ret = vtoy_json_parse(json, buf);
2876 if (ret)
2877 {
2878 grub_printf("Syntax error detected in ventoy.json, please check it.\n");
2879 goto end;
2880 }
2881
2882 grub_snprintf(key, sizeof(key), "%s_%s", args[1], g_arch_mode_suffix);
2883 for (node = json->pstChild; node; node = node->pstNext)
2884 {
2885 if (grub_strcmp(node->pcName, args[1]) == 0 || grub_strcmp(node->pcName, key) == 0)
2886 {
2887 break;
2888 }
2889 }
2890
2891 if (!node)
2892 {
2893 grub_printf("%s is NOT found in ventoy.json\n", args[1]);
2894 goto end;
2895 }
2896
2897 for (i = 0; i < (int)ARRAY_SIZE(g_plugin_entries); i++)
2898 {
2899 if (grub_strcmp(g_plugin_entries[i].key, args[1]) == 0)
2900 {
2901 if (g_plugin_entries[i].checkfunc)
2902 {
2903 ret = g_plugin_entries[i].checkfunc(node, args[2]);
2904 }
2905 break;
2906 }
2907 }
2908
2909 end:
2910 check_free(file, grub_file_close);
2911 check_free(json, vtoy_json_destroy);
2912 grub_check_free(buf);
2913
2914 return 0;
2915 }
2916
2917 grub_err_t ventoy_cmd_set_theme(grub_extcmd_context_t ctxt, int argc, char **args)
2918 {
2919 grub_uint32_t i = 0;
2920 grub_uint32_t mod = 0;
2921 theme_list *node = g_theme_head;
2922 struct grub_datetime datetime;
2923
2924 (void)argc;
2925 (void)args;
2926 (void)ctxt;
2927
2928 if (g_theme_single_file[0])
2929 {
2930 debug("single theme %s\n", g_theme_single_file);
2931 grub_env_set("theme", g_theme_single_file);
2932 goto end;
2933 }
2934
2935 debug("g_theme_num = %d\n", g_theme_num);
2936
2937 if (g_theme_num == 0)
2938 {
2939 goto end;
2940 }
2941
2942 grub_memset(&datetime, 0, sizeof(datetime));
2943 grub_get_datetime(&datetime);
2944
2945 if (g_theme_random == vtoy_theme_random_boot_second)
2946 {
2947 grub_divmod32((grub_uint32_t)datetime.second, (grub_uint32_t)g_theme_num, &mod);
2948 }
2949 else if (g_theme_random == vtoy_theme_random_boot_day)
2950 {
2951 grub_divmod32((grub_uint32_t)datetime.day, (grub_uint32_t)g_theme_num, &mod);
2952 }
2953 else if (g_theme_random == vtoy_theme_random_boot_month)
2954 {
2955 grub_divmod32((grub_uint32_t)datetime.month, (grub_uint32_t)g_theme_num, &mod);
2956 }
2957
2958 debug("%04d/%02d/%02d %02d:%02d:%02d radom:%d mod:%d\n",
2959 datetime.year, datetime.month, datetime.day,
2960 datetime.hour, datetime.minute, datetime.second,
2961 g_theme_random, mod);
2962
2963 for (i = 0; i < mod && node; i++)
2964 {
2965 node = node->next;
2966 }
2967
2968 debug("random theme %s\n", node->theme.path);
2969 grub_env_set("theme", node->theme.path);
2970
2971 end:
2972 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2973 }
2974
2975