blob: 4f1c9b6fbd7f134c1f7cdbb917f59c4ae76f4b09 [file] [log] [blame]
// Copyright 2018 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 <stdarg.h>
#include <stdlib.h>
#include <utility>
#include <fbl/array.h>
#include <fbl/unique_fd.h>
#include <fbl/vector.h>
#include "src/storage/fvm/format.h"
namespace fvm {
// Checker defines a class which may be used to validate an FVM
// (provided as either a regular file or a raw block device).
class Checker {
Checker(fbl::unique_fd fd, uint32_t block_size, bool silent);
// Sets the path of the block device / image to read the FVM from.
void SetDevice(fbl::unique_fd fd) { fd_ = std::move(fd); }
// Sets the block size of the provided device. Not automatically queried from the underlying
// device, since this checker may operate on a regular file, which does not have an
// attached block size.
void SetBlockSize(uint32_t block_size) { block_size_ = block_size; }
// Toggles the output of future calls to |Log|.
void SetSilent(bool silent) { logger_.SetSilent(silent); }
// Read from and validate the provided device, logging information if requested.
bool Validate() const;
class Logger {
Logger() : silent_(false) {}
explicit Logger(bool silent) : silent_(silent) {}
// Toggles the output of future calls to |Log|.
void SetSilent(bool silent) { silent_ = silent; }
// Prints the format string and arguments to stderr.
void Error(const char* format, ...) const {
va_list arg;
va_start(arg, format);
vprintf(format, arg);
// Prints the format string and arguments to stdout, unless explicitly silenced.
void Log(const char* format, ...) const {
va_list arg;
if (!silent_) {
va_start(arg, format);
vprintf(format, arg);
bool silent_;
// Cached information from loading and validating the FVM.
struct FvmInfo {
// Contains both copies of metadata.
fbl::Array<uint8_t> metadata;
size_t valid_metadata_offset;
const uint8_t* valid_metadata;
const uint8_t* invalid_metadata;
size_t block_size;
size_t block_count;
size_t device_size;
size_t slice_size;
struct Slice {
uint64_t virtual_partition;
uint64_t virtual_slice;
uint64_t physical_slice;
struct Partition {
bool Allocated() const { return entry != nullptr; }
const fvm::VPartitionEntry* entry = nullptr;
fbl::Vector<Slice> slices;
// Parses the FVM info from the device, and validate it (minimally).
bool LoadFVM(FvmInfo* out) const;
// Outputs and checks information about the FVM, optionally logging parsed information.
bool CheckFVM(const FvmInfo& info) const;
// Acquires a list of slices and partitions while parsing the FVM.
// Returns false if the FVM contains contradictory or invalid data.
bool LoadPartitions(const size_t slice_count, const fvm::SliceEntry* slice_table,
const fvm::VPartitionEntry* vpart_table, fbl::Vector<Slice>* out_slices,
fbl::Array<Partition>* out_partitions) const;
// Displays information about |slices|, assuming they are sorted in physical slice order.
void DumpSlices(const fbl::Vector<Slice>& slices) const;
// Confirms the Checker has received necessary arguments before beginning validation.
bool ValidateOptions() const;
fbl::unique_fd fd_;
uint32_t block_size_ = 512;
Logger logger_;
} // namespace fvm