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