blob: 23880893c9c79e1604e0dc44ec18ad56452fb2f8 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <fcntl.h>
#include <limits.h>
#include <stdint.h>
#include <utility>
#include <fbl/unique_fd.h>
#include <fbl/unique_ptr.h>
#include <gpt/gpt.h>
#include <gpt/guid.h>
namespace {
constexpr uint32_t kBlockSize = 512;
constexpr uint64_t kBlockCount = 1 << 20;
constexpr uint64_t kAccptableMinimumSize = kBlockSize * kBlockCount;
constexpr uint64_t kGptMetadataSize = 1 << 18; // 256KiB for now. See comment in LibGptTest::Init
static_assert(kGptMetadataSize <= kAccptableMinimumSize,
"GPT size greater than kAccptableMinimumSize");
class LibGptTest {
public:
LibGptTest(bool use_ramdisk) : use_ramdisk_(use_ramdisk) {}
~LibGptTest() {}
// Creates a ramdisk and initialize GPT on it.
bool Init();
// Removes the backing ramdisk device.
bool Teardown();
// Returns total size of the disk under test.
uint64_t GetDiskSize() const { return blk_size_ * blk_count_; }
// Return block size of the disk under test.
uint32_t GetBlockSize() const { return blk_size_; }
// Returns total number of block in the disk.
uint64_t GetBlockCount() const { return blk_count_; }
// Return total number of block free in disk after GPT is created.
uint64_t GetUsableBlockCount() const { return usable_last_block_ - usable_start_block_; }
// First block that is free to use after GPT is created.
uint64_t GetUsableStartBlock() const { return usable_start_block_; }
// Last block that is free to use after GPT is created.
uint64_t GetUsableLastBlock() const { return usable_last_block_; }
// Returns number of block GPT uses.
uint64_t GptMetadataBlocksCount() const {
// See comment in LibGptTest::Init
return kGptMetadataSize / blk_size_;
}
// Returns the full device path.
const char* GetDevicePath() const { return disk_path_; }
// Remove all partition from GPT and keep device in GPT initialized state.
bool Reset();
// Finalize uninitialized disk and verify.
bool Finalize();
// Sync and verify.
bool Sync();
// Get the Range from GPT.
bool ReadRange();
// Prepare disk to run Add Partition tests.
// 1. initialize GPT
// 2. optionally sync
// 3. get the usable range
bool PrepDisk(bool sync);
// gpt_ changes across Reset(). So we do not expose pointer to GptDevice to
// any of the test. Instead we expose following wrapper funtions for
// a few GptDevice methods.
bool IsGptValid() const { return gpt_->Valid(); }
zx_status_t GetDiffs(uint32_t partition_index, uint32_t* diffs) const {
return gpt_->GetDiffs(partition_index, diffs);
}
// Get's a partition at index pindex.
gpt_partition_t* GetPartition(uint32_t pindex) const { return gpt_->GetPartition(pindex); }
// Adds a partition
zx_status_t AddPartition(const char* name, const uint8_t* type, const uint8_t* guid,
uint64_t offset, uint64_t blocks, uint64_t flags) {
return gpt_->AddPartition(name, type, guid, offset, blocks, flags);
}
// removes a partition.
zx_status_t RemovePartition(const uint8_t* guid) { return gpt_->RemovePartition(guid); }
// removes all partitions.
zx_status_t RemoveAllPartitions() { return gpt_->RemoveAllPartitions(); }
// wrapper around GptDevice's SetPartitionType
zx_status_t SetPartitionType(uint32_t partition_index, const uint8_t* type) {
return gpt_->SetPartitionType(partition_index, type);
}
// wrapper around GptDevice's SetPartitionGuid
zx_status_t SetPartitionGuid(uint32_t partition_index, const uint8_t* guid) {
return gpt_->SetPartitionGuid(partition_index, guid);
}
// wrapper around GptDevice's SetPartitionRange
zx_status_t SetPartitionRange(uint32_t partition_index, uint64_t start, uint64_t end) {
return gpt_->SetPartitionRange(partition_index, start, end);
}
// wrapper around GptDevice's SetPartitionVisibility
zx_status_t SetPartitionVisibility(uint32_t index, bool visible) {
return gpt_->SetPartitionVisibility(index, visible);
}
// wrapper around GptDevice's GetPartitionFlags
zx_status_t GetPartitionFlags(uint32_t index, uint64_t* flags) {
return gpt_->GetPartitionFlags(index, flags);
}
// wrapper around GptDevice's SetPartitionFlags
zx_status_t SetPartitionFlags(uint32_t index, uint64_t flags) {
return gpt_->SetPartitionFlags(index, flags);
}
private:
// Initialize a physical media.
bool InitDisk(const char* disk_path);
// Create and initialize and ramdisk.
bool InitRamDisk();
// Teardown the disk.
bool TearDownDisk();
// Teardown and destroy ram disk.
bool TearDownRamDisk();
// Block size of the device.
uint32_t blk_size_ = kBlockSize;
// Number of block in the disk.
uint64_t blk_count_ = kBlockCount;
// disk path
char disk_path_[PATH_MAX] = {};
// pointer to read GptDevice.
fbl::unique_ptr<gpt::GptDevice> gpt_;
// Open file descriptor to block device.
fbl::unique_fd fd_;
// Create and use ramdisk instead of a physical disk.
bool use_ramdisk_;
// An optional ramdisk structure, which is only non-nullptr if
// |use_ramdisk_| is true.
struct ramdisk_client* ramdisk_ = nullptr;
// usable start block offset.
uint64_t usable_start_block_ = UINT64_MAX;
// usable last block offset.
uint64_t usable_last_block_ = UINT64_MAX;
};
} // namespace