blob: 1a880a0263e69d40225c267776d103d5b2c18d42 [file] [log] [blame] [edit]
// Copyright 2021 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_LIB_PAVER_FLASHMAP_CLIENT_H_
#define SRC_STORAGE_LIB_PAVER_FLASHMAP_CLIENT_H_
#include <fidl/fuchsia.acpi.chromeos/cpp/wire.h>
#include <fidl/fuchsia.io/cpp/wire.h>
#include <fidl/fuchsia.nand.flashmap/cpp/wire.h>
#include <fidl/fuchsia.vboot/cpp/wire.h>
#include <lib/fzl/vmo-mapper.h>
#include <fbl/unique_fd.h>
#include "src/storage/lib/paver/partition-client.h"
#include "third_party/vboot_reference/firmware/include/gbb_header.h"
namespace paver {
struct FlashmapArea {
std::string name;
uint32_t offset;
uint32_t size;
bool preserve;
explicit FlashmapArea(fuchsia_nand_flashmap::wire::Area other)
: name(other.name.data(), other.name.size()),
offset(other.offset),
size(other.size),
preserve(other.flags & fuchsia_nand_flashmap::wire::AreaFlags::kPreserve) {}
};
// Partition client that reads and writes flashmap-formatted images.
// Note that we don't support substantially changing the flash layout, because the current
// implementation assumes that the new image has the same layout as the installed image.
class FlashmapPartitionClient : public PartitionClient {
public:
// Public for the benefit of std::make_unique. You probably want |FlashmapClient::Create|.
explicit FlashmapPartitionClient(fidl::ClientEnd<fuchsia_nand_flashmap::Flashmap> flashmap,
fidl::ClientEnd<fuchsia_acpi_chromeos::Device> cros_acpi,
fidl::ClientEnd<fuchsia_vboot::FirmwareParam> fwparam)
: flashmap_(std::move(flashmap)),
cros_acpi_(std::move(cros_acpi)),
fwparam_(std::move(fwparam)) {}
static zx::status<std::unique_ptr<FlashmapPartitionClient>> Create(
const fbl::unique_fd& devfs_root, fidl::UnownedClientEnd<fuchsia_io::Directory> svc_root,
zx::duration timeout);
// Helper for creating partition client in tests.
static zx::status<std::unique_ptr<FlashmapPartitionClient>> CreateWithClients(
fidl::ClientEnd<fuchsia_nand_flashmap::Flashmap> flashmap,
fidl::ClientEnd<fuchsia_acpi_chromeos::Device> cros_acpi,
fidl::ClientEnd<fuchsia_vboot::FirmwareParam> fwparam);
zx::status<size_t> GetBlockSize() final { return zx::ok(erase_block_size_); }
zx::status<size_t> GetPartitionSize() final;
zx::status<> Read(const zx::vmo& vmo, size_t size) final;
zx::status<> Write(const zx::vmo& vmo, size_t vmo_size) final;
zx::status<> Trim() final { return zx::ok(); }
zx::status<> Flush() final { return zx::ok(); }
fbl::unique_fd block_fd() final { return fbl::unique_fd(); }
private:
// Initialisation of state that might fail (i.e. getting area list and erase block size over
// FIDL).
zx::status<> Init();
// Do a full update, overwriting RW and RO flash sections, except areas marked as PRESERVE. Also
// preserve the HWID and GBB flags.
zx::status<> FullUpdate(fzl::VmoMapper& new_image);
// Do an A/B update, updating the inactive RW section only.
zx::status<> ABUpdate(fzl::VmoMapper& new_image);
// Compare the public keys stored in the GBB with the current GBB to determine if the new firmware
// image needs a full update.
bool NeedsFullUpdate(GoogleBinaryBlockHeader* cur_gbb, GoogleBinaryBlockHeader* new_gbb);
// Returns true if the RO section of flash is writable.
zx::status<bool> CanWriteRO();
std::optional<FlashmapArea> FindArea(const char* name);
// Returns true if the given region differs between |new_image| and |flashmap_|.
zx::status<bool> NeedsUpdate(const fzl::VmoMapper& new_image, const FlashmapArea& region);
// Returns true if the two GBBs have compatible HWIDs.
// Note that we never overwrite HWID, but we use the first word ("ATLAS", "EVE", etc.) to
// make sure that the firmware we're going to try installing is correct.
bool IsHWIDCompatible(const GoogleBinaryBlockHeader* cur_gbb,
const GoogleBinaryBlockHeader* new_gbb);
fidl::WireSyncClient<fuchsia_nand_flashmap::Flashmap> flashmap_;
fidl::WireSyncClient<fuchsia_acpi_chromeos::Device> cros_acpi_;
fidl::WireSyncClient<fuchsia_vboot::FirmwareParam> fwparam_;
std::vector<FlashmapArea> areas_;
uint32_t erase_block_size_ = 0;
};
} // namespace paver
#endif // SRC_STORAGE_LIB_PAVER_FLASHMAP_CLIENT_H_