]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c
6bb4e9c0b89181161790460b5c80f13cbe01324c
[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 persistence_config *g_persistence_head = NULL;
45 static menu_alias *g_menu_alias_head = NULL;
46 static menu_class *g_menu_class_head = NULL;
47
48 static int ventoy_plugin_control_check(VTOY_JSON *json, const char *isodisk)
49 {
50 int rc = 0;
51 VTOY_JSON *pNode = NULL;
52 VTOY_JSON *pChild = NULL;
53
54 (void)isodisk;
55
56 if (json->enDataType != JSON_TYPE_ARRAY)
57 {
58 grub_printf("Not array type %d\n", json->enDataType);
59 return 1;
60 }
61
62 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
63 {
64 if (pNode->enDataType == JSON_TYPE_OBJECT)
65 {
66 pChild = pNode->pstChild;
67 if (pChild->enDataType == JSON_TYPE_STRING)
68 {
69 grub_printf("%s: %s\n", pChild->pcName, pChild->unData.pcStrVal);
70 }
71 else
72 {
73 grub_printf("%s is NOT string type\n", pChild->pcName);
74 rc = 1;
75 }
76 }
77 else
78 {
79 grub_printf("%s is not an object\n", pNode->pcName);
80 rc = 1;
81 }
82 }
83
84 return rc;
85 }
86
87 static int ventoy_plugin_control_entry(VTOY_JSON *json, const char *isodisk)
88 {
89 VTOY_JSON *pNode = NULL;
90 VTOY_JSON *pChild = NULL;
91
92 (void)isodisk;
93
94 if (json->enDataType != JSON_TYPE_ARRAY)
95 {
96 debug("Not array %d\n", json->enDataType);
97 return 0;
98 }
99
100 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
101 {
102 if (pNode->enDataType == JSON_TYPE_OBJECT)
103 {
104 pChild = pNode->pstChild;
105 if (pChild->enDataType == JSON_TYPE_STRING && pChild->pcName && pChild->unData.pcStrVal)
106 {
107 ventoy_set_env(pChild->pcName, pChild->unData.pcStrVal);
108 }
109 }
110 }
111
112 return 0;
113 }
114
115 static int ventoy_plugin_theme_check(VTOY_JSON *json, const char *isodisk)
116 {
117 int exist = 0;
118 const char *value;
119 VTOY_JSON *node;
120
121 value = vtoy_json_get_string_ex(json->pstChild, "file");
122 if (value)
123 {
124 grub_printf("file: %s\n", value);
125 if (value[0] == '/')
126 {
127 exist = ventoy_is_file_exist("%s%s", isodisk, value);
128 }
129 else
130 {
131 exist = ventoy_is_file_exist("%s/ventoy/%s", isodisk, value);
132 }
133
134 if (exist == 0)
135 {
136 grub_printf("Theme file %s does NOT exist\n", value);
137 return 1;
138 }
139 }
140
141 value = vtoy_json_get_string_ex(json->pstChild, "gfxmode");
142 if (value)
143 {
144 grub_printf("gfxmode: %s\n", value);
145 }
146
147 value = vtoy_json_get_string_ex(json->pstChild, "display_mode");
148 if (value)
149 {
150 grub_printf("display_mode: %s\n", value);
151 }
152
153 value = vtoy_json_get_string_ex(json->pstChild, "ventoy_left");
154 if (value)
155 {
156 grub_printf("ventoy_left: %s\n", value);
157 }
158
159 value = vtoy_json_get_string_ex(json->pstChild, "ventoy_top");
160 if (value)
161 {
162 grub_printf("ventoy_top: %s\n", value);
163 }
164
165 value = vtoy_json_get_string_ex(json->pstChild, "ventoy_color");
166 if (value)
167 {
168 grub_printf("ventoy_color: %s\n", value);
169 }
170
171 node = vtoy_json_find_item(json->pstChild, JSON_TYPE_ARRAY, "fonts");
172 if (node)
173 {
174 for (node = node->pstChild; node; node = node->pstNext)
175 {
176 if (node->enDataType == JSON_TYPE_STRING)
177 {
178 if (ventoy_check_file_exist("%s%s", isodisk, node->unData.pcStrVal))
179 {
180 grub_printf("%s [OK]\n", node->unData.pcStrVal);
181 }
182 else
183 {
184 grub_printf("%s [NOT EXIST]\n", node->unData.pcStrVal);
185 }
186 }
187 }
188 }
189 else
190 {
191 grub_printf("fonts NOT found\n");
192 }
193
194 return 0;
195 }
196
197 static int ventoy_plugin_theme_entry(VTOY_JSON *json, const char *isodisk)
198 {
199 const char *value;
200 char filepath[256];
201 VTOY_JSON *node;
202
203 value = vtoy_json_get_string_ex(json->pstChild, "file");
204 if (value)
205 {
206 if (value[0] == '/')
207 {
208 grub_snprintf(filepath, sizeof(filepath), "%s%s", isodisk, value);
209 }
210 else
211 {
212 grub_snprintf(filepath, sizeof(filepath), "%s/ventoy/%s", isodisk, value);
213 }
214
215 if (ventoy_is_file_exist(filepath) == 0)
216 {
217 debug("Theme file %s does not exist\n", filepath);
218 return 0;
219 }
220
221 debug("vtoy_theme %s\n", filepath);
222 grub_env_set("vtoy_theme", filepath);
223 }
224
225 value = vtoy_json_get_string_ex(json->pstChild, "gfxmode");
226 if (value)
227 {
228 debug("vtoy_gfxmode %s\n", value);
229 grub_env_set("vtoy_gfxmode", value);
230 }
231
232 value = vtoy_json_get_string_ex(json->pstChild, "display_mode");
233 if (value)
234 {
235 debug("display_mode %s\n", value);
236 grub_env_set("vtoy_display_mode", value);
237 }
238
239 value = vtoy_json_get_string_ex(json->pstChild, "ventoy_left");
240 if (value)
241 {
242 grub_env_set("VTLE_LFT", value);
243 }
244
245 value = vtoy_json_get_string_ex(json->pstChild, "ventoy_top");
246 if (value)
247 {
248 grub_env_set("VTLE_TOP", value);
249 }
250
251 value = vtoy_json_get_string_ex(json->pstChild, "ventoy_color");
252 if (value)
253 {
254 grub_env_set("VTLE_CLR", value);
255 }
256
257 node = vtoy_json_find_item(json->pstChild, JSON_TYPE_ARRAY, "fonts");
258 if (node)
259 {
260 for (node = node->pstChild; node; node = node->pstNext)
261 {
262 if (node->enDataType == JSON_TYPE_STRING &&
263 ventoy_check_file_exist("%s%s", isodisk, node->unData.pcStrVal))
264 {
265 grub_snprintf(filepath, sizeof(filepath), "%s%s", isodisk, node->unData.pcStrVal);
266 grub_font_load(filepath);
267 }
268 }
269 }
270
271 return 0;
272 }
273
274 static int ventoy_plugin_check_path(const char *path, const char *file)
275 {
276 if (file[0] != '/')
277 {
278 grub_printf("%s is NOT begin with '/' \n", file);
279 return 1;
280 }
281
282 if (grub_strchr(file, '\\'))
283 {
284 grub_printf("%s contains invalid '\\' \n", file);
285 return 1;
286 }
287
288 if (grub_strstr(file, "//"))
289 {
290 grub_printf("%s contains invalid double slash\n", file);
291 return 1;
292 }
293
294 if (grub_strstr(file, "../"))
295 {
296 grub_printf("%s contains invalid '../' \n", file);
297 return 1;
298 }
299
300 if (!ventoy_is_file_exist("%s%s", path, file))
301 {
302 grub_printf("%s%s does NOT exist\n", path, file);
303 return 1;
304 }
305
306 return 0;
307 }
308
309 static int ventoy_plugin_check_fullpath
310 (
311 VTOY_JSON *json,
312 const char *isodisk,
313 const char *key
314 )
315 {
316 int rc = 0;
317 int ret = 0;
318 VTOY_JSON *node = json;
319 VTOY_JSON *child = NULL;
320
321 while (node)
322 {
323 if (0 == grub_strcmp(key, node->pcName))
324 {
325 break;
326 }
327 node = node->pstNext;
328 }
329
330 if (!node)
331 {
332 return 1;
333 }
334
335 if (JSON_TYPE_STRING == node->enDataType)
336 {
337 ret = ventoy_plugin_check_path(isodisk, node->unData.pcStrVal);
338 grub_printf("%s: %s [%s]\n", key, node->unData.pcStrVal, ret ? "FAIL" : "OK");
339 }
340 else if (JSON_TYPE_ARRAY == node->enDataType)
341 {
342 for (child = node->pstChild; child; child = child->pstNext)
343 {
344 if (JSON_TYPE_STRING != child->enDataType)
345 {
346 grub_printf("Non string json type\n");
347 }
348 else
349 {
350 rc = ventoy_plugin_check_path(isodisk, child->unData.pcStrVal);
351 grub_printf("%s: %s [%s]\n", key, child->unData.pcStrVal, rc ? "FAIL" : "OK");
352 ret += rc;
353 }
354 }
355 }
356
357 return ret;
358 }
359
360 static int ventoy_plugin_parse_fullpath
361 (
362 VTOY_JSON *json,
363 const char *isodisk,
364 const char *key,
365 file_fullpath **fullpath,
366 int *pathnum
367 )
368 {
369 int rc = 1;
370 int count = 0;
371 VTOY_JSON *node = json;
372 VTOY_JSON *child = NULL;
373 file_fullpath *path = NULL;
374
375 while (node)
376 {
377 if (0 == grub_strcmp(key, node->pcName))
378 {
379 break;
380 }
381 node = node->pstNext;
382 }
383
384 if (!node)
385 {
386 return 1;
387 }
388
389 if (JSON_TYPE_STRING == node->enDataType)
390 {
391 debug("%s is string type data\n", node->pcName);
392
393 if ((node->unData.pcStrVal[0] != '/') || (!ventoy_is_file_exist("%s%s", isodisk, node->unData.pcStrVal)))
394 {
395 debug("%s%s file not found\n", isodisk, node->unData.pcStrVal);
396 return 1;
397 }
398
399 path = (file_fullpath *)grub_zalloc(sizeof(file_fullpath));
400 if (path)
401 {
402 grub_snprintf(path->path, sizeof(path->path), "%s", node->unData.pcStrVal);
403 *fullpath = path;
404 *pathnum = 1;
405 rc = 0;
406 }
407 }
408 else if (JSON_TYPE_ARRAY == node->enDataType)
409 {
410 for (child = node->pstChild; child; child = child->pstNext)
411 {
412 if ((JSON_TYPE_STRING != child->enDataType) || (child->unData.pcStrVal[0] != '/'))
413 {
414 debug("Invalid data type:%d\n", child->enDataType);
415 return 1;
416 }
417 count++;
418 }
419 debug("%s is array type data, count=%d\n", node->pcName, count);
420
421 path = (file_fullpath *)grub_zalloc(sizeof(file_fullpath) * count);
422 if (path)
423 {
424 *fullpath = path;
425
426 for (count = 0, child = node->pstChild; child; child = child->pstNext)
427 {
428 if (ventoy_is_file_exist("%s%s", isodisk, child->unData.pcStrVal))
429 {
430 grub_snprintf(path->path, sizeof(path->path), "%s", child->unData.pcStrVal);
431 path++;
432 count++;
433 }
434 }
435
436 *pathnum = count;
437 rc = 0;
438 }
439 }
440
441 return rc;
442 }
443
444 static int ventoy_plugin_auto_install_check(VTOY_JSON *json, const char *isodisk)
445 {
446 const char *iso = NULL;
447 VTOY_JSON *pNode = NULL;
448
449 if (json->enDataType != JSON_TYPE_ARRAY)
450 {
451 grub_printf("Not array type %d\n", json->enDataType);
452 return 1;
453 }
454
455 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
456 {
457 if (pNode->enDataType != JSON_TYPE_OBJECT)
458 {
459 grub_printf("NOT object type\n");
460 }
461
462 iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
463 if (iso)
464 {
465 if (0 == ventoy_plugin_check_path(isodisk, iso))
466 {
467 grub_printf("image: %s [OK]\n", iso);
468 ventoy_plugin_check_fullpath(pNode->pstChild, isodisk, "template");
469 }
470 else
471 {
472 grub_printf("image: %s [FAIL]\n", iso);
473 }
474 }
475 else
476 {
477 grub_printf("image not found\n");
478 }
479 }
480
481 return 0;
482 }
483
484 static int ventoy_plugin_auto_install_entry(VTOY_JSON *json, const char *isodisk)
485 {
486 int pathnum = 0;
487 const char *iso = NULL;
488 VTOY_JSON *pNode = NULL;
489 install_template *node = NULL;
490 install_template *next = NULL;
491 file_fullpath *templatepath = NULL;
492
493 if (json->enDataType != JSON_TYPE_ARRAY)
494 {
495 debug("Not array %d\n", json->enDataType);
496 return 0;
497 }
498
499 if (g_install_template_head)
500 {
501 for (node = g_install_template_head; node; node = next)
502 {
503 next = node->next;
504 grub_check_free(node->templatepath);
505 grub_free(node);
506 }
507
508 g_install_template_head = NULL;
509 }
510
511 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
512 {
513 iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
514 if (iso && iso[0] == '/')
515 {
516 if (0 == ventoy_plugin_parse_fullpath(pNode->pstChild, isodisk, "template", &templatepath, &pathnum))
517 {
518 node = grub_zalloc(sizeof(install_template));
519 if (node)
520 {
521 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", iso);
522 node->templatepath = templatepath;
523 node->templatenum = pathnum;
524
525 if (g_install_template_head)
526 {
527 node->next = g_install_template_head;
528 }
529
530 g_install_template_head = node;
531 }
532 }
533 }
534 }
535
536 return 0;
537 }
538
539 static int ventoy_plugin_persistence_check(VTOY_JSON *json, const char *isodisk)
540 {
541 const char *iso = NULL;
542 VTOY_JSON *pNode = NULL;
543
544 if (json->enDataType != JSON_TYPE_ARRAY)
545 {
546 grub_printf("Not array type %d\n", json->enDataType);
547 return 1;
548 }
549
550 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
551 {
552 if (pNode->enDataType != JSON_TYPE_OBJECT)
553 {
554 grub_printf("NOT object type\n");
555 }
556
557 iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
558 if (iso)
559 {
560 if (0 == ventoy_plugin_check_path(isodisk, iso))
561 {
562 grub_printf("image: %s [OK]\n", iso);
563 ventoy_plugin_check_fullpath(pNode->pstChild, isodisk, "backend");
564 }
565 else
566 {
567 grub_printf("image: %s [FAIL]\n", iso);
568 }
569 }
570 else
571 {
572 grub_printf("image not found\n");
573 }
574 }
575
576 return 0;
577 }
578
579 static int ventoy_plugin_persistence_entry(VTOY_JSON *json, const char *isodisk)
580 {
581 int pathnum = 0;
582 const char *iso = NULL;
583 VTOY_JSON *pNode = NULL;
584 persistence_config *node = NULL;
585 persistence_config *next = NULL;
586 file_fullpath *backendpath = NULL;
587
588 (void)isodisk;
589
590 if (json->enDataType != JSON_TYPE_ARRAY)
591 {
592 debug("Not array %d\n", json->enDataType);
593 return 0;
594 }
595
596 if (g_persistence_head)
597 {
598 for (node = g_persistence_head; node; node = next)
599 {
600 next = node->next;
601 grub_check_free(node->backendpath);
602 grub_free(node);
603 }
604
605 g_persistence_head = NULL;
606 }
607
608 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
609 {
610 iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
611 if (iso && iso[0] == '/')
612 {
613 if (0 == ventoy_plugin_parse_fullpath(pNode->pstChild, isodisk, "backend", &backendpath, &pathnum))
614 {
615 node = grub_zalloc(sizeof(persistence_config));
616 if (node)
617 {
618 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", iso);
619 node->backendpath = backendpath;
620 node->backendnum = pathnum;
621
622 if (g_persistence_head)
623 {
624 node->next = g_persistence_head;
625 }
626
627 g_persistence_head = node;
628 }
629 }
630 }
631 }
632
633 return 0;
634 }
635
636 static int ventoy_plugin_menualias_check(VTOY_JSON *json, const char *isodisk)
637 {
638 const char *iso = NULL;
639 const char *alias = NULL;
640 VTOY_JSON *pNode = NULL;
641
642 (void)isodisk;
643
644 if (json->enDataType != JSON_TYPE_ARRAY)
645 {
646 grub_printf("Not array %d\n", json->enDataType);
647 return 1;
648 }
649
650 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
651 {
652 iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
653 alias = vtoy_json_get_string_ex(pNode->pstChild, "alias");
654 if (iso && iso[0] == '/' && alias)
655 {
656 if (ventoy_is_file_exist("%s%s", isodisk, iso))
657 {
658 grub_printf("image: <%s> [ OK ]\n", iso);
659 }
660 else
661 {
662 grub_printf("image: <%s> [ NOT EXIST ]\n", iso);
663 }
664
665 grub_printf("alias: <%s>\n\n", alias);
666 }
667 }
668
669 return 0;
670 }
671
672 static int ventoy_plugin_menualias_entry(VTOY_JSON *json, const char *isodisk)
673 {
674 const char *iso = NULL;
675 const char *alias = NULL;
676 VTOY_JSON *pNode = NULL;
677 menu_alias *node = NULL;
678 menu_alias *next = NULL;
679
680 (void)isodisk;
681
682 if (json->enDataType != JSON_TYPE_ARRAY)
683 {
684 debug("Not array %d\n", json->enDataType);
685 return 0;
686 }
687
688 if (g_menu_alias_head)
689 {
690 for (node = g_menu_alias_head; node; node = next)
691 {
692 next = node->next;
693 grub_free(node);
694 }
695
696 g_menu_alias_head = NULL;
697 }
698
699 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
700 {
701 iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
702 alias = vtoy_json_get_string_ex(pNode->pstChild, "alias");
703 if (iso && iso[0] == '/' && alias)
704 {
705 node = grub_zalloc(sizeof(menu_alias));
706 if (node)
707 {
708 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", iso);
709 grub_snprintf(node->alias, sizeof(node->alias), "%s", alias);
710
711 if (g_menu_alias_head)
712 {
713 node->next = g_menu_alias_head;
714 }
715
716 g_menu_alias_head = node;
717 }
718 }
719 }
720
721 return 0;
722 }
723
724 static int ventoy_plugin_menuclass_entry(VTOY_JSON *json, const char *isodisk)
725 {
726 const char *key = NULL;
727 const char *class = NULL;
728 VTOY_JSON *pNode = NULL;
729 menu_class *tail = NULL;
730 menu_class *node = NULL;
731 menu_class *next = NULL;
732
733 (void)isodisk;
734
735 if (json->enDataType != JSON_TYPE_ARRAY)
736 {
737 debug("Not array %d\n", json->enDataType);
738 return 0;
739 }
740
741 if (g_menu_class_head)
742 {
743 for (node = g_menu_class_head; node; node = next)
744 {
745 next = node->next;
746 grub_free(node);
747 }
748
749 g_menu_class_head = NULL;
750 }
751
752 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
753 {
754 key = vtoy_json_get_string_ex(pNode->pstChild, "key");
755 class = vtoy_json_get_string_ex(pNode->pstChild, "class");
756 if (key && class)
757 {
758 node = grub_zalloc(sizeof(menu_class));
759 if (node)
760 {
761 node->patlen = grub_snprintf(node->pattern, sizeof(node->pattern), "%s", key);
762 grub_snprintf(node->class, sizeof(node->class), "%s", class);
763
764 if (g_menu_class_head)
765 {
766 tail->next = node;
767 }
768 else
769 {
770 g_menu_class_head = node;
771 }
772 tail = node;
773 }
774 }
775 }
776
777 return 0;
778 }
779
780 static int ventoy_plugin_menuclass_check(VTOY_JSON *json, const char *isodisk)
781 {
782 const char *key = NULL;
783 const char *class = NULL;
784 VTOY_JSON *pNode = NULL;
785
786 (void)isodisk;
787
788 if (json->enDataType != JSON_TYPE_ARRAY)
789 {
790 grub_printf("Not array %d\n", json->enDataType);
791 return 1;
792 }
793
794 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
795 {
796 key = vtoy_json_get_string_ex(pNode->pstChild, "key");
797 class = vtoy_json_get_string_ex(pNode->pstChild, "class");
798 if (key && class)
799 {
800 grub_printf("key: <%s>\n", key);
801 grub_printf("class: <%s>\n\n", class);
802 }
803 }
804
805 return 0;
806 }
807
808 static plugin_entry g_plugin_entries[] =
809 {
810 { "control", ventoy_plugin_control_entry, ventoy_plugin_control_check },
811 { "theme", ventoy_plugin_theme_entry, ventoy_plugin_theme_check },
812 { "auto_install", ventoy_plugin_auto_install_entry, ventoy_plugin_auto_install_check },
813 { "persistence", ventoy_plugin_persistence_entry, ventoy_plugin_persistence_check },
814 { "menu_alias", ventoy_plugin_menualias_entry, ventoy_plugin_menualias_check },
815 { "menu_class", ventoy_plugin_menuclass_entry, ventoy_plugin_menuclass_check },
816 };
817
818 static int ventoy_parse_plugin_config(VTOY_JSON *json, const char *isodisk)
819 {
820 int i;
821 VTOY_JSON *cur = json;
822
823 grub_snprintf(g_iso_disk_name, sizeof(g_iso_disk_name), "%s", isodisk);
824
825 while (cur)
826 {
827 for (i = 0; i < (int)ARRAY_SIZE(g_plugin_entries); i++)
828 {
829 if (grub_strcmp(g_plugin_entries[i].key, cur->pcName) == 0)
830 {
831 debug("Plugin entry for %s\n", g_plugin_entries[i].key);
832 g_plugin_entries[i].entryfunc(cur, isodisk);
833 break;
834 }
835 }
836
837 cur = cur->pstNext;
838 }
839
840 return 0;
841 }
842
843 grub_err_t ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **args)
844 {
845 int ret = 0;
846 char *buf = NULL;
847 grub_file_t file;
848 VTOY_JSON *json = NULL;
849
850 (void)ctxt;
851 (void)argc;
852
853 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s/ventoy/ventoy.json", args[0]);
854 if (!file)
855 {
856 return GRUB_ERR_NONE;
857 }
858
859 debug("json configuration file size %d\n", (int)file->size);
860
861 buf = grub_malloc(file->size + 1);
862 if (!buf)
863 {
864 grub_file_close(file);
865 return 1;
866 }
867
868 buf[file->size] = 0;
869 grub_file_read(file, buf, file->size);
870 grub_file_close(file);
871
872 json = vtoy_json_create();
873 if (!json)
874 {
875 return 1;
876 }
877
878
879
880 ret = vtoy_json_parse(json, buf);
881 if (ret)
882 {
883 debug("Failed to parse json string %d\n", ret);
884 grub_free(buf);
885 return 1;
886 }
887
888 ventoy_parse_plugin_config(json->pstChild, args[0]);
889
890 vtoy_json_destroy(json);
891
892 grub_free(buf);
893
894 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
895 }
896
897 void ventoy_plugin_dump_auto_install(void)
898 {
899 int i;
900 install_template *node = NULL;
901
902 for (node = g_install_template_head; node; node = node->next)
903 {
904 grub_printf("\nIMAGE:<%s>\n", node->isopath);
905 for (i = 0; i < node->templatenum; i++)
906 {
907 grub_printf("SCRIPT %d:<%s>\n", i, node->templatepath[i].path);
908 }
909 }
910
911 return;
912 }
913
914 void ventoy_plugin_dump_persistence(void)
915 {
916 int rc;
917 int i = 0;
918 persistence_config *node = NULL;
919 ventoy_img_chunk_list chunk_list;
920
921 for (node = g_persistence_head; node; node = node->next)
922 {
923 grub_printf("\nIMAGE:<%s>\n", node->isopath);
924
925 for (i = 0; i < node->backendnum; i++)
926 {
927 grub_printf("PERSIST %d:<%s>", i, node->backendpath[i].path);
928 rc = ventoy_plugin_get_persistent_chunklist(node->isopath, i, &chunk_list);
929 if (rc == 0)
930 {
931 grub_printf(" [ SUCCESS ]\n");
932 grub_free(chunk_list.chunk);
933 }
934 else
935 {
936 grub_printf(" [ FAILED ]\n");
937 }
938 }
939 }
940
941 return;
942 }
943
944 install_template * ventoy_plugin_find_install_template(const char *isopath)
945 {
946 install_template *node = NULL;
947 int len = (int)grub_strlen(isopath);
948
949 for (node = g_install_template_head; node; node = node->next)
950 {
951 if (node->pathlen == len && grub_strcmp(node->isopath, isopath) == 0)
952 {
953 return node;
954 }
955 }
956
957 return NULL;
958 }
959
960 char * ventoy_plugin_get_cur_install_template(const char *isopath)
961 {
962 install_template *node = NULL;
963
964 node = ventoy_plugin_find_install_template(isopath);
965 if ((!node) || (!node->templatepath))
966 {
967 return NULL;
968 }
969
970 if (node->cursel < 0 || node->cursel >= node->templatenum)
971 {
972 return NULL;
973 }
974
975 return node->templatepath[node->cursel].path;
976 }
977
978 persistence_config * ventoy_plugin_find_persistent(const char *isopath)
979 {
980 persistence_config *node = NULL;
981 int len = (int)grub_strlen(isopath);
982
983 for (node = g_persistence_head; node; node = node->next)
984 {
985 if ((len == node->pathlen) && (grub_strcmp(node->isopath, isopath) == 0))
986 {
987 return node;
988 }
989 }
990
991 return NULL;
992 }
993
994 int ventoy_plugin_get_persistent_chunklist(const char *isopath, int index, ventoy_img_chunk_list *chunk_list)
995 {
996 int rc = 1;
997 grub_uint64_t start = 0;
998 grub_file_t file = NULL;
999 persistence_config *node = NULL;
1000
1001 node = ventoy_plugin_find_persistent(isopath);
1002 if ((!node) || (!node->backendpath))
1003 {
1004 return 1;
1005 }
1006
1007 if (index < 0)
1008 {
1009 index = node->cursel;
1010 }
1011
1012 if (index < 0 || index >= node->backendnum)
1013 {
1014 return 1;
1015 }
1016
1017 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", g_iso_disk_name, node->backendpath[index].path);
1018 if (!file)
1019 {
1020 debug("Failed to open file %s%s\n", g_iso_disk_name, node->backendpath[index].path);
1021 goto end;
1022 }
1023
1024 grub_memset(chunk_list, 0, sizeof(ventoy_img_chunk_list));
1025 chunk_list->chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
1026 if (NULL == chunk_list->chunk)
1027 {
1028 goto end;
1029 }
1030
1031 chunk_list->max_chunk = DEFAULT_CHUNK_NUM;
1032 chunk_list->cur_chunk = 0;
1033
1034 start = file->device->disk->partition->start;
1035 ventoy_get_block_list(file, chunk_list, start);
1036
1037 if (0 != ventoy_check_block_list(file, chunk_list, start))
1038 {
1039 grub_free(chunk_list->chunk);
1040 chunk_list->chunk = NULL;
1041 goto end;
1042 }
1043
1044 rc = 0;
1045
1046 end:
1047 if (file)
1048 grub_file_close(file);
1049
1050 return rc;
1051 }
1052
1053 const char * ventoy_plugin_get_menu_alias(const char *isopath)
1054 {
1055 menu_alias *node = NULL;
1056 int len = (int)grub_strlen(isopath);
1057
1058 for (node = g_menu_alias_head; node; node = node->next)
1059 {
1060 if (node->pathlen == len && grub_strcmp(node->isopath, isopath) == 0)
1061 {
1062 return node->alias;
1063 }
1064 }
1065
1066 return NULL;
1067 }
1068
1069 const char * ventoy_plugin_get_menu_class(const char *isoname)
1070 {
1071 menu_class *node = NULL;
1072 int len = (int)grub_strlen(isoname);
1073
1074 for (node = g_menu_class_head; node; node = node->next)
1075 {
1076 if (node->patlen <= len && grub_strstr(isoname, node->pattern))
1077 {
1078 return node->class;
1079 }
1080 }
1081
1082 return NULL;
1083 }
1084
1085
1086 grub_err_t ventoy_cmd_plugin_check_json(grub_extcmd_context_t ctxt, int argc, char **args)
1087 {
1088 int i = 0;
1089 int ret = 0;
1090 char *buf = NULL;
1091 grub_file_t file;
1092 VTOY_JSON *node = NULL;
1093 VTOY_JSON *json = NULL;
1094
1095 (void)ctxt;
1096
1097 if (argc != 3)
1098 {
1099 return 0;
1100 }
1101
1102 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s/ventoy/ventoy.json", args[0]);
1103 if (!file)
1104 {
1105 grub_printf("Plugin json file /ventoy/ventoy.json does NOT exist.\n");
1106 goto end;
1107 }
1108
1109 buf = grub_malloc(file->size + 1);
1110 if (!buf)
1111 {
1112 grub_printf("Failed to malloc memory %lu.\n", (ulong)(file->size + 1));
1113 goto end;
1114 }
1115
1116 buf[file->size] = 0;
1117 grub_file_read(file, buf, file->size);
1118
1119 json = vtoy_json_create();
1120 if (!json)
1121 {
1122 grub_printf("Failed to create json\n");
1123 goto end;
1124 }
1125
1126 ret = vtoy_json_parse(json, buf);
1127 if (ret)
1128 {
1129 grub_printf("Syntax error detected in ventoy.json, please check it.\n");
1130 goto end;
1131 }
1132
1133 for (node = json->pstChild; node; node = node->pstNext)
1134 {
1135 if (grub_strcmp(node->pcName, args[1]) == 0)
1136 {
1137 break;
1138 }
1139 }
1140
1141 if (!node)
1142 {
1143 grub_printf("%s is NOT found in ventoy.json\n", args[1]);
1144 goto end;
1145 }
1146
1147 for (i = 0; i < (int)ARRAY_SIZE(g_plugin_entries); i++)
1148 {
1149 if (grub_strcmp(g_plugin_entries[i].key, args[1]) == 0)
1150 {
1151 if (g_plugin_entries[i].checkfunc)
1152 {
1153 ret = g_plugin_entries[i].checkfunc(node, args[2]);
1154 }
1155 break;
1156 }
1157 }
1158
1159 end:
1160 check_free(file, grub_file_close);
1161 check_free(json, vtoy_json_destroy);
1162 grub_check_free(buf);
1163
1164 return 0;
1165 }
1166