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