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