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