makebootable: add support for GPT partition tables; fixes #9291

* with #4028 implemented, we can now use makebootable on
  GPT formatted disks as well.
This commit is contained in:
Jessica Hamilton 2015-06-04 21:26:52 +12:00
parent e20eba976b
commit 42f25fe91b
2 changed files with 68 additions and 88 deletions

View File

@ -55,6 +55,9 @@
#endif
#if USE_PARTITION_MAP
# include "guid.h"
# include "gpt_known_guids.h"
# include "Header.h"
# include "PartitionMap.h"
# include "PartitionMapParser.h"
#endif
@ -238,6 +241,59 @@ dump_partition_map(const PartitionMap& map)
}
}
static void
get_partition_offset(int deviceFD, off_t deviceStart, off_t deviceSize,
int blockSize, int partitionIndex, char *deviceName,
int64 &_partitionOffset)
{
PartitionMapParser parser(deviceFD, deviceStart, deviceSize, blockSize);
PartitionMap map;
status_t error = parser.Parse(NULL, &map);
if (error == B_OK) {
Partition *partition = map.PartitionAt(partitionIndex - 1);
if (!partition || partition->IsEmpty()) {
fprintf(stderr, "Error: Invalid partition index %d.\n",
partitionIndex);
dump_partition_map(map);
exit(1);
}
if (partition->IsExtended()) {
fprintf(stderr, "Error: Partition %d is an extended "
"partition.\n", partitionIndex);
dump_partition_map(map);
exit(1);
}
_partitionOffset = partition->Offset();
} else {
// try again using GPT instead
EFI::Header gptHeader(deviceFD, deviceSize, blockSize);
error = gptHeader.InitCheck();
if (error == B_OK && partitionIndex < gptHeader.EntryCount()) {
efi_partition_entry partition = gptHeader.EntryAt(partitionIndex - 1);
static_guid bfs_uuid = {0x42465331, 0x3BA3, 0x10F1,
0x802A4861696B7521LL};
if (!(bfs_uuid == partition.partition_type)) {
fprintf(stderr, "Error: Partition %d does not have the "
"BFS UUID.\n", partitionIndex);
exit(1);
}
_partitionOffset = partition.StartBlock() * blockSize;
} else {
fprintf(stderr, "Error: Parsing partition table on device "
"\"%s\" failed: %s\n", deviceName, strerror(error));
exit(1);
}
}
close(deviceFD);
}
#endif
@ -407,36 +463,8 @@ main(int argc, const char *const *argv)
// parse the partition map
// TODO: block size!
PartitionMapParser parser(baseFD, 0, deviceSize, 512);
PartitionMap map;
error = parser.Parse(NULL, &map);
if (error != B_OK) {
fprintf(stderr, "Error: Parsing partition table on "
"device \"%s\" failed: %s\n", baseDeviceName,
strerror(error));
exit(1);
}
close(baseFD);
// check the partition we are supposed to write at
Partition *partition = map.PartitionAt(partitionIndex - 1);
if (!partition || partition->IsEmpty()) {
fprintf(stderr, "Error: Invalid partition index %d.\n",
partitionIndex);
dump_partition_map(map);
exit(1);
}
if (partition->IsExtended()) {
fprintf(stderr, "Error: Partition %d is an extended "
"partition.\n", partitionIndex);
dump_partition_map(map);
exit(1);
}
partitionOffset = partition->Offset();
get_partition_offset(baseFD, 0, deviceSize, 512,
partitionIndex, baseDeviceName, partitionOffset);
} else {
// The given device is the base device. We'll write at
// offset 0.
@ -498,35 +526,8 @@ main(int argc, const char *const *argv)
// parse the partition map
// TODO: block size!
PartitionMapParser parser(baseFD, 0, deviceSize, 512);
PartitionMap map;
error = parser.Parse(NULL, &map);
if (error != B_OK) {
fprintf(stderr, "Error: Parsing partition table on "
"device \"%s\" failed: %s\n", baseDeviceName,
strerror(error));
exit(1);
}
close(baseFD);
// check the partition we are supposed to write at
Partition *partition = map.PartitionAt(partitionIndex - 1);
if (!partition || partition->IsEmpty()) {
fprintf(stderr, "Error: Invalid partition index %d.\n",
partitionIndex);
dump_partition_map(map);
exit(1);
}
if (partition->IsExtended()) {
fprintf(stderr, "Error: Partition %d is an extended "
"partition.\n", partitionIndex);
dump_partition_map(map);
exit(1);
}
partitionOffset = partition->Offset();
get_partition_offset(baseFD, 0, deviceSize, 512,
partitionIndex, baseDeviceName, partitionOffset);
} else {
// The given device is the base device. We'll write at
// offset 0.
@ -571,34 +572,8 @@ main(int argc, const char *const *argv)
deviceSize = blockSize * blockCount;
// parse the partition map
PartitionMapParser parser(baseFD, 0, deviceSize, blockSize);
PartitionMap map;
error = parser.Parse(NULL, &map);
if (error != B_OK) {
fprintf(stderr, "Error: Parsing partition table on "
"device \"%s\" failed: %s\n", baseDeviceName,
strerror(error));
exit(1);
}
close(baseFD);
// check the partition we are supposed to write at
Partition *partition = map.PartitionAt(partitionIndex - 1);
if (!partition || partition->IsEmpty()) {
fprintf(stderr, "Error: Invalid partition index %d.\n",
partitionIndex);
dump_partition_map(map);
exit(1);
}
if (partition->IsExtended()) {
fprintf(stderr, "Error: Partition %d is an extended "
"partition.\n", partitionIndex);
dump_partition_map(map);
exit(1);
}
partitionOffset = partition->Offset();
get_partition_offset(baseFD, 0, deviceSize, 512,
partitionIndex, baseDeviceName, partitionOffset);
#else
// partitions are block devices under Haiku, but not under BeOS
#ifdef HAIKU_TARGET_PLATFORM_HAIKU

View File

@ -12,10 +12,15 @@ USES_BE_API on <build>makebootable = true ;
local hostPlatformSources ;
if $(HOST_PLATFORM) = linux || $(HOST_PLATFORM) = freebsd || $(HOST_PLATFORM) = darwin {
hostPlatformSources = PartitionMap.cpp PartitionMapParser.cpp ;
UsePrivateHeaders interface ;
hostPlatformSources = PartitionMap.cpp PartitionMapParser.cpp
crc32.cpp Header.cpp utility.cpp ;
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons kernel
partitioning_systems intel ] ;
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons kernel
partitioning_systems gpt ] ;
DEFINES += _USER_MODE ;
}