]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - Plugson/src/Core/ventoy_disk_linux.c
1.0.73 release
[Ventoy.git] / Plugson / src / Core / ventoy_disk_linux.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 static int g_fatlib_media_fd = 0;
40 static uint64_t g_fatlib_media_offset = 0;
41
42 static const char *g_ventoy_dev_type_str[VTOY_DEVICE_END] =
43 {
44 "unknown", "scsi", "USB", "ide", "dac960",
45 "cpqarray", "file", "ataraid", "i2o",
46 "ubd", "dasd", "viodasd", "sx8", "dm",
47 "xvd", "sd/mmc", "virtblk", "aoe",
48 "md", "loopback", "nvme", "brd", "pmem"
49 };
50
51 static const char * ventoy_get_dev_type_name(ventoy_dev_type type)
52 {
53 return (type < VTOY_DEVICE_END) ? g_ventoy_dev_type_str[type] : "unknown";
54 }
55
56 static int ventoy_check_blk_major(int major, const char *type)
57 {
58 int flag = 0;
59 int valid = 0;
60 int devnum = 0;
61 int len = 0;
62 char line[64];
63 char *pos = NULL;
64 FILE *fp = NULL;
65
66 fp = fopen("/proc/devices", "r");
67 if (!fp)
68 {
69 return 0;
70 }
71
72 len = (int)strlen(type);
73 while (fgets(line, sizeof(line), fp))
74 {
75 if (flag)
76 {
77 pos = strchr(line, ' ');
78 if (pos)
79 {
80 devnum = (int)strtol(line, NULL, 10);
81 if (devnum == major)
82 {
83 if (strncmp(pos + 1, type, len) == 0)
84 {
85 valid = 1;
86 }
87 break;
88 }
89 }
90 }
91 else if (strncmp(line, "Block devices:", 14) == 0)
92 {
93 flag = 1;
94 }
95 }
96
97 fclose(fp);
98 return valid;
99 }
100
101 static int ventoy_get_disk_devnum(const char *name, int *major, int* minor)
102 {
103 int rc;
104 char *pos;
105 char devnum[16] = {0};
106
107 rc = ventoy_get_sys_file_line(devnum, sizeof(devnum), "/sys/block/%s/dev", name);
108 if (rc)
109 {
110 return 1;
111 }
112
113 pos = strstr(devnum, ":");
114 if (!pos)
115 {
116 return 1;
117 }
118
119 *major = (int)strtol(devnum, NULL, 10);
120 *minor = (int)strtol(pos + 1, NULL, 10);
121
122 return 0;
123 }
124
125 static ventoy_dev_type ventoy_get_dev_type(const char *name, int major, int minor)
126 {
127 int rc;
128 char syspath[128];
129 char dstpath[256];
130
131 memset(syspath, 0, sizeof(syspath));
132 memset(dstpath, 0, sizeof(dstpath));
133
134 scnprintf(syspath, sizeof(syspath), "/sys/block/%s", name);
135 rc = readlink(syspath, dstpath, sizeof(dstpath) - 1);
136 if (rc > 0 && strstr(dstpath, "/usb"))
137 {
138 return VTOY_DEVICE_USB;
139 }
140
141 if (SCSI_BLK_MAJOR(major) && (minor % 0x10 == 0))
142 {
143 return VTOY_DEVICE_SCSI;
144 }
145 else if (IDE_BLK_MAJOR(major) && (minor % 0x40 == 0))
146 {
147 return VTOY_DEVICE_IDE;
148 }
149 else if (major == DAC960_MAJOR && (minor % 0x8 == 0))
150 {
151 return VTOY_DEVICE_DAC960;
152 }
153 else if (major == ATARAID_MAJOR && (minor % 0x10 == 0))
154 {
155 return VTOY_DEVICE_ATARAID;
156 }
157 else if (major == AOE_MAJOR && (minor % 0x10 == 0))
158 {
159 return VTOY_DEVICE_AOE;
160 }
161 else if (major == DASD_MAJOR && (minor % 0x4 == 0))
162 {
163 return VTOY_DEVICE_DASD;
164 }
165 else if (major == VIODASD_MAJOR && (minor % 0x8 == 0))
166 {
167 return VTOY_DEVICE_VIODASD;
168 }
169 else if (SX8_BLK_MAJOR(major) && (minor % 0x20 == 0))
170 {
171 return VTOY_DEVICE_SX8;
172 }
173 else if (I2O_BLK_MAJOR(major) && (minor % 0x10 == 0))
174 {
175 return VTOY_DEVICE_I2O;
176 }
177 else if (CPQARRAY_BLK_MAJOR(major) && (minor % 0x10 == 0))
178 {
179 return VTOY_DEVICE_CPQARRAY;
180 }
181 else if (UBD_MAJOR == major && (minor % 0x10 == 0))
182 {
183 return VTOY_DEVICE_UBD;
184 }
185 else if (XVD_MAJOR == major && (minor % 0x10 == 0))
186 {
187 return VTOY_DEVICE_XVD;
188 }
189 else if (SDMMC_MAJOR == major && (minor % 0x8 == 0))
190 {
191 return VTOY_DEVICE_SDMMC;
192 }
193 else if (ventoy_check_blk_major(major, "virtblk"))
194 {
195 return VTOY_DEVICE_VIRTBLK;
196 }
197 else if (major == LOOP_MAJOR)
198 {
199 return VTOY_DEVICE_LOOP;
200 }
201 else if (major == MD_MAJOR)
202 {
203 return VTOY_DEVICE_MD;
204 }
205 else if (major == RAM_MAJOR)
206 {
207 return VTOY_DEVICE_RAM;
208 }
209 else if (strstr(name, "nvme") && ventoy_check_blk_major(major, "blkext"))
210 {
211 return VTOY_DEVICE_NVME;
212 }
213 else if (strstr(name, "pmem") && ventoy_check_blk_major(major, "blkext"))
214 {
215 return VTOY_DEVICE_PMEM;
216 }
217
218 return VTOY_DEVICE_END;
219 }
220
221 static int ventoy_is_possible_blkdev(const char *name)
222 {
223 if (name[0] == '.')
224 {
225 return 0;
226 }
227
228 /* /dev/ramX */
229 if (name[0] == 'r' && name[1] == 'a' && name[2] == 'm')
230 {
231 return 0;
232 }
233
234 /* /dev/zramX */
235 if (name[0] == 'z' && name[1] == 'r' && name[2] == 'a' && name[3] == 'm')
236 {
237 return 0;
238 }
239
240 /* /dev/loopX */
241 if (name[0] == 'l' && name[1] == 'o' && name[2] == 'o' && name[3] == 'p')
242 {
243 return 0;
244 }
245
246 /* /dev/dm-X */
247 if (name[0] == 'd' && name[1] == 'm' && name[2] == '-' && isdigit(name[3]))
248 {
249 return 0;
250 }
251
252 /* /dev/srX */
253 if (name[0] == 's' && name[1] == 'r' && isdigit(name[2]))
254 {
255 return 0;
256 }
257
258 return 1;
259 }
260
261 uint64_t ventoy_get_disk_size_in_byte(const char *disk)
262 {
263 int fd;
264 int rc;
265 unsigned long long size = 0;
266 char diskpath[256] = {0};
267 char sizebuf[64] = {0};
268
269 // Try 1: get size from sysfs
270 scnprintf(diskpath, sizeof(diskpath) - 1, "/sys/block/%s/size", disk);
271 if (access(diskpath, F_OK) >= 0)
272 {
273 vdebug("get disk size from sysfs for %s\n", disk);
274
275 fd = open(diskpath, O_RDONLY | O_BINARY);
276 if (fd >= 0)
277 {
278 read(fd, sizebuf, sizeof(sizebuf));
279 size = strtoull(sizebuf, NULL, 10);
280 close(fd);
281 return (uint64_t)(size * 512);
282 }
283 }
284 else
285 {
286 vdebug("%s not exist \n", diskpath);
287 }
288
289 // Try 2: get size from ioctl
290 scnprintf(diskpath, sizeof(diskpath) - 1, "/dev/%s", disk);
291 fd = open(diskpath, O_RDONLY);
292 if (fd >= 0)
293 {
294 vdebug("get disk size from ioctl for %s\n", disk);
295 rc = ioctl(fd, BLKGETSIZE64, &size);
296 if (rc == -1)
297 {
298 size = 0;
299 vdebug("failed to ioctl %d\n", rc);
300 }
301 close(fd);
302 }
303 else
304 {
305 vdebug("failed to open %s %d\n", diskpath, errno);
306 }
307
308 vdebug("disk %s size %llu bytes\n", disk, size);
309 return size;
310 }
311
312 int ventoy_get_disk_vendor(const char *name, char *vendorbuf, int bufsize)
313 {
314 return ventoy_get_sys_file_line(vendorbuf, bufsize, "/sys/block/%s/device/vendor", name);
315 }
316
317 int ventoy_get_disk_model(const char *name, char *modelbuf, int bufsize)
318 {
319 return ventoy_get_sys_file_line(modelbuf, bufsize, "/sys/block/%s/device/model", name);
320 }
321
322 static int fatlib_media_sector_read(uint32 sector, uint8 *buffer, uint32 sector_count)
323 {
324 lseek(g_fatlib_media_fd, (sector + g_fatlib_media_offset) * 512ULL, SEEK_SET);
325 read(g_fatlib_media_fd, buffer, sector_count * 512);
326
327 return 1;
328 }
329
330 static int fatlib_is_secure_boot_enable(void)
331 {
332 void *flfile = NULL;
333
334 flfile = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
335 if (flfile)
336 {
337 vlog("/EFI/BOOT/grubx64_real.efi find, secure boot in enabled\n");
338 fl_fclose(flfile);
339 return 1;
340 }
341 else
342 {
343 vlog("/EFI/BOOT/grubx64_real.efi not exist\n");
344 }
345
346 return 0;
347 }
348
349 static int fatlib_get_ventoy_version(char *verbuf, int bufsize)
350 {
351 int rc = 1;
352 int size = 0;
353 char *buf = NULL;
354 char *pos = NULL;
355 char *end = NULL;
356 void *flfile = NULL;
357
358 flfile = fl_fopen("/grub/grub.cfg", "rb");
359 if (flfile)
360 {
361 fl_fseek(flfile, 0, SEEK_END);
362 size = (int)fl_ftell(flfile);
363
364 fl_fseek(flfile, 0, SEEK_SET);
365
366 buf = malloc(size + 1);
367 if (buf)
368 {
369 fl_fread(buf, 1, size, flfile);
370 buf[size] = 0;
371
372 pos = strstr(buf, "VENTOY_VERSION=");
373 if (pos)
374 {
375 pos += strlen("VENTOY_VERSION=");
376 if (*pos == '"')
377 {
378 pos++;
379 }
380
381 end = pos;
382 while (*end != 0 && *end != '"' && *end != '\r' && *end != '\n')
383 {
384 end++;
385 }
386
387 *end = 0;
388
389 scnprintf(verbuf, bufsize - 1, "%s", pos);
390 rc = 0;
391 }
392 free(buf);
393 }
394
395 fl_fclose(flfile);
396 }
397 else
398 {
399 vdebug("No grub.cfg found\n");
400 }
401
402 return rc;
403 }
404
405 /* <BEGIN>: Deleted by longpanda, 20211028 PN:XX LABEL:XX */
406 #if 0
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 #endif /* #if 0 */
569 /* <END> : Deleted by longpanda, 20211028 PN:XX LABEL:XX */
570
571
572 int ventoy_get_disk_info(char **argv)
573 {
574 uint64_t size;
575 char vendor[128];
576 char model[128];
577 char *disk = argv[4];
578
579 if (strncmp(argv[4], "/dev/", 4) == 0)
580 {
581 disk += 4;
582 }
583 ventoy_get_disk_vendor(disk, vendor, sizeof(vendor));
584 ventoy_get_disk_model(disk, model, sizeof(model));
585
586 scnprintf(g_sysinfo.cur_model, sizeof(g_sysinfo.cur_model), "%s %s [%s]", vendor, model, argv[4]);
587 strlcpy(g_sysinfo.cur_ventoy_ver, argv[5]);
588 strlcpy(g_sysinfo.cur_fsname, argv[6]);
589 g_sysinfo.cur_part_style = (int)strtol(argv[7], NULL, 10);
590 g_sysinfo.cur_secureboot = (int)strtol(argv[8], NULL, 10);
591
592 size = ventoy_get_disk_size_in_byte(disk);
593 scnprintf(g_sysinfo.cur_capacity, sizeof(g_sysinfo.cur_capacity), "%dGB", (int)ventoy_get_human_readable_gb(size));
594
595 return 0;
596 }
597
598 int ventoy_disk_init(void)
599 {
600 return 0;
601 }
602
603 void ventoy_disk_exit(void)
604 {
605 }
606
607