/*
* File: DataSource.h
*
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
*
* Freescale Semiconductor, Inc.
* Proprietary & Confidential
*
* This source code and the algorithms implemented therein constitute
* confidential information and may comprise trade secrets of Freescale Semiconductor, Inc.
* or its associates, and any use thereof is subject to the terms and
* conditions of the Confidential Disclosure Agreement pursual to which this
* source code was originally received.
*/
#if !defined(_IVTDataSource_h_)
#define _IVTDataSource_h_
#include "DataSource.h"
/** Header field components
* @ingroup hdr
*/
typedef struct hab_hdr {
uint8_t tag; /**< Tag field */
uint8_t len[2]; /**< Length field in bytes (big-endian) */
uint8_t par; /**< Parameters field */
} hab_hdr_t;
/** Image entry function prototype
* @ingroup rvt
*
* This typedef serves as the return type for hab_rvt.authenticate_image(). It
* specifies a void-void function pointer, but can be cast to another function
* pointer type if required.
*/
typedef void (*hab_image_entry_f)(void);
/** @ref ivt structure
* @ingroup ivt
*
* @par Format
*
* An @ref ivt consists of a @ref hdr followed by a list of addresses as
* described further below.
*
* @warning The @a entry address may not be NULL.
*
* @warning On an IC not configured as #HAB_CFG_CLOSED, the
* @a csf address may be NULL. If it is not NULL, the @ref csf will be
* processed, but any failures should be non-fatal.
*
* @warning On an IC configured as #HAB_CFG_CLOSED, the @a
* csf address may not be NULL, and @ref csf failures are typically fatal.
*
* @remark The Boot Data located using the @a boot_data field is interpreted
* by the HAB caller in a boot-mode specific manner. This may be used by the
* boot ROM as to determine the load address and boot device configuration for
* images loaded from block devices (see @ref ref_rug for details).
*
* @remark All addresses given in the IVT, including the Boot Data (if
* present) are those for the final load location.
*
* @anchor ila
*
* @par Initial load addresses
*
* The @a self field is used to calculate addresses in boot modes where an
* initial portion of the image is loaded to an initial location. In such
* cases, the IVT, Boot Data (if present) and DCD (if present) are used in
* configuring the IC and loading the full image to its final location. Only
* the IVT, Boot Data (if present) and DCD (if present) are required to be
* within the initial image portion.
*
* The method for calculating an initial load address for the DCD is
* illustrated in the following C fragment. Similar calculations apply to
* other fields.
*
@verbatim
hab_ivt_t* ivt_initial = <initial IVT load address>;
const void* dcd_initial = ivt_initial->dcd;
if (ivt_initial->dcd != NULL)
dcd_initial = (const uint8_t*)ivt_initial
+ (ivt_initial->dcd - ivt_initial->self)
@endverbatim
* \note The void* types in this structure have been changed to uint32_t so
* that this code will work correctly when compiled on a 64-bit host.
* Otherwise the structure would come out incorrect.
*/
struct hab_ivt {
/** @ref hdr with tag #HAB_TAG_IVT, length and HAB version fields
* (see @ref data)
*/
hab_hdr_t hdr;
/** Absolute address of the first instruction to execute from the
* image
*/
/*hab_image_entry_f*/ uint32_t entry;
/** Reserved in this version of HAB: should be NULL. */
/*const void*/ uint32_t reserved1;
/** Absolute address of the image DCD: may be NULL. */
/*const void*/ uint32_t dcd;
/** Absolute address of the Boot Data: may be NULL, but not interpreted
* any further by HAB
*/
/*const void*/ uint32_t boot_data;
/** Absolute address of the IVT.*/
/*const void*/ uint32_t self;
/** Absolute address of the image CSF.*/
/*const void*/ uint32_t csf;
/** Reserved in this version of HAB: should be zero. */
uint32_t reserved2;
};
/** @name HAB version */
/*@{*/
#define HAB_MAJOR_VERSION 4 /**< Major version of this HAB release */
#define HAB_MINOR_VERSION 0 /**< Minor version of this HAB release */
#define HAB_VER_MAJ_WIDTH 4 /**< Major version field width */
#define HAB_VER_MAJ_SHIFT 4 /**< Major version field offset */
#define HAB_VER_MIN_WIDTH 4 /**< Minor version field width */
#define HAB_VER_MIN_SHIFT 0 /**< Minor version field offset */
/** Full version of this HAB release @hideinitializer */
#define HAB_VERSION HAB_VER(HAB_MAJOR_VERSION, HAB_MINOR_VERSION)
/** Base version for this HAB release @hideinitializer */
#define HAB_BASE_VERSION HAB_VER(HAB_MAJOR_VERSION, 0)
/*@}*/
namespace elftosb {
/*!
* \brief Data source for an IVT structure used by HAB4.
*
* This data source represents an IVT structure used by HAB4. Fields of the IVT can be set
* by name, making it easy to interface with a parser. And it has some intelligence regarding
* the IVT's self pointer. Before the data is copied out by the getData() method, the self field
* will be filled in automatically if it has not already been set and there is an associated
* data target object. This lets the IVT pick up its own address from the location where it is
* being loaded. Alternatively, if the self pointer is filled in explicitly, then the data
* source will have a natural location equal to the self pointer.
*
* This data source acts as its own segment.
*/
class IVTDataSource : public DataSource, public DataSource::Segment
{
public:
//! \brief Default constructor.
IVTDataSource();
//! \brief There is only one segment.
virtual unsigned getSegmentCount() { return 1; }
//! \brief Returns this object, as it is its own segment.
virtual DataSource::Segment * getSegmentAt(unsigned index) { return this; }
//! \name Segment methods
//@{
//! \brief Copy out some or all of the IVT structure.
//!
virtual unsigned getData(unsigned offset, unsigned maxBytes, uint8_t * buffer);
//! \brief Gets the length of the segment's data.
virtual unsigned getLength();
//! \brief Returns whether the segment has an associated address.
virtual bool hasNaturalLocation();
//! \brief Returns the address associated with the segment.
virtual uint32_t getBaseAddress();
//@}
//! \name IVT access
//@{
//! \brief Set one of the IVT's fields by providing its name.
//!
//! Acceptable field names are:
//! - entry
//! - dcd
//! - boot_data
//! - self
//! - csf
//!
//! As long as the \a name parameter specifies one of these fields, the return value
//! will be true. If \a name contains any other value, then false will be returned and
//! the IVT left unmodified.
//!
//! Once the \a self field has been set to any value, the data source will have a
//! natural location. This works even if the \a self address is 0.
//!
//! \param name The name of the field to set. Field names are case sensitive, just like in
//! the C language.
//! \param value The value to which the field will be set.
//! \retval true The field was set successfully.
//! \retval false There is no field with the provided name.
bool setFieldByName(const std::string & name, uint32_t value);
//! \brief Returns a reference to the IVT structure.
hab_ivt_t & getIVT() { return m_ivt; }
//@}
protected:
hab_ivt_t m_ivt; //!< The IVT structure.
bool m_isSelfSet; //!< True if the IVT self pointer was explicitly set.
};