]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - LinuxGUI/Ventoy2Disk/Core/ventoy_disk.c
Update ru_RU.txt (#2120)
[Ventoy.git] / LinuxGUI / Ventoy2Disk / Core / ventoy_disk.c
1 /******************************************************************************
2 * ventoy_disk.c ---- ventoy disk
3 * Copyright (c) 2021, longpanda <admin@ventoy.net>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 3 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stdint.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <ctype.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <sys/types.h>
28 #include <sys/ioctl.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <linux/fs.h>
32 #include <dirent.h>
33 #include <time.h>
34 #include <ventoy_define.h>
35 #include <ventoy_disk.h>
36 #include <ventoy_util.h>
37 #include <fat_filelib.h>
38
39 int g_disk_num = 0;
40 static int g_fatlib_media_fd = 0;
41 static uint64_t g_fatlib_media_offset = 0;
42 ventoy_disk *g_disk_list = NULL;
43
44 static const char *g_ventoy_dev_type_str[VTOY_DEVICE_END] =
45 {
46 "unknown", "scsi", "USB", "ide", "dac960",
47 "cpqarray", "file", "ataraid", "i2o",
48 "ubd", "dasd", "viodasd", "sx8", "dm",
49 "xvd", "sd/mmc", "virtblk", "aoe",
50 "md", "loopback", "nvme", "brd", "pmem"
51 };
52
53 static const char * ventoy_get_dev_type_name(ventoy_dev_type type)
54 {
55 return (type < VTOY_DEVICE_END) ? g_ventoy_dev_type_str[type] : "unknown";
56 }
57
58 static int ventoy_check_blk_major(int major, const char *type)
59 {
60 int flag = 0;
61 int valid = 0;
62 int devnum = 0;
63 int len = 0;
64 char line[64];
65 char *pos = NULL;
66 FILE *fp = NULL;
67
68 fp = fopen("/proc/devices", "r");
69 if (!fp)
70 {
71 return 0;
72 }
73
74 len = (int)strlen(type);
75 while (fgets(line, sizeof(line), fp))
76 {
77 if (flag)
78 {
79 pos = strchr(line, ' ');
80 if (pos)
81 {
82 devnum = (int)strtol(line, NULL, 10);
83 if (devnum == major)
84 {
85 if (strncmp(pos + 1, type, len) == 0)
86 {
87 valid = 1;
88 }
89 break;
90 }
91 }
92 }
93 else if (strncmp(line, "Block devices:", 14) == 0)
94 {
95 flag = 1;
96 }
97 }
98
99 fclose(fp);
100 return valid;
101 }
102
103 static int ventoy_get_disk_devnum(const char *name, int *major, int* minor)
104 {
105 int rc;
106 char *pos;
107 char devnum[16] = {0};
108
109 rc = ventoy_get_sys_file_line(devnum, sizeof(devnum), "/sys/block/%s/dev", name);
110 if (rc)
111 {
112 return 1;
113 }
114
115 pos = strstr(devnum, ":");
116 if (!pos)
117 {
118 return 1;
119 }
120
121 *major = (int)strtol(devnum, NULL, 10);
122 *minor = (int)strtol(pos + 1, NULL, 10);
123
124 return 0;
125 }
126
127 static ventoy_dev_type ventoy_get_dev_type(const char *name, int major, int minor)
128 {
129 int rc;
130 char syspath[128];
131 char dstpath[256];
132
133 memset(syspath, 0, sizeof(syspath));
134 memset(dstpath, 0, sizeof(dstpath));
135
136 scnprintf(syspath, "/sys/block/%s", name);
137 rc = readlink(syspath, dstpath, sizeof(dstpath) - 1);
138 if (rc > 0 && strstr(dstpath, "/usb"))
139 {
140 return VTOY_DEVICE_USB;
141 }
142
143 if (SCSI_BLK_MAJOR(major) && (minor % 0x10 == 0))
144 {
145 return VTOY_DEVICE_SCSI;
146 }
147 else if (IDE_BLK_MAJOR(major) && (minor % 0x40 == 0))
148 {
149 return VTOY_DEVICE_IDE;
150 }
151 else if (major == DAC960_MAJOR && (minor % 0x8 == 0))
152 {
153 return VTOY_DEVICE_DAC960;
154 }
155 else if (major == ATARAID_MAJOR && (minor % 0x10 == 0))
156 {
157 return VTOY_DEVICE_ATARAID;
158 }
159 else if (major == AOE_MAJOR && (minor % 0x10 == 0))
160 {
161 return VTOY_DEVICE_AOE;
162 }
163 else if (major == DASD_MAJOR && (minor % 0x4 == 0))
164 {
165 return VTOY_DEVICE_DASD;
166 }
167 else if (major == VIODASD_MAJOR && (minor % 0x8 == 0))
168 {
169 return VTOY_DEVICE_VIODASD;
170 }
171 else if (SX8_BLK_MAJOR(major) && (minor % 0x20 == 0))
172 {
173 return VTOY_DEVICE_SX8;
174 }
175 else if (I2O_BLK_MAJOR(major) && (minor % 0x10 == 0))
176 {
177 return VTOY_DEVICE_I2O;
178 }
179 else if (CPQARRAY_BLK_MAJOR(major) && (minor % 0x10 == 0))
180 {
181 return VTOY_DEVICE_CPQARRAY;
182 }
183 else if (UBD_MAJOR == major && (minor % 0x10 == 0))
184 {
185 return VTOY_DEVICE_UBD;
186 }
187 else if (XVD_MAJOR == major && (minor % 0x10 == 0))
188 {
189 return VTOY_DEVICE_XVD;
190 }
191 else if (SDMMC_MAJOR == major && (minor % 0x8 == 0))
192 {
193 return VTOY_DEVICE_SDMMC;
194 }
195 else if (ventoy_check_blk_major(major, "virtblk"))
196 {
197 return VTOY_DEVICE_VIRTBLK;
198 }
199 else if (major == LOOP_MAJOR)
200 {
201 return VTOY_DEVICE_LOOP;
202 }
203 else if (major == MD_MAJOR)
204 {
205 return VTOY_DEVICE_MD;
206 }
207 else if (major == RAM_MAJOR)
208 {
209 return VTOY_DEVICE_RAM;
210 }
211 else if (strstr(name, "nvme") && ventoy_check_blk_major(major, "blkext"))
212 {
213 return VTOY_DEVICE_NVME;
214 }
215 else if (strstr(name, "pmem") && ventoy_check_blk_major(major, "blkext"))
216 {
217 return VTOY_DEVICE_PMEM;
218 }
219
220 return VTOY_DEVICE_END;
221 }
222
223 static int ventoy_is_possible_blkdev(const char *name)
224 {
225 if (name[0] == '.')
226 {
227 return 0;
228 }
229
230 /* /dev/ramX */
231 if (name[0] == 'r' && name[1] == 'a' && name[2] == 'm')
232 {
233 return 0;
234 }
235
236 /* /dev/zramX */
237 if (name[0] == 'z' && name[1] == 'r' && name[2] == 'a' && name[3] == 'm')
238 {
239 return 0;
240 }
241
242 /* /dev/loopX */
243 if (name[0] == 'l' && name[1] == 'o' && name[2] == 'o' && name[3] == 'p')
244 {
245 return 0;
246 }
247
248 /* /dev/dm-X */
249 if (name[0] == 'd' && name[1] == 'm' && name[2] == '-' && isdigit(name[3]))
250 {
251 return 0;
252 }
253
254 /* /dev/srX */
255 if (name[0] == 's' && name[1] == 'r' && isdigit(name[2]))
256 {
257 return 0;
258 }
259
260 return 1;
261 }
262
263 uint64_t ventoy_get_disk_size_in_byte(const char *disk)
264 {
265 int fd;
266 int rc;
267 unsigned long long size = 0;
268 char diskpath[256] = {0};
269 char sizebuf[64] = {0};
270
271 // Try 1: get size from sysfs
272 snprintf(diskpath, sizeof(diskpath) - 1, "/sys/block/%s/size", disk);
273 if (access(diskpath, F_OK) >= 0)
274 {
275 vdebug("get disk size from sysfs for %s\n", disk);
276
277 fd = open(diskpath, O_RDONLY | O_BINARY);
278 if (fd >= 0)
279 {
280 read(fd, sizebuf, sizeof(sizebuf));
281 size = strtoull(sizebuf, NULL, 10);
282 close(fd);
283 return (uint64_t)(size * 512);
284 }
285 }
286 else
287 {
288 vdebug("%s not exist \n", diskpath);
289 }
290
291 // Try 2: get size from ioctl
292 snprintf(diskpath, sizeof(diskpath) - 1, "/dev/%s", disk);
293 fd = open(diskpath, O_RDONLY);
294 if (fd >= 0)
295 {
296 vdebug("get disk size from ioctl for %s\n", disk);
297 rc = ioctl(fd, BLKGETSIZE64, &size);
298 if (rc == -1)
299 {
300 size = 0;
301 vdebug("failed to ioctl %d\n", rc);
302 }
303 close(fd);
304 }
305 else
306 {
307 vdebug("failed to open %s %d\n", diskpath, errno);
308 }
309
310 vdebug("disk %s size %llu bytes\n", disk, size);
311 return size;
312 }
313
314 int ventoy_get_disk_vendor(const char *name, char *vendorbuf, int bufsize)
315 {
316 return ventoy_get_sys_file_line(vendorbuf, bufsize, "/sys/block/%s/device/vendor", name);
317 }
318
319 int ventoy_get_disk_model(const char *name, char *modelbuf, int bufsize)
320 {
321 return ventoy_get_sys_file_line(modelbuf, bufsize, "/sys/block/%s/device/model", name);
322 }
323
324 static int fatlib_media_sector_read(uint32 sector, uint8 *buffer, uint32 sector_count)
325 {
326 lseek(g_fatlib_media_fd, (sector + g_fatlib_media_offset) * 512ULL, SEEK_SET);
327 read(g_fatlib_media_fd, buffer, sector_count * 512);
328
329 return 1;
330 }
331
332 static int fatlib_is_secure_boot_enable(void)
333 {
334 void *flfile = NULL;
335
336 flfile = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
337 if (flfile)
338 {
339 vlog("/EFI/BOOT/grubx64_real.efi find, secure boot in enabled\n");
340 fl_fclose(flfile);
341 return 1;
342 }
343 else
344 {
345 vlog("/EFI/BOOT/grubx64_real.efi not exist\n");
346 }
347
348 return 0;
349 }
350
351 static int fatlib_get_ventoy_version(char *verbuf, int bufsize)
352 {
353 int rc = 1;
354 int size = 0;
355 char *buf = NULL;
356 char *pos = NULL;
357 char *end = NULL;
358 void *flfile = NULL;
359
360 flfile = fl_fopen("/grub/grub.cfg", "rb");
361 if (flfile)
362 {
363 fl_fseek(flfile, 0, SEEK_END);
364 size = (int)fl_ftell(flfile);
365
366 fl_fseek(flfile, 0, SEEK_SET);
367
368 buf = malloc(size + 1);
369 if (buf)
370 {
371 fl_fread(buf, 1, size, flfile);
372 buf[size] = 0;
373
374 pos = strstr(buf, "VENTOY_VERSION=");
375 if (pos)
376 {
377 pos += strlen("VENTOY_VERSION=");
378 if (*pos == '"')
379 {
380 pos++;
381 }
382
383 end = pos;
384 while (*end != 0 && *end != '"' && *end != '\r' && *end != '\n')
385 {
386 end++;
387 }
388
389 *end = 0;
390
391 snprintf(verbuf, bufsize - 1, "%s", pos);
392 rc = 0;
393 }
394 free(buf);
395 }
396
397 fl_fclose(flfile);
398 }
399 else
400 {
401 vdebug("No grub.cfg found\n");
402 }
403
404 return rc;
405 }
406
407 int ventoy_get_vtoy_data(ventoy_disk *info, int *ppartstyle)
408 {
409 int i;
410 int fd;
411 int len;
412 int rc = 1;
413 int ret = 1;
414 int part_style;
415 uint64_t part1_start_sector;
416 uint64_t part1_sector_count;
417 uint64_t part2_start_sector;
418 uint64_t part2_sector_count;
419 uint64_t preserved_space;
420 char name[64] = {0};
421 disk_ventoy_data *vtoy = NULL;
422 VTOY_GPT_INFO *gpt = NULL;
423
424 vtoy = &(info->vtoydata);
425 gpt = &(vtoy->gptinfo);
426 memset(vtoy, 0, sizeof(disk_ventoy_data));
427
428 vdebug("ventoy_get_vtoy_data %s\n", info->disk_path);
429
430 if (info->size_in_byte < (2 * VTOYEFI_PART_BYTES))
431 {
432 vdebug("disk %s is too small %llu\n", info->disk_path, (_ull)info->size_in_byte);
433 return 1;
434 }
435
436 fd = open(info->disk_path, O_RDONLY | O_BINARY);
437 if (fd < 0)
438 {
439 vdebug("failed to open %s %d\n", info->disk_path, errno);
440 return 1;
441 }
442
443 len = (int)read(fd, &(vtoy->gptinfo), sizeof(VTOY_GPT_INFO));
444 if (len != sizeof(VTOY_GPT_INFO))
445 {
446 vdebug("failed to read %s %d\n", info->disk_path, errno);
447 goto end;
448 }
449
450 if (gpt->MBR.Byte55 != 0x55 || gpt->MBR.ByteAA != 0xAA)
451 {
452 vdebug("Invalid mbr magic 0x%x 0x%x\n", gpt->MBR.Byte55, gpt->MBR.ByteAA);
453 goto end;
454 }
455
456 if (gpt->MBR.PartTbl[0].FsFlag == 0xEE && strncmp(gpt->Head.Signature, "EFI PART", 8) == 0)
457 {
458 part_style = GPT_PART_STYLE;
459 if (ppartstyle)
460 {
461 *ppartstyle = part_style;
462 }
463
464 if (gpt->PartTbl[0].StartLBA == 0 || gpt->PartTbl[1].StartLBA == 0)
465 {
466 vdebug("NO ventoy efi part layout <%llu %llu>\n",
467 (_ull)gpt->PartTbl[0].StartLBA,
468 (_ull)gpt->PartTbl[1].StartLBA);
469 goto end;
470 }
471
472 for (i = 0; i < 36; i++)
473 {
474 name[i] = (char)(gpt->PartTbl[1].Name[i]);
475 }
476 if (strcmp(name, "VTOYEFI"))
477 {
478 vdebug("Invalid efi part2 name <%s>\n", name);
479 goto end;
480 }
481
482 part1_start_sector = gpt->PartTbl[0].StartLBA;
483 part1_sector_count = gpt->PartTbl[0].LastLBA - part1_start_sector + 1;
484 part2_start_sector = gpt->PartTbl[1].StartLBA;
485 part2_sector_count = gpt->PartTbl[1].LastLBA - part2_start_sector + 1;
486
487 preserved_space = info->size_in_byte - (part2_start_sector + part2_sector_count + 33) * 512;
488 }
489 else
490 {
491 part_style = MBR_PART_STYLE;
492 if (ppartstyle)
493 {
494 *ppartstyle = part_style;
495 }
496
497 part1_start_sector = gpt->MBR.PartTbl[0].StartSectorId;
498 part1_sector_count = gpt->MBR.PartTbl[0].SectorCount;
499 part2_start_sector = gpt->MBR.PartTbl[1].StartSectorId;
500 part2_sector_count = gpt->MBR.PartTbl[1].SectorCount;
501
502 preserved_space = info->size_in_byte - (part2_start_sector + part2_sector_count) * 512;
503 }
504
505 if (part1_start_sector != VTOYIMG_PART_START_SECTOR ||
506 part2_sector_count != VTOYEFI_PART_SECTORS ||
507 (part1_start_sector + part1_sector_count) != part2_start_sector)
508 {
509 vdebug("Not valid ventoy partition layout [%llu %llu] [%llu %llu]\n",
510 part1_start_sector, part1_sector_count, part2_start_sector, part2_sector_count);
511 goto end;
512 }
513
514 vdebug("ventoy partition layout check OK: [%llu %llu] [%llu %llu]\n",
515 part1_start_sector, part1_sector_count, part2_start_sector, part2_sector_count);
516
517 vtoy->ventoy_valid = 1;
518
519 vdebug("now check secure boot for %s ...\n", info->disk_path);
520
521 g_fatlib_media_fd = fd;
522 g_fatlib_media_offset = part2_start_sector;
523 fl_init();
524
525 if (0 == fl_attach_media(fatlib_media_sector_read, NULL))
526 {
527 ret = fatlib_get_ventoy_version(vtoy->ventoy_ver, sizeof(vtoy->ventoy_ver));
528 if (ret == 0 && vtoy->ventoy_ver[0])
529 {
530 vtoy->secure_boot_flag = fatlib_is_secure_boot_enable();
531 }
532 else
533 {
534 vdebug("fatlib_get_ventoy_version failed %d\n", ret);
535 }
536 }
537 else
538 {
539 vdebug("fl_attach_media failed\n");
540 }
541
542 fl_shutdown();
543 g_fatlib_media_fd = -1;
544 g_fatlib_media_offset = 0;
545
546 if (vtoy->ventoy_ver[0] == 0)
547 {
548 vtoy->ventoy_ver[0] = '?';
549 }
550
551 if (0 == vtoy->ventoy_valid)
552 {
553 goto end;
554 }
555
556 lseek(fd, 2040 * 512, SEEK_SET);
557 read(fd, vtoy->rsvdata, sizeof(vtoy->rsvdata));
558
559 vtoy->preserved_space = preserved_space;
560 vtoy->partition_style = part_style;
561 vtoy->part2_start_sector = part2_start_sector;
562
563 rc = 0;
564 end:
565 vtoy_safe_close_fd(fd);
566 return rc;
567 }
568
569 int ventoy_get_disk_info(const char *name, ventoy_disk *info)
570 {
571 char vendor[64] = {0};
572 char model[128] = {0};
573
574 vdebug("get disk info %s\n", name);
575
576 strlcpy(info->disk_name, name);
577 scnprintf(info->disk_path, "/dev/%s", name);
578
579 if (strstr(name, "nvme") || strstr(name, "mmc") || strstr(name, "nbd"))
580 {
581 scnprintf(info->part1_name, "%sp1", name);
582 scnprintf(info->part1_path, "/dev/%sp1", name);
583 scnprintf(info->part2_name, "%sp2", name);
584 scnprintf(info->part2_path, "/dev/%sp2", name);
585 }
586 else
587 {
588 scnprintf(info->part1_name, "%s1", name);
589 scnprintf(info->part1_path, "/dev/%s1", name);
590 scnprintf(info->part2_name, "%s2", name);
591 scnprintf(info->part2_path, "/dev/%s2", name);
592 }
593
594 info->size_in_byte = ventoy_get_disk_size_in_byte(name);
595
596 ventoy_get_disk_devnum(name, &info->major, &info->minor);
597 info->type = ventoy_get_dev_type(name, info->major, info->minor);
598 ventoy_get_disk_vendor(name, vendor, sizeof(vendor));
599 ventoy_get_disk_model(name, model, sizeof(model));
600
601 scnprintf(info->human_readable_size, "%llu GB", (_ull)ventoy_get_human_readable_gb(info->size_in_byte));
602 scnprintf(info->disk_model, "%s %s (%s)", vendor, model, ventoy_get_dev_type_name(info->type));
603
604 ventoy_get_vtoy_data(info, &(info->partstyle));
605
606 vdebug("disk:<%s %d:%d> model:<%s> size:%llu (%s)\n",
607 info->disk_path, info->major, info->minor, info->disk_model, info->size_in_byte, info->human_readable_size);
608
609 if (info->vtoydata.ventoy_valid)
610 {
611 vdebug("%s Ventoy:<%s> %s secureboot:%d preserve:%llu\n", info->disk_path, info->vtoydata.ventoy_ver,
612 info->vtoydata.partition_style == MBR_PART_STYLE ? "MBR" : "GPT",
613 info->vtoydata.secure_boot_flag, (_ull)(info->vtoydata.preserved_space));
614 }
615 else
616 {
617 vdebug("%s NO Ventoy detected\n", info->disk_path);
618 }
619
620 return 0;
621 }
622
623 static int ventoy_disk_compare(const ventoy_disk *disk1, const ventoy_disk *disk2)
624 {
625 if (disk1->type == VTOY_DEVICE_USB && disk2->type == VTOY_DEVICE_USB)
626 {
627 return strcmp(disk1->disk_name, disk2->disk_name);
628 }
629 else if (disk1->type == VTOY_DEVICE_USB)
630 {
631 return -1;
632 }
633 else if (disk2->type == VTOY_DEVICE_USB)
634 {
635 return 1;
636 }
637 else
638 {
639 return strcmp(disk1->disk_name, disk2->disk_name);
640 }
641 }
642
643 static int ventoy_disk_sort(void)
644 {
645 int i, j;
646 ventoy_disk *tmp;
647
648 tmp = malloc(sizeof(ventoy_disk));
649 if (!tmp)
650 {
651 return 1;
652 }
653
654 for (i = 0; i < g_disk_num; i++)
655 for (j = i + 1; j < g_disk_num; j++)
656 {
657 if (ventoy_disk_compare(g_disk_list + i, g_disk_list + j) > 0)
658 {
659 memcpy(tmp, g_disk_list + i, sizeof(ventoy_disk));
660 memcpy(g_disk_list + i, g_disk_list + j, sizeof(ventoy_disk));
661 memcpy(g_disk_list + j, tmp, sizeof(ventoy_disk));
662 }
663 }
664
665 free(tmp);
666 return 0;
667 }
668
669 int ventoy_disk_enumerate_all(void)
670 {
671 int rc = 0;
672 DIR* dir = NULL;
673 struct dirent* p = NULL;
674
675 vdebug("ventoy_disk_enumerate_all\n");
676
677 dir = opendir("/sys/block");
678 if (!dir)
679 {
680 vlog("Failed to open /sys/block %d\n", errno);
681 return 1;
682 }
683
684 while (((p = readdir(dir)) != NULL) && (g_disk_num < MAX_DISK_NUM))
685 {
686 if (ventoy_is_possible_blkdev(p->d_name))
687 {
688 memset(g_disk_list + g_disk_num, 0, sizeof(ventoy_disk));
689 if (0 == ventoy_get_disk_info(p->d_name, g_disk_list + g_disk_num))
690 {
691 g_disk_num++;
692 }
693 }
694 }
695 closedir(dir);
696
697 ventoy_disk_sort();
698
699 return rc;
700 }
701
702 void ventoy_disk_dump(ventoy_disk *cur)
703 {
704 if (cur->vtoydata.ventoy_valid)
705 {
706 vdebug("%s [%s] %s\tVentoy: %s %s secureboot:%d preserve:%llu\n",
707 cur->disk_path, cur->human_readable_size, cur->disk_model,
708 cur->vtoydata.ventoy_ver, cur->vtoydata.partition_style == MBR_PART_STYLE ? "MBR" : "GPT",
709 cur->vtoydata.secure_boot_flag, (_ull)(cur->vtoydata.preserved_space));
710 }
711 else
712 {
713 vdebug("%s [%s] %s\tVentoy: NA\n", cur->disk_path, cur->human_readable_size, cur->disk_model);
714 }
715 }
716
717 void ventoy_disk_dump_all(void)
718 {
719 int i;
720
721 vdebug("============= DISK DUMP ============\n");
722 for (i = 0; i < g_disk_num; i++)
723 {
724 ventoy_disk_dump(g_disk_list + i);
725 }
726 }
727
728 int ventoy_disk_install(ventoy_disk *disk, void *efipartimg)
729 {
730 return 0;
731 }
732
733
734 int ventoy_disk_init(void)
735 {
736 g_disk_list = malloc(sizeof(ventoy_disk) * MAX_DISK_NUM);
737
738 ventoy_disk_enumerate_all();
739 ventoy_disk_dump_all();
740
741 return 0;
742 }
743
744 void ventoy_disk_exit(void)
745 {
746 check_free(g_disk_list);
747 g_disk_list = NULL;
748 g_disk_num = 0;
749 }
750
751