blob: 67cfb5a103711dc00686b8b8bcd2c103dac3752a [file] [log] [blame]
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include "google3/cr51_image_descriptor.h"
#include "google3/host_commands.h"
#include "host_command.hpp"
#include "message_util.hpp"
#include "payload_update_interface.hpp"
#include "sys.hpp"
#include <stdplus/handle/managed.hpp>
#include <optional>
#include <span>
#include <string>
#include <vector>
namespace google
{
namespace hoth
{
namespace internal
{
// Struct used to send activate request:
struct ActivateRequest
{
payload_update_packet header;
payload_update_activate activate;
};
// Struct used to send confirm request:
struct ConfirmRequest
{
payload_update_packet header;
payload_update_confirm confirm;
};
// Maximum allowed payload size
constexpr size_t max_packet_size =
mailbox_size - sizeof(payload_update_packet) - sizeof(ReqHeader);
constexpr size_t kImageDescriptorAlignment = 64 * 1024;
constexpr uint64_t kDescriptorMagic = 0x5f435344474d495f; // "_IMGDSC_"
constexpr uint32_t kSectorSizeBytes = 4096;
constexpr uint32_t kEraseChunkSizeBytes = kSectorSizeBytes * 32;
/** @class PayloadUpdateImpl
* @brief PayloadUpdate method implementation
* @details Methods to interface with Hoth to perform payload update
*/
class PayloadUpdateImpl : public PayloadUpdate
{
public:
explicit PayloadUpdateImpl(HostCommand* hostCmd,
const Sys* sys = &sys_impl) :
hostCmd(hostCmd), sys(sys)
{}
void initiate() const override;
void erase(uint32_t offset, uint32_t size) const override;
void eraseAndSendStaticWP(const std::string& path) const override;
void read(uint32_t offset, std::span<uint8_t> data) const override;
void verify() const override;
payload_update_status getStatus() const override;
void activate(Side side, Persistence persistence) const override;
void send(const std::string& imagePath) const override;
std::optional<payload_update_confirm_response>
confirm(enum payload_update_confirm_option option, uint32_t timeout,
uint64_t confirmation_cookie) const override;
bool findDescriptor(const std::string& path, uint32_t* desc_offset) const override;
void eraseAndSendStaticWPRegions(const std::string& path,
uint32_t desc_offset) const override;
// Arbitrarily picked due to the performance of the calls taking ~0.4s
static constexpr size_t verify_size = 512 * 1024;
private:
void sendCommand(uint8_t command, uint32_t offset = 0,
uint32_t len = 0) const;
void sendCommand(std::span<const uint8_t> request) const;
[[nodiscard]] std::span<const uint8_t>
sendCommand(std::vector<uint8_t>& buf, uint8_t command,
uint32_t offset = 0, uint32_t len = 0) const;
[[nodiscard]] std::span<const uint8_t>
sendCommand(std::vector<uint8_t>& buf,
std::span<const uint8_t> request) const;
void trimAndSend(std::span<const uint8_t> data,
uint32_t globalOffset) const;
/** @brief RAII wrapper and its destructor for opening a file descriptor */
static void closeFd(int&& fd, const Sys*& sys)
{
if (sys)
{
sys->close(fd);
}
}
using Fd = stdplus::Managed<int, const Sys*>::Handle<closeFd>;
/** @brief Connection to Hoth for sending and receiving host commands */
HostCommand* hostCmd = nullptr;
const Sys* sys = nullptr;
};
} // namespace internal
} // namespace hoth
} // namespace google