| // 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 <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 { |
| public: |
| Checker(); |
| Checker(fbl::unique_fd fd, uint32_t block_size, bool silent); |
| ~Checker(); |
| |
| // 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; |
| |
| private: |
| class Logger { |
| public: |
| 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); |
| 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: |
| 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 |
| |
| #endif // SRC_STORAGE_FVM_FVM_CHECK_H_ |