1 /******************************************************************************
2 * vtoydump.c ---- Dump ventoy os parameters
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
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.
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.
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/>.
27 #include <sys/types.h>
29 #include <sys/ioctl.h>
31 #include <sys/types.h>
35 #define IS_DIGIT(x) ((x) >= '0' && (x) <= '9')
39 typedef unsigned long long uint64_t;
41 typedef unsigned int uint32_t;
42 typedef unsigned short uint16_t;
43 typedef unsigned char uint8_t;
46 #define VENTOY_GUID { 0x77772020, 0x2e77, 0x6576, { 0x6e, 0x74, 0x6f, 0x79, 0x2e, 0x6e, 0x65, 0x74 }}
48 typedef enum ventoy_fs_type
50 ventoy_fs_exfat
= 0, /* 0: exfat */
51 ventoy_fs_ntfs
, /* 1: NTFS */
52 ventoy_fs_ext
, /* 2: ext2/ext3/ext4 */
53 ventoy_fs_xfs
, /* 3: XFS */
54 ventoy_fs_udf
, /* 4: UDF */
55 ventoy_fs_fat
, /* 5: FAT */
62 typedef struct ventoy_guid
71 typedef struct ventoy_image_disk_region
73 uint32_t image_sector_count
; /* image sectors contained in this region */
74 uint32_t image_start_sector
; /* image sector start */
75 uint64_t disk_start_sector
; /* disk sector start */
76 }ventoy_image_disk_region
;
78 typedef struct ventoy_image_location
82 /* image sector size, currently this value is always 2048 */
83 uint32_t image_sector_size
;
85 /* disk sector size, normally the value is 512 */
86 uint32_t disk_sector_size
;
88 uint32_t region_count
;
92 * If the image file has more than one fragments in disk,
93 * there will be more than one region data here.
94 * You can calculate the region count by
96 ventoy_image_disk_region regions
[1];
98 /* ventoy_image_disk_region regions[2~region_count-1] */
99 }ventoy_image_location
;
101 typedef struct ventoy_os_param
103 ventoy_guid guid
; // VENTOY_GUID
104 uint8_t chksum
; // checksum
106 uint8_t vtoy_disk_guid
[16];
107 uint64_t vtoy_disk_size
; // disk size in bytes
108 uint16_t vtoy_disk_part_id
; // begin with 1
109 uint16_t vtoy_disk_part_type
; // 0:exfat 1:ntfs other: reserved
110 char vtoy_img_path
[384]; // It seems to be enough, utf-8 format
111 uint64_t vtoy_img_size
; // image file size in bytes
114 * Ventoy will write a copy of ventoy_image_location data into runtime memory
115 * this is the physically address and length of that memory.
116 * Address 0 means no such data exist.
117 * Address will be aligned by 4KB.
120 uint64_t vtoy_img_location_addr
;
121 uint32_t vtoy_img_location_len
;
123 uint64_t vtoy_reserved
[4]; // Internal use by ventoy
125 uint8_t vtoy_disk_signature
[4];
127 uint8_t reserved
[27];
135 #if defined(_dragon_fly) || defined(_free_BSD) || defined(_QNX)
136 #define MMAP_FLAGS MAP_SHARED
138 #define MMAP_FLAGS MAP_PRIVATE
141 #define SEARCH_MEM_START 0x80000
142 #define SEARCH_MEM_LEN 0x1c000
144 static int verbose
= 0;
145 #define debug(fmt, ...) if(verbose) printf(fmt, ##__VA_ARGS__)
147 static ventoy_guid vtoy_guid
= VENTOY_GUID
;
149 static const char *g_ventoy_fs
[ventoy_fs_max
] =
151 "exfat", "ntfs", "ext*", "xfs", "udf", "fat"
154 static int vtoy_check_os_param(ventoy_os_param
*param
)
158 uint8_t *buf
= (uint8_t *)param
;
160 if (memcmp(¶m
->guid
, &vtoy_guid
, sizeof(ventoy_guid
)))
162 uint8_t *data1
= (uint8_t *)(¶m
->guid
);
163 uint8_t *data2
= (uint8_t *)(&vtoy_guid
);
165 for (i
= 0; i
< 16; i
++)
167 if (data1
[i
] != data2
[i
])
169 debug("guid not equal i = %u, 0x%02x, 0x%02x\n", i
, data1
[i
], data2
[i
]);
175 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
182 debug("Invalid checksum 0x%02x\n", chksum
);
189 static int vtoy_os_param_from_file(const char *filename
, ventoy_os_param
*param
)
194 fd
= open(filename
, O_RDONLY
| O_BINARY
);
197 fprintf(stderr
, "Failed to open file %s error %d\n", filename
, errno
);
201 read(fd
, param
, sizeof(ventoy_os_param
));
203 if (vtoy_check_os_param(param
) == 0)
205 debug("find ventoy os param in file %s\n", filename
);
209 debug("ventoy os pararm NOT found in file %s\n", filename
);
217 static void vtoy_dump_os_param(ventoy_os_param
*param
)
219 printf("################# dump os param ################\n");
221 printf("param->chksum = 0x%x\n", param
->chksum
);
222 printf("param->vtoy_disk_guid = %02x %02x %02x %02x\n",
223 param
->vtoy_disk_guid
[0], param
->vtoy_disk_guid
[1],
224 param
->vtoy_disk_guid
[2], param
->vtoy_disk_guid
[3]);
226 printf("param->vtoy_disk_signature = %02x %02x %02x %02x\n",
227 param
->vtoy_disk_signature
[0], param
->vtoy_disk_signature
[1],
228 param
->vtoy_disk_signature
[2], param
->vtoy_disk_signature
[3]);
230 printf("param->vtoy_disk_size = %llu\n", (unsigned long long)param
->vtoy_disk_size
);
231 printf("param->vtoy_disk_part_id = %u\n", param
->vtoy_disk_part_id
);
232 printf("param->vtoy_disk_part_type = %u\n", param
->vtoy_disk_part_type
);
233 printf("param->vtoy_img_path = <%s>\n", param
->vtoy_img_path
);
234 printf("param->vtoy_img_size = <%llu>\n", (unsigned long long)param
->vtoy_img_size
);
235 printf("param->vtoy_img_location_addr = <0x%llx>\n", (unsigned long long)param
->vtoy_img_location_addr
);
236 printf("param->vtoy_img_location_len = <%u>\n", param
->vtoy_img_location_len
);
237 printf("param->vtoy_reserved[0] = 0x%llx\n", (unsigned long long)param
->vtoy_reserved
[0]);
238 printf("param->vtoy_reserved[1] = 0x%llx\n", (unsigned long long)param
->vtoy_reserved
[1]);
243 static int vtoy_get_disk_guid(const char *diskname
, uint8_t *vtguid
, uint8_t *vtsig
)
247 char devdisk
[128] = {0};
249 snprintf(devdisk
, sizeof(devdisk
) - 1, "/dev/%s", diskname
);
251 fd
= open(devdisk
, O_RDONLY
| O_BINARY
);
254 lseek(fd
, 0x180, SEEK_SET
);
255 read(fd
, vtguid
, 16);
257 lseek(fd
, 0x1b8, SEEK_SET
);
261 debug("GUID for %s: <", devdisk
);
262 for (i
= 0; i
< 16; i
++)
264 debug("%02x", vtguid
[i
]);
272 debug("failed to open %s %d\n", devdisk
, errno
);
277 static unsigned long long vtoy_get_disk_size_in_byte(const char *disk
)
281 unsigned long long size
= 0;
282 char diskpath
[256] = {0};
283 char sizebuf
[64] = {0};
285 // Try 1: get size from sysfs
286 snprintf(diskpath
, sizeof(diskpath
) - 1, "/sys/block/%s/size", disk
);
287 if (access(diskpath
, F_OK
) >= 0)
289 debug("get disk size from sysfs for %s\n", disk
);
291 fd
= open(diskpath
, O_RDONLY
| O_BINARY
);
294 read(fd
, sizebuf
, sizeof(sizebuf
));
295 size
= strtoull(sizebuf
, NULL
, 10);
302 debug("%s not exist \n", diskpath
);
305 // Try 2: get size from ioctl
306 snprintf(diskpath
, sizeof(diskpath
) - 1, "/dev/%s", disk
);
307 fd
= open(diskpath
, O_RDONLY
);
310 debug("get disk size from ioctl for %s\n", disk
);
311 rc
= ioctl(fd
, BLKGETSIZE64
, &size
);
315 debug("failed to ioctl %d\n", rc
);
321 debug("failed to open %s %d\n", diskpath
, errno
);
324 debug("disk %s size %llu bytes\n", disk
, (unsigned long long)size
);
328 static int vtoy_is_possible_blkdev(const char *name
)
336 if (name
[0] == 'r' && name
[1] == 'a' && name
[2] == 'm')
342 if (name
[0] == 'l' && name
[1] == 'o' && name
[2] == 'o' && name
[3] == 'p')
348 if (name
[0] == 'd' && name
[1] == 'm' && name
[2] == '-' && IS_DIGIT(name
[3]))
354 if (name
[0] == 's' && name
[1] == 'r' && IS_DIGIT(name
[2]))
362 static int vtoy_find_disk_by_size(unsigned long long size
, char *diskname
)
364 unsigned long long cursize
= 0;
366 struct dirent
* p
= NULL
;
369 dir
= opendir("/sys/block");
375 while ((p
= readdir(dir
)) != NULL
)
377 if (!vtoy_is_possible_blkdev(p
->d_name
))
379 debug("disk %s is filted by name\n", p
->d_name
);
383 cursize
= vtoy_get_disk_size_in_byte(p
->d_name
);
384 debug("disk %s size %llu\n", p
->d_name
, (unsigned long long)cursize
);
387 sprintf(diskname
, "%s", p
->d_name
);
395 static int vtoy_find_disk_by_guid(ventoy_os_param
*param
, char *diskname
)
400 struct dirent
* p
= NULL
;
404 dir
= opendir("/sys/block");
410 while ((p
= readdir(dir
)) != NULL
)
412 if (!vtoy_is_possible_blkdev(p
->d_name
))
414 debug("disk %s is filted by name\n", p
->d_name
);
418 memset(vtguid
, 0, sizeof(vtguid
));
419 rc
= vtoy_get_disk_guid(p
->d_name
, vtguid
, vtsig
);
420 if (rc
== 0 && memcmp(vtguid
, param
->vtoy_disk_guid
, 16) == 0 &&
421 memcmp(vtsig
, param
->vtoy_disk_signature
, 4) == 0)
423 sprintf(diskname
, "%s", p
->d_name
);
432 static int vtoy_printf_iso_path(ventoy_os_param
*param
)
434 printf("%s\n", param
->vtoy_img_path
);
438 static int vtoy_check_device(ventoy_os_param
*param
, const char *device
)
440 unsigned long long size
;
441 uint8_t vtguid
[16] = {0};
442 uint8_t vtsig
[4] = {0};
444 debug("vtoy_check_device for <%s>\n", device
);
446 size
= vtoy_get_disk_size_in_byte(device
);
447 vtoy_get_disk_guid(device
, vtguid
, vtsig
);
449 debug("param->vtoy_disk_size=%llu size=%llu\n",
450 (unsigned long long)param
->vtoy_disk_size
, (unsigned long long)size
);
452 if (memcmp(vtguid
, param
->vtoy_disk_guid
, 16) == 0 &&
453 memcmp(vtsig
, param
->vtoy_disk_signature
, 4) == 0)
455 debug("<%s> is right ventoy disk\n", device
);
460 debug("<%s> is NOT right ventoy disk\n", device
);
465 static int vtoy_print_os_param(ventoy_os_param
*param
, char *diskname
)
468 char *path
= param
->vtoy_img_path
;
471 cnt
= vtoy_find_disk_by_size(param
->vtoy_disk_size
, diskname
);
472 debug("find disk by size %llu, cnt=%d...\n", (unsigned long long)param
->vtoy_disk_size
, cnt
);
475 if (vtoy_check_device(param
, diskname
) != 0)
482 cnt
= vtoy_find_disk_by_guid(param
, diskname
);
483 debug("find disk by guid cnt=%d...\n", cnt
);
486 if (param
->vtoy_disk_part_type
< ventoy_fs_max
)
488 fs
= g_ventoy_fs
[param
->vtoy_disk_part_type
];
497 printf("/dev/%s#%s#%s\n", diskname
, fs
, path
);
507 * Find disk and image path from ventoy runtime data.
508 * By default data is read from phymem(legacy bios) or efivar(UEFI), if -f is input, data is read from file.
510 * -f datafile os param data file.
511 * -c /dev/xxx check ventoy disk
513 * -l also print image disk location
515 int vtoydump_main(int argc
, char **argv
)
520 char filename
[256] = {0};
521 char diskname
[256] = {0};
522 char device
[64] = {0};
523 ventoy_os_param
*param
= NULL
;
525 while ((ch
= getopt(argc
, argv
, "c:f:p:v::")) != -1)
529 strncpy(filename
, optarg
, sizeof(filename
) - 1);
537 strncpy(device
, optarg
, sizeof(device
) - 1);
542 strncpy(filename
, optarg
, sizeof(filename
) - 1);
546 fprintf(stderr
, "Usage: %s -f datafile [ -v ] \n", argv
[0]);
551 if (filename
[0] == 0)
553 fprintf(stderr
, "Usage: %s -f datafile [ -v ] \n", argv
[0]);
557 param
= malloc(sizeof(ventoy_os_param
));
560 fprintf(stderr
, "failed to alloc memory with size %d error %d\n",
561 (int)sizeof(ventoy_os_param
), errno
);
565 memset(param
, 0, sizeof(ventoy_os_param
));
567 debug("get os pararm from file %s\n", filename
);
568 rc
= vtoy_os_param_from_file(filename
, param
);
571 debug("ventoy os param not found %d %d\n", rc
, ENOENT
);
574 debug("now try with file %s\n", "/ventoy/ventoy_os_param");
575 rc
= vtoy_os_param_from_file("/ventoy/ventoy_os_param", param
);
589 vtoy_dump_os_param(param
);
594 rc
= vtoy_printf_iso_path(param
);
598 rc
= vtoy_check_device(param
, device
);
602 // print os param, you can change the output format in the function
603 rc
= vtoy_print_os_param(param
, diskname
);
615 #ifndef BUILD_VTOY_TOOL
616 int main(int argc
, char **argv
)
618 return vtoydump_main(argc
, argv
);