blob: 49224a9059c0f3a4d82bf96f61b00c9cfdf4e717 [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.
#ifndef SRC_STORAGE_FVM_FVM_CHECK_H_
#define SRC_STORAGE_FVM_FVM_CHECK_H_
#include <fidl/fuchsia.hardware.block/cpp/wire.h>
#include <fidl/fuchsia.io/cpp/wire.h>
#include <stdarg.h>
#include <stdlib.h>
#include <utility>
#include <fbl/array.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 {
public:
Checker(fidl::UnownedClientEnd<fuchsia_hardware_block::Block> block, uint32_t block_size,
bool silent);
Checker(fidl::UnownedClientEnd<fuchsia_io::File> file, uint32_t block_size, bool silent);
// Read from and validate the provided device, logging information if requested.
bool Validate() const;
private:
class Logger {
public:
explicit Logger(bool silent) : silent_(silent) {}
// Prints the format string and arguments to stderr.
static void Error(const char* format, ...) {
va_list arg;
va_start(arg, format);
vprintf(format, arg);
va_end(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);
va_end(arg);
}
}
private:
const bool silent_;
};
class Interface {
public:
virtual ~Interface() = default;
virtual zx::result<size_t> Size() const = 0;
virtual zx::result<size_t> Read(void* buf, size_t count) const = 0;
};
Checker(std::unique_ptr<Interface> interface, uint32_t block_size, bool silent);
class Block : public Interface {
public:
explicit Block(fidl::UnownedClientEnd<fuchsia_hardware_block::Block> block);
~Block() override;
private:
zx::result<size_t> Size() const override;
zx::result<size_t> Read(void* buf, size_t count) const override;
const fidl::UnownedClientEnd<fuchsia_hardware_block::Block> block_;
};
class File : public Interface {
public:
explicit File(fidl::UnownedClientEnd<fuchsia_io::File> file);
~File() override;
private:
zx::result<size_t> Size() const override;
zx::result<size_t> Read(void* buf, size_t count) const override;
const fidl::UnownedClientEnd<fuchsia_io::File> file_;
};
// 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(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;
const std::unique_ptr<Interface> interface_;
const uint32_t block_size_;
const Logger logger_;
};
} // namespace fvm
#endif // SRC_STORAGE_FVM_FVM_CHECK_H_