| // SPDX-License-Identifier: GPL-2.0+ OR MIT |
| #include "erofs/internal.h" |
| |
| static int erofs_vmdk_desc_add_extent(FILE *f, u64 sectors, |
| const char *filename, u64 offset) |
| { |
| static const char extent_line_fmt[] = |
| "RW %" PRIu64 " FLAT \"%s\" %" PRIu64 "\n"; |
| |
| while (sectors) { |
| u64 count = min_t(u64, sectors, 0x80000000 >> 9); |
| int ret; |
| |
| ret = fprintf(f, extent_line_fmt, count, filename, offset); |
| if (ret < 0) |
| return -errno; |
| offset += count; |
| sectors -= count; |
| } |
| return 0; |
| } |
| |
| int erofs_dump_vmdk_desc(FILE *f, struct erofs_sb_info *sbi) |
| { |
| static const char desc_template_1[] = |
| "# Disk DescriptorFile\n" |
| "version=1\n" |
| "CID=%" PRIx32 "\n" |
| "parentCID=%" PRIx32 "\n" |
| "createType=\"%s\"\n" |
| "\n" |
| "# Extent description\n"; |
| static const char desc_template_2[] = |
| "\n" |
| "# The Disk Data Base\n" |
| "#DDB\n" |
| "\n" |
| "ddb.virtualHWVersion = \"%s\"\n" |
| "ddb.geometry.cylinders = \"%" PRIu64 "\"\n" |
| "ddb.geometry.heads = \"%" PRIu32 "\"\n" |
| "ddb.geometry.sectors = \"63\"\n" |
| "ddb.adapterType = \"%s\"\n"; |
| static const char subformat[] = "twoGbMaxExtentFlat"; |
| static const char adapter_type[] = "ide"; |
| u32 cid = ((u32 *)sbi->uuid)[0] ^ ((u32 *)sbi->uuid)[1] ^ |
| ((u32 *)sbi->uuid)[2] ^ ((u32 *)sbi->uuid)[3]; |
| u32 parent_cid = 0xffffffff; |
| u32 number_heads = 16; |
| char *hw_version = "4"; |
| u64 total_sectors, sectors; |
| int ret, i; |
| |
| fprintf(f, desc_template_1, cid, parent_cid, subformat); |
| sectors = sbi->primarydevice_blocks << (sbi->blkszbits - 9); |
| ret = erofs_vmdk_desc_add_extent(f, sectors, (char *)sbi->devname, 0); |
| if (ret) |
| return ret; |
| total_sectors = sectors; |
| for (i = 0; i < sbi->extra_devices; ++i) { |
| const char *name = sbi->devs[i].src_path ?: |
| (const char *)sbi->devs[i].tag; |
| |
| sectors = (u64)sbi->devs[i].blocks << (sbi->blkszbits - 9); |
| ret = erofs_vmdk_desc_add_extent(f, sectors, name, 0); |
| if (ret) |
| return ret; |
| total_sectors += sectors; |
| } |
| |
| fprintf(f, desc_template_2, hw_version, |
| (u64)DIV_ROUND_UP(total_sectors, 63ULL * number_heads), |
| number_heads, adapter_type); |
| return 0; |
| } |