blob: da4d5f49efce1b51ce4ace0608ec020eab553740 [file] [log] [blame]
// Copyright 2016 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.
#pragma once
#include <fbl/unique_fd.h>
#include <fbl/unique_ptr.h>
#include <gpt/c/gpt.h>
namespace gpt {
constexpr uint32_t kPartitionCount = 128;
constexpr uint64_t kGuidStrLength = 37;
constexpr uint32_t kGptDiffType = 0x01;
constexpr uint32_t kGptDiffGuid = 0x02;
constexpr uint32_t kGptDiffFirst = 0x04;
constexpr uint32_t kGptDiffLast = 0x08;
constexpr uint32_t kGptDiffFlags = 0x10;
constexpr uint32_t kGptDiffName = 0x20;
class GptDevice {
public:
static zx_status_t Create(int fd, uint32_t blocksize, uint64_t blocks,
fbl::unique_ptr<GptDevice>* out_dev);
// returns true if the partition table on the device is valid
bool Valid() const { return valid_; }
// Returns the range of usable blocks within the GPT, from [block_start, block_end] (inclusive)
zx_status_t Range(uint64_t* block_start, uint64_t* block_end) const;
// Writes changes to partition table to the device. If the device does not contain valid
// GPT, a gpt header gets created. Sync doesn't nudge block device driver to rescan the
// partitions. So it is the caller's responsibility to rescan partitions for the changes
// if needed.
zx_status_t Sync();
// perform all checks and computations on the in-memory representation, but DOES
// NOT write it out to disk. To perform checks AND write to disk, use Sync
zx_status_t Finalize();
// Adds a partition to in-memory instance of GptDevice. The changes stay visible
// only to this instace. Needs a Sync to write the changes to the device.
zx_status_t AddPartition(const char* name, const uint8_t* type, const uint8_t* guid,
uint64_t offset, uint64_t blocks, uint64_t flags);
// Writes zeroed blocks at an arbitrary offset (in blocks) within the device.
//
// Can be used alongside gpt_partition_add to ensure a newly created partition
// will not read stale superblock data.
zx_status_t ClearPartition(uint64_t offset, uint64_t blocks);
// Removes a partition from in-memory instance of GptDevice. The changes stay visible
// only to this instace. Needs a Sync to write the changes to the device.
zx_status_t RemovePartition(const uint8_t* guid);
// Removes all partitions from in-memory instance of GptDevice. The changes stay visible
// only to this instace. Needs a Sync to write the changes to the device.
zx_status_t RemoveAllPartitions();
// given a gpt device, get the GUID for the disk
void GetHeaderGuid(uint8_t (*disk_guid_out)[GPT_GUID_LEN]) const;
// return true if partition# idx has been locally modified
zx_status_t GetDiffs(uint32_t idx, uint32_t* diffs) const;
// returns a pointer to partition at index pindex
gpt_partition_t* GetPartition(uint32_t pindex) const {
ZX_ASSERT(pindex < kPartitionCount);
return partitions_[pindex];
}
// print out the GPT
void PrintTable() const;
zx_status_t BlockRrPart() {
return static_cast<zx_status_t>(ioctl_block_rr_part(fd_.get()));
}
// Return device's block size
uint64_t BlockSize() const { return blocksize_; }
// Return total number of blocks in the device
uint64_t TotalBlockCount() const { return blocks_; }
private:
GptDevice() { valid_ = false; };
zx_status_t FinalizeAndSync(bool persist);
// read the partition table from the device.
zx_status_t Init(int fd, uint32_t blocksize, uint64_t blocks);
// true if the partition table on the device is valid
bool valid_;
// pointer to a list of partitions
gpt_partition_t* partitions_[kPartitionCount] = {};
// device to use
fbl::unique_fd fd_;
// block size in bytes
uint64_t blocksize_ = 0;
// number of blocks
uint64_t blocks_ = 0;
// true if valid mbr exists on disk
bool mbr_ = false;
// header buffer, should be primary copy
gpt_header_t header_ = {};
// partition table buffer
gpt_partition_t ptable_[kPartitionCount] = {};
// copy of buffer from when last init'd or sync'd.
gpt_partition_t ptable_backup_[kPartitionCount] = {};
};
} // namespace gpt