blob: 316a8ffc94b28a54bb53b8e9689b6bbcef5e7d64 [file]
// 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;
}