blob: 8025e50f6d2e3028ba0b7b767cb84f5d8d87ebf5 [file] [log] [blame]
// Copyright 2020 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_FIRMWARE_LIB_ZIRCON_BOOT_INCLUDE_LIB_ZIRCON_BOOT_ZIRCON_BOOT_H_
#define SRC_FIRMWARE_LIB_ZIRCON_BOOT_INCLUDE_LIB_ZIRCON_BOOT_ZIRCON_BOOT_H_
// Standard library may not be available for all platforms. If that's the case,
// device should provide their own header that implements the equivalents.
//
// The library uses ABR library in this sdk, where there is also a switch to
// decide whether to use standard library. It should be adjusted accordingly as well.
#ifdef ZIRCON_BOOT_CUSTOM_SYSDEPS_HEADER
#include <zircon_boot_sysdeps.h>
#else
#include <stddef.h>
#endif
// This should point to the abr.h in the abr library in firmware sdk.
#include <lib/abr/abr.h>
// This should point to the zbi.h in the zbi library in firmware sdk.
#include <lib/zbi/zbi.h>
#include <lib/zircon_boot/zbi_utils.h>
#include <libavb_atx/libavb_atx.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum ZirconBootResult {
kBootResultOK = 0,
kBootResultErrorMarkUnbootable,
kBootResultErrorReadHeader,
kBootResultErrorZbiHeaderNotFound,
kBootResultErrorReadImage,
kBootResultErrorSlotFail,
kBootResultErrorNoValidSlot,
kBootResultErrorGetFirmwareSlot,
kBootResultErrorMismatchedFirmwareSlot,
kBootResultRebootReturn,
kBootResultBootReturn,
kBootResultErrorInvalidSlotIdx,
kBootResultErrorImageTooLarge,
kBootResultErrorAppendZbiItems,
kBootResultErrorSlotVerification,
} ZirconBootResult;
struct ZirconBootOps;
typedef struct ZirconBootOps ZirconBootOps;
// Firmware specific operations required to use the library.
struct ZirconBootOps {
// Device-specific data.
void* context;
// Reads from a partition.
//
// @ops: Pointer to the host |ZirconBootOps|.
// @part: Name of the partition.
// @offset: Offset in the partition to read from.
// @size: Number of bytes to read.
// @dst: Output buffer.
// @read_size: Output pointer for storing the actual number of bytes read. The libary uses
// this value to verify the integrity of read data. It expects it to always equal the
// requested number of bytes.
//
// Returns true on success.
bool (*read_from_partition)(ZirconBootOps* ops, const char* part, size_t offset, size_t size,
void* dst, size_t* read_size);
// Writes data to partition.
//
// @ops: Pointer to the host |ZirconBootOps|.
// @part: Name of the partition.
// @offset: Offset in the partition to write to.
// @size: Number of bytes to write.
// @src: Payload buffer.
// @write_size: Output pointer for storing the actual number of bytes written. The library
// uses this value to verify the integrity of write data. It expects it to always equal the
// number of bytes requested to be written.
//
// Returns true on success.
bool (*write_to_partition)(ZirconBootOps* ops, const char* part, size_t offset, size_t size,
const void* src, size_t* write_size);
// Boots image in memory.
//
// @ops: Pointer to the host |ZirconBootOps|.
// @image: Pointer to the zircon kernel image in memory. It is expected to be a zbi
// container.
// @capacity: Capacity of the container.
// @slot: The A/B/R slot index of the image.
//
// The function is not expected to return if boot is successful.
void (*boot)(ZirconBootOps* ops, zbi_header_t* image, size_t capacity, AbrSlotIndex slot);
// Gets the A/B/R slot of the currrently running firmware. The method needs to be implemented
// to support firmware A/B/R logic. Specifically, device needs to find a way to store and pass
// this information from non-A/B/R bootloader, i.e. stashing in registers.
//
// LoadAndBoot() will check whether this pointer is NULL to decide whether to boot according to
// OS ABR or firmware ABR.
//
// @ops: Pointer to the host |ZirconBootOps|
// @out_slot: An output pointer for returning firmware slot
//
// Returns true on success.
bool (*get_firmware_slot)(ZirconBootOps* ops, AbrSlotIndex* out_slot);
// Reboots the device.
//
// @ops: Pointer to the host |ZirconBootOps|
// @force_recovery: Enable/Disable force recovery.
//
// The function is not expected to return if reboot is successful.
void (*reboot)(ZirconBootOps* ops, bool force_recovery);
// Adds device-specific ZBI items based on available boot information. The method is optional and
// may be set to NULL, in which case no zbi items will be appended to the boot image.
//
// @ops: Pointer to the host |ZirconBootOps|
// @image: The loaded kernel image as a ZBI container. Items should be appended to it.
// @capacity: Capacity of the ZBI container.
// @slot: A/B/R slot of the loaded image.
//
// Returns true on success.
bool (*add_zbi_items)(ZirconBootOps* ops, zbi_header_t* image, size_t capacity,
AbrSlotIndex slot);
// Following are operations required to perform zircon verified boot.
// Verified boot implemented in this library is based on libavb. The library use the following
// provided operations to interact with libavb for kernel verification.
// If any of the following function pointers is set to NULL, verified boot is bypassed.
// Gets the size of a partition with the name in |part|
// (NUL-terminated UTF-8 string). Returns the value in
// |out|.
//
// @ops: Pointer to the ZirconBootOps that host this ZirconVBootOps object.
// @part: Name of the partition.
// @out: Output pointer storing the result.
//
// Returns true on success.
bool (*verified_boot_get_partition_size)(ZirconBootOps* ops, const char* part, size_t* out);
// Gets the rollback index corresponding to the location given by
// |rollback_index_location|. The value is returned in
// |out_rollback_index|.
//
// @ops: Pointer to the ZirconBootOps that host this ZirconVBootOps object.
// @rollback_index_location: Location to write rollback index.
// @out_rollback_index: Output pointer for storing the index value.
//
// A device may have a limited amount of rollback index locations (say,
// one or four) so may error out if |rollback_index_location| exceeds
// this number.
//
// Returns true on success.
bool (*verified_boot_read_rollback_index)(ZirconBootOps* ops, size_t rollback_index_location,
uint64_t* out_rollback_index);
// Sets the rollback index corresponding to the location given by
// |rollback_index_location| to |rollback_index|.
//
// @ops: Pointer to the ZirconBootOps that host this ZirconVBootOps object.
// @rollback_index_location: Location to rollback index to write.
// @rollback_index: Value of the rollback index to write.
//
// A device may have a limited amount of rollback index locations (say,
// one or four) so may error out if |rollback_index_location| exceeds
// this number.
//
// Returns true on success.
bool (*verified_boot_write_rollback_index)(ZirconBootOps* ops, size_t rollback_index_location,
uint64_t rollback_index);
// Gets whether the device is locked. The value is returned in
// |out_is_locked| (true if locked, false otherwise).
//
// @ops: Pointer to the ZirconBootOps that host this ZirconVBootOps object.
// @out_is_locked: Output pointer for storing the status.
//
// Returns true on success.
bool (*verified_boot_read_is_device_locked)(ZirconBootOps* ops, bool* out_is_locked);
// Reads permanent |attributes| data. There are no restrictions on where this
// data is stored.
//
// @ops: Pointer to the ZirconBootOps that host this ZirconVBootOps object.
// @attribute: Output pointer for storing the permanent attribute.
//
// Returns true on success.
bool (*verified_boot_read_permanent_attributes)(ZirconBootOps* ops,
AvbAtxPermanentAttributes* attribute);
// Reads a |hash| of permanent attributes. This hash MUST be retrieved from a
// permanently read-only location (e.g. fuses) when a device is LOCKED.
//
// @ops: Pointer to the ZirconBootOps that host this ZirconVBootOps object.
// @hash: Output buffer that stores the hash values. The buffer must be able to hold
// |AVB_SHA256_DIGEST_SIZE| bytes.
//
// Returns true on success.
bool (*verified_boot_read_permanent_attributes_hash)(ZirconBootOps* ops, uint8_t* hash);
};
typedef enum ForceRecovery {
kForceRecoveryOn,
kForceRecoveryOff,
} ForceRecovery;
// Loads kernel image into memory and boots it. if ops.get_firmware_slot is set, the function
// boots according to firwmare ABR. Otherwise it boots according to OS ABR.
//
// @ops: Required operations.
// @load_address: Pointer to the target memory to load image.
// @load_address_size: Maximum size of the memory for loading the image.
// @force_recovery: Enable/Disable force recovery.
//
// The function is not expected to return if boot is successful.
ZirconBootResult LoadAndBoot(ZirconBootOps* ops, void* load_address, size_t load_address_size,
ForceRecovery force_recovery);
// Create operations for libabr from a ZirconBootOps.
AbrOps GetAbrOpsFromZirconBootOps(ZirconBootOps* ops);
// Returns the zircon partition name of a given slot.
const char* GetSlotPartitionName(AbrSlotIndex slot);
#ifdef __cplusplus
}
#endif
#endif // SRC_FIRMWARE_LIB_ZIRCON_BOOT_INCLUDE_LIB_ZIRCON_BOOT_ZIRCON_BOOT_H_