blob: 0a155b985d284423949c8c39f7e0babf16c7738d [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 "ec_util.hpp"
#include "firmware_updater_interface.hpp"
#include "host_command_interface.hpp"
#include "mtd_util_interface.hpp"
#include "payload_update_interface.hpp"
#include "sys_interface.hpp"
#include <sdbusplus/bus.hpp>
#include <xyz/openbmc_project/Control/Hoth/server.hpp>
#include <future>
namespace google
{
namespace hoth
{
template <typename... T>
using ServerObject = typename sdbusplus::server::object::object<T...>;
using HothInterface = sdbusplus::xyz::openbmc_project::Control::server::Hoth;
using HothObject = ServerObject<HothInterface>;
/** @class Hoth
* @brief Hoth control interface implementation.
* @details A concrete implementation for xyz.openbmc_project.Control.Hoth
* DBus API.
*/
class Hoth : public HothObject
{
public:
/** @brief Constructs Hoth Control Interface
*
* @param[in] bus - The Dbus bus object
* @param[in] objPath - The Dbus object path
* @param[in] hostCmd - Reference to the host command interface
* @param[in] payloadUpdate - Reference to the payload update interface
* @param[in] ecutil - Reference to the ec utility interface
* @param[in] mtd - Reference to the MTD utility interface
* @param[in] sys - Reference to the Sys call interface
* @param[in] firmwareUpdater - Reference to the firmware updater interface
*/
Hoth(sdbusplus::bus::bus& bus, const char* objPath,
internal::HostCommand* hostCmd, internal::PayloadUpdate* payloadUpdate,
internal::EcUtil* ecutil, internal::FirmwareUpdater* firmwareUpdater) :
HothObject(bus, objPath),
hostCmd(hostCmd), payloadUpdate(payloadUpdate), ecUtil(ecutil),
firmwareUpdater(firmwareUpdater),
lastFirmwareUpdateStatus(FirmwareUpdateStatus::None),
lastInitiatePayloadStatus(FirmwareUpdateStatus::None),
lastSendPayloadStatus(FirmwareUpdateStatus::None),
lastVerifyPayloadStatus(FirmwareUpdateStatus::None)
{
// Nothing to do
}
/** @brief Implementation for SendHostCommand
* Send a host command to Hoth if it isn't banned and return the
* response. This will block on Hoth completing its internal operations.
* This method should be called from the IPMI HostCommand passthrough.
*
* @param[in] command - Data to write to Hoth SPI host command offset.
*
* @return response[std::vector<uint8_t>] - Data read from Hoth SPI host
* command offset.
*/
std::vector<uint8_t> sendHostCommand(std::vector<uint8_t> command) override;
/** @brief Implementation for SendTrustedHostCommand
* Send a host command to Hoth and return the response. This will block on
* Hoth completing its internal operations. This method should be called
* from the BMC.
*
* @param[in] command - Data to write to Hoth SPI host command offset.
*
* @return response[std::vector<uint8_t>] - Data read from Hoth SPI host
* command offset.
*/
std::vector<uint8_t>
sendTrustedHostCommand(std::vector<uint8_t> command) override;
/** @brief Implementation for SendHostCommandAsync
* Send a host command to Hoth and immediately return without waiting for
* response. Caller can either poll with calls to GetHostCommandResponse
* until retrieving the response, or wait for a ResponseReady signal.
*
* @param[in] command - Data to write to Hoth SPI host command offset.
*
* @return callToken[uint64_t] - The representation for the call made, if
* it was posted
*/
uint64_t sendHostCommandAsync(std::vector<uint8_t> command) override;
/** @brief Implementation for GetHostCommandResponse
* Read the response from Hoth mailbox.
*
* @param[in] callToken - The token returned from SendHostCommandAsync()
*
* @return response[std::vector<uint8_t>] - Data read from Hoth SPI host
* command offset.
*/
std::vector<uint8_t> getHostCommandResponse(uint64_t callToken) override;
/** @brief Implementation for UpdateFirmware
* Write given firmware data to the Hoth firmware partition in EEPROM.
*
* @param[in] firmwareData - Hoth firmware image.
*/
void updateFirmware(std::vector<uint8_t> firmwareData) override;
/** @brief Implementation for SpiWrite
* Write the byte data to the specified address in EEPROM.
*
* @param[in] address - Address to start writing from
* @param[in] data - Data to be written
*/
void spiWrite(uint32_t address, std::vector<uint8_t> data) override;
/** @brief Implementation for GetFirmwareUpdateStatus
* Get the status of the firmware update process.
*
* @return status[FirmwareUpdateStatus] - Status of the firmware update
*/
FirmwareUpdateStatus getFirmwareUpdateStatus() override;
/** @brief Implementation for InitiatePayload
* Initiates erasure of the EEPROM staging area. Note that this will lock
* up access to Hoth for an extended time and may go over the kernel's SPI
* write timeout. Calling multiple small ErasePayload is recommended.
*/
void initiatePayload() override;
/** @brief Implementation for GetInitiatePayloadStatus
* Get the status of the payload initiation process.
*
* @return status[FirmwareUpdateStatus] - Status of the payload initiation
*/
FirmwareUpdateStatus getInitiatePayloadStatus() override;
/** @brief Implementation for SendPayload
* Chunk and send the binary specified in the image path
*
* @param[in] imagePath - Firmware image path
*/
void sendPayload(std::string imagePath) override;
/** @brief Implementation for GetSendPayloadStatus
* Get the status of the send payload process.
*
* @return status[FirmwareUpdateStatus] - Status of the send payload
* process.
*/
FirmwareUpdateStatus getSendPayloadStatus() override;
/** @brief Implementation for ErasePayload
* Erases the given size starting at the specified offset of the staging
* partition.
*
* @param[in] offset - Offset of the staging partition to start erasing
* from.
* @param[in] size - Size of the staging partition to erase.
*/
void erasePayload(uint32_t offset, uint32_t size) override;
/** @brief Implementation for eraseAndSendStaticWPPayload
* Erases and writes only the static and write protected regions of the
* image provided.
*
* @param[in] imagePath - Firmware image path
*/
void eraseAndSendStaticWPPayload(std::string imagePath) override;
/** @brief Implementation for VerifyPayload
* Initiates the verification process without activating the staging area.
*/
void verifyPayload() override;
/** @brief Implementation for GetInitiatePayloadStatus
* Get the status of the payload verification process.
*
* @return status[FirmwareUpdateStatus] - Status of the payload
* verification
*/
FirmwareUpdateStatus getVerifyPayloadStatus() override;
/** @brief Implementation for ActivatePayload
* Activates the staging area as persistent or non-persistent for next boot
* if verification was successful.
*
* @param[in] makePersistent - Flag to determine whether to activate the
* staged image as persistent or non-persistent for next boot.
*/
void activatePayload(bool makePersistent) override;
/** @brief Implementation for DeactivatePayload
* Deactivates the staging area
*
*/
void deactivatePayload() override;
/** @brief Implementation for GetPayloadSize
*
* @return The size of the payload region
*/
uint32_t getPayloadSize() override;
/** @brief Implementation for Confirm
* Prevents hoth from rolling back and using the previous image. When an
* image can be comfirmed to be working well, this command is given, which
* disarms the hoth watchdog.
*/
void confirm() override;
/** @brief Implementation for GetTotalBootTime.
*
* @return Time spent in microseconds from reset to HVNGOOD.
*/
uint32_t getTotalBootTime() override;
/** @brief Implementation for GetFirmwareUpdateTime.
*
* @return Time spent in microseconds in the self update routine.
*/
uint32_t getFirmwareUpdateTime() override;
/** @brief Implementation for GetFirmwareMirroringTime.
*
* @return Time spent in microseconds in mirroing the self-update.
*/
uint32_t getFirmwareMirroringTime() override;
/** @brief Implementation for GetPayloadValidationTime.
*
* @return Time spent in microseconds in validating the payload.
*/
uint32_t getPayloadValidationTime() override;
/**
* @brief Implementation for CollectHothLogs
*
*/
void collectHothLogs() override;
/**
* @brief Trigger Uart log scheduler if not already working over Dbus
*/
void collectUartLogs() override;
/**
* @brief Manual Stop to Uart log scheduler over Dbus
*/
void stopUartLogs() override;
private:
/** @brief Connection to Hoth for sending and receiving host commands */
internal::HostCommand* hostCmd = nullptr;
/** @brief Payload object to conduct payload update with Hoth */
internal::PayloadUpdate* payloadUpdate = nullptr;
/** @brief EC utility object to access the utility function from Hoth */
internal::EcUtil* ecUtil = nullptr;
/** @brief FirmwareUpdater object */
internal::FirmwareUpdater* firmwareUpdater = nullptr;
/** @brief Wrapper function to determine the status of an async thread
*
* @param[in] asyncFuture - Pointer to the async thread of interest
* @return status[FirmwareUpdateStatus] - Status of the async thread
*/
static FirmwareUpdateStatus getAsyncStatus(std::future<void>* asyncFuture);
/** @brief Check for any ongoing payload async threads
* If an ongoing payload async thread is found, throw an exception via elog
*/
void checkForOngoingPayload();
/** @brief Check for any ongoing SPI write threads
* If an SPI write async thread is found, throw an exception via elog
*/
void checkForOngoingSpiWrite();
/** @brief Future object for initiate paylaod */
std::future<void> futInitiatePayload;
/** @brief Future object for send payload */
std::future<void> futSendPayload;
/** @brief Future object for verify payload */
std::future<void> futVerifyPayload;
/** @brief Future object for SPI write */
std::future<void> futSpiWrite;
/** @brief Last FirmwareUpdateStatus checked for firmware update */
FirmwareUpdateStatus lastFirmwareUpdateStatus;
/** @brief Last FirmwareUpdateStatus checked for initiate payload */
FirmwareUpdateStatus lastInitiatePayloadStatus;
/** @brief Last FirmwareUpdateStatus checked for send payload */
FirmwareUpdateStatus lastSendPayloadStatus;
/** @brief Last FirmwareUpdateStatus checked for verify payload */
FirmwareUpdateStatus lastVerifyPayloadStatus;
};
} // namespace hoth
} // namespace google