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