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