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