blob: 0122861c3361b134a57b4fac9054f1f4402b37d9 [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 <cstring>
#ifdef __Fuchsia__
#include <fuchsia/hardware/block/volume/c/fidl.h>
#endif
#include <fvm/format.h>
#include <zircon/assert.h>
namespace fvm {
namespace {
// Used to check whether a given VPartitionEntry is flagged as an inactive partition.
// This flags are a mirror of those exposed in the fidl interface. Since this code is used in host
// too, we can't rely on them directly, but enforce compile time checks that the values match.
constexpr uint32_t kVPartitionEntryFlagMask = 0x00000001;
constexpr uint32_t kVPartitionEntryFlagInactive = 0x00000001;
#ifdef __Fuchsia__
// Enforce target and host flags to match.
static_assert(kVPartitionEntryFlagInactive ==
fuchsia_hardware_block_volume_AllocatePartitionFlagInactive,
"Inactive Flag must match FIDL definition.");
#endif
// Slice Entry mask for retrieving the assigned partition.
constexpr uint64_t kVPartitionEntryMax = (1ull << kSliceEntryVPartitionBits) - 1;
constexpr uint64_t kVPartitionEntryMask = kVPartitionEntryMax;
static_assert(kMaxVPartitions <= kVPartitionEntryMax,
"VPartition addres space needs to fit within Slice Entry VPartitionBits.");
// Slice Entry mask for retrieving the assigned vslice.
constexpr uint64_t kSliceEntryVSliceMax = (1ull << kSliceEntryVSliceBits) - 1;
constexpr uint64_t kSliceEntryVSliceMask = kSliceEntryVSliceMax << kSliceEntryVPartitionBits;
static_assert(kSliceEntryVSliceMax >= fvm::kMaxVSlices,
"SliceEntry must be able to address the range [0. kMaxVSlice)");
// Remaining bits.
constexpr uint64_t kSliceEntryReservedBits = 16;
static_assert(kSliceEntryVPartitionBits + kSliceEntryVSliceBits + kSliceEntryReservedBits == 64,
"Exceeding SliceEntry payload size.");
} // namespace
VPartitionEntry VPartitionEntry::Create(const uint8_t* type, const uint8_t* guid, uint32_t slices,
const char* name, uint32_t flags) {
VPartitionEntry entry = VPartitionEntry::Create();
entry.slices = slices;
// Filter out unallowed flags.
entry.flags = ParseFlags(flags);
memcpy(&entry.type, type, kGuidSize);
memcpy(&entry.guid, guid, kGuidSize);
memcpy(&entry.name, name, kMaxVPartitionNameLength);
return entry;
}
uint32_t VPartitionEntry::ParseFlags(uint32_t raw_flags) {
return raw_flags & kVPartitionEntryFlagMask;
}
bool VPartitionEntry::IsActive() const {
return (flags & kVPartitionEntryFlagInactive) == 0;
}
bool VPartitionEntry::IsInactive() const {
return !IsActive();
}
bool VPartitionEntry::IsAllocated() const {
return slices != 0;
}
bool VPartitionEntry::IsFree() const {
return !IsAllocated();
}
void VPartitionEntry::Release() {
memset(this, 0, sizeof(VPartitionEntry));
ZX_DEBUG_ASSERT_MSG(IsFree(),
"VPartitionEntry must be free after calling VPartitionEntry::Release()");
}
void VPartitionEntry::SetActive(bool is_active) {
if (is_active) {
flags &= (~kVPartitionEntryFlagInactive);
} else {
flags |= kVPartitionEntryFlagInactive;
}
}
SliceEntry SliceEntry::Create(uint64_t vpartition, uint64_t vslice) {
SliceEntry entry;
entry.Set(vpartition, vslice);
return entry;
}
void SliceEntry::Set(uint64_t vpartition, uint64_t vslice) {
ZX_DEBUG_ASSERT(vpartition < kVPartitionEntryMax);
ZX_DEBUG_ASSERT(vslice < kSliceEntryVSliceMax);
data = 0ull | (vpartition & kVPartitionEntryMax) |
((vslice & kSliceEntryVSliceMax) << (kSliceEntryVPartitionBits));
}
void SliceEntry::Release() {
data = 0;
}
bool SliceEntry::IsAllocated() const {
return VPartition() != 0;
}
bool SliceEntry::IsFree() const {
return !IsAllocated();
}
uint64_t SliceEntry::VSlice() const {
uint64_t vslice = (data & kSliceEntryVSliceMask) >> kSliceEntryVPartitionBits;
ZX_DEBUG_ASSERT_MSG(vslice < (1ul << kSliceEntryVSliceBits),
"Slice assigned to vslice out of range.");
return vslice;
}
uint64_t SliceEntry::VPartition() const {
uint64_t vpartition = (data & kVPartitionEntryMask);
ZX_DEBUG_ASSERT_MSG(vpartition < kMaxVPartitions, "Slice assigned to Partition out of range.");
return vpartition;
}
} // namespace fvm