1 /******************************************************************************
2 * vtoydm.c ---- ventoy device mapper tool
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>
34 #include "biso_list.h"
35 #include "biso_util.h"
36 #include "biso_plat.h"
37 #include "biso_9660.h"
44 typedef unsigned long long uint64_t;
45 typedef unsigned int uint32_t;
49 typedef struct ventoy_img_chunk
51 uint32_t img_start_sector
; // sector size: 2KB
52 uint32_t img_end_sector
; // included
54 uint64_t disk_start_sector
; // in disk_sector_size
55 uint64_t disk_end_sector
; // included
59 static int verbose
= 0;
60 #define debug(fmt, ...) if(verbose) printf(fmt, ##__VA_ARGS__)
62 #define CMD_PRINT_TABLE 1
63 #define CMD_CREATE_DM 2
64 #define CMD_DUMP_ISO_INFO 3
65 #define CMD_EXTRACT_ISO_FILE 4
66 #define CMD_PRINT_EXTRACT_ISO_FILE 5
68 static uint64_t g_iso_file_size
;
69 static char g_disk_name
[128];
70 static int g_img_chunk_num
= 0;
71 static ventoy_img_chunk
*g_img_chunk
= NULL
;
72 static unsigned char g_iso_sector_buf
[2048];
74 ventoy_img_chunk
* vtoydm_get_img_map_data(const char *img_map_file
, int *plen
)
79 ventoy_img_chunk
*chunk
= NULL
;
81 fp
= fopen(img_map_file
, "rb");
84 fprintf(stderr
, "Failed to open file %s err:%d\n", img_map_file
, errno
);
88 fseek(fp
, 0, SEEK_END
);
90 fseek(fp
, 0, SEEK_SET
);
92 debug("File <%s> len:%d\n", img_map_file
, len
);
94 chunk
= (ventoy_img_chunk
*)malloc(len
);
97 fprintf(stderr
, "Failed to malloc memory len:%d err:%d\n", len
, errno
);
101 if (fread(chunk
, 1, len
, fp
) != len
)
103 fprintf(stderr
, "Failed to read file err:%d\n", errno
);
107 if (len
% sizeof(ventoy_img_chunk
))
109 fprintf(stderr
, "image map file size %d is not aligned with %d\n",
110 len
, (int)sizeof(ventoy_img_chunk
));
132 UINT64
vtoydm_get_file_size(const char *pcFileName
)
136 debug("vtoydm_get_file_size %s %lu\n", pcFileName
, (unsigned long)g_iso_file_size
);
138 return g_iso_file_size
;
141 BISO_FILE_S
* vtoydm_open_file(const char *pcFileName
)
145 debug("vtoydm_open_file %s\n", pcFileName
);
147 file
= malloc(sizeof(BISO_FILE_S
));
150 memset(file
, 0, sizeof(BISO_FILE_S
));
152 file
->FileSize
= g_iso_file_size
;
159 void vtoydm_close_file(BISO_FILE_S
*pstFile
)
161 debug("vtoydm_close_file\n");
169 INT64
vtoydm_seek_file(BISO_FILE_S
*pstFile
, INT64 i64Offset
, INT iFromWhere
)
171 debug("vtoydm_seek_file %d\n", (int)i64Offset
);
173 if (iFromWhere
== SEEK_SET
)
175 pstFile
->CurPos
= (UINT64
)i64Offset
;
181 UINT64
vtoydm_map_iso_sector(UINT64 sector
)
184 UINT64 disk_sector
= 0;
186 for (i
= 0; i
< g_img_chunk_num
; i
++)
188 if (sector
>= g_img_chunk
[i
].img_start_sector
&& sector
<= g_img_chunk
[i
].img_end_sector
)
190 disk_sector
= ((sector
- g_img_chunk
[i
].img_start_sector
) << 2) + g_img_chunk
[i
].disk_start_sector
;
198 int vtoydm_read_iso_sector(UINT64 sector
, void *buf
)
202 UINT64 disk_sector
= 0;
204 for (i
= 0; i
< g_img_chunk_num
; i
++)
206 if (sector
>= g_img_chunk
[i
].img_start_sector
&& sector
<= g_img_chunk
[i
].img_end_sector
)
208 disk_sector
= ((sector
- g_img_chunk
[i
].img_start_sector
) << 2) + g_img_chunk
[i
].disk_start_sector
;
213 fd
= open(g_disk_name
, O_RDONLY
| O_BINARY
);
216 debug("Failed to open %s\n", g_disk_name
);
220 lseek(fd
, disk_sector
* 512, SEEK_SET
);
228 UINT64 vtoydm_read_file
230 BISO_FILE_S
*pstFile
,
238 UINT64 readlen
= uiBlkSize
* uiBlkNum
;
239 char *curbuf
= (char *)pBuf
;
241 debug("vtoydm_read_file length:%u\n", uiBlkSize
* uiBlkNum
);
243 pos
= (int)(pstFile
->CurPos
% 2048);
248 vtoydm_read_iso_sector(pstFile
->CurPos
/ 2048, g_iso_sector_buf
);
251 memcpy(curbuf
, g_iso_sector_buf
+ pos
, align
);
254 pstFile
->CurPos
+= align
;
258 memcpy(curbuf
, g_iso_sector_buf
+ pos
, readlen
);
259 pstFile
->CurPos
+= readlen
;
264 while (readlen
> 2048)
266 vtoydm_read_iso_sector(pstFile
->CurPos
/ 2048, curbuf
);
267 pstFile
->CurPos
+= 2048;
275 vtoydm_read_iso_sector(pstFile
->CurPos
/ 2048, g_iso_sector_buf
);
276 memcpy(curbuf
, g_iso_sector_buf
, readlen
);
277 pstFile
->CurPos
+= readlen
;
280 return uiBlkSize
* uiBlkNum
;
283 int vtoydm_dump_iso(const char *img_map_file
, const char *diskname
)
289 ventoy_img_chunk
*chunk
= NULL
;
291 BISO_PARSER_S
*parser
= NULL
;
292 char label
[64] = {0};
294 chunk
= vtoydm_get_img_map_data(img_map_file
, &len
);
300 for (i
= 0; i
< len
/ sizeof(ventoy_img_chunk
); i
++)
302 sector_num
= chunk
[i
].img_end_sector
- chunk
[i
].img_start_sector
+ 1;
303 g_iso_file_size
+= sector_num
* 2048;
306 strncpy(g_disk_name
, diskname
, sizeof(g_disk_name
) - 1);
308 g_img_chunk_num
= len
/ sizeof(ventoy_img_chunk
);
310 debug("iso file size : %llu\n", (unsigned long long)g_iso_file_size
);
312 iso
= BISO_AllocReadHandle();
319 ret
= BISO_OpenImage("XXX", iso
);
320 debug("open iso image ret=0x%lx\n", ret
);
322 parser
= (BISO_PARSER_S
*)iso
;
323 memcpy(label
, parser
->pstPVD
->szVolumeId
, 32);
324 for (i
= 32; i
>=0; i
--)
326 if (label
[i
] != 0 && label
[i
] != ' ')
338 printf("VENTOY_ISO_LABEL %s\n", label
);
341 BISO_DumpFileTree(iso
);
343 BISO_FreeReadHandle(iso
);
349 static int vtoydm_extract_iso
351 const char *img_map_file
,
352 const char *diskname
,
353 unsigned long first_sector
,
354 unsigned long long file_size
,
361 g_img_chunk
= vtoydm_get_img_map_data(img_map_file
, &len
);
362 if (NULL
== g_img_chunk
)
367 strncpy(g_disk_name
, diskname
, sizeof(g_disk_name
) - 1);
368 g_img_chunk_num
= len
/ sizeof(ventoy_img_chunk
);
370 fp
= fopen(outfile
, "wb");
373 fprintf(stderr
, "Failed to create file %s err:%d\n", outfile
, errno
);
378 while (file_size
> 0)
380 vtoydm_read_iso_sector(first_sector
++, g_iso_sector_buf
);
381 if (file_size
> 2048)
383 fwrite(g_iso_sector_buf
, 2048, 1, fp
);
388 fwrite(g_iso_sector_buf
, 1, file_size
, fp
);
399 static int vtoydm_print_extract_iso
401 const char *img_map_file
,
402 const char *diskname
,
403 unsigned long first_sector
,
404 unsigned long long file_size
,
411 uint32_t disk_first
= 0;
414 uint64_t size
= file_size
;
417 g_img_chunk
= vtoydm_get_img_map_data(img_map_file
, &len
);
418 if (NULL
== g_img_chunk
)
423 strncpy(g_disk_name
, diskname
, sizeof(g_disk_name
) - 1);
424 g_img_chunk_num
= len
/ sizeof(ventoy_img_chunk
);
426 fp
= fopen(outfile
, "wb");
429 fprintf(stderr
, "Failed to create file %s err:%d\n", outfile
, errno
);
434 fwrite(g_disk_name
, 1, 32, fp
);
435 fwrite(&size
, 1, 8, fp
);
437 while (file_size
> 0)
439 sector
= vtoydm_map_iso_sector(first_sector
++);
441 if (count
> 0 && sector
== last
+ 4)
452 fwrite(buf
, 1, sizeof(buf
), fp
);
460 if (file_size
> 2048)
474 fwrite(buf
, 1, sizeof(buf
), fp
);
485 static int vtoydm_print_linear_table(const char *img_map_file
, const char *diskname
)
489 uint32_t disk_sector_num
;
490 uint32_t sector_start
;
491 ventoy_img_chunk
*chunk
= NULL
;
493 chunk
= vtoydm_get_img_map_data(img_map_file
, &len
);
499 for (i
= 0; i
< len
/ sizeof(ventoy_img_chunk
); i
++)
501 sector_start
= chunk
[i
].img_start_sector
;
502 disk_sector_num
= (uint32_t)(chunk
[i
].disk_end_sector
+ 1 - chunk
[i
].disk_start_sector
);
504 /* TBD: to be more flexible */
506 printf("%u %u linear %s %llu\n",
507 (sector_start
<< 2), disk_sector_num
,
508 diskname
, (unsigned long long)chunk
[i
].disk_start_sector
);
510 if (strstr(diskname
, "nvme") || strstr(diskname
, "mmc"))
512 printf("%u %u linear %sp1 %llu\n",
513 (sector_start
<< 2), disk_sector_num
,
514 diskname
, (unsigned long long)chunk
[i
].disk_start_sector
- 2048);
518 printf("%u %u linear %s1 %llu\n",
519 (sector_start
<< 2), disk_sector_num
,
520 diskname
, (unsigned long long)chunk
[i
].disk_start_sector
- 2048);
529 static int vtoydm_print_help(FILE *fp
)
531 fprintf(fp
, "Usage: \n"
532 " vtoydm -p -f img_map_file -d diskname [ -v ] \n"
533 " vtoydm -c -f img_map_file -d diskname [ -v ] \n"
534 " vtoydm -i -f img_map_file -d diskname [ -v ] \n"
535 " vtoydm -e -f img_map_file -d diskname -s sector -l len -o file [ -v ] \n"
540 int vtoydm_main(int argc
, char **argv
)
544 unsigned long first_sector
= 0;
545 unsigned long long file_size
= 0;
546 char diskname
[128] = {0};
547 char filepath
[300] = {0};
548 char outfile
[300] = {0};
550 while ((ch
= getopt(argc
, argv
, "s:l:o:d:f:v::i::p::c::h::e::E::")) != -1)
554 strncpy(diskname
, optarg
, sizeof(diskname
) - 1);
558 strncpy(filepath
, optarg
, sizeof(filepath
) - 1);
562 cmd
= CMD_PRINT_TABLE
;
570 cmd
= CMD_DUMP_ISO_INFO
;
574 cmd
= CMD_EXTRACT_ISO_FILE
;
578 cmd
= CMD_PRINT_EXTRACT_ISO_FILE
;
582 first_sector
= strtoul(optarg
, NULL
, 10);
586 file_size
= strtoull(optarg
, NULL
, 10);
590 strncpy(outfile
, optarg
, sizeof(outfile
) - 1);
598 return vtoydm_print_help(stdout
);
602 vtoydm_print_help(stderr
);
607 if (filepath
[0] == 0 || diskname
[0] == 0)
609 fprintf(stderr
, "Must input file and disk\n");
613 debug("cmd=%d file=<%s> disk=<%s> first_sector=%lu file_size=%llu\n",
614 cmd
, filepath
, diskname
, first_sector
, file_size
);
618 case CMD_PRINT_TABLE
:
620 return vtoydm_print_linear_table(filepath
, diskname
);
626 case CMD_DUMP_ISO_INFO
:
628 return vtoydm_dump_iso(filepath
, diskname
);
630 case CMD_EXTRACT_ISO_FILE
:
632 return vtoydm_extract_iso(filepath
, diskname
, first_sector
, file_size
, outfile
);
634 case CMD_PRINT_EXTRACT_ISO_FILE
:
636 return vtoydm_print_extract_iso(filepath
, diskname
, first_sector
, file_size
, outfile
);
640 fprintf(stderr
, "Invalid cmd \n");
649 #ifndef BUILD_VTOY_TOOL
650 int main(int argc
, char **argv
)
652 return vtoydm_main(argc
, argv
);