]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c
f44a4ea466c4756601639ac42adf459faba07971
[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 iso = vtoy_json_get_string_ex(pCNode->pstChild, "file");
880 pwd = vtoy_json_get_string_ex(pCNode->pstChild, "pwd");
881 if (iso && pwd && iso[0] == '/')
882 {
883 node = grub_zalloc(sizeof(menu_password));
884 if (node)
885 {
886 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", iso);
887
888 if (ventoy_plugin_parse_pwdstr((char *)pwd, &(node->password)))
889 {
890 grub_free(node);
891 continue;
892 }
893
894 if (g_pwd_head)
895 {
896 tail->next = node;
897 }
898 else
899 {
900 g_pwd_head = node;
901 }
902 tail = node;
903 }
904 }
905 }
906 }
907 }
908
909 return 0;
910 }
911
912 static int ventoy_plugin_pwd_check(VTOY_JSON *json, const char *isodisk)
913 {
914 int type = -1;
915 char *pos = NULL;
916 const char *iso = NULL;
917 const char *pwd = NULL;
918 VTOY_JSON *pNode = NULL;
919 VTOY_JSON *pCNode = NULL;
920
921 if (json->enDataType != JSON_TYPE_OBJECT)
922 {
923 grub_printf("Not object %d\n", json->enDataType);
924 return 0;
925 }
926
927 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
928 {
929 if (pNode->pcName && grub_strcmp("bootpwd", pNode->pcName) == 0)
930 {
931 if (0 == ventoy_plugin_parse_pwdstr(pNode->unData.pcStrVal, NULL))
932 {
933 grub_printf("bootpwd:<%s>\n", pNode->unData.pcStrVal);
934 }
935 else
936 {
937 grub_printf("Invalid bootpwd.\n");
938 }
939 }
940 else if ((type = ventoy_plugin_get_pwd_type(pNode->pcName)) >= 0)
941 {
942 if (0 == ventoy_plugin_parse_pwdstr(pNode->unData.pcStrVal, NULL))
943 {
944 grub_printf("%s:<%s>\n", pNode->pcName, pNode->unData.pcStrVal);
945 }
946 else
947 {
948 grub_printf("Invalid pwd <%s>\n", pNode->unData.pcStrVal);
949 }
950 }
951 else if (pNode->pcName && grub_strcmp("menupwd", pNode->pcName) == 0)
952 {
953 grub_printf("\n");
954 for (pCNode = pNode->pstChild; pCNode; pCNode = pCNode->pstNext)
955 {
956 if (pCNode->enDataType != JSON_TYPE_OBJECT)
957 {
958 grub_printf("Not object %d\n", pCNode->enDataType);
959 continue;
960 }
961
962 iso = vtoy_json_get_string_ex(pCNode->pstChild, "file");
963 if (iso)
964 {
965 pos = grub_strchr(iso, '*');
966 if (pos || 0 == ventoy_plugin_check_path(isodisk, iso))
967 {
968 pwd = vtoy_json_get_string_ex(pCNode->pstChild, "pwd");
969
970 if (0 == ventoy_plugin_parse_pwdstr((char *)pwd, NULL))
971 {
972 grub_printf("file:<%s> [%s]\n", iso, (pos ? "*" : "OK"));
973 grub_printf("pwd:<%s>\n\n", pwd);
974 }
975 else
976 {
977 grub_printf("Invalid password for <%s>\n", iso);
978 }
979 }
980 else
981 {
982 grub_printf("<%s%s> not found\n", isodisk, iso);
983 }
984 }
985 else
986 {
987 grub_printf("No file item found in json.\n");
988 }
989 }
990 }
991 }
992
993 return 0;
994 }
995
996 static int ventoy_plugin_persistence_check(VTOY_JSON *json, const char *isodisk)
997 {
998 int autosel = 0;
999 int pathnum = 0;
1000 char *pos = NULL;
1001 const char *iso = NULL;
1002 VTOY_JSON *pNode = NULL;
1003
1004 if (json->enDataType != JSON_TYPE_ARRAY)
1005 {
1006 grub_printf("Not array type %d\n", json->enDataType);
1007 return 1;
1008 }
1009
1010 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1011 {
1012 if (pNode->enDataType != JSON_TYPE_OBJECT)
1013 {
1014 grub_printf("NOT object type\n");
1015 }
1016
1017 iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
1018 if (iso)
1019 {
1020 pos = grub_strchr(iso, '*');
1021 if (pos || 0 == ventoy_plugin_check_path(isodisk, iso))
1022 {
1023 grub_printf("image: %s [%s]\n", iso, (pos ? "*" : "OK"));
1024 ventoy_plugin_check_fullpath(pNode->pstChild, isodisk, "backend", &pathnum);
1025
1026 if (JSON_SUCCESS == vtoy_json_get_int(pNode->pstChild, "autosel", &autosel))
1027 {
1028 if (autosel >= 0 && autosel <= pathnum)
1029 {
1030 grub_printf("autosel: %d [OK]\n", autosel);
1031 }
1032 else
1033 {
1034 grub_printf("autosel: %d [FAIL]\n", autosel);
1035 }
1036 }
1037 }
1038 else
1039 {
1040 grub_printf("image: %s [FAIL]\n", iso);
1041 }
1042 }
1043 else
1044 {
1045 grub_printf("image not found\n");
1046 }
1047 }
1048
1049 return 0;
1050 }
1051
1052 static int ventoy_plugin_persistence_entry(VTOY_JSON *json, const char *isodisk)
1053 {
1054 int autosel = 0;
1055 int pathnum = 0;
1056 const char *iso = NULL;
1057 VTOY_JSON *pNode = NULL;
1058 persistence_config *node = NULL;
1059 persistence_config *next = NULL;
1060 file_fullpath *backendpath = NULL;
1061
1062 (void)isodisk;
1063
1064 if (json->enDataType != JSON_TYPE_ARRAY)
1065 {
1066 debug("Not array %d\n", json->enDataType);
1067 return 0;
1068 }
1069
1070 if (g_persistence_head)
1071 {
1072 for (node = g_persistence_head; node; node = next)
1073 {
1074 next = node->next;
1075 grub_check_free(node->backendpath);
1076 grub_free(node);
1077 }
1078
1079 g_persistence_head = NULL;
1080 }
1081
1082 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1083 {
1084 iso = vtoy_json_get_string_ex(pNode->pstChild, "image");
1085 if (iso && iso[0] == '/')
1086 {
1087 if (0 == ventoy_plugin_parse_fullpath(pNode->pstChild, isodisk, "backend", &backendpath, &pathnum))
1088 {
1089 node = grub_zalloc(sizeof(persistence_config));
1090 if (node)
1091 {
1092 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", iso);
1093 node->backendpath = backendpath;
1094 node->backendnum = pathnum;
1095
1096 node->autosel = -1;
1097 if (JSON_SUCCESS == vtoy_json_get_int(pNode->pstChild, "autosel", &autosel))
1098 {
1099 if (autosel >= 0 && autosel <= pathnum)
1100 {
1101 node->autosel = autosel;
1102 }
1103 }
1104
1105 if (g_persistence_head)
1106 {
1107 node->next = g_persistence_head;
1108 }
1109
1110 g_persistence_head = node;
1111 }
1112 }
1113 }
1114 }
1115
1116 return 0;
1117 }
1118
1119 static int ventoy_plugin_menualias_check(VTOY_JSON *json, const char *isodisk)
1120 {
1121 int type;
1122 const char *path = NULL;
1123 const char *alias = NULL;
1124 VTOY_JSON *pNode = NULL;
1125
1126 (void)isodisk;
1127
1128 if (json->enDataType != JSON_TYPE_ARRAY)
1129 {
1130 grub_printf("Not array %d\n", json->enDataType);
1131 return 1;
1132 }
1133
1134 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1135 {
1136 type = vtoy_alias_image_file;
1137 path = vtoy_json_get_string_ex(pNode->pstChild, "image");
1138 if (!path)
1139 {
1140 path = vtoy_json_get_string_ex(pNode->pstChild, "dir");
1141 type = vtoy_alias_directory;
1142 }
1143
1144 alias = vtoy_json_get_string_ex(pNode->pstChild, "alias");
1145 if (path && path[0] == '/' && alias)
1146 {
1147 if (vtoy_alias_image_file == type)
1148 {
1149 if (grub_strchr(path, '*'))
1150 {
1151 grub_printf("image: <%s> [ * ]\n", path);
1152 }
1153 else if (ventoy_is_file_exist("%s%s", isodisk, path))
1154 {
1155 grub_printf("image: <%s> [ OK ]\n", path);
1156 }
1157 else
1158 {
1159 grub_printf("image: <%s> [ NOT EXIST ]\n", path);
1160 }
1161 }
1162 else
1163 {
1164 if (ventoy_is_dir_exist("%s%s", isodisk, path))
1165 {
1166 grub_printf("dir: <%s> [ OK ]\n", path);
1167 }
1168 else
1169 {
1170 grub_printf("dir: <%s> [ NOT EXIST ]\n", path);
1171 }
1172 }
1173
1174 grub_printf("alias: <%s>\n\n", alias);
1175 }
1176 }
1177
1178 return 0;
1179 }
1180
1181 static int ventoy_plugin_menualias_entry(VTOY_JSON *json, const char *isodisk)
1182 {
1183 int type;
1184 const char *path = NULL;
1185 const char *alias = NULL;
1186 VTOY_JSON *pNode = NULL;
1187 menu_alias *node = NULL;
1188 menu_alias *next = NULL;
1189
1190 (void)isodisk;
1191
1192 if (json->enDataType != JSON_TYPE_ARRAY)
1193 {
1194 debug("Not array %d\n", json->enDataType);
1195 return 0;
1196 }
1197
1198 if (g_menu_alias_head)
1199 {
1200 for (node = g_menu_alias_head; node; node = next)
1201 {
1202 next = node->next;
1203 grub_free(node);
1204 }
1205
1206 g_menu_alias_head = NULL;
1207 }
1208
1209 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1210 {
1211 type = vtoy_alias_image_file;
1212 path = vtoy_json_get_string_ex(pNode->pstChild, "image");
1213 if (!path)
1214 {
1215 path = vtoy_json_get_string_ex(pNode->pstChild, "dir");
1216 type = vtoy_alias_directory;
1217 }
1218
1219 alias = vtoy_json_get_string_ex(pNode->pstChild, "alias");
1220 if (path && path[0] == '/' && alias)
1221 {
1222 node = grub_zalloc(sizeof(menu_alias));
1223 if (node)
1224 {
1225 node->type = type;
1226 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", path);
1227 grub_snprintf(node->alias, sizeof(node->alias), "%s", alias);
1228
1229 if (g_menu_alias_head)
1230 {
1231 node->next = g_menu_alias_head;
1232 }
1233
1234 g_menu_alias_head = node;
1235 }
1236 }
1237 }
1238
1239 return 0;
1240 }
1241
1242
1243 static int ventoy_plugin_injection_check(VTOY_JSON *json, const char *isodisk)
1244 {
1245 const char *path = NULL;
1246 const char *archive = NULL;
1247 VTOY_JSON *pNode = NULL;
1248
1249 (void)isodisk;
1250
1251 if (json->enDataType != JSON_TYPE_ARRAY)
1252 {
1253 grub_printf("Not array %d\n", json->enDataType);
1254 return 0;
1255 }
1256
1257 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1258 {
1259 path = vtoy_json_get_string_ex(pNode->pstChild, "image");
1260 if (!path)
1261 {
1262 grub_printf("image not found\n");
1263 continue;
1264 }
1265
1266 archive = vtoy_json_get_string_ex(pNode->pstChild, "archive");
1267 if (!archive)
1268 {
1269 grub_printf("archive not found\n");
1270 continue;
1271 }
1272
1273 if (grub_strchr(path, '*'))
1274 {
1275 grub_printf("image: <%s> [*]\n", path);
1276 }
1277 else
1278 {
1279 grub_printf("image: <%s> [%s]\n", path, ventoy_check_file_exist("%s%s", isodisk, path) ? "OK" : "NOT EXIST");
1280 }
1281
1282 grub_printf("archive: <%s> [%s]\n\n", archive, ventoy_check_file_exist("%s%s", isodisk, archive) ? "OK" : "NOT EXIST");
1283 }
1284
1285 return 0;
1286 }
1287
1288 static int ventoy_plugin_injection_entry(VTOY_JSON *json, const char *isodisk)
1289 {
1290 const char *path = NULL;
1291 const char *archive = NULL;
1292 VTOY_JSON *pNode = NULL;
1293 injection_config *node = NULL;
1294 injection_config *next = NULL;
1295
1296 (void)isodisk;
1297
1298 if (json->enDataType != JSON_TYPE_ARRAY)
1299 {
1300 debug("Not array %d\n", json->enDataType);
1301 return 0;
1302 }
1303
1304 if (g_injection_head)
1305 {
1306 for (node = g_injection_head; node; node = next)
1307 {
1308 next = node->next;
1309 grub_free(node);
1310 }
1311
1312 g_injection_head = NULL;
1313 }
1314
1315 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1316 {
1317 path = vtoy_json_get_string_ex(pNode->pstChild, "image");
1318 archive = vtoy_json_get_string_ex(pNode->pstChild, "archive");
1319 if (path && path[0] == '/' && archive && archive[0] == '/')
1320 {
1321 node = grub_zalloc(sizeof(injection_config));
1322 if (node)
1323 {
1324 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", path);
1325 grub_snprintf(node->archive, sizeof(node->archive), "%s", archive);
1326
1327 if (g_injection_head)
1328 {
1329 node->next = g_injection_head;
1330 }
1331
1332 g_injection_head = node;
1333 }
1334 }
1335 }
1336
1337 return 0;
1338 }
1339
1340 static int ventoy_plugin_menuclass_entry(VTOY_JSON *json, const char *isodisk)
1341 {
1342 int type;
1343 int parent = 0;
1344 const char *key = NULL;
1345 const char *class = NULL;
1346 VTOY_JSON *pNode = NULL;
1347 menu_class *tail = NULL;
1348 menu_class *node = NULL;
1349 menu_class *next = NULL;
1350
1351 (void)isodisk;
1352
1353 if (json->enDataType != JSON_TYPE_ARRAY)
1354 {
1355 debug("Not array %d\n", json->enDataType);
1356 return 0;
1357 }
1358
1359 if (g_menu_class_head)
1360 {
1361 for (node = g_menu_class_head; node; node = next)
1362 {
1363 next = node->next;
1364 grub_free(node);
1365 }
1366
1367 g_menu_class_head = NULL;
1368 }
1369
1370 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1371 {
1372 parent = 0;
1373 type = vtoy_class_image_file;
1374 key = vtoy_json_get_string_ex(pNode->pstChild, "key");
1375 if (!key)
1376 {
1377 key = vtoy_json_get_string_ex(pNode->pstChild, "parent");
1378 if (key)
1379 {
1380 parent = 1;
1381 }
1382 else
1383 {
1384 key = vtoy_json_get_string_ex(pNode->pstChild, "dir");
1385 type = vtoy_class_directory;
1386 }
1387 }
1388
1389 class = vtoy_json_get_string_ex(pNode->pstChild, "class");
1390 if (key && class)
1391 {
1392 node = grub_zalloc(sizeof(menu_class));
1393 if (node)
1394 {
1395 node->type = type;
1396 node->parent = parent;
1397 node->patlen = grub_snprintf(node->pattern, sizeof(node->pattern), "%s", key);
1398 grub_snprintf(node->class, sizeof(node->class), "%s", class);
1399
1400 if (g_menu_class_head)
1401 {
1402 tail->next = node;
1403 }
1404 else
1405 {
1406 g_menu_class_head = node;
1407 }
1408 tail = node;
1409 }
1410 }
1411 }
1412
1413 return 0;
1414 }
1415
1416 static int ventoy_plugin_menuclass_check(VTOY_JSON *json, const char *isodisk)
1417 {
1418 const char *name = NULL;
1419 const char *key = NULL;
1420 const char *class = NULL;
1421 VTOY_JSON *pNode = NULL;
1422
1423 (void)isodisk;
1424
1425 if (json->enDataType != JSON_TYPE_ARRAY)
1426 {
1427 grub_printf("Not array %d\n", json->enDataType);
1428 return 1;
1429 }
1430
1431 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1432 {
1433 name = "key";
1434 key = vtoy_json_get_string_ex(pNode->pstChild, "key");
1435 if (!key)
1436 {
1437 name = "parent";
1438 key = vtoy_json_get_string_ex(pNode->pstChild, "parent");
1439 if (!key)
1440 {
1441 name = "dir";
1442 key = vtoy_json_get_string_ex(pNode->pstChild, "dir");
1443 }
1444 }
1445
1446 class = vtoy_json_get_string_ex(pNode->pstChild, "class");
1447 if (key && class)
1448 {
1449 grub_printf("%s: <%s>\n", name, key);
1450 grub_printf("class: <%s>\n\n", class);
1451 }
1452 }
1453
1454 return 0;
1455 }
1456
1457 static int ventoy_plugin_custom_boot_entry(VTOY_JSON *json, const char *isodisk)
1458 {
1459 int type;
1460 int len;
1461 const char *key = NULL;
1462 const char *cfg = NULL;
1463 VTOY_JSON *pNode = NULL;
1464 custom_boot *tail = NULL;
1465 custom_boot *node = NULL;
1466 custom_boot *next = NULL;
1467
1468 (void)isodisk;
1469
1470 if (json->enDataType != JSON_TYPE_ARRAY)
1471 {
1472 debug("Not array %d\n", json->enDataType);
1473 return 0;
1474 }
1475
1476 if (g_custom_boot_head)
1477 {
1478 for (node = g_custom_boot_head; node; node = next)
1479 {
1480 next = node->next;
1481 grub_free(node);
1482 }
1483
1484 g_custom_boot_head = NULL;
1485 }
1486
1487 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1488 {
1489 type = vtoy_custom_boot_image_file;
1490 key = vtoy_json_get_string_ex(pNode->pstChild, "file");
1491 if (!key)
1492 {
1493 key = vtoy_json_get_string_ex(pNode->pstChild, "dir");
1494 type = vtoy_custom_boot_directory;
1495 }
1496
1497 cfg = vtoy_json_get_string_ex(pNode->pstChild, "vcfg");
1498 if (key && cfg)
1499 {
1500 node = grub_zalloc(sizeof(custom_boot));
1501 if (node)
1502 {
1503 node->type = type;
1504 node->pathlen = grub_snprintf(node->path, sizeof(node->path), "%s", key);
1505 len = (int)grub_snprintf(node->cfg, sizeof(node->cfg), "%s", cfg);
1506
1507 if (len >= 5 && grub_strncmp(node->cfg + len - 5, ".vcfg", 5) == 0)
1508 {
1509 if (g_custom_boot_head)
1510 {
1511 tail->next = node;
1512 }
1513 else
1514 {
1515 g_custom_boot_head = node;
1516 }
1517 tail = node;
1518 }
1519 else
1520 {
1521 grub_free(node);
1522 }
1523 }
1524 }
1525 }
1526
1527 return 0;
1528 }
1529
1530 static int ventoy_plugin_custom_boot_check(VTOY_JSON *json, const char *isodisk)
1531 {
1532 int type;
1533 int len;
1534 const char *key = NULL;
1535 const char *cfg = NULL;
1536 VTOY_JSON *pNode = NULL;
1537
1538 (void)isodisk;
1539
1540 if (json->enDataType != JSON_TYPE_ARRAY)
1541 {
1542 grub_printf("Not array %d\n", json->enDataType);
1543 return 1;
1544 }
1545
1546 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1547 {
1548 type = vtoy_custom_boot_image_file;
1549 key = vtoy_json_get_string_ex(pNode->pstChild, "file");
1550 if (!key)
1551 {
1552 key = vtoy_json_get_string_ex(pNode->pstChild, "dir");
1553 type = vtoy_custom_boot_directory;
1554 }
1555
1556 cfg = vtoy_json_get_string_ex(pNode->pstChild, "vcfg");
1557 len = (int)grub_strlen(cfg);
1558 if (key && cfg)
1559 {
1560 if (len < 5 || grub_strncmp(cfg + len - 5, ".vcfg", 5))
1561 {
1562 grub_printf("<%s> does not have \".vcfg\" suffix\n\n", cfg);
1563 }
1564 else
1565 {
1566 grub_printf("%s: <%s>\n", (type == vtoy_custom_boot_directory) ? "dir" : "file", key);
1567 grub_printf("vcfg: <%s>\n\n", cfg);
1568 }
1569 }
1570 }
1571
1572 return 0;
1573 }
1574
1575 static int ventoy_plugin_conf_replace_entry(VTOY_JSON *json, const char *isodisk)
1576 {
1577 const char *isof = NULL;
1578 const char *orgf = NULL;
1579 const char *newf = NULL;
1580 VTOY_JSON *pNode = NULL;
1581 conf_replace *tail = NULL;
1582 conf_replace *node = NULL;
1583 conf_replace *next = NULL;
1584
1585 (void)isodisk;
1586
1587 if (json->enDataType != JSON_TYPE_ARRAY)
1588 {
1589 debug("Not array %d\n", json->enDataType);
1590 return 0;
1591 }
1592
1593 if (g_conf_replace_head)
1594 {
1595 for (node = g_conf_replace_head; node; node = next)
1596 {
1597 next = node->next;
1598 grub_free(node);
1599 }
1600
1601 g_conf_replace_head = NULL;
1602 }
1603
1604 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1605 {
1606 isof = vtoy_json_get_string_ex(pNode->pstChild, "iso");
1607 orgf = vtoy_json_get_string_ex(pNode->pstChild, "org");
1608 newf = vtoy_json_get_string_ex(pNode->pstChild, "new");
1609 if (isof && orgf && newf && isof[0] == '/' && orgf[0] == '/' && newf[0] == '/')
1610 {
1611 node = grub_zalloc(sizeof(conf_replace));
1612 if (node)
1613 {
1614 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", isof);
1615 grub_snprintf(node->orgconf, sizeof(node->orgconf), "%s", orgf);
1616 grub_snprintf(node->newconf, sizeof(node->newconf), "%s", newf);
1617
1618 if (g_conf_replace_head)
1619 {
1620 tail->next = node;
1621 }
1622 else
1623 {
1624 g_conf_replace_head = node;
1625 }
1626 tail = node;
1627 }
1628 }
1629 }
1630
1631 return 0;
1632 }
1633
1634 static int ventoy_plugin_conf_replace_check(VTOY_JSON *json, const char *isodisk)
1635 {
1636 const char *isof = NULL;
1637 const char *orgf = NULL;
1638 const char *newf = NULL;
1639 VTOY_JSON *pNode = NULL;
1640 grub_file_t file = NULL;
1641 char cmd[256];
1642
1643 (void)isodisk;
1644
1645 if (json->enDataType != JSON_TYPE_ARRAY)
1646 {
1647 grub_printf("Not array %d\n", json->enDataType);
1648 return 1;
1649 }
1650
1651 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1652 {
1653 isof = vtoy_json_get_string_ex(pNode->pstChild, "iso");
1654 orgf = vtoy_json_get_string_ex(pNode->pstChild, "org");
1655 newf = vtoy_json_get_string_ex(pNode->pstChild, "new");
1656 if (isof && orgf && newf && isof[0] == '/' && orgf[0] == '/' && newf[0] == '/')
1657 {
1658 if (ventoy_check_file_exist("%s%s", isodisk, isof))
1659 {
1660 grub_printf("iso:<%s> [OK]\n", isof);
1661
1662 grub_snprintf(cmd, sizeof(cmd), "loopback vtisocheck \"%s%s\"", isodisk, isof);
1663 grub_script_execute_sourcecode(cmd);
1664
1665 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(vtisocheck)/%s", orgf);
1666 if (file)
1667 {
1668 if (grub_strcmp(file->fs->name, "iso9660") == 0)
1669 {
1670 grub_printf("org:<%s> [OK]\n", orgf);
1671 }
1672 else
1673 {
1674 grub_printf("org:<%s> [Exist But NOT ISO9660]\n", orgf);
1675 }
1676 grub_file_close(file);
1677 }
1678 else
1679 {
1680 grub_printf("org:<%s> [NOT Exist]\n", orgf);
1681 }
1682
1683 grub_script_execute_sourcecode("loopback -d vtisocheck");
1684 }
1685 else if (grub_strchr(isof, '*'))
1686 {
1687 grub_printf("iso:<%s> [*]\n", isof);
1688 grub_printf("org:<%s>\n", orgf);
1689 }
1690 else
1691 {
1692 grub_printf("iso:<%s> [NOT Exist]\n", isof);
1693 grub_printf("org:<%s>\n", orgf);
1694 }
1695
1696 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", isodisk, newf);
1697 if (file)
1698 {
1699 if (file->size > vtoy_max_replace_file_size)
1700 {
1701 grub_printf("new:<%s> [Too Big %lu] \n", newf, (ulong)file->size);
1702 }
1703 else
1704 {
1705 grub_printf("new:<%s> [OK]\n", newf);
1706 }
1707 grub_file_close(file);
1708 }
1709 else
1710 {
1711 grub_printf("new:<%s> [NOT Exist]\n", newf);
1712 }
1713 grub_printf("\n");
1714 }
1715 }
1716
1717 return 0;
1718 }
1719
1720 static int ventoy_plugin_auto_memdisk_entry(VTOY_JSON *json, const char *isodisk)
1721 {
1722 VTOY_JSON *pNode = NULL;
1723 auto_memdisk *node = NULL;
1724 auto_memdisk *next = NULL;
1725
1726 (void)isodisk;
1727
1728 if (json->enDataType != JSON_TYPE_ARRAY)
1729 {
1730 debug("Not array %d\n", json->enDataType);
1731 return 0;
1732 }
1733
1734 if (g_auto_memdisk_head)
1735 {
1736 for (node = g_auto_memdisk_head; node; node = next)
1737 {
1738 next = node->next;
1739 grub_free(node);
1740 }
1741
1742 g_auto_memdisk_head = NULL;
1743 }
1744
1745 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1746 {
1747 if (pNode->enDataType == JSON_TYPE_STRING)
1748 {
1749 node = grub_zalloc(sizeof(auto_memdisk));
1750 if (node)
1751 {
1752 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", pNode->unData.pcStrVal);
1753
1754 if (g_auto_memdisk_head)
1755 {
1756 node->next = g_auto_memdisk_head;
1757 }
1758
1759 g_auto_memdisk_head = node;
1760 }
1761 }
1762 }
1763
1764 return 0;
1765 }
1766
1767 static int ventoy_plugin_auto_memdisk_check(VTOY_JSON *json, const char *isodisk)
1768 {
1769 VTOY_JSON *pNode = NULL;
1770
1771 if (json->enDataType != JSON_TYPE_ARRAY)
1772 {
1773 grub_printf("Not array %d\n", json->enDataType);
1774 return 1;
1775 }
1776
1777 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1778 {
1779 if (pNode->enDataType == JSON_TYPE_STRING)
1780 {
1781 grub_printf("<%s> ", pNode->unData.pcStrVal);
1782
1783 if (grub_strchr(pNode->unData.pcStrVal, '*'))
1784 {
1785 grub_printf(" [*]\n");
1786 }
1787 else if (ventoy_check_file_exist("%s%s", isodisk, pNode->unData.pcStrVal))
1788 {
1789 grub_printf(" [OK]\n");
1790 }
1791 else
1792 {
1793 grub_printf(" [NOT EXIST]\n");
1794 }
1795 }
1796 }
1797
1798 return 0;
1799 }
1800
1801 static int ventoy_plugin_image_list_entry(VTOY_JSON *json, const char *isodisk)
1802 {
1803 VTOY_JSON *pNode = NULL;
1804 image_list *node = NULL;
1805 image_list *next = NULL;
1806 image_list *tail = NULL;
1807
1808 (void)isodisk;
1809
1810 if (json->enDataType != JSON_TYPE_ARRAY)
1811 {
1812 debug("Not array %d\n", json->enDataType);
1813 return 0;
1814 }
1815
1816 if (g_image_list_head)
1817 {
1818 for (node = g_image_list_head; node; node = next)
1819 {
1820 next = node->next;
1821 grub_free(node);
1822 }
1823
1824 g_image_list_head = NULL;
1825 }
1826
1827 if (grub_strncmp(json->pcName, "image_blacklist", 15) == 0)
1828 {
1829 g_plugin_image_list = VENTOY_IMG_BLACK_LIST;
1830 }
1831 else
1832 {
1833 g_plugin_image_list = VENTOY_IMG_WHITE_LIST;
1834 }
1835
1836 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1837 {
1838 if (pNode->enDataType == JSON_TYPE_STRING)
1839 {
1840 node = grub_zalloc(sizeof(image_list));
1841 if (node)
1842 {
1843 node->pathlen = grub_snprintf(node->isopath, sizeof(node->isopath), "%s", pNode->unData.pcStrVal);
1844
1845 if (g_image_list_head)
1846 {
1847 tail->next = node;
1848 }
1849 else
1850 {
1851 g_image_list_head = node;
1852 }
1853 tail = node;
1854 }
1855 }
1856 }
1857
1858 return 0;
1859 }
1860
1861 static int ventoy_plugin_image_list_check(VTOY_JSON *json, const char *isodisk)
1862 {
1863 VTOY_JSON *pNode = NULL;
1864
1865 if (json->enDataType != JSON_TYPE_ARRAY)
1866 {
1867 grub_printf("Not array %d\n", json->enDataType);
1868 return 1;
1869 }
1870
1871 for (pNode = json->pstChild; pNode; pNode = pNode->pstNext)
1872 {
1873 if (pNode->enDataType == JSON_TYPE_STRING)
1874 {
1875 grub_printf("<%s> ", pNode->unData.pcStrVal);
1876
1877 if (grub_strchr(pNode->unData.pcStrVal, '*'))
1878 {
1879 grub_printf(" [*]\n");
1880 }
1881 else if (ventoy_check_file_exist("%s%s", isodisk, pNode->unData.pcStrVal))
1882 {
1883 grub_printf(" [OK]\n");
1884 }
1885 else
1886 {
1887 grub_printf(" [NOT EXIST]\n");
1888 }
1889 }
1890 }
1891
1892 return 0;
1893 }
1894
1895 static plugin_entry g_plugin_entries[] =
1896 {
1897 { "control", ventoy_plugin_control_entry, ventoy_plugin_control_check },
1898 { "theme", ventoy_plugin_theme_entry, ventoy_plugin_theme_check },
1899 { "auto_install", ventoy_plugin_auto_install_entry, ventoy_plugin_auto_install_check },
1900 { "persistence", ventoy_plugin_persistence_entry, ventoy_plugin_persistence_check },
1901 { "menu_alias", ventoy_plugin_menualias_entry, ventoy_plugin_menualias_check },
1902 { "menu_class", ventoy_plugin_menuclass_entry, ventoy_plugin_menuclass_check },
1903 { "injection", ventoy_plugin_injection_entry, ventoy_plugin_injection_check },
1904 { "auto_memdisk", ventoy_plugin_auto_memdisk_entry, ventoy_plugin_auto_memdisk_check },
1905 { "image_list", ventoy_plugin_image_list_entry, ventoy_plugin_image_list_check },
1906 { "image_blacklist", ventoy_plugin_image_list_entry, ventoy_plugin_image_list_check },
1907 { "conf_replace", ventoy_plugin_conf_replace_entry, ventoy_plugin_conf_replace_check },
1908 { "dud", ventoy_plugin_dud_entry, ventoy_plugin_dud_check },
1909 { "password", ventoy_plugin_pwd_entry, ventoy_plugin_pwd_check },
1910 { "custom_boot", ventoy_plugin_custom_boot_entry, ventoy_plugin_custom_boot_check },
1911 };
1912
1913 static int ventoy_parse_plugin_config(VTOY_JSON *json, const char *isodisk)
1914 {
1915 int i;
1916 char key[128];
1917 VTOY_JSON *cur = json;
1918
1919 grub_snprintf(g_iso_disk_name, sizeof(g_iso_disk_name), "%s", isodisk);
1920
1921 while (cur)
1922 {
1923 for (i = 0; i < (int)ARRAY_SIZE(g_plugin_entries); i++)
1924 {
1925 grub_snprintf(key, sizeof(key), "%s_%s", g_plugin_entries[i].key, g_arch_mode_suffix);
1926 if (grub_strcmp(g_plugin_entries[i].key, cur->pcName) == 0 || grub_strcmp(key, cur->pcName) == 0)
1927 {
1928 debug("Plugin entry for %s\n", g_plugin_entries[i].key);
1929 g_plugin_entries[i].entryfunc(cur, isodisk);
1930 break;
1931 }
1932 }
1933
1934 cur = cur->pstNext;
1935 }
1936
1937 return 0;
1938 }
1939
1940 grub_err_t ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **args)
1941 {
1942 int ret = 0;
1943 char *buf = NULL;
1944 grub_file_t file;
1945 VTOY_JSON *json = NULL;
1946
1947 (void)ctxt;
1948 (void)argc;
1949
1950 file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s/ventoy/ventoy.json", args[0]);
1951 if (!file)
1952 {
1953 return GRUB_ERR_NONE;
1954 }
1955
1956 debug("json configuration file size %d\n", (int)file->size);
1957
1958 buf = grub_malloc(file->size + 1);
1959 if (!buf)
1960 {
1961 grub_file_close(file);
1962 return 1;
1963 }
1964
1965 buf[file->size] = 0;
1966 grub_file_read(file, buf, file->size);
1967 grub_file_close(file);
1968
1969 json = vtoy_json_create();
1970 if (!json)
1971 {
1972 return 1;
1973 }
1974
1975
1976
1977 ret = vtoy_json_parse(json, buf);
1978 if (ret)
1979 {
1980 grub_env_set("VTOY_PLUGIN_SYNTAX_ERROR", "1");
1981 grub_env_export("VTOY_PLUGIN_SYNTAX_ERROR");
1982
1983 debug("Failed to parse json string %d\n", ret);
1984 grub_free(buf);
1985 return 1;
1986 }
1987
1988 ventoy_parse_plugin_config(json->pstChild, args[0]);
1989
1990 vtoy_json_destroy(json);
1991
1992 grub_free(buf);
1993
1994 if (g_boot_pwd.type)
1995 {
1996 grub_printf("\n\n======= %s ======\n\n", grub_env_get("VTOY_TEXT_MENU_VER"));
1997 if (ventoy_check_password(&g_boot_pwd, 3))
1998 {
1999 grub_printf("\n!!! Password check failed, will exit after 5 seconds. !!!\n");
2000 grub_refresh();
2001 grub_sleep(5);
2002 grub_exit();
2003 }
2004 }
2005
2006 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2007 }
2008
2009 void ventoy_plugin_dump_injection(void)
2010 {
2011 injection_config *node = NULL;
2012
2013 for (node = g_injection_head; node; node = node->next)
2014 {
2015 grub_printf("\nIMAGE:<%s>\n", node->isopath);
2016 grub_printf("ARCHIVE:<%s>\n", node->archive);
2017 }
2018
2019 return;
2020 }
2021
2022
2023 void ventoy_plugin_dump_auto_install(void)
2024 {
2025 int i;
2026 install_template *node = NULL;
2027
2028 for (node = g_install_template_head; node; node = node->next)
2029 {
2030 grub_printf("\nIMAGE:<%s> <%d>\n", node->isopath, node->templatenum);
2031 for (i = 0; i < node->templatenum; i++)
2032 {
2033 grub_printf("SCRIPT %d:<%s>\n", i, node->templatepath[i].path);
2034 }
2035 }
2036
2037 return;
2038 }
2039
2040 void ventoy_plugin_dump_persistence(void)
2041 {
2042 int rc;
2043 int i = 0;
2044 persistence_config *node = NULL;
2045 ventoy_img_chunk_list chunk_list;
2046
2047 for (node = g_persistence_head; node; node = node->next)
2048 {
2049 grub_printf("\nIMAGE:<%s> <%d>\n", node->isopath, node->backendnum);
2050
2051 for (i = 0; i < node->backendnum; i++)
2052 {
2053 grub_printf("PERSIST %d:<%s>", i, node->backendpath[i].path);
2054 rc = ventoy_plugin_get_persistent_chunklist(node->isopath, i, &chunk_list);
2055 if (rc == 0)
2056 {
2057 grub_printf(" [ SUCCESS ]\n");
2058 grub_free(chunk_list.chunk);
2059 }
2060 else
2061 {
2062 grub_printf(" [ FAILED ]\n");
2063 }
2064 }
2065 }
2066
2067 return;
2068 }
2069
2070 install_template * ventoy_plugin_find_install_template(const char *isopath)
2071 {
2072 int len;
2073 install_template *node = NULL;
2074
2075 if (!g_install_template_head)
2076 {
2077 return NULL;
2078 }
2079
2080 len = (int)grub_strlen(isopath);
2081 for (node = g_install_template_head; node; node = node->next)
2082 {
2083 if (node->pathlen == len && ventoy_strcmp(node->isopath, isopath) == 0)
2084 {
2085 return node;
2086 }
2087 }
2088
2089 return NULL;
2090 }
2091
2092 char * ventoy_plugin_get_cur_install_template(const char *isopath)
2093 {
2094 install_template *node = NULL;
2095
2096 node = ventoy_plugin_find_install_template(isopath);
2097 if ((!node) || (!node->templatepath))
2098 {
2099 return NULL;
2100 }
2101
2102 if (node->cursel < 0 || node->cursel >= node->templatenum)
2103 {
2104 return NULL;
2105 }
2106
2107 return node->templatepath[node->cursel].path;
2108 }
2109
2110 persistence_config * ventoy_plugin_find_persistent(const char *isopath)
2111 {
2112 int len;
2113 persistence_config *node = NULL;
2114
2115 if (!g_persistence_head)
2116 {
2117 return NULL;
2118 }
2119
2120 len = (int)grub_strlen(isopath);
2121 for (node = g_persistence_head; node; node = node->next)
2122 {
2123 if ((len == node->pathlen) && (ventoy_strcmp(node->isopath, isopath) == 0))
2124 {
2125 return node;
2126 }
2127 }
2128
2129 return NULL;
2130 }
2131
2132 int ventoy_plugin_get_persistent_chunklist(const char *isopath, int index, ventoy_img_chunk_list *chunk_list)
2133 {
2134 int rc = 1;
2135 grub_uint64_t start = 0;
2136 grub_file_t file = NULL;
2137 persistence_config *node = NULL;
2138
2139 node = ventoy_plugin_find_persistent(isopath);
2140 if ((!node) || (!node->backendpath))
2141 {
2142 return 1;
2143 }
2144
2145 if (index < 0)
2146 {
2147 index = node->cursel;
2148 }
2149
2150 if (index < 0 || index >= node->backendnum)
2151 {
2152 return 1;
2153 }
2154
2155 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", g_iso_disk_name, node->backendpath[index].path);
2156 if (!file)
2157 {
2158 debug("Failed to open file %s%s\n", g_iso_disk_name, node->backendpath[index].path);
2159 goto end;
2160 }
2161
2162 grub_memset(chunk_list, 0, sizeof(ventoy_img_chunk_list));
2163 chunk_list->chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
2164 if (NULL == chunk_list->chunk)
2165 {
2166 goto end;
2167 }
2168
2169 chunk_list->max_chunk = DEFAULT_CHUNK_NUM;
2170 chunk_list->cur_chunk = 0;
2171
2172 start = file->device->disk->partition->start;
2173 ventoy_get_block_list(file, chunk_list, start);
2174
2175 if (0 != ventoy_check_block_list(file, chunk_list, start))
2176 {
2177 grub_free(chunk_list->chunk);
2178 chunk_list->chunk = NULL;
2179 goto end;
2180 }
2181
2182 rc = 0;
2183
2184 end:
2185 if (file)
2186 grub_file_close(file);
2187
2188 return rc;
2189 }
2190
2191 const char * ventoy_plugin_get_injection(const char *isopath)
2192 {
2193 int len;
2194 injection_config *node = NULL;
2195
2196 if (!g_injection_head)
2197 {
2198 return NULL;
2199 }
2200
2201 len = (int)grub_strlen(isopath);
2202 for (node = g_injection_head; node; node = node->next)
2203 {
2204 if (node->pathlen == len && ventoy_strcmp(node->isopath, isopath) == 0)
2205 {
2206 return node->archive;
2207 }
2208 }
2209
2210 return NULL;
2211 }
2212
2213 const char * ventoy_plugin_get_menu_alias(int type, const char *isopath)
2214 {
2215 int len;
2216 menu_alias *node = NULL;
2217
2218 if (!g_menu_alias_head)
2219 {
2220 return NULL;
2221 }
2222
2223 len = (int)grub_strlen(isopath);
2224 for (node = g_menu_alias_head; node; node = node->next)
2225 {
2226 if (node->type == type && node->pathlen &&
2227 node->pathlen == len && ventoy_strcmp(node->isopath, isopath) == 0)
2228 {
2229 return node->alias;
2230 }
2231 }
2232
2233 return NULL;
2234 }
2235
2236 const char * ventoy_plugin_get_menu_class(int type, const char *name, const char *path)
2237 {
2238 int len;
2239 menu_class *node = NULL;
2240
2241 if (!g_menu_class_head)
2242 {
2243 return NULL;
2244 }
2245
2246 if (vtoy_class_image_file == type)
2247 {
2248 for (node = g_menu_class_head; node; node = node->next)
2249 {
2250 if (node->type != type)
2251 {
2252 continue;
2253 }
2254
2255 if (node->parent)
2256 {
2257 len = (int)grub_strlen(path);
2258 if ((node->patlen < len) && (path[node->patlen] == '/') &&
2259 (grub_strncmp(path, node->pattern, node->patlen) == 0))
2260 {
2261 return node->class;
2262 }
2263 }
2264 else
2265 {
2266 len = (int)grub_strlen(name);
2267 if ((node->patlen < len) && grub_strstr(name, node->pattern))
2268 {
2269 return node->class;
2270 }
2271 }
2272 }
2273 }
2274 else
2275 {
2276 len = (int)grub_strlen(name);
2277 for (node = g_menu_class_head; node; node = node->next)
2278 {
2279 if (node->type == type && node->patlen == len && grub_strncmp(name, node->pattern, len) == 0)
2280 {
2281 return node->class;
2282 }
2283 }
2284 }
2285
2286 return NULL;
2287 }
2288
2289 int ventoy_plugin_add_custom_boot(const char *vcfgpath)
2290 {
2291 int len;
2292 custom_boot *node = NULL;
2293
2294 node = grub_zalloc(sizeof(custom_boot));
2295 if (node)
2296 {
2297 node->type = vtoy_custom_boot_image_file;
2298 node->pathlen = grub_snprintf(node->path, sizeof(node->path), "%s", vcfgpath);
2299 grub_snprintf(node->cfg, sizeof(node->cfg), "%s", vcfgpath);
2300
2301 /* .vcfg */
2302 len = node->pathlen - 5;
2303 node->path[len] = 0;
2304 node->pathlen = len;
2305
2306 if (g_custom_boot_head)
2307 {
2308 node->next = g_custom_boot_head;
2309 }
2310 g_custom_boot_head = node;
2311 }
2312
2313 return 0;
2314 }
2315
2316 const char * ventoy_plugin_get_custom_boot(const char *isopath)
2317 {
2318 int i;
2319 int len;
2320 custom_boot *node = NULL;
2321
2322 if (!g_custom_boot_head)
2323 {
2324 return NULL;
2325 }
2326
2327 len = (int)grub_strlen(isopath);
2328
2329 for (node = g_custom_boot_head; node; node = node->next)
2330 {
2331 if (node->type == vtoy_custom_boot_image_file)
2332 {
2333 if (node->pathlen == len && grub_strncmp(isopath, node->path, len) == 0)
2334 {
2335 return node->cfg;
2336 }
2337 }
2338 else
2339 {
2340 if (node->pathlen < len && isopath[node->pathlen] == '/' &&
2341 grub_strncmp(isopath, node->path, node->pathlen) == 0)
2342 {
2343 for (i = node->pathlen + 1; i < len; i++)
2344 {
2345 if (isopath[i] == '/')
2346 {
2347 break;
2348 }
2349 }
2350
2351 if (i >= len)
2352 {
2353 return node->cfg;
2354 }
2355 }
2356 }
2357 }
2358
2359 return NULL;
2360 }
2361
2362 grub_err_t ventoy_cmd_dump_custom_boot(grub_extcmd_context_t ctxt, int argc, char **args)
2363 {
2364 custom_boot *node = NULL;
2365
2366 (void)argc;
2367 (void)ctxt;
2368 (void)args;
2369
2370 for (node = g_custom_boot_head; node; node = node->next)
2371 {
2372 grub_printf("[%s] <%s>:<%s>\n", (node->type == vtoy_custom_boot_directory) ? "dir" : "file",
2373 node->path, node->cfg);
2374 }
2375
2376 return 0;
2377 }
2378
2379 int ventoy_plugin_check_memdisk(const char *isopath)
2380 {
2381 int len;
2382 auto_memdisk *node = NULL;
2383
2384 if (!g_auto_memdisk_head)
2385 {
2386 return 0;
2387 }
2388
2389 len = (int)grub_strlen(isopath);
2390 for (node = g_auto_memdisk_head; node; node = node->next)
2391 {
2392 if (node->pathlen == len && ventoy_strncmp(node->isopath, isopath, len) == 0)
2393 {
2394 return 1;
2395 }
2396 }
2397
2398 return 0;
2399 }
2400
2401 int ventoy_plugin_get_image_list_index(int type, const char *name)
2402 {
2403 int len;
2404 int index = 1;
2405 image_list *node = NULL;
2406
2407 if (!g_image_list_head)
2408 {
2409 return 0;
2410 }
2411
2412 len = (int)grub_strlen(name);
2413
2414 for (node = g_image_list_head; node; node = node->next, index++)
2415 {
2416 if (vtoy_class_directory == type)
2417 {
2418 if (len < node->pathlen && ventoy_strncmp(node->isopath, name, len) == 0)
2419 {
2420 return index;
2421 }
2422 }
2423 else
2424 {
2425 if (len == node->pathlen && ventoy_strncmp(node->isopath, name, len) == 0)
2426 {
2427 return index;
2428 }
2429 }
2430 }
2431
2432 return 0;
2433 }
2434
2435 conf_replace * ventoy_plugin_find_conf_replace(const char *iso)
2436 {
2437 int len;
2438 conf_replace *node;
2439
2440 if (!g_conf_replace_head)
2441 {
2442 return NULL;
2443 }
2444
2445 len = (int)grub_strlen(iso);
2446
2447 for (node = g_conf_replace_head; node; node = node->next)
2448 {
2449 if (node->pathlen == len && ventoy_strncmp(node->isopath, iso, len) == 0)
2450 {
2451 return node;
2452 }
2453 }
2454
2455 return NULL;
2456 }
2457
2458 dud * ventoy_plugin_find_dud(const char *iso)
2459 {
2460 int len;
2461 dud *node;
2462
2463 if (!g_dud_head)
2464 {
2465 return NULL;
2466 }
2467
2468 len = (int)grub_strlen(iso);
2469 for (node = g_dud_head; node; node = node->next)
2470 {
2471 if (node->pathlen == len && ventoy_strncmp(node->isopath, iso, len) == 0)
2472 {
2473 return node;
2474 }
2475 }
2476
2477 return NULL;
2478 }
2479
2480 int ventoy_plugin_load_dud(dud *node, const char *isopart)
2481 {
2482 int i;
2483 char *buf;
2484 grub_file_t file;
2485
2486 for (i = 0; i < node->dudnum; i++)
2487 {
2488 if (node->files[i].size > 0)
2489 {
2490 debug("file %d has been loaded\n", i);
2491 continue;
2492 }
2493
2494 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", isopart, node->dudpath[i].path);
2495 if (file)
2496 {
2497 buf = grub_malloc(file->size);
2498 if (buf)
2499 {
2500 grub_file_read(file, buf, file->size);
2501 node->files[i].size = (int)file->size;
2502 node->files[i].buf = buf;
2503 }
2504 grub_file_close(file);
2505 }
2506 }
2507
2508 return 0;
2509 }
2510
2511 static const vtoy_password * ventoy_plugin_get_password(const char *isopath)
2512 {
2513 int i;
2514 int len;
2515 const char *pos = NULL;
2516 menu_password *node = NULL;
2517
2518 if (!isopath)
2519 {
2520 return NULL;
2521 }
2522
2523 if (g_pwd_head)
2524 {
2525 len = (int)grub_strlen(isopath);
2526 for (node = g_pwd_head; node; node = node->next)
2527 {
2528 if (node->pathlen == len && ventoy_strncmp(node->isopath, isopath, len) == 0)
2529 {
2530 return &(node->password);
2531 }
2532 }
2533 }
2534
2535 while (*isopath)
2536 {
2537 if (*isopath == '.')
2538 {
2539 pos = isopath;
2540 }
2541 isopath++;
2542 }
2543
2544 if (pos)
2545 {
2546 for (i = 0; i < (int)ARRAY_SIZE(g_menu_prefix); i++)
2547 {
2548 if (g_file_type_pwd[i].type && 0 == grub_strcasecmp(pos + 1, g_menu_prefix[i]))
2549 {
2550 return g_file_type_pwd + i;
2551 }
2552 }
2553 }
2554
2555 return NULL;
2556 }
2557
2558 grub_err_t ventoy_cmd_check_password(grub_extcmd_context_t ctxt, int argc, char **args)
2559 {
2560 int ret;
2561 const vtoy_password *pwd = NULL;
2562
2563 (void)ctxt;
2564 (void)argc;
2565
2566 pwd = ventoy_plugin_get_password(args[0]);
2567 if (pwd)
2568 {
2569 if (0 == ventoy_check_password(pwd, 1))
2570 {
2571 ret = 1;
2572 }
2573 else
2574 {
2575 ret = 0;
2576 }
2577 }
2578 else
2579 {
2580 ret = 1;
2581 }
2582
2583 grub_errno = 0;
2584 return ret;
2585 }
2586
2587 grub_err_t ventoy_cmd_plugin_check_json(grub_extcmd_context_t ctxt, int argc, char **args)
2588 {
2589 int i = 0;
2590 int ret = 0;
2591 char *buf = NULL;
2592 char key[128];
2593 grub_file_t file;
2594 VTOY_JSON *node = NULL;
2595 VTOY_JSON *json = NULL;
2596
2597 (void)ctxt;
2598
2599 if (argc != 3)
2600 {
2601 return 0;
2602 }
2603
2604 file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s/ventoy/ventoy.json", args[0]);
2605 if (!file)
2606 {
2607 grub_printf("Plugin json file /ventoy/ventoy.json does NOT exist.\n");
2608 grub_printf("Attention: directory name and filename are both case-sensitive.\n");
2609 goto end;
2610 }
2611
2612 buf = grub_malloc(file->size + 1);
2613 if (!buf)
2614 {
2615 grub_printf("Failed to malloc memory %lu.\n", (ulong)(file->size + 1));
2616 goto end;
2617 }
2618
2619 buf[file->size] = 0;
2620 grub_file_read(file, buf, file->size);
2621
2622 json = vtoy_json_create();
2623 if (!json)
2624 {
2625 grub_printf("Failed to create json\n");
2626 goto end;
2627 }
2628
2629 ret = vtoy_json_parse(json, buf);
2630 if (ret)
2631 {
2632 grub_printf("Syntax error detected in ventoy.json, please check it.\n");
2633 goto end;
2634 }
2635
2636 grub_snprintf(key, sizeof(key), "%s_%s", args[1], g_arch_mode_suffix);
2637 for (node = json->pstChild; node; node = node->pstNext)
2638 {
2639 if (grub_strcmp(node->pcName, args[1]) == 0 || grub_strcmp(node->pcName, key) == 0)
2640 {
2641 break;
2642 }
2643 }
2644
2645 if (!node)
2646 {
2647 grub_printf("%s is NOT found in ventoy.json\n", args[1]);
2648 goto end;
2649 }
2650
2651 for (i = 0; i < (int)ARRAY_SIZE(g_plugin_entries); i++)
2652 {
2653 if (grub_strcmp(g_plugin_entries[i].key, args[1]) == 0)
2654 {
2655 if (g_plugin_entries[i].checkfunc)
2656 {
2657 ret = g_plugin_entries[i].checkfunc(node, args[2]);
2658 }
2659 break;
2660 }
2661 }
2662
2663 end:
2664 check_free(file, grub_file_close);
2665 check_free(json, vtoy_json_destroy);
2666 grub_check_free(buf);
2667
2668 return 0;
2669 }
2670