Add KBOOT.
This commit is contained in:
77
src/autobaud/autobaud.h
Normal file
77
src/autobaud/autobaud.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _autobaud_h
|
||||
#define _autobaud_h
|
||||
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader_config.h"
|
||||
|
||||
//! @addtogroup autobaud
|
||||
//! @{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// API
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//! @name Autobaud
|
||||
//@{
|
||||
|
||||
//! @brief If completed sets the rate after calculation as 9600, 19200, etc.
|
||||
// If not yet completed returns failure
|
||||
//!
|
||||
//! @retval #kStatus_Success The baud rate has been calculated successfully.
|
||||
//! @retval #kStatus_Fail Not enough edges have been received yet to determine the baud rate.
|
||||
status_t autobaud_get_rate(uint32_t instance, uint32_t *rate);
|
||||
|
||||
//! @brief Initializes autobaud detection
|
||||
void autobaud_init(uint32_t instance);
|
||||
|
||||
#if BL_FEATURE_UART_AUTOBAUD_IRQ
|
||||
//! @brief De-initializes autobaud detection
|
||||
void autobaud_deinit(uint32_t instance);
|
||||
#endif
|
||||
|
||||
//@}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // _autobaud_h
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
170
src/autobaud/src/autobaud_irq.c
Normal file
170
src/autobaud/src/autobaud_irq.c
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "fsl_device_registers.h"
|
||||
#include "autobaud/autobaud.h"
|
||||
#include "microseconds/microseconds.h"
|
||||
#include "bootloader_common.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Definitions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
enum _autobaud_counts
|
||||
{
|
||||
//! the number of falling edge transitions being counted
|
||||
//! for 0x5A
|
||||
kFirstByteRequiredFallingEdges = 4,
|
||||
//! the number of falling edge transitions being counted
|
||||
//! for 0xA6
|
||||
kSecondByteRequiredFallingEdges = 3,
|
||||
//! the number of bits being measured for the baud rate
|
||||
//! for 0x5A we have the start bit + 7 bits to the last falling edge = 8 bits
|
||||
kNumberOfBitsForFirstByteMeasured = 8,
|
||||
//! for 0xA6 we have the start bit + 6 bits to the last falling edge = 7 bits
|
||||
kNumberOfBitsForSecondByteMeasured = 7,
|
||||
//! Time in microseconds that we will wait in between toggles before restarting detection
|
||||
//! Make this value 8 bits at 100 baud worth of time = 80000 microseconds
|
||||
kMaximumTimeBetweenFallingEdges = 80000,
|
||||
//! Autobaud baud step size that our calculation will be rounded to, this is to ensure
|
||||
//! that we can use a valid multiplier in the UART configuration which runs into problems
|
||||
//! at higher baud rates with slightly off baud rates (e.g. if we measure 115458 vs 115200)
|
||||
//! a calculation of UartClock at 48MHz gives an SBR calculation of 48000000/ (16 * 115458) = 25
|
||||
//! giving a baud rate calculation of 48000000/(16 * 25) = 120000 baud
|
||||
//! which is out of spec and fails
|
||||
kAutobaudStepSize = 1200
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Prototypes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void instance_transition_callback(uint32_t instance);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Variables
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static uint32_t s_transitionCount;
|
||||
static uint64_t s_firstByteTotalTicks;
|
||||
static uint64_t s_secondByteTotalTicks;
|
||||
static uint64_t s_lastToggleTicks;
|
||||
static uint64_t s_ticksBetweenFailure;
|
||||
static uint32_t s_instanceMeasured;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Code
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void autobaud_init(uint32_t instance)
|
||||
{
|
||||
s_transitionCount = 0;
|
||||
s_firstByteTotalTicks = 0;
|
||||
s_secondByteTotalTicks = 0;
|
||||
s_lastToggleTicks = 0;
|
||||
s_instanceMeasured = 0;
|
||||
s_ticksBetweenFailure = microseconds_convert_to_ticks(kMaximumTimeBetweenFallingEdges);
|
||||
enable_autobaud_pin_irq(instance, instance_transition_callback);
|
||||
}
|
||||
|
||||
void autobaud_deinit(uint32_t instance)
|
||||
{
|
||||
disable_autobaud_pin_irq(instance);
|
||||
}
|
||||
|
||||
status_t autobaud_get_rate(uint32_t instance, uint32_t *rate)
|
||||
{
|
||||
if ((s_transitionCount == (kFirstByteRequiredFallingEdges + kSecondByteRequiredFallingEdges)) &&
|
||||
(instance == s_instanceMeasured))
|
||||
{
|
||||
uint32_t calculatedBaud =
|
||||
(microseconds_get_clock() * (kNumberOfBitsForFirstByteMeasured + kNumberOfBitsForSecondByteMeasured)) /
|
||||
(uint32_t)(s_firstByteTotalTicks + s_secondByteTotalTicks);
|
||||
|
||||
// Round the rate to the nearest step size
|
||||
// rounded = stepSize * (value/stepSize + .5)
|
||||
// multiplying by 10 since we can't work with floats
|
||||
*rate = ((((calculatedBaud * 10) / kAutobaudStepSize) + 5) / 10) * kAutobaudStepSize;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
// no baud rate yet/inactive
|
||||
return kStatus_Fail;
|
||||
}
|
||||
}
|
||||
|
||||
void instance_transition_callback(uint32_t instance)
|
||||
{
|
||||
uint64_t ticks = microseconds_get_ticks();
|
||||
s_transitionCount++;
|
||||
|
||||
uint64_t delta = ticks - s_lastToggleTicks;
|
||||
|
||||
// The last toggle was longer than we allow so treat this as the first one
|
||||
if (delta > s_ticksBetweenFailure)
|
||||
{
|
||||
s_transitionCount = 1;
|
||||
}
|
||||
|
||||
switch (s_transitionCount)
|
||||
{
|
||||
case 1:
|
||||
// This is our first falling edge, store the initial ticks temporarily in firstByteTicks
|
||||
// and save the instance that we are measuring
|
||||
s_firstByteTotalTicks = ticks;
|
||||
s_instanceMeasured = instance;
|
||||
break;
|
||||
|
||||
case kFirstByteRequiredFallingEdges:
|
||||
// We reached the end of our measurable first byte, subtract the current ticks from the initial
|
||||
// first byte ticks
|
||||
s_firstByteTotalTicks = ticks - s_firstByteTotalTicks;
|
||||
break;
|
||||
|
||||
case (kFirstByteRequiredFallingEdges + 1):
|
||||
// We hit our first falling edge of the second byte, store the initial ticks temporarily in secondByteTicks
|
||||
s_secondByteTotalTicks = ticks;
|
||||
break;
|
||||
|
||||
case (kFirstByteRequiredFallingEdges + kSecondByteRequiredFallingEdges):
|
||||
// We reached the end of our measurable second byte, subtract the current ticks from the initial
|
||||
// second byte ticks
|
||||
s_secondByteTotalTicks = ticks - s_secondByteTotalTicks;
|
||||
disable_autobaud_pin_irq(instance);
|
||||
break;
|
||||
}
|
||||
|
||||
s_lastToggleTicks = ticks;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
147
src/blfwk/AESCounter.h
Normal file
147
src/blfwk/AESCounter.h
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* File: AESCounter.h
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
|
||||
* See included license file for license details.
|
||||
*/
|
||||
#if !defined(_AESCounter_h_)
|
||||
#define _AESCounter_h_
|
||||
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include "Random.h"
|
||||
|
||||
//! An AES-128 counter is 128 bits, or 16 bytes.
|
||||
typedef uint8_t aes128_counter_t[16];
|
||||
|
||||
/*!
|
||||
* \brief Base class for AESCounter<S>.
|
||||
*
|
||||
* This class implements some bigger, non-template methods used in the
|
||||
* AESCounter<S> templated subclass.
|
||||
*/
|
||||
class AESCounterBase
|
||||
{
|
||||
public:
|
||||
//! \brief Reads hex encoded data from \a stream.
|
||||
void _readFromStream(std::istream &stream, unsigned bytes, uint8_t *buffer);
|
||||
|
||||
//! \brief Writes hex encoded data to \a stream.
|
||||
void _writeToStream(std::ostream &stream, unsigned bytes, const uint8_t *buffer) const;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Generic AES Counter class.
|
||||
*
|
||||
* The template parameter \a S is the number of bits in the counter.
|
||||
*
|
||||
* The underlying counter type can be accessed like this: AESCounter<128>::counter_t
|
||||
*
|
||||
* When a counter instance is destroyed, it erases the counter data by setting it
|
||||
* to all zeroes.
|
||||
*
|
||||
* \todo Add a way to allow only counter sizes of 128, 192, and 256 bits.
|
||||
* \todo Find a cross platform way to prevent the counter data from being written
|
||||
* to the VM swapfile.
|
||||
*
|
||||
* AESCounter<128> counter = AESCounter<128>::readFromStream(s);
|
||||
*/
|
||||
template <int S>
|
||||
class AESCounter : public AESCounterBase
|
||||
{
|
||||
public:
|
||||
//! Type for this size of AES counter.
|
||||
typedef uint8_t counter_t[S / 8];
|
||||
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
//!
|
||||
//! Initializes the counter to 0.
|
||||
AESCounter() { memset(m_counter, 0, sizeof(m_counter)); }
|
||||
//! \brief Constructor taking a counter value reference.
|
||||
AESCounter(const counter_t &counter) { memcpy(m_counter, &counter, sizeof(m_counter)); }
|
||||
// \brief Constructor taking a counter value pointer.
|
||||
AESCounter(const counter_t *counter) { memcpy(m_counter, counter, sizeof(m_counter)); }
|
||||
//! \brief Constructor, reads counter from stream in hex format.
|
||||
AESCounter(std::istream &stream) { readFromStream(stream); }
|
||||
//! \brief Copy constructor.
|
||||
AESCounter(const AESCounter<S> &other) { memcpy(m_counter, other.m_counter, sizeof(m_counter)); }
|
||||
//! \brief Destructor.
|
||||
//!
|
||||
//! Sets the counter value to zero.
|
||||
~AESCounter() { memset(m_counter, 0, sizeof(m_counter)); }
|
||||
//! \brief Set to the counter to a randomly generated value.
|
||||
void randomize()
|
||||
{
|
||||
RandomNumberGenerator rng;
|
||||
rng.generateBlock(m_counter, sizeof(m_counter));
|
||||
}
|
||||
|
||||
//! \brief Reads the counter from a hex encoded data stream.
|
||||
void readFromStream(std::istream &stream)
|
||||
{
|
||||
_readFromStream(stream, S / 8, reinterpret_cast<uint8_t *>(&m_counter));
|
||||
}
|
||||
|
||||
//! \brief Writes the counter to a data stream in hex encoded format.
|
||||
void writeToStream(std::ostream &stream) const
|
||||
{
|
||||
_writeToStream(stream, S / 8, reinterpret_cast<const uint8_t *>(&m_counter));
|
||||
}
|
||||
|
||||
//! \brief Increments the counter by val
|
||||
void incrementCounter(unsigned val)
|
||||
{
|
||||
for (unsigned j = 0; j < val; j++)
|
||||
{
|
||||
for (int i = sizeof(AESCounter<S>::counter_t) - 1, carry = 1; (i >= 0) && carry; i--)
|
||||
{
|
||||
carry = !++m_counter[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! \name Counter accessors
|
||||
//@{
|
||||
inline const counter_t &getCounter() const { return m_counter; }
|
||||
inline void getCounter(counter_t *counter) const { memcpy(counter, m_counter, sizeof(m_counter)); }
|
||||
inline void setCounter(const counter_t &counter) { memcpy(m_counter, &counter, sizeof(m_counter)); }
|
||||
inline void setCounter(const counter_t *counter) { memcpy(m_counter, counter, sizeof(m_counter)); }
|
||||
inline void setCounter(const AESCounter<S> &counter) { memcpy(m_counter, counter.m_counter, sizeof(m_counter)); }
|
||||
//@}
|
||||
|
||||
//! \name Operators
|
||||
//@{
|
||||
const AESCounter<S> &operator=(const AESCounter<S> &counter)
|
||||
{
|
||||
setCounter(counter);
|
||||
return *this;
|
||||
}
|
||||
const AESCounter<S> &operator=(const counter_t &counter)
|
||||
{
|
||||
setCounter(counter);
|
||||
return *this;
|
||||
}
|
||||
const AESCounter<S> &operator=(const counter_t *counter)
|
||||
{
|
||||
setCounter(counter);
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator const counter_t &() const { return m_counter; }
|
||||
operator const counter_t *() const { return m_counter; }
|
||||
friend std::ostream &operator<<(std::ostream &os, const AESCounter<S> &counter)
|
||||
{
|
||||
counter.writeToStream(os);
|
||||
return os;
|
||||
}
|
||||
//@}
|
||||
|
||||
protected:
|
||||
counter_t m_counter; //!< The counter value.
|
||||
};
|
||||
|
||||
//! Standard type definition for an AES-128 counter.
|
||||
typedef AESCounter<128> AES128Counter;
|
||||
|
||||
#endif // _AESCounter_h_
|
||||
132
src/blfwk/AESKey.h
Normal file
132
src/blfwk/AESKey.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* File: AESKey.h
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
|
||||
* See included license file for license details.
|
||||
*/
|
||||
#if !defined(_AESKey_h_)
|
||||
#define _AESKey_h_
|
||||
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include "Random.h"
|
||||
|
||||
//! An AES-128 key is 128 bits, or 16 bytes.
|
||||
typedef uint8_t aes128_key_t[16];
|
||||
|
||||
/*!
|
||||
* \brief Base class for AESKey<S>.
|
||||
*
|
||||
* This class implements some bigger, non-template methods used in the
|
||||
* AESKey<S> templated subclass.
|
||||
*/
|
||||
class AESKeyBase
|
||||
{
|
||||
public:
|
||||
//! \brief Reads hex encoded data from \a stream.
|
||||
void _readFromStream(std::istream &stream, unsigned bytes, uint8_t *buffer) const;
|
||||
|
||||
//! \brief Writes hex encoded data to \a stream.
|
||||
void _writeToStream(std::ostream &stream, unsigned bytes, const uint8_t *buffer) const;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Generic AES key class.
|
||||
*
|
||||
* The template parameter \a S is the number of bits in the key.
|
||||
*
|
||||
* The underlying key type can be accessed like this: AESKey<128>::key_t
|
||||
*
|
||||
* When a key instance is destroyed, it erases the key data by setting it
|
||||
* to all zeroes.
|
||||
*
|
||||
* \todo Add a way to allow only key sizes of 128, 192, and 256 bits.
|
||||
* \todo Find a cross platform way to prevent the key data from being written
|
||||
* to the VM swapfile.
|
||||
*
|
||||
* AESKey<128> key = AESKey<128>::readFromStream(s);
|
||||
*/
|
||||
template <int S>
|
||||
class AESKey : public AESKeyBase
|
||||
{
|
||||
public:
|
||||
//! Type for this size of AES key.
|
||||
typedef uint8_t key_t[S / 8];
|
||||
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
//!
|
||||
//! Initializes the key to 0.
|
||||
AESKey() { memset(m_key, 0, sizeof(m_key)); }
|
||||
//! \brief Constructor taking a key value reference.
|
||||
AESKey(const key_t &key) { memcpy(m_key, &key, sizeof(m_key)); }
|
||||
// \brief Constructor taking a key value pointer.
|
||||
AESKey(const key_t *key) { memcpy(m_key, key, sizeof(m_key)); }
|
||||
//! \brief Constructor, reads key from stream in hex format.
|
||||
AESKey(std::istream &stream) { readFromStream(stream); }
|
||||
//! \brief Copy constructor.
|
||||
AESKey(const AESKey<S> &other) { memcpy(m_key, other.m_key, sizeof(m_key)); }
|
||||
//! \brief Destructor.
|
||||
//!
|
||||
//! Sets the key value to zero.
|
||||
~AESKey() { memset(m_key, 0, sizeof(m_key)); }
|
||||
//! \brief Set to the key to a randomly generated value.
|
||||
void randomize()
|
||||
{
|
||||
RandomNumberGenerator rng;
|
||||
rng.generateBlock(m_key, sizeof(m_key));
|
||||
}
|
||||
|
||||
//! \brief Reads the key from a hex encoded data stream.
|
||||
void readFromStream(std::istream &stream) { _readFromStream(stream, S / 8, reinterpret_cast<uint8_t *>(&m_key)); }
|
||||
//! \brief Writes the key to a data stream in hex encoded format.
|
||||
void writeToStream(std::ostream &stream) const
|
||||
{
|
||||
_writeToStream(stream, S / 8, reinterpret_cast<const uint8_t *>(&m_key));
|
||||
}
|
||||
|
||||
//! \name Key accessors
|
||||
//@{
|
||||
inline const key_t &getKey() const { return m_key; }
|
||||
inline void getKey(key_t *key) const { memcpy(key, m_key, sizeof(m_key)); }
|
||||
inline void setKey(const key_t &key) { memcpy(m_key, &key, sizeof(m_key)); }
|
||||
inline void setKey(const key_t *key) { memcpy(m_key, key, sizeof(m_key)); }
|
||||
inline void setKey(const AESKey<S> &key) { memcpy(m_key, key.m_key, sizeof(m_key)); }
|
||||
//@}
|
||||
|
||||
//! \name Operators
|
||||
//@{
|
||||
const AESKey<S> &operator=(const AESKey<S> &key)
|
||||
{
|
||||
setKey(key);
|
||||
return *this;
|
||||
}
|
||||
const AESKey<S> &operator=(const key_t &key)
|
||||
{
|
||||
setKey(key);
|
||||
return *this;
|
||||
}
|
||||
const AESKey<S> &operator=(const key_t *key)
|
||||
{
|
||||
setKey(key);
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator const key_t &() const { return m_key; }
|
||||
operator const key_t *() const { return m_key; }
|
||||
friend std::ostream &operator<<(std::ostream &os, const AESKey<S> &key)
|
||||
{
|
||||
key.writeToStream(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
protected:
|
||||
key_t m_key; //!< The key value.
|
||||
};
|
||||
|
||||
//! Standard type definition for an AES-128 key.
|
||||
typedef AESKey<128> AES128Key;
|
||||
|
||||
#endif // _AESKey_h_
|
||||
34
src/blfwk/BlfwkErrors.h
Normal file
34
src/blfwk/BlfwkErrors.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* File: BlfwkErrors.h
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
|
||||
* See included license file for license details.
|
||||
*/
|
||||
#if !defined(_BlfwkErrors_h_)
|
||||
#define _BlfwkErrors_h_
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
//! @addtogroup host_error
|
||||
//! @{
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* \brief A semantic error discovered while processing the command file AST.
|
||||
*/
|
||||
class semantic_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
explicit semantic_error(const std::string &msg)
|
||||
: std::runtime_error(msg)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
}; // namespace blfwk
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // _BlfwkErrors_h_
|
||||
93
src/blfwk/Blob.h
Normal file
93
src/blfwk/Blob.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_Blob_h_)
|
||||
#define _Blob_h_
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
//! \class Blob
|
||||
//!
|
||||
//! \brief Manages a binary object of arbitrary length.
|
||||
//!
|
||||
//! The data block is allocated with malloc() instead of the new
|
||||
//! operator so that we can use realloc() to resize it.
|
||||
//!
|
||||
class Blob
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
Blob();
|
||||
|
||||
//! \brief Constructor.
|
||||
Blob(const uint8_t *data, unsigned length);
|
||||
|
||||
//! \brief Copy constructor.
|
||||
Blob(const Blob &other);
|
||||
|
||||
//! \brief Destructor.
|
||||
virtual ~Blob();
|
||||
|
||||
//! \name Operations
|
||||
//@{
|
||||
//! \brief Replaces the blob's data.
|
||||
void setData(const uint8_t *data, unsigned length);
|
||||
|
||||
//! \brief Change the size of the blob's data.
|
||||
void setLength(unsigned length);
|
||||
|
||||
//! \brief Adds data to the end of the blob.
|
||||
void append(const uint8_t *newData, unsigned newDataLength);
|
||||
|
||||
//! \brief Disposes of the data.
|
||||
void clear();
|
||||
|
||||
//! \brief Tell the blob that it no longer owns its data.
|
||||
void relinquish();
|
||||
//@}
|
||||
|
||||
//! \name Accessors
|
||||
//@{
|
||||
uint8_t *getData() { return m_data; }
|
||||
const uint8_t *getData() const { return m_data; }
|
||||
unsigned getLength() const { return m_length; }
|
||||
//@}
|
||||
|
||||
//! \name Operators
|
||||
//@{
|
||||
operator uint8_t *() { return m_data; }
|
||||
operator const uint8_t *() const { return m_data; }
|
||||
//@}
|
||||
|
||||
protected:
|
||||
uint8_t *m_data; //!< The binary data held by this object.
|
||||
unsigned m_length; //!< Number of bytes pointed to by #m_data.
|
||||
};
|
||||
|
||||
#endif // _Blob_h_
|
||||
113
src/blfwk/Bootloader.h
Normal file
113
src/blfwk/Bootloader.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _Bootloader_h_
|
||||
#define _Bootloader_h_
|
||||
|
||||
#include "Command.h"
|
||||
#include "Packetizer.h"
|
||||
#include "Peripheral.h"
|
||||
#include "Logging.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
//! @addtogroup blfwk
|
||||
//! @{
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* @brief Represents the host bootloader.
|
||||
*
|
||||
* This class provides a convenient way to access other bootloader
|
||||
* framework objects.
|
||||
*/
|
||||
class Bootloader
|
||||
{
|
||||
public:
|
||||
//! @brief Default Constructor for Simulator.
|
||||
Bootloader();
|
||||
|
||||
//! @brief Constructor.
|
||||
Bootloader(const Peripheral::PeripheralConfigData &config);
|
||||
|
||||
//! @brief Destructor.
|
||||
virtual ~Bootloader();
|
||||
|
||||
//! @brief Inject a command into the bootloader.
|
||||
//!
|
||||
//! @param cmd The command to send
|
||||
void inject(Command &cmd)
|
||||
{
|
||||
clock_t start = clock();
|
||||
cmd.sendTo(*m_hostPacketizer);
|
||||
clock_t finish = clock();
|
||||
Log::debug(" - took %2.3f seconds\n", (double)(finish - start) / CLOCKS_PER_SEC);
|
||||
}
|
||||
|
||||
//! @brief Flush state.
|
||||
void flush();
|
||||
|
||||
//! \brief Execute the execute command.
|
||||
void execute(uint32_t entry_point, uint32_t param = 0, uint32_t stack_pointer = 0);
|
||||
|
||||
//! \brief Execute the reset command.
|
||||
void reset();
|
||||
|
||||
//! \brief Execute the get-property(current-version) command.
|
||||
standard_version_t getVersion();
|
||||
|
||||
//! \brief Execute the get-property(flash-security-state) command.
|
||||
uint32_t getSecurityState();
|
||||
|
||||
//! \brief Send a ping if applicable.
|
||||
void ping(int retries, unsigned int delay, int comSpeed);
|
||||
|
||||
//! @name Accessors.
|
||||
//@{
|
||||
|
||||
//! @brief Get the host packetizer.
|
||||
Packetizer *getPacketizer() const { return m_hostPacketizer; }
|
||||
//@}
|
||||
|
||||
protected:
|
||||
Packetizer *m_hostPacketizer; //!< Packet interface to send commands on.
|
||||
FileLogger *m_logger; //!< Singleton logger instance.
|
||||
};
|
||||
|
||||
} // namespace blfwk
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // _Bootloader_h_
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
284
src/blfwk/BusPal.h
Normal file
284
src/blfwk/BusPal.h
Normal file
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _BusPal_h_
|
||||
#define _BusPal_h_
|
||||
|
||||
#include "host_types.h"
|
||||
|
||||
//! @addtogroup bus_pal
|
||||
//! @{
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* @brief Interface with the BusPal.
|
||||
*
|
||||
* For hardware documentation, see http://dangerousprototypes.com/docs/Bus_Pirate.
|
||||
* This class is based on the pyBusPirateLite python package, see
|
||||
* http://dangerousprototypes.com/docs/Bus_Pirate_Scripting_in_Python.
|
||||
*/
|
||||
class BusPal
|
||||
{
|
||||
public:
|
||||
//! @brief Constants.
|
||||
enum
|
||||
{
|
||||
kResetCount = 20, //!< Max number of nulls to send to enter BBIO mode
|
||||
kResponseOk = 0x01, //!< Successful command response
|
||||
kBulkTransferMax = 4096, //!< Max number of bytes per bulk transfer
|
||||
kMaxResponse = kBulkTransferMax //!< Max number of bytes in command response, including bulk transfer response,
|
||||
//!plus some padding
|
||||
};
|
||||
|
||||
//! @brief BusPal Transports.
|
||||
enum bus_pal_function_t
|
||||
{
|
||||
kBusPalFunction_None,
|
||||
kBusPalFunction_SPI,
|
||||
kBusPalFunction_I2C,
|
||||
kBusPalFunction_CAN,
|
||||
kBusPalFunction_GPIO_CONFIG,
|
||||
kBusPalFunction_GPIO_SET,
|
||||
kBusPalFunction_FPGA_CLOCK_SET
|
||||
};
|
||||
|
||||
//! @brief SPI clock polarity configuration.
|
||||
enum spi_clock_polarity_t
|
||||
{
|
||||
kSpiClockPolarity_ActiveHigh = 0, //!< Active-high SPI clock (idles low).
|
||||
kSpiClockPolarity_ActiveLow = 1 //!< Active-low SPI clock (idles high).
|
||||
};
|
||||
|
||||
//! @brief SPI clock phase configuration.
|
||||
enum spi_clock_phase_t
|
||||
{
|
||||
kSpiClockPhase_FirstEdge =
|
||||
0, //!< First edge on SPSCK occurs at the middle of the first cycle of a data transfer.
|
||||
kSpiClockPhase_SecondEdge =
|
||||
1 //!< First edge on SPSCK occurs at the start of the first cycle of a data transfer.
|
||||
};
|
||||
|
||||
//! @brief SPI data shifter direction options.
|
||||
enum spi_shift_direction_t
|
||||
{
|
||||
kSpiMsbFirst = 0, //!< Data transfers start with most significant bit.
|
||||
kSpiLsbFirst = 1 //!< Data transfers start with least significant bit.
|
||||
};
|
||||
|
||||
//! @brief I2C default address.
|
||||
static const uint8_t kBusPalDefaultI2cSlaveAddress = 0x10; // I2C Slave 7-bit address
|
||||
|
||||
public:
|
||||
//! @brief BusPal configuration data.
|
||||
struct BusPalConfigData
|
||||
{
|
||||
bus_pal_function_t function;
|
||||
uint32_t spiSpeedKHz;
|
||||
spi_clock_polarity_t spiPolarity;
|
||||
spi_clock_phase_t spiPhase;
|
||||
spi_shift_direction_t spiDirection;
|
||||
uint8_t i2cAddress;
|
||||
uint32_t i2cSpeedKHz;
|
||||
uint32_t canSpeed;
|
||||
uint32_t canTxid;
|
||||
uint32_t canRxid;
|
||||
uint8_t gpioPort;
|
||||
uint8_t gpioPinNum;
|
||||
uint8_t gpioLevel;
|
||||
uint8_t gpioMux;
|
||||
uint32_t fpgaClockMhz;
|
||||
|
||||
BusPalConfigData(bus_pal_function_t bus = BusPal::kBusPalFunction_None)
|
||||
: function(bus)
|
||||
{
|
||||
spiSpeedKHz = 100;
|
||||
spiPolarity = BusPal::kSpiClockPolarity_ActiveLow;
|
||||
spiPhase = BusPal::kSpiClockPhase_SecondEdge;
|
||||
spiDirection = BusPal::kSpiMsbFirst;
|
||||
i2cAddress = BusPal::kBusPalDefaultI2cSlaveAddress;
|
||||
i2cSpeedKHz = 100;
|
||||
canSpeed = 4; // 4: 1M
|
||||
canTxid = 0x321;
|
||||
canRxid = 0x123;
|
||||
gpioPort = 0;
|
||||
gpioPinNum = 0;
|
||||
gpioLevel = 0;
|
||||
gpioMux = 0;
|
||||
fpgaClockMhz = 0;
|
||||
}
|
||||
};
|
||||
|
||||
//! @brief Constructor.
|
||||
BusPal(int fileDescriptor);
|
||||
|
||||
//! @brief Destructor.
|
||||
virtual ~BusPal(){};
|
||||
|
||||
//! @brief parse the passed in options into the config structure.
|
||||
static bool parse(const string_vector_t ¶ms, BusPal::BusPalConfigData &config);
|
||||
|
||||
//! @brief Reset to bit bang mode from another peripheral mode.
|
||||
virtual bool reset();
|
||||
|
||||
//! @brief Reset the bus pal, comes up in terminal mode.
|
||||
virtual bool resetHardware();
|
||||
|
||||
//! @brief Enter bit bang (binary scripting) mode.
|
||||
//!
|
||||
//! Call this first before entering other peripheral modes.
|
||||
virtual bool enterBitBangMode();
|
||||
|
||||
//! @brief Enter Spi mode.
|
||||
virtual bool enterSpiMode();
|
||||
|
||||
//! @brief Enter Can mode.
|
||||
virtual bool enterCanMode();
|
||||
|
||||
//! @brief Enter I2c mode.
|
||||
virtual bool enterI2cMode();
|
||||
|
||||
//! @brief Enter Uart mode. Not currently supported for bus pal
|
||||
virtual bool enterUartMode() { return false; }
|
||||
//! @brief Enter 1wire mode. Not currently supported for bus pal
|
||||
virtual bool enter1WireMode() { return false; }
|
||||
//! @brief Enter raw wire mode. Not currently supported for bus pal
|
||||
virtual bool enterRawWireMode() { return false; }
|
||||
//! @brief Raw configure pins.
|
||||
virtual bool rawConfigurePins(uint8_t port, uint8_t pin, uint8_t muxVal);
|
||||
|
||||
//! @brief Set GPIO pin
|
||||
virtual bool rawSetPins(uint8_t port, uint8_t pin, uint8_t level);
|
||||
|
||||
//! @brief Configure pins.
|
||||
virtual bool configurePins(uint8_t config = 0) { return true; }
|
||||
//! @brief Read pins.
|
||||
virtual uint8_t readPins() { return 0; }
|
||||
//! @brief Sets the FPGA clock, clock is in hertz
|
||||
virtual bool setFPGAClock(uint32_t clock);
|
||||
|
||||
//! @brief Set SPI speed.
|
||||
virtual bool setSpiSpeed(unsigned int speed);
|
||||
|
||||
//! @brief Sets the SPI configuration
|
||||
virtual bool setSpiConfig(spi_clock_polarity_t polarity, spi_clock_phase_t phase, spi_shift_direction_t direction);
|
||||
|
||||
//! @brief Set I2c address
|
||||
virtual bool setI2cAddress(uint8_t address);
|
||||
|
||||
//! @brief Set I2c speed
|
||||
virtual bool setI2cSpeed(uint32_t speed);
|
||||
|
||||
//! @brief Set CAN speed.
|
||||
virtual bool setCanSpeed(unsigned int speed);
|
||||
|
||||
//! @brief Set CAN txid.
|
||||
virtual bool setCanTxid(unsigned int txid);
|
||||
|
||||
//! @brief Set CAN rxid.
|
||||
virtual bool setCanRxid(unsigned int rxid);
|
||||
|
||||
//! @brief Read response.
|
||||
//!
|
||||
//! @retval NULL No response from device
|
||||
//! @retval Non-NULL Pointer to internal array of bytes at least size byteCount
|
||||
virtual uint8_t *response(size_t byteCount = 1);
|
||||
|
||||
//! @brief writes the data over the previously selected interface
|
||||
virtual bool write(const uint8_t *data, size_t byteCount = 1);
|
||||
|
||||
//! @brief Read data.
|
||||
virtual int read(uint8_t *data, size_t byteCount);
|
||||
|
||||
protected:
|
||||
//! @brief Write command, check string response.
|
||||
virtual bool writeCommand(uint8_t commandByte, const char *expectedResponse);
|
||||
|
||||
//! @brief Write command, return 1 byte response.
|
||||
virtual uint8_t writeCommand(uint8_t commandByte);
|
||||
|
||||
//! @brief write multi-byte command, return 1 byte response.
|
||||
virtual uint8_t writeCommand(uint8_t *command, unsigned int length);
|
||||
|
||||
//! @brief write via Spi
|
||||
virtual bool writeSpi(const uint8_t *data, size_t byteCount = 1);
|
||||
|
||||
//! @brief write via I2c
|
||||
virtual bool writeI2c(const uint8_t *data, size_t byteCount = 1);
|
||||
|
||||
//! @brief write via Can
|
||||
virtual bool writeCan(const uint8_t *data, size_t byteCount = 1);
|
||||
|
||||
//! @brief read via Spi
|
||||
virtual int readSpi(uint8_t *data, size_t byteCount);
|
||||
|
||||
//! @brief read via Can
|
||||
virtual int readCan(uint8_t *data, size_t byteCount);
|
||||
|
||||
//! @brief worker function to actually read SPI data
|
||||
int readSpiActual(uint8_t *data, size_t byteCount);
|
||||
|
||||
//! @brief read via I2c
|
||||
virtual int readI2c(uint8_t *data, size_t byteCount);
|
||||
|
||||
//! @brief Overriden serial_read for logging
|
||||
int buspal_serial_read(uint8_t *buf, int size, bool isCommandData = false);
|
||||
|
||||
//! @brief Overriden serial_write for logging
|
||||
int buspal_serial_write(uint8_t *buf, int size, bool isCommandData = false);
|
||||
|
||||
//! @brief Flushes the serial port of any RX data
|
||||
void flushRX();
|
||||
|
||||
protected:
|
||||
enum bus_pal_mode_t
|
||||
{
|
||||
kBusPalModeBitBang,
|
||||
kBusPalModeSpi,
|
||||
kBusPalModeI2c,
|
||||
kBusPalModeCan
|
||||
};
|
||||
int m_fileDescriptor; //!< PC COM port file descriptor.
|
||||
uint8_t m_responseBuffer[kMaxResponse]; //!< Command response buffer.
|
||||
bus_pal_mode_t m_mode;
|
||||
unsigned int m_spiWriteByteCount;
|
||||
unsigned int m_canWriteByteCount;
|
||||
unsigned int m_canFirstReadDelay;
|
||||
};
|
||||
|
||||
} // namespace blfwk
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // _BusPal_h_
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
88
src/blfwk/BusPalPeripheral.h
Normal file
88
src/blfwk/BusPalPeripheral.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _BusPalPeripheral_h_
|
||||
#define _BusPalPeripheral_h_
|
||||
|
||||
#include "UartPeripheral.h"
|
||||
#include "BusPal.h"
|
||||
|
||||
//! @addtogroup bus_pal_peripheral
|
||||
//! @{
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* @brief Peripheral that talks to the target device over BusPal UART hardware.
|
||||
*/
|
||||
class BusPalUartPeripheral : public UartPeripheral
|
||||
{
|
||||
public:
|
||||
//! @brief Parameterized constructor that opens the serial port.
|
||||
//!
|
||||
//! Opens and configures the port. Throws exception if port configuration fails.
|
||||
//!
|
||||
//! Note: following COM port configuration is assumed: 8 bits, 1 stop bit, no parity.
|
||||
//!
|
||||
//! @param port OS file path for COM port. For example "COM1" on Windows.
|
||||
//! @param speed Port speed, e.g. 9600.
|
||||
BusPalUartPeripheral(const char *port, long speed, const BusPal::BusPalConfigData &config);
|
||||
|
||||
//! @brief Destructor.
|
||||
virtual ~BusPalUartPeripheral();
|
||||
|
||||
//! @brief configure the bus pal with the passed in options
|
||||
void configure(const BusPal::BusPalConfigData &config);
|
||||
|
||||
//! @brief Read bytes.
|
||||
//!
|
||||
//! @param buffer Pointer to buffer
|
||||
//! @param requestedBytes Number of bytes to read
|
||||
virtual status_t read(uint8_t *buffer, uint32_t requestedBytes, uint32_t *actualBytes, uint32_t timeoutMs);
|
||||
|
||||
//! @brief Write bytes.
|
||||
//!
|
||||
//! @param buffer Pointer to buffer to write
|
||||
//! @param byteCount Number of bytes to write
|
||||
virtual status_t write(const uint8_t *buffer, uint32_t byteCount);
|
||||
|
||||
protected:
|
||||
BusPal *m_busPal; //!< Represents Bus Pal hardware.
|
||||
};
|
||||
|
||||
} // namespace blfwk
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // _BusPalPeripheral_h_
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
1601
src/blfwk/Command.h
Normal file
1601
src/blfwk/Command.h
Normal file
File diff suppressed because it is too large
Load Diff
63
src/blfwk/Crc.h
Normal file
63
src/blfwk/Crc.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2013-15, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if !defined(_Crc_h_)
|
||||
#define _Crc_h_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* \brief Crc class contains the functionality about crc ccalculation.
|
||||
*/
|
||||
class Crc
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
Crc(){};
|
||||
|
||||
//! \brief Destructor.
|
||||
virtual ~Crc(){};
|
||||
|
||||
//! \brief calculate crc32 for a given memory region
|
||||
//!
|
||||
//! \param start The start address of a memory region that contains the data
|
||||
//! \
|
||||
//! \param length Length in bytes to calculate
|
||||
//! \
|
||||
//! \return calculated result
|
||||
static uint32_t calculate_application_crc32(const uint8_t *start, uint32_t length);
|
||||
//@}
|
||||
//
|
||||
};
|
||||
|
||||
} // namespace blfwk
|
||||
#endif // _Crc_h_
|
||||
326
src/blfwk/DataSource.h
Normal file
326
src/blfwk/DataSource.h
Normal file
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_DataSource_h_)
|
||||
#define _DataSource_h_
|
||||
|
||||
#include <vector>
|
||||
#include "Value.h"
|
||||
#include "smart_ptr.h"
|
||||
#include "StExecutableImage.h"
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
// Forward declaration
|
||||
class DataTarget;
|
||||
|
||||
/*!
|
||||
* \brief Abstract base class for data sources.
|
||||
*
|
||||
* Data sources represent any sort of data that can be placed or loaded
|
||||
* into a target region. Sources may be a single blob of data read from
|
||||
* a file or may consist of many segments.
|
||||
*
|
||||
* The three most important features of data sources are:
|
||||
* - Sources may be multi-segmented.
|
||||
* - Sources and/or segments can have a "natural" or default target location.
|
||||
* - The target for a source may be taken into consideration when the source
|
||||
* describes itself.
|
||||
*/
|
||||
class DataSource
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* \brief Discrete, contiguous part of the source's data.
|
||||
*
|
||||
* This class is purely abstract and subclasses of DataSource are expected
|
||||
* to subclass it to implement a segment particular to their needs.
|
||||
*/
|
||||
class Segment
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
Segment(DataSource &source)
|
||||
: m_source(source)
|
||||
{
|
||||
}
|
||||
|
||||
//! \brief Destructor.
|
||||
virtual ~Segment() {}
|
||||
//! \brief Gets all or a portion of the segment's data.
|
||||
//!
|
||||
//! The data is copied into \a buffer. Up to \a maxBytes bytes may be
|
||||
//! copied, so \a buffer must be at least that large.
|
||||
//!
|
||||
//! \param offset Index of the first byte to start copying from.
|
||||
//! \param maxBytes The maximum number of bytes that can be returned. \a buffer
|
||||
//! must be at least this large.
|
||||
//! \param buffer Pointer to buffer where the data is copied.
|
||||
//! \return The number of bytes copied into \a buffer.
|
||||
virtual unsigned getData(unsigned offset, unsigned maxBytes, uint8_t *buffer) = 0;
|
||||
|
||||
//! \brief Gets the length of the segment's data.
|
||||
virtual unsigned getLength() = 0;
|
||||
|
||||
//! \brief Returns whether the segment has an associated address.
|
||||
virtual bool hasNaturalLocation() = 0;
|
||||
|
||||
//! \brief Returns the address associated with the segment.
|
||||
virtual uint32_t getBaseAddress() { return 0; }
|
||||
protected:
|
||||
DataSource &m_source; //!< The data source to which this segment belongs.
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief This is a special type of segment containing a repeating pattern.
|
||||
*
|
||||
* By default the segment doesn't have a specific length or data. The length depends
|
||||
* on the target's address range. And the data is just the pattern, repeated
|
||||
* many times. In addition, pattern segments do not have a natural location.
|
||||
*
|
||||
* Calling code should look for instances of PatternSegment and handle them
|
||||
* as special cases that can be optimized.
|
||||
*/
|
||||
class PatternSegment : public Segment
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
PatternSegment(DataSource &source);
|
||||
|
||||
//! \brief Constructor taking a fill pattern.
|
||||
PatternSegment(DataSource &source, const SizedIntegerValue &pattern);
|
||||
|
||||
//! \brief Constructor taking a byte fill pattern.
|
||||
PatternSegment(DataSource &source, uint8_t pattern);
|
||||
|
||||
//! \brief Constructor taking a half-word fill pattern.
|
||||
PatternSegment(DataSource &source, uint16_t pattern);
|
||||
|
||||
//! \brief Constructor taking a word fill pattern.
|
||||
PatternSegment(DataSource &source, uint32_t pattern);
|
||||
|
||||
//! \name Segment methods
|
||||
//@{
|
||||
//! \brief Pattern segments have no natural address.
|
||||
virtual bool hasNaturalLocation() { return false; }
|
||||
//! \brief Performs a pattern fill into the \a buffer.
|
||||
virtual unsigned getData(unsigned offset, unsigned maxBytes, uint8_t *buffer);
|
||||
|
||||
//! \brief Returns a length based on the data target's address range.
|
||||
virtual unsigned getLength();
|
||||
//@}
|
||||
|
||||
//! \name Pattern accessors
|
||||
//@{
|
||||
//! \brief Assigns a new fill pattern.
|
||||
inline void setPattern(const SizedIntegerValue &newPattern) { m_pattern = newPattern; }
|
||||
//! \brief Return the fill pattern for the segment.
|
||||
inline SizedIntegerValue &getPattern() { return m_pattern; }
|
||||
//! \brief Assignment operator, sets the pattern value and length.
|
||||
PatternSegment &operator=(const SizedIntegerValue &value)
|
||||
{
|
||||
m_pattern = value;
|
||||
return *this;
|
||||
}
|
||||
//@}
|
||||
|
||||
protected:
|
||||
SizedIntegerValue m_pattern; //!< The fill pattern.
|
||||
};
|
||||
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
DataSource()
|
||||
: m_target(0)
|
||||
{
|
||||
}
|
||||
|
||||
//! \brief Destructor.
|
||||
virtual ~DataSource() {}
|
||||
//! \name Data target
|
||||
//@{
|
||||
//! \brief Sets the associated data target.
|
||||
inline void setTarget(DataTarget *target) { m_target = target; }
|
||||
//! \brief Gets the associated data target.
|
||||
inline DataTarget *getTarget() const { return m_target; }
|
||||
//@}
|
||||
|
||||
//! \name Segments
|
||||
//@{
|
||||
//! \brief Returns the number of segments in this data source.
|
||||
virtual unsigned getSegmentCount() = 0;
|
||||
|
||||
//! \brief Returns segment number \a index of the data source.
|
||||
virtual Segment *getSegmentAt(unsigned index) = 0;
|
||||
//@}
|
||||
|
||||
protected:
|
||||
DataTarget *m_target; //!< Corresponding target for this source.
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Data source for a repeating pattern.
|
||||
*
|
||||
* The pattern is represented by a SizedIntegerValue object. Thus the pattern
|
||||
* can be either byte, half-word, or word sized.
|
||||
*
|
||||
* This data source has only one segment, and the PatternSource instance acts
|
||||
* as its own single segment.
|
||||
*/
|
||||
class PatternSource : public DataSource, public DataSource::PatternSegment
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
PatternSource();
|
||||
|
||||
//! \brief Constructor taking the pattern value.
|
||||
PatternSource(const SizedIntegerValue &value);
|
||||
|
||||
//! \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; }
|
||||
//! \brief Assignment operator, sets the pattern value and length.
|
||||
PatternSource &operator=(const SizedIntegerValue &value)
|
||||
{
|
||||
setPattern(value);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Data source for data that is not memory mapped (has no natural address).
|
||||
*
|
||||
* This data source can only manage a single block of data, which has no
|
||||
* associated address. It acts as its own Segment.
|
||||
*/
|
||||
class UnmappedDataSource : public DataSource, public DataSource::Segment
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
UnmappedDataSource();
|
||||
|
||||
//! \brief Constructor taking the data, which is copied.
|
||||
UnmappedDataSource(const uint8_t *data, unsigned length);
|
||||
|
||||
//! \brief Sets the source's data.
|
||||
void setData(const uint8_t *data, unsigned length);
|
||||
|
||||
//! \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 Unmapped data sources have no natural address.
|
||||
virtual bool hasNaturalLocation() { return false; }
|
||||
//! \brief Copies a portion of the data into \a buffer.
|
||||
virtual unsigned getData(unsigned offset, unsigned maxBytes, uint8_t *buffer);
|
||||
|
||||
//! \brief Returns the number of bytes of data managed by the source.
|
||||
virtual unsigned getLength() { return m_length; }
|
||||
//! \brief Returns the address associated with the segment.
|
||||
virtual uint32_t getBaseAddress();
|
||||
|
||||
//@}
|
||||
|
||||
protected:
|
||||
smart_array_ptr<uint8_t> m_data; //!< The data.
|
||||
unsigned m_length; //!< Byte count of the data.
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Data source that takes its data from an executable image.
|
||||
*
|
||||
* \see StExecutableImage
|
||||
*/
|
||||
class MemoryImageDataSource : public DataSource
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
MemoryImageDataSource(StExecutableImage *image);
|
||||
|
||||
//! \brief Destructor.
|
||||
virtual ~MemoryImageDataSource();
|
||||
|
||||
//! \brief Returns the number of memory regions in the image.
|
||||
virtual unsigned getSegmentCount();
|
||||
|
||||
//! \brief Returns the data source segment at position \a index.
|
||||
virtual DataSource::Segment *getSegmentAt(unsigned index);
|
||||
|
||||
protected:
|
||||
/*!
|
||||
* \brief Segment corresponding to a text region of the executable image.
|
||||
*/
|
||||
class TextSegment : public DataSource::Segment
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor
|
||||
TextSegment(MemoryImageDataSource &source, StExecutableImage *image, unsigned index);
|
||||
|
||||
virtual unsigned getData(unsigned offset, unsigned maxBytes, uint8_t *buffer);
|
||||
virtual unsigned getLength();
|
||||
|
||||
virtual bool hasNaturalLocation() { return true; }
|
||||
virtual uint32_t getBaseAddress();
|
||||
|
||||
protected:
|
||||
StExecutableImage *m_image; //!< Coalesced image of the file.
|
||||
unsigned m_index; //!< Record index.
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Segment corresponding to a fill region of the executable image.
|
||||
*/
|
||||
class FillSegment : public DataSource::PatternSegment
|
||||
{
|
||||
public:
|
||||
FillSegment(MemoryImageDataSource &source, StExecutableImage *image, unsigned index);
|
||||
|
||||
virtual unsigned getLength();
|
||||
|
||||
virtual bool hasNaturalLocation() { return true; }
|
||||
virtual uint32_t getBaseAddress();
|
||||
|
||||
protected:
|
||||
StExecutableImage *m_image; //!< Coalesced image of the file.
|
||||
unsigned m_index; //!< Record index.
|
||||
};
|
||||
|
||||
protected:
|
||||
StExecutableImage *m_image; //!< The memory image that is the data source.
|
||||
|
||||
typedef std::vector<DataSource::Segment *> segment_array_t; //!< An array of segments.
|
||||
segment_array_t m_segments; //!< The array of Segment instances.
|
||||
};
|
||||
|
||||
}; // namespace blfwk
|
||||
|
||||
#endif // _DataSource_h_
|
||||
53
src/blfwk/DataSourceImager.h
Normal file
53
src/blfwk/DataSourceImager.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* File: DataSourceImager.h
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
|
||||
* See included license file for license details.
|
||||
*/
|
||||
#if !defined(_DataSourceImager_h_)
|
||||
#define _DataSourceImager_h_
|
||||
|
||||
#include "Blob.h"
|
||||
#include "DataSource.h"
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* \brief Converts a DataSource into a single binary buffer.
|
||||
*/
|
||||
class DataSourceImager : public Blob
|
||||
{
|
||||
public:
|
||||
//! \brief Constructor.
|
||||
DataSourceImager();
|
||||
|
||||
//! \name Setup
|
||||
//@{
|
||||
void setBaseAddress(uint32_t address);
|
||||
void setFillPattern(uint8_t pattern);
|
||||
//@}
|
||||
|
||||
void reset();
|
||||
|
||||
//! \name Accessors
|
||||
//@{
|
||||
uint32_t getBaseAddress() { return m_baseAddress; }
|
||||
//@}
|
||||
|
||||
//! \name Operations
|
||||
//@{
|
||||
//! \brief Adds all of the segments of which \a dataSource is composed.
|
||||
void addDataSource(DataSource *source);
|
||||
|
||||
//! \brief Adds the data from one data segment.
|
||||
void addDataSegment(DataSource::Segment *segment);
|
||||
//@}
|
||||
|
||||
protected:
|
||||
uint8_t m_fill;
|
||||
uint32_t m_baseAddress;
|
||||
bool m_isBaseAddressSet;
|
||||
};
|
||||
};
|
||||
|
||||
#endif // _DataSourceImager_h_
|
||||
155
src/blfwk/DataTarget.h
Normal file
155
src/blfwk/DataTarget.h
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_DataTarget_h_)
|
||||
#define _DataTarget_h_
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "DataSource.h"
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
// Forward declaration
|
||||
class DataSource;
|
||||
|
||||
/*!
|
||||
* \brief Abstract base class for the target address or range of data.
|
||||
*
|
||||
* Targets at the most basic level have a single address, and potentially
|
||||
* an address range. Unbounded targets have a beginning address but no
|
||||
* specific end address, while bounded targets do have an end address.
|
||||
*
|
||||
* Users of a data target can access the begin and end addresses directly.
|
||||
* However, the most powerful way to use a target is with the
|
||||
* getRangeForSegment() method. This method returns the target address range
|
||||
* for a segment of a data source. The value of the resulting range can be
|
||||
* completely dependent upon the segment's properties, those of its data
|
||||
* source, and the type of data target.
|
||||
*
|
||||
* \see blfwk::DataSource
|
||||
*/
|
||||
class DataTarget
|
||||
{
|
||||
public:
|
||||
//! \brief Simple structure that describes an addressed region of memory.
|
||||
//! \todo Decide if the end address is inclusive or not.
|
||||
struct AddressRange
|
||||
{
|
||||
uint32_t m_begin;
|
||||
uint32_t m_end;
|
||||
};
|
||||
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
DataTarget()
|
||||
: m_source(0)
|
||||
{
|
||||
}
|
||||
|
||||
//! \brief Destructor.
|
||||
virtual ~DataTarget() {}
|
||||
//! \brief Whether the target is just a single address or has an end to it.
|
||||
virtual bool isBounded() { return false; }
|
||||
virtual uint32_t getBeginAddress() { return 0; }
|
||||
virtual uint32_t getEndAddress() { return 0; }
|
||||
//! \brief Return the address range for a segment of a data source.
|
||||
virtual DataTarget::AddressRange getRangeForSegment(DataSource &source, DataSource::Segment &segment) = 0;
|
||||
|
||||
inline void setSource(DataSource *source) { m_source = source; }
|
||||
inline DataSource *getSource() const { return m_source; }
|
||||
protected:
|
||||
DataSource *m_source; //!< Corresponding data source for this target.
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Target with a constant values for the addresses.
|
||||
*
|
||||
* This target type supports can be both bounded and unbounded. It always has
|
||||
* at least one address, the beginning address. The end address is optional,
|
||||
* and if not provided makes the target unbounded.
|
||||
*/
|
||||
class ConstantDataTarget : public DataTarget
|
||||
{
|
||||
public:
|
||||
//! \brief Constructor taking only a begin address.
|
||||
ConstantDataTarget(uint32_t start)
|
||||
: DataTarget()
|
||||
, m_begin(start)
|
||||
, m_end(0)
|
||||
, m_hasEnd(false)
|
||||
{
|
||||
}
|
||||
|
||||
//! \brief Constructor taking both begin and end addresses.
|
||||
ConstantDataTarget(uint32_t start, uint32_t end)
|
||||
: DataTarget()
|
||||
, m_begin(start)
|
||||
, m_end(end)
|
||||
, m_hasEnd(true)
|
||||
{
|
||||
}
|
||||
|
||||
//! \brief The target is bounded if an end address was specified.
|
||||
virtual bool isBounded() { return m_hasEnd; }
|
||||
virtual uint32_t getBeginAddress() { return m_begin; }
|
||||
virtual uint32_t getEndAddress() { return m_end; }
|
||||
//! \brief Return the address range for a segment of a data source.
|
||||
virtual DataTarget::AddressRange getRangeForSegment(DataSource &source, DataSource::Segment &segment);
|
||||
|
||||
protected:
|
||||
uint32_t m_begin; //!< Start address.
|
||||
uint32_t m_end; //!< End address.
|
||||
bool m_hasEnd; //!< Was an end address specified?
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Target address that is the "natural" location of whatever the source data is.
|
||||
*
|
||||
* The data source used with the target must have a natural location. If
|
||||
* getRangeForSegment() is called with a segment that does not have a natural
|
||||
* location, a semantic_error will be thrown.
|
||||
*/
|
||||
class NaturalDataTarget : public DataTarget
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
NaturalDataTarget()
|
||||
: DataTarget()
|
||||
{
|
||||
}
|
||||
|
||||
//! \brief Natural data targets are bounded by their source's segment lengths.
|
||||
virtual bool isBounded() { return true; }
|
||||
//! \brief Return the address range for a segment of a data source.
|
||||
virtual DataTarget::AddressRange getRangeForSegment(DataSource &source, DataSource::Segment &segment);
|
||||
};
|
||||
|
||||
}; // namespace blfwk
|
||||
|
||||
#endif // _DataTarget_h_
|
||||
372
src/blfwk/ELF.h
Normal file
372
src/blfwk/ELF.h
Normal file
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_ELF_h_)
|
||||
#define _ELF_h_
|
||||
|
||||
//! \name ELF types
|
||||
//! Types used in ELF file structures.
|
||||
//@{
|
||||
typedef uint32_t Elf32_Addr;
|
||||
typedef uint16_t Elf32_Half;
|
||||
typedef /*off_t*/ uint32_t Elf32_Off;
|
||||
typedef int32_t Elf32_Sword;
|
||||
typedef uint32_t Elf32_Word;
|
||||
//@}
|
||||
|
||||
// All ELF structures are byte aligned. Any alignment padding is explicit.
|
||||
#pragma pack(1)
|
||||
|
||||
//! \name File header
|
||||
//@{
|
||||
|
||||
/*!
|
||||
* Constants for the various fields of Elf32_Ehdr.e_ident.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
EI_MAG0 = 0,
|
||||
EI_MAG1,
|
||||
EI_MAG2,
|
||||
EI_MAG3,
|
||||
EI_CLASS,
|
||||
EI_DATA,
|
||||
EI_VERSION,
|
||||
EI_PAD,
|
||||
EI_NIDENT = 16,
|
||||
|
||||
// Magic number.
|
||||
ELFMAG0 = 0x7f,
|
||||
ELFMAG1 = 'E',
|
||||
ELFMAG2 = 'L',
|
||||
ELFMAG3 = 'F',
|
||||
|
||||
// EI_CLASS
|
||||
ELFCLASSNONE = 0,
|
||||
ELFCLASS32 = 1,
|
||||
ELFCLASS64 = 2,
|
||||
|
||||
// EI_DATA
|
||||
ELFDATANONE = 0,
|
||||
ELFDATA2LSB = 1,
|
||||
ELFDATA2MSB = 2
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief ELF file header.
|
||||
*/
|
||||
struct Elf32_Ehdr
|
||||
{
|
||||
unsigned char e_ident[EI_NIDENT]; //!< Magic number identifying the file format.
|
||||
Elf32_Half e_type; //!< Identifies the object file format.
|
||||
Elf32_Half e_machine; //!< Specified the architecture for the object file.
|
||||
Elf32_Word e_version; //!< Object file version.
|
||||
Elf32_Addr e_entry; //!< Virtual address of the entry point, or 0.
|
||||
Elf32_Off e_phoff; //!< Program header table offset in bytes, or 0 if no program header table.
|
||||
Elf32_Off e_shoff; //!< Section header table offset in bytes, or 0 if no section header table.
|
||||
Elf32_Word e_flags; //!< Processor-specific flags associated with the file.
|
||||
Elf32_Half e_ehsize; //!< The ELF header's size in bytes.
|
||||
Elf32_Half e_phentsize; //!< Size in bytes of one entry in the program header table.
|
||||
Elf32_Half e_phnum; //!< Number of entries in the program header table.
|
||||
Elf32_Half e_shentsize; //!< Size in bytes of an entry in the section header table.
|
||||
Elf32_Half e_shnum; //!< Number of entries in the section header table.
|
||||
Elf32_Half e_shstrndx; //!< Section header table index of the section name string table.
|
||||
};
|
||||
|
||||
/*!
|
||||
* Constants for #Elf32_Ehdr.e_type.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
ET_NONE, //!< No file type.
|
||||
ET_REL, //!< Relocatable file.
|
||||
ET_EXEC, //!< Executable file.
|
||||
ET_DYN, //!< Shared object file.
|
||||
ET_CORE, //!< Core file.
|
||||
ET_LOPROC, //!< Low bound of processor-specific file types.
|
||||
ET_HIPROC //!< High bound of processor-specific file types.
|
||||
};
|
||||
|
||||
/*!
|
||||
* ARM-specific #Elf32_Ehdr.e_flags
|
||||
*/
|
||||
enum
|
||||
{
|
||||
EF_ARM_HASENTRY = 0x02, //!< #Elf32_Ehdr.e_entry contains a program-loader entry point.
|
||||
EF_ARM_SYMSARESORTED = 0x04, //!< Each subsection of the symbol table is sorted by symbol value.
|
||||
EF_ARM_DYNSYMSUSESEGIDX = 0x08, //!< Symbols in dynamic symbol tables that are defined in sections included in
|
||||
//!program segment n have #Elf32_Sym.st_shndx = n + 1.
|
||||
EF_ARM_MAPSYMSFIRST = 0x10, //!< Mapping symbols precede other local symbols in the symbol table.
|
||||
EF_ARM_EABIMASK = 0xff000000, //!< This masks an 8-bit version number, the version of the ARM EABI to which this ELF
|
||||
//!file conforms. The current EABI version is #ARM_EABI_VERSION.
|
||||
|
||||
ARM_EABI_VERSION = 0x02000000 //!< Current ARM EABI version.
|
||||
};
|
||||
|
||||
//@}
|
||||
|
||||
//! \name Sections
|
||||
//@{
|
||||
|
||||
/*!
|
||||
* \brief ELF section header.
|
||||
*
|
||||
* An object file's section header table lets one locate all the file's
|
||||
* sections. The section header table is an array of #Elf32_Shdr structures.
|
||||
* A section header table index is a subscript into this array. The ELF
|
||||
* header's #Elf32_Ehdr::e_shoff member gives the byte offset from the beginning of
|
||||
* the file to the section header table; #Elf32_Ehdr::e_shnum tells how many entries
|
||||
* the section header table contains; #Elf32_Ehdr::e_shentsize gives the size in bytes
|
||||
* of each entry.
|
||||
*
|
||||
* Some section header table indexes are reserved. An object file will not
|
||||
* have sections for these special indexes:
|
||||
* - #SHN_UNDEF
|
||||
* - #SHN_LORESERVE
|
||||
* - #SHN_LOPROC
|
||||
* - #SHN_HIPROC
|
||||
* - #SHN_ABS
|
||||
* - #SHN_COMMON
|
||||
* - #SHN_HIRESERVE
|
||||
*/
|
||||
struct Elf32_Shdr
|
||||
{
|
||||
Elf32_Word sh_name; //!< The section's name. Index into the section header string table section.
|
||||
Elf32_Word sh_type; //!< Section type, describing the contents and semantics.
|
||||
Elf32_Word sh_flags; //!< Section flags describing various attributes.
|
||||
Elf32_Addr sh_addr; //!< The address at which the section will appear in the memory image, or 0.
|
||||
Elf32_Off sh_offset; //!< Offset from beginning of the file to the first byte in the section.
|
||||
Elf32_Word sh_size; //!< The section's size in bytes.
|
||||
Elf32_Word sh_link; //!< Section header table link index. Interpretation depends on section type.
|
||||
Elf32_Word sh_info; //!< Extra information about the section. Depends on section type.
|
||||
Elf32_Word sh_addralign; //!< Address alignment constraint. Values are 0 and positive powers of 2.
|
||||
Elf32_Word sh_entsize; //!< Size in bytes of section entries, or 0 if the section does not have fixed-size entries.
|
||||
};
|
||||
|
||||
/*!
|
||||
* Special section indexes.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
SHN_UNDEF = 0,
|
||||
SHN_LORESERVE = 0xff00,
|
||||
SHN_LOPROC = 0xff00,
|
||||
SHN_HIPROC = 0xff1f,
|
||||
SHN_ABS = 0xfff1, //!< The symbol has an absolute value that will not change because of relocation.
|
||||
SHN_COMMON = 0xfff2, //!< The symbol labels a common block that has not yet been allocated.
|
||||
SHN_HIRESERVE = 0xffff
|
||||
};
|
||||
|
||||
/*!
|
||||
* Section type constants.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
SHT_NULL = 0,
|
||||
SHT_PROGBITS = 1,
|
||||
SHT_SYMTAB = 2,
|
||||
SHT_STRTAB = 3,
|
||||
SHT_RELA = 4,
|
||||
SHT_HASH = 5,
|
||||
SHT_DYNAMIC = 6,
|
||||
SHT_NOTE = 7,
|
||||
SHT_NOBITS = 8,
|
||||
SHT_REL = 9,
|
||||
SHT_SHLIB = 10,
|
||||
SHT_DYNSYM = 11
|
||||
};
|
||||
|
||||
/*!
|
||||
* Section flag constants.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
SHF_WRITE = 0x1, //!< Section is writable.
|
||||
SHF_ALLOC = 0x2, //!< Allocate section.
|
||||
SHF_EXECINSTR = 0x4 //!< Section contains executable instructions.
|
||||
};
|
||||
|
||||
/*!
|
||||
* ARM-specific section flag constants
|
||||
*/
|
||||
enum
|
||||
{
|
||||
SHF_ENTRYSECT = 0x10000000, //!< The section contains an entry point.
|
||||
SHF_COMDEF = 0x80000000 //!< The section may be multiply defined in the input to a link step.
|
||||
};
|
||||
|
||||
#define BSS_SECTION_NAME ".bss"
|
||||
#define DATA_SECTION_NAME ".data"
|
||||
#define TEXT_SECTION_NAME ".text"
|
||||
#define SHSTRTAB_SECTION_NAME ".shstrtab"
|
||||
#define STRTAB_SECTION_NAME ".strtab"
|
||||
#define SYMTAB_SECTION_NAME ".symtab"
|
||||
|
||||
//@}
|
||||
|
||||
//! \name Segments
|
||||
//@{
|
||||
|
||||
/*!
|
||||
* \brief ELF program header.
|
||||
*
|
||||
* An executable or shared object file's program header table is an array of
|
||||
* structures, each describing a segment or other information the system needs
|
||||
* to prepare the program for execution. An object file segment contains one
|
||||
* or more sections. Program headers are meaningful only for executable and
|
||||
* shared object files. A file specifies its own program header size with the
|
||||
* ELF header's #Elf32_Ehdr::e_phentsize and #Elf32_Ehdr::e_phnum members.
|
||||
*/
|
||||
struct Elf32_Phdr
|
||||
{
|
||||
Elf32_Word p_type; //!< What type of segment this header describes.
|
||||
Elf32_Off p_offset; //!< Offset in bytes from start of file to the first byte of the segment.
|
||||
Elf32_Addr p_vaddr; //!< Virtual address at which the segment will reside in memory.
|
||||
Elf32_Addr p_paddr; //!< Physical address, for systems where this is relevant.
|
||||
Elf32_Word p_filesz; //!< Number of bytes of file data the segment consumes. May be zero.
|
||||
Elf32_Word p_memsz; //!< Size in bytes of the segment in memory. May be zero.
|
||||
Elf32_Word p_flags; //!< Flags relevant to the segment.
|
||||
Elf32_Word p_align; //!< Alignment constraint for segment addresses. Possible values are 0 and positive powers of 2.
|
||||
};
|
||||
|
||||
/*!
|
||||
* Segment type constants.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
PT_NULL = 0,
|
||||
PT_LOAD = 1,
|
||||
PT_DYNAMIC = 2,
|
||||
PT_INTERP = 3,
|
||||
PT_NOTE = 4,
|
||||
PT_SHLIB = 5,
|
||||
PT_PHDR = 6
|
||||
};
|
||||
|
||||
/*!
|
||||
* Program header flag constants.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
PF_X = 0x1, //!< Segment is executable.
|
||||
PF_W = 0x2, //!< Segment is writable.
|
||||
PF_R = 0x4 //!< Segment is readable.
|
||||
};
|
||||
|
||||
//@}
|
||||
|
||||
//! \name Symbol table
|
||||
//@{
|
||||
|
||||
enum
|
||||
{
|
||||
STN_UNDEF = 0 //!< Undefined symbol index.
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief ELF symbol table entry.
|
||||
*
|
||||
* An object file's symbol table holds information needed to locate and
|
||||
* relocate a program's symbolic definitions and references. A symbol
|
||||
* table index is a subscript into this array. Index 0 both designates
|
||||
* the first entry in the table and serves as the undefined symbol index.
|
||||
*/
|
||||
struct Elf32_Sym
|
||||
{
|
||||
Elf32_Word st_name; //!< Index into file's string table.
|
||||
Elf32_Addr st_value; //!< Value associated with the symbol. Depends on context.
|
||||
Elf32_Word st_size; //!< Size associated with symbol. 0 if the symbol has no size or an unknown size.
|
||||
unsigned char st_info; //!< Specified the symbol's type and binding attributes.
|
||||
unsigned char st_other; //!< Currently 0 (reserved).
|
||||
Elf32_Half st_shndx; //!< Section header table index for this symbol.
|
||||
};
|
||||
|
||||
//! \name st_info macros
|
||||
//! Macros for manipulating the st_info field of Elf32_Sym struct.
|
||||
//@{
|
||||
#define ELF32_ST_BIND(i) ((i) >> 4) //!< Get binding attributes.
|
||||
#define ELF32_ST_TYPE(i) ((i)&0x0f) //!< Get symbol type.
|
||||
#define ELF32_ST_INFO(b, t) \
|
||||
(((b) << 4) + ((t)&0x0f)) //!< Construct st_info value from binding attributes and symbol type.
|
||||
//@}
|
||||
|
||||
/*!
|
||||
* \brief Symbol binding attributes.
|
||||
*
|
||||
* These constants are mask values.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
STB_LOCAL = 0, //!< Local symbol not visible outside the object file.
|
||||
STB_GLOBAL = 1, //!< Symbol is visible to all object files being linked together.
|
||||
STB_WEAK = 2, //!< Like global symbols, but with lower precedence.
|
||||
|
||||
// Processor-specific semantics.
|
||||
STB_LOPROC = 13,
|
||||
STB_HIPROC = 15
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Symbol types.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
STT_NOTYPE = 0, //!< The symbol's type is not specified.
|
||||
STT_OBJECT = 1, //!< The symbol is associated with a data object, such as a variable or array.
|
||||
STT_FUNC = 2, //!< The symbol is associated with a function or other executable code.
|
||||
STT_SECTION = 3, //!< The synmbol is associated with a section. Primarily used for relocation.
|
||||
STT_FILE = 4, //!< A file symbol has STB_LOCAL binding, its section index is SHN_ABS, and it precedes the other
|
||||
//!STB_LOCAL symbols for the file, if it is present.
|
||||
|
||||
STT_LOPROC = 13, //!< Low bound of processor-specific symbol types.
|
||||
STT_HIPROC = 15 //!< High bound of processor-specific symbol types.
|
||||
};
|
||||
|
||||
/*!
|
||||
* GHS-specific constants
|
||||
*/
|
||||
enum
|
||||
{
|
||||
STO_THUMB = 1 //!< This flag is set on #Elf32_Sym.st_other if the symbol is Thumb mode code.
|
||||
};
|
||||
|
||||
#define ARM_SEQUENCE_MAPSYM "$a"
|
||||
#define DATA_SEQUENCE_MAPSYM "$d"
|
||||
#define THUMB_SEQUENCE_MAPSYM "$t"
|
||||
|
||||
#define THUMB_BL_TAGSYM "$b"
|
||||
#define FN_PTR_CONST_TAGSYM "$f"
|
||||
#define INDIRECT_FN_CALL_TAGSYM "$p"
|
||||
#define MAPPING_SYMBOL_COUNT_TAGSYM "$m"
|
||||
|
||||
//@}
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#endif // _ELF_h_
|
||||
250
src/blfwk/ELFSourceFile.h
Normal file
250
src/blfwk/ELFSourceFile.h
Normal file
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_ELFSourceFile_h_)
|
||||
#define _ELFSourceFile_h_
|
||||
|
||||
#include "SourceFile.h"
|
||||
#include "StELFFile.h"
|
||||
#include "smart_ptr.h"
|
||||
#include "DataSource.h"
|
||||
#include "DataTarget.h"
|
||||
#include "ELF.h"
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
//! Set of supported compiler toolsets.
|
||||
enum elf_toolset_t
|
||||
{
|
||||
kUnknownToolset, //!< Unknown.
|
||||
kGHSToolset, //!< Green Hills Software MULTI
|
||||
kGCCToolset, //!< GNU GCC
|
||||
kADSToolset //!< ARM UK RealView
|
||||
};
|
||||
|
||||
//! Options for handling the .secinfo section in GHS-produced ELF files.
|
||||
enum secinfo_clear_t
|
||||
{
|
||||
// Default value for the .secinfo action.
|
||||
kSecinfoDefault,
|
||||
|
||||
//! Ignore the .secinfo section if present. The standard ELF loading
|
||||
//! rules are followed.
|
||||
kSecinfoIgnore,
|
||||
|
||||
//! The boot ROM clears only those SHT_NOBITS sections present in .secinfo.
|
||||
kSecinfoROMClear,
|
||||
|
||||
//! The C startup is responsible for clearing sections. No fill commands
|
||||
//! are generated for any SHT_NOBITS sections.
|
||||
kSecinfoCStartupClear
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Executable and Loading Format (ELF) source file.
|
||||
*/
|
||||
class ELFSourceFile : public SourceFile
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
ELFSourceFile(const std::string &path);
|
||||
|
||||
//! \brief Destructor.
|
||||
virtual ~ELFSourceFile();
|
||||
|
||||
//! \brief Identifies whether the stream contains an ELF file.
|
||||
static bool isELFFile(std::istream &stream);
|
||||
|
||||
//! \name Opening and closing
|
||||
//@{
|
||||
//! \brief Opens the file.
|
||||
virtual void open();
|
||||
|
||||
//! \brief Closes the file.
|
||||
virtual void close();
|
||||
//@}
|
||||
|
||||
//! \name Format capabilities
|
||||
//@{
|
||||
virtual bool supportsNamedSections() const { return true; }
|
||||
virtual bool supportsNamedSymbols() const { return true; }
|
||||
//@}
|
||||
|
||||
//! \name Data source
|
||||
//@{
|
||||
//! \brief Creates a data source from the entire file.
|
||||
virtual DataSource *createDataSource();
|
||||
|
||||
//! \brief Creates a data source from one or more sections of the file.
|
||||
virtual DataSource *createDataSource(StringMatcher &matcher);
|
||||
//@}
|
||||
|
||||
//! \brief Creates a data source from sections of the file that either match or do not match the
|
||||
// baseAddress
|
||||
virtual DataSource *createDataSource(const std::vector<uint32_t> &baseAddress, bool match);
|
||||
//@}
|
||||
|
||||
//! \name Entry point
|
||||
//@{
|
||||
//! \brief Returns true if an entry point was set in the file.
|
||||
virtual bool hasEntryPoint();
|
||||
|
||||
//! \brief Returns the entry point address.
|
||||
virtual uint32_t getEntryPointAddress();
|
||||
//@}
|
||||
|
||||
//! \name Data target
|
||||
//@{
|
||||
virtual DataTarget *createDataTargetForSection(const std::string §ion);
|
||||
virtual DataTarget *createDataTargetForSymbol(const std::string &symbol);
|
||||
//@}
|
||||
|
||||
//! \name Symbols
|
||||
//@{
|
||||
//! \brief Returns whether a symbol exists in the source file.
|
||||
virtual bool hasSymbol(const std::string &name);
|
||||
|
||||
//! \brief Returns the value of a symbol.
|
||||
virtual uint32_t getSymbolValue(const std::string &name);
|
||||
|
||||
//! \brief Returns the size of a symbol.
|
||||
virtual unsigned getSymbolSize(const std::string &name);
|
||||
//@}
|
||||
|
||||
//! \name Direct ELF format access
|
||||
//@{
|
||||
//! \brief Returns the underlying StELFFile object.
|
||||
StELFFile *getELFFile() { return m_file; }
|
||||
//! \brief Gets information about a symbol in the ELF file.
|
||||
bool lookupSymbol(const std::string &name, Elf32_Sym &info);
|
||||
//@}
|
||||
|
||||
protected:
|
||||
smart_ptr<StELFFile> m_file; //!< Parser for the ELF file.
|
||||
elf_toolset_t m_toolset; //!< Toolset that produced the ELF file.
|
||||
secinfo_clear_t m_secinfoOption; //!< How to deal with the .secinfo section. Ignored if the toolset is not GHS.
|
||||
|
||||
protected:
|
||||
//! \brief Parses the toolset option value.
|
||||
elf_toolset_t readToolsetOption();
|
||||
|
||||
//! \brief Reads the secinfoClear option.
|
||||
secinfo_clear_t readSecinfoClearOption();
|
||||
|
||||
protected:
|
||||
/*!
|
||||
* \brief A data source with ELF file sections as the contents.
|
||||
*
|
||||
* Each segment of this data source corresponds directly with a named section
|
||||
* of the ELF file it represents. When the data source is created, it contains
|
||||
* no segments. Segments are created with the addSection() method, which takes
|
||||
* the index of an ELF section and creates a corresponding segment.
|
||||
*
|
||||
* Two segment subclasses are used with this data source. The first, ProgBitsSegment,
|
||||
* is used to represent sections whose type is #SHT_PROGBITS. These sections have
|
||||
* binary data stored in the ELF file. The second segment type is NoBitsSegment.
|
||||
* It is used to represent sections whose type is #SHT_NOBITS. These sections have
|
||||
* no data, but simply allocate a region of memory to be filled with zeroes.
|
||||
* As such, the NoBitsSegment class is a subclass of DataSource::PatternSegment.
|
||||
*/
|
||||
class ELFDataSource : public DataSource
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* \brief Represents one named #SHT_PROGBITS section within the ELF file.
|
||||
*/
|
||||
class ProgBitsSegment : public DataSource::Segment
|
||||
{
|
||||
public:
|
||||
ProgBitsSegment(ELFDataSource &source, StELFFile *elf, unsigned index);
|
||||
|
||||
virtual unsigned getData(unsigned offset, unsigned maxBytes, uint8_t *buffer);
|
||||
virtual unsigned getLength();
|
||||
|
||||
virtual bool hasNaturalLocation() { return true; }
|
||||
virtual uint32_t getBaseAddress();
|
||||
|
||||
protected:
|
||||
StELFFile *m_elf; //!< The format parser instance for this ELF file.
|
||||
unsigned m_sectionIndex; //!< The index of the section this segment represents.
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Represents one named #SHT_NOBITS section within the ELF file.
|
||||
*
|
||||
* This segment class is a subclass of DataSource::PatternSegment since it
|
||||
* represents a region of memory to be filled with zeroes.
|
||||
*/
|
||||
class NoBitsSegment : public DataSource::PatternSegment
|
||||
{
|
||||
public:
|
||||
NoBitsSegment(ELFDataSource &source, StELFFile *elf, unsigned index);
|
||||
|
||||
virtual unsigned getLength();
|
||||
|
||||
virtual bool hasNaturalLocation() { return true; }
|
||||
virtual uint32_t getBaseAddress();
|
||||
|
||||
protected:
|
||||
StELFFile *m_elf; //!< The format parser instance for this ELF file.
|
||||
unsigned m_sectionIndex; //!< The index of the section this segment represents.
|
||||
};
|
||||
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
ELFDataSource(StELFFile *elf)
|
||||
: DataSource()
|
||||
, m_elf(elf)
|
||||
{
|
||||
}
|
||||
|
||||
//! \brief Destructor.
|
||||
virtual ~ELFDataSource();
|
||||
|
||||
//! Set the option to control .secinfo usage.
|
||||
inline void setSecinfoOption(secinfo_clear_t option) { m_secinfoOption = option; }
|
||||
//! \brief Adds the ELF section at position \a sectionIndex to the data source.
|
||||
void addSection(unsigned sectionIndex);
|
||||
|
||||
//! \brief Returns the number of segments in the source.
|
||||
virtual unsigned getSegmentCount() { return (unsigned)m_segments.size(); }
|
||||
//! \brief Returns the segment at position \a index.
|
||||
virtual DataSource::Segment *getSegmentAt(unsigned index) { return m_segments[index]; }
|
||||
protected:
|
||||
StELFFile *m_elf; //!< The ELF file parser.
|
||||
secinfo_clear_t m_secinfoOption; //!< How to deal with the .secinfo section. Ignored if the toolset is not GHS.
|
||||
|
||||
typedef std::vector<DataSource::Segment *> segment_vector_t; //!< A list of segment instances.
|
||||
segment_vector_t m_segments; //!< The segments of this data source.
|
||||
};
|
||||
};
|
||||
|
||||
}; // namespace blfwk
|
||||
|
||||
#endif // _ELFSourceFile_h_
|
||||
172
src/blfwk/EndianUtilities.h
Normal file
172
src/blfwk/EndianUtilities.h
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_EndianUtilities_h_)
|
||||
#define _EndianUtilities_h_
|
||||
|
||||
//! \name Swap macros
|
||||
//! These macros always swap the data.
|
||||
//@{
|
||||
|
||||
//! Byte swap 16-bit value.
|
||||
#define _BYTESWAP16(value) (((((uint16_t)value) << 8) & 0xFF00) | ((((uint16_t)value) >> 8) & 0x00FF))
|
||||
|
||||
//! Byte swap 32-bit value.
|
||||
#define _BYTESWAP32(value) \
|
||||
(((((uint32_t)value) << 24) & 0xFF000000) | ((((uint32_t)value) << 8) & 0x00FF0000) | \
|
||||
((((uint32_t)value) >> 8) & 0x0000FF00) | ((((uint32_t)value) >> 24) & 0x000000FF))
|
||||
|
||||
//! Byte swap 64-bit value.
|
||||
#define _BYTESWAP64(value) \
|
||||
(((((uint64_t)value) << 56) & 0xFF00000000000000ULL) | ((((uint64_t)value) << 40) & 0x00FF000000000000ULL) | \
|
||||
((((uint64_t)value) << 24) & 0x0000FF0000000000ULL) | ((((uint64_t)value) << 8) & 0x000000FF00000000ULL) | \
|
||||
((((uint64_t)value) >> 8) & 0x00000000FF000000ULL) | ((((uint64_t)value) >> 24) & 0x0000000000FF0000ULL) | \
|
||||
((((uint64_t)value) >> 40) & 0x000000000000FF00ULL) | ((((uint64_t)value) >> 56) & 0x00000000000000FFULL))
|
||||
|
||||
//@}
|
||||
|
||||
//! \name Inline swap functions
|
||||
//@{
|
||||
|
||||
inline uint16_t _swap_u16(uint16_t value)
|
||||
{
|
||||
return _BYTESWAP16(value);
|
||||
}
|
||||
inline int16_t _swap_s16(int16_t value)
|
||||
{
|
||||
return (int16_t)_BYTESWAP16((uint16_t)value);
|
||||
}
|
||||
|
||||
inline uint32_t _swap_u32(uint32_t value)
|
||||
{
|
||||
return _BYTESWAP32(value);
|
||||
}
|
||||
inline int32_t _swap_s32(int32_t value)
|
||||
{
|
||||
return (int32_t)_BYTESWAP32((uint32_t)value);
|
||||
}
|
||||
|
||||
inline uint64_t _swap_u64(uint64_t value)
|
||||
{
|
||||
return _BYTESWAP64(value);
|
||||
}
|
||||
inline int64_t _swap_s64(int64_t value)
|
||||
{
|
||||
return (uint64_t)_BYTESWAP64((uint64_t)value);
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
#if defined(__LITTLE_ENDIAN__)
|
||||
|
||||
/* little endian host */
|
||||
|
||||
#define ENDIAN_BIG_TO_HOST_U16(value) (_swap_u16(value))
|
||||
#define ENDIAN_HOST_TO_BIG_U16(value) (_swap_u16(value))
|
||||
|
||||
#define ENDIAN_BIG_TO_HOST_S16(value) (_swap_s16(value))
|
||||
#define ENDIAN_HOST_TO_BIG_S16(value) (_swap_s16(value))
|
||||
|
||||
#define ENDIAN_BIG_TO_HOST_U32(value) (_swap_u32(value))
|
||||
#define ENDIAN_HOST_TO_BIG_U32(value) (_swap_u32(value))
|
||||
|
||||
#define ENDIAN_BIG_TO_HOST_S32(value) (_swap_s32(value))
|
||||
#define ENDIAN_HOST_TO_BIG_S32(value) (_swap_s32(value))
|
||||
|
||||
#define ENDIAN_BIG_TO_HOST_U64(value) (_swap_u64(value))
|
||||
#define ENDIAN_HOST_TO_BIG_U64(value) (_swap_u64(value))
|
||||
|
||||
#define ENDIAN_BIG_TO_HOST_S64(value) (_swap_s64(value))
|
||||
#define ENDIAN_HOST_TO_BIG_S64(value) (_swap_s64(value))
|
||||
|
||||
/* no-ops */
|
||||
|
||||
#define ENDIAN_LITTLE_TO_HOST_U16(value) (value)
|
||||
#define ENDIAN_HOST_TO_LITTLE_U16(value) (value)
|
||||
|
||||
#define ENDIAN_LITTLE_TO_HOST_S16(value) (value)
|
||||
#define ENDIAN_HOST_TO_LITTLE_S16(value) (value)
|
||||
|
||||
#define ENDIAN_LITTLE_TO_HOST_U32(value) (value)
|
||||
#define ENDIAN_HOST_TO_LITTLE_U32(value) (value)
|
||||
|
||||
#define ENDIAN_LITTLE_TO_HOST_S32(value) (value)
|
||||
#define ENDIAN_HOST_TO_LITTLE_S32(value) (value)
|
||||
|
||||
#define ENDIAN_LITTLE_TO_HOST_U64(value) (value)
|
||||
#define ENDIAN_HOST_TO_LITTLE_U64(value) (value)
|
||||
|
||||
#define ENDIAN_LITTLE_TO_HOST_S64(value) (value)
|
||||
#define ENDIAN_HOST_TO_LITTLE_S64(value) (value)
|
||||
|
||||
#elif defined(__BIG_ENDIAN__)
|
||||
|
||||
/* big endian host */
|
||||
|
||||
#define ENDIAN_LITTLE_TO_HOST_U16(value) (_swap_u16(value))
|
||||
#define ENDIAN_HOST_TO_LITTLE_U16(value) (_swap_u16(value))
|
||||
|
||||
#define ENDIAN_LITTLE_TO_HOST_S16(value) (_swap_s16(value))
|
||||
#define ENDIAN_HOST_TO_LITTLE_S16(value) (_swap_s16(value))
|
||||
|
||||
#define ENDIAN_LITTLE_TO_HOST_U32(value) (_swap_u32(value))
|
||||
#define ENDIAN_HOST_TO_LITTLE_U32(value) (_swap_u32(value))
|
||||
|
||||
#define ENDIAN_LITTLE_TO_HOST_S32(value) (_swap_s32(value))
|
||||
#define ENDIAN_HOST_TO_LITTLE_S32(value) (_swap_s32(value))
|
||||
|
||||
#define ENDIAN_LITTLE_TO_HOST_U64(value) (_swap_u64(value))
|
||||
#define ENDIAN_HOST_TO_LITTLE_U64(value) (_swap_u64(value))
|
||||
|
||||
#define ENDIAN_LITTLE_TO_HOST_S64(value) (_swap_s64(value))
|
||||
#define ENDIAN_HOST_TO_LITTLE_S64(value) (_swap_s64(value))
|
||||
|
||||
/* no-ops */
|
||||
|
||||
#define ENDIAN_BIG_TO_HOST_U16(value) (value)
|
||||
#define ENDIAN_HOST_TO_BIG_U16(value) (value)
|
||||
|
||||
#define ENDIAN_BIG_TO_HOST_S16(value) (value)
|
||||
#define ENDIAN_HOST_TO_BIG_S16(value) (value)
|
||||
|
||||
#define ENDIAN_BIG_TO_HOST_U32(value) (value)
|
||||
#define ENDIAN_HOST_TO_BIG_U32(value) (value)
|
||||
|
||||
#define ENDIAN_BIG_TO_HOST_S32(value) (value)
|
||||
#define ENDIAN_HOST_TO_BIG_S32(value) (value)
|
||||
|
||||
#define ENDIAN_BIG_TO_HOST_U64(value) (value)
|
||||
#define ENDIAN_HOST_TO_BIG_U64(value) (value)
|
||||
|
||||
#define ENDIAN_BIG_TO_HOST_S64(value) (value)
|
||||
#define ENDIAN_HOST_TO_BIG_S64(value) (value)
|
||||
|
||||
#endif
|
||||
|
||||
#endif // _EndianUtilities_h_
|
||||
66
src/blfwk/ExcludesListMatcher.h
Normal file
66
src/blfwk/ExcludesListMatcher.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* File: ExcludesListMatcher.h
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
|
||||
* See included license file for license details.
|
||||
*/
|
||||
#if !defined(_ExcludesListMatcher_h_)
|
||||
#define _ExcludesListMatcher_h_
|
||||
|
||||
#include "GlobMatcher.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* \brief Matches strings using a series of include and exclude glob patterns.
|
||||
*
|
||||
* This string matcher class uses a sequential, ordered list of glob patterns to
|
||||
* determine whether a string matches. Attached to each pattern is an include/exclude
|
||||
* action. The patterns in the list effectively form a Boolean expression. Includes
|
||||
* act as an OR operator while excludes act as an AND NOT operator.
|
||||
*
|
||||
* Examples (plus prefix is include, minus prefix is exclude):
|
||||
* - +foo: foo
|
||||
* - -foo: !foo
|
||||
* - +foo, +bar: foo || bar
|
||||
* - +foo, -bar: foo && !bar
|
||||
* - +foo, -bar, +baz: foo && !bar || baz
|
||||
*
|
||||
* The only reason for inheriting from GlobMatcher is so we can access the protected
|
||||
* globMatch() method.
|
||||
*/
|
||||
class ExcludesListMatcher : public GlobMatcher
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
ExcludesListMatcher();
|
||||
|
||||
//! \brief Destructor.
|
||||
~ExcludesListMatcher();
|
||||
|
||||
//! \name Pattern list
|
||||
//@{
|
||||
//! \brief Add one include or exclude pattern to the end of the match list.
|
||||
void addPattern(bool isInclude, const std::string &pattern);
|
||||
//@}
|
||||
|
||||
//! \brief Performs a single string match test against testValue.
|
||||
virtual bool match(const std::string &testValue);
|
||||
|
||||
protected:
|
||||
//! \brief Information about one glob pattern entry in a match list.
|
||||
struct glob_list_item_t
|
||||
{
|
||||
bool m_isInclude; //!< True if include, false if exclude.
|
||||
std::string m_glob; //!< The glob pattern to match.
|
||||
};
|
||||
|
||||
typedef std::vector<glob_list_item_t> glob_list_t;
|
||||
glob_list_t m_patterns; //!< Ordered list of include and exclude patterns.
|
||||
};
|
||||
|
||||
}; // namespace blfwk
|
||||
|
||||
#endif // _ExcludesListMatcher_h_
|
||||
93
src/blfwk/GHSSecInfo.h
Normal file
93
src/blfwk/GHSSecInfo.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_GHSSecInfo_h_)
|
||||
#define _GHSSecInfo_h_
|
||||
|
||||
#include "StELFFile.h"
|
||||
#include "smart_ptr.h"
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* \brief Wrapper around the GHS-specific .secinfo ELF section.
|
||||
*
|
||||
* ELF files produced by the Green Hills MULTI toolset will have a
|
||||
* special .secinfo section. For the most part, this section contains
|
||||
* a list of address
|
||||
* ranges that should be filled by the C runtime startup code. The
|
||||
* address ranges correspond to those of ELF sections whose type is
|
||||
* #SHT_NOBITS. The GHS runtime uses this table instead of just filling
|
||||
* all #SHT_NOBITS sections because the linker command file can
|
||||
* be used to optionally not fill individual sections.
|
||||
*
|
||||
* The isSectionFilled() methods let calling code determine if an ELF
|
||||
* section is found in the .secinfo table. If the section is found,
|
||||
* then it should be filled.
|
||||
*/
|
||||
class GHSSecInfo
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
GHSSecInfo(StELFFile *elf);
|
||||
|
||||
//! \brief Returns true if there is a .secinfo section present in the ELF file.
|
||||
bool hasSecinfo() const { return m_hasInfo; }
|
||||
//! \brief Determines if a section should be filled.
|
||||
bool isSectionFilled(uint32_t addr, uint32_t length);
|
||||
|
||||
//! \brief Determines if \a section should be filled.
|
||||
bool isSectionFilled(const Elf32_Shdr §ion);
|
||||
|
||||
protected:
|
||||
#pragma pack(1)
|
||||
|
||||
/*!
|
||||
* \brief The structure of one .secinfo entry.
|
||||
*/
|
||||
struct ghs_secinfo_t
|
||||
{
|
||||
uint32_t m_clearAddr; //!< Address to start filling from.
|
||||
uint32_t m_clearValue; //!< Value to fill with.
|
||||
uint32_t m_numBytesToClear; //!< Number of bytes to fill.
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
protected:
|
||||
StELFFile *m_elf; //!< The parser object for our ELF file.
|
||||
bool m_hasInfo; //!< Whether .secinfo is present in the ELF file.
|
||||
smart_array_ptr<ghs_secinfo_t>
|
||||
m_info; //!< Pointer to the .secinfo entries. Will be NULL if there is no .secinfo section in the file.
|
||||
unsigned m_entryCount; //!< Number of entries in #m_info.
|
||||
};
|
||||
|
||||
}; // namespace blfwk
|
||||
|
||||
#endif // _GHSSecInfo_h_
|
||||
59
src/blfwk/GlobMatcher.h
Normal file
59
src/blfwk/GlobMatcher.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* File: GlobMatcher.h
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
|
||||
* See included license file for license details.
|
||||
*/
|
||||
#if !defined(_GlobMatcher_h_)
|
||||
#define _GlobMatcher_h_
|
||||
|
||||
#include "StringMatcher.h"
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* \brief This class uses glob pattern matching to match strings.
|
||||
*
|
||||
* Glob patterns:
|
||||
* - * matches zero or more characters
|
||||
* - ? matches any single character
|
||||
* - [set] matches any character in the set
|
||||
* - [^set] matches any character NOT in the set
|
||||
* where a set is a group of characters or ranges. a range
|
||||
* is written as two characters seperated with a hyphen: a-z denotes
|
||||
* all characters between a to z inclusive.
|
||||
* - [-set] set matches a literal hypen and any character in the set
|
||||
* - []set] matches a literal close bracket and any character in the set
|
||||
*
|
||||
* - char matches itself except where char is '*' or '?' or '['
|
||||
* - \\char matches char, including any pattern character
|
||||
*
|
||||
* Examples:
|
||||
* - a*c ac abc abbc ...
|
||||
* - a?c acc abc aXc ...
|
||||
* - a[a-z]c aac abc acc ...
|
||||
* - a[-a-z]c a-c aac abc ...
|
||||
*/
|
||||
class GlobMatcher : public StringMatcher
|
||||
{
|
||||
public:
|
||||
//! \brief Constructor.
|
||||
GlobMatcher(const std::string &pattern)
|
||||
: StringMatcher()
|
||||
, m_pattern(pattern)
|
||||
{
|
||||
}
|
||||
|
||||
//! \brief Returns whether \a testValue matches the glob pattern.
|
||||
virtual bool match(const std::string &testValue);
|
||||
|
||||
protected:
|
||||
std::string m_pattern; //!< The glob pattern to match against.
|
||||
|
||||
//! \brief Glob implementation.
|
||||
bool globMatch(const char *str, const char *p);
|
||||
};
|
||||
|
||||
}; // namespace blfwk
|
||||
|
||||
#endif // _GlobMatcher_h_
|
||||
21
src/blfwk/HexValues.h
Normal file
21
src/blfwk/HexValues.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* File: HexValues.h
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
|
||||
* See included license file for license details.
|
||||
*/
|
||||
#if !defined(_HexValues_h_)
|
||||
#define _HexValues_h_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
//! \brief Determines whether \a c is a hex digit character.
|
||||
bool isHexDigit(char c);
|
||||
|
||||
//! \brief Converts a hexidecimal character to the integer equivalent.
|
||||
uint8_t hexCharToInt(char c);
|
||||
|
||||
//! \brief Converts a hex-encoded byte to the integer equivalent.
|
||||
uint8_t hexByteToInt(const char *encodedByte);
|
||||
|
||||
#endif // _HexValues_h_
|
||||
101
src/blfwk/IntelHexSourceFile.h
Normal file
101
src/blfwk/IntelHexSourceFile.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2013-15, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_IntelHexSourceFile_h_)
|
||||
#define _IntelHexSourceFile_h_
|
||||
|
||||
#include "SourceFile.h"
|
||||
#include "StIntelHexFile.h"
|
||||
#include "StExecutableImage.h"
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* \brief Executable file in the Intel Hex format.
|
||||
*
|
||||
* Instead of presenting each Intel Hex in the file separately, this class
|
||||
* builds up a memory image of all of the records. Records next to each other
|
||||
* in memory are coalesced into a single memory region. The data source that
|
||||
* is returned from createDataSource() exposes these regions as its segments.
|
||||
*/
|
||||
class IntelHexSourceFile : public SourceFile
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
IntelHexSourceFile(const std::string &path);
|
||||
|
||||
//! \brief Destructor.
|
||||
virtual ~IntelHexSourceFile() {}
|
||||
//! \brief Test whether the \a stream contains a valid Intel Hex file.
|
||||
static bool isIntelHexFile(std::istream &stream);
|
||||
|
||||
//! \name Opening and closing
|
||||
//@{
|
||||
//! \brief Opens the file.
|
||||
virtual void open();
|
||||
|
||||
//! \brief Closes the file.
|
||||
virtual void close();
|
||||
//@}
|
||||
|
||||
//! \name Format capabilities
|
||||
//@{
|
||||
virtual bool supportsNamedSections() const { return false; }
|
||||
virtual bool supportsNamedSymbols() const { return false; }
|
||||
//@}
|
||||
|
||||
//! \name Data sources
|
||||
//@{
|
||||
//! \brief Returns data source for the entire file.
|
||||
virtual DataSource *createDataSource();
|
||||
//@}
|
||||
|
||||
//! \name Entry point
|
||||
//@{
|
||||
//! \brief Returns true if an entry point was set in the file.
|
||||
virtual bool hasEntryPoint();
|
||||
|
||||
//! \brief Returns the entry point address.
|
||||
virtual uint32_t getEntryPointAddress();
|
||||
//@}
|
||||
|
||||
protected:
|
||||
StIntelHexFile *m_file; //!< Intel Hex parser instance.
|
||||
StExecutableImage *m_image; //!< Memory image of the Intel Hex file..
|
||||
bool m_hasEntryRecord; //!< Whether a type 03 or 05 record was found.
|
||||
StIntelHexFile::IntelHex m_entryRecord; //!< Record for the entry point.
|
||||
|
||||
protected:
|
||||
//! \brief Build memory image of the Intel Hex file.
|
||||
void buildMemoryImage();
|
||||
};
|
||||
|
||||
}; // namespace blfwk
|
||||
|
||||
#endif // _IntelHexSourceFile_h_
|
||||
284
src/blfwk/Logging.h
Normal file
284
src/blfwk/Logging.h
Normal file
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_Logging_h_)
|
||||
#define _Logging_h_
|
||||
|
||||
#include <string>
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <fstream>
|
||||
|
||||
//! @addtogroup logging
|
||||
//! @{
|
||||
|
||||
/*!
|
||||
* \brief Base logger class.
|
||||
*
|
||||
* There are two types of logging levels that are used by this class. First
|
||||
* there is the filter level. Any log message that is assigned a level
|
||||
* higher than the current filter level is discarded. Secondly there is the
|
||||
* current output level. Log messages that do not have their own level
|
||||
* use the current output level to determine if they should be shown or
|
||||
* not.
|
||||
*
|
||||
* The two methods setFilterLevel() and setOutputLevel() set the filter
|
||||
* and default output logging levels, respectively. There are corresponding
|
||||
* getter methods as well. Both the filter and output levels are
|
||||
* initialized to #kInfo during object construction.
|
||||
*
|
||||
* Most use of the logger classes is expected to be through the Log
|
||||
* class. It provides static logging methods that call through to a global
|
||||
* singleton logger instance. There is also a Log::SetOutputLevel utility
|
||||
* class that makes it extremely easiy to temporarily change the default
|
||||
* output logging level.
|
||||
*
|
||||
* Of all the overloaded log() methods in this class, none of them are
|
||||
* really expected to be reimplemented by subclasses. Instead, there is
|
||||
* the single protected _log() method that takes a simple string pointer.
|
||||
* The other log methods all wind up calling _log(), so it provides a
|
||||
* single point to override. In fact, _log() is pure virtual, so subclasses
|
||||
* must implement it.
|
||||
*
|
||||
* \see Log
|
||||
*/
|
||||
class Logger
|
||||
{
|
||||
public:
|
||||
//! \brief Logging levels.
|
||||
enum log_level_t
|
||||
{
|
||||
kUrgent = 0, //!< The lowest level, for messages that must always be logged.
|
||||
kJson, //!< For machine language output only.
|
||||
kError, //!< For fatal error messages.
|
||||
kWarning, //!< For non-fatal warning messages.
|
||||
kInfo, //!< The normal log level, for status messages.
|
||||
kInfo2, //!< For verbose status messages.
|
||||
kDebug, //!< For internal reporting.
|
||||
kDebug2, //!< Highest log level; verbose debug logging.
|
||||
kInfo1 = kInfo, //!< Alias for #kInfo
|
||||
kDebug1 = kDebug //!< Alias for #kDebug
|
||||
};
|
||||
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
Logger()
|
||||
: m_filter(kInfo)
|
||||
, m_level(kInfo)
|
||||
{
|
||||
}
|
||||
|
||||
//! \brief Destructor.
|
||||
virtual ~Logger() {}
|
||||
//! \name Logging levels
|
||||
//@{
|
||||
//! \brief Changes the logging level to \a level.
|
||||
inline void setFilterLevel(log_level_t level) { m_filter = level; }
|
||||
//! \brief Returns the current logging filter level.
|
||||
inline log_level_t getFilterLevel() const { return m_filter; }
|
||||
//! \brief Changes the logging output level to \a level.
|
||||
inline void setOutputLevel(log_level_t level) { m_level = level; }
|
||||
//! \brief Returns the current logging output level.
|
||||
inline log_level_t getOutputLevel() const { return m_level; }
|
||||
//@}
|
||||
|
||||
//! \name Logging
|
||||
//@{
|
||||
//! \brief Log with format.
|
||||
virtual void log(const char *fmt, ...);
|
||||
|
||||
//! \brief Log a string object.
|
||||
virtual void log(const std::string &msg) { log(msg.c_str()); }
|
||||
//! \brief Log with format at a specific output level.
|
||||
virtual void log(log_level_t level, const char *fmt, ...);
|
||||
|
||||
//! \brief Log a string output at a specific output level.
|
||||
virtual void log(log_level_t level, const std::string &msg) { log(level, msg.c_str()); }
|
||||
//! \brief Log with format using an argument list.
|
||||
virtual void log(const char *fmt, va_list args);
|
||||
|
||||
//! \brief Log with format using an argument with a specific output level.
|
||||
virtual void log(log_level_t level, const char *fmt, va_list args);
|
||||
//@}
|
||||
|
||||
protected:
|
||||
log_level_t m_filter; //!< The current logging filter level.
|
||||
log_level_t m_level; //!< The current log output level.
|
||||
|
||||
protected:
|
||||
//! \brief The base pure virtual logging function implemented by subclasses.
|
||||
virtual void _log(const char *msg) = 0;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Wraps a set of static functions for easy global logging access.
|
||||
*
|
||||
* This class has a set of static methods that make it easy to access a global
|
||||
* logger instance without having to worry about extern symbols. It does this
|
||||
* by keeping a static member variable pointing at the singleton logger instance,
|
||||
* which is set with the setLogger() static method.
|
||||
*
|
||||
* There is also an inner utility class called SetOutputLevel that uses
|
||||
* C++ scoping rules to temporarily change the output logging level. When the
|
||||
* SetOutputLevel instance falls out of scope the output level is restored
|
||||
* to the previous value.
|
||||
*/
|
||||
class Log
|
||||
{
|
||||
public:
|
||||
//! \name Singleton logger access
|
||||
//@{
|
||||
//! \brief Returns the current global logger singleton.
|
||||
static inline Logger *getLogger() { return s_logger; }
|
||||
//! \brief Sets the global logger singleton instance.
|
||||
static inline void setLogger(Logger *logger) { s_logger = logger; }
|
||||
//@}
|
||||
|
||||
//! \name Logging
|
||||
//@{
|
||||
//! \brief Log with format.
|
||||
static void log(const char *fmt, ...);
|
||||
|
||||
//! \brief Log a string object.
|
||||
static void log(const std::string &msg);
|
||||
|
||||
//! \brief Log with format at a specific output level.
|
||||
static void log(Logger::log_level_t level, const char *fmt, ...);
|
||||
|
||||
//! \brief Log a string output at a specific output level.
|
||||
static void log(Logger::log_level_t level, const std::string &msg);
|
||||
//@}
|
||||
|
||||
//! @name Logging level helpers
|
||||
//!
|
||||
//! These static methods log a message with an implicit log level.
|
||||
//@{
|
||||
static void urgent(const char *fmt, ...); //!< Log a message with #Logger::kUrgent level.
|
||||
static void json(const char *fmt, ...); //!< Log a message with #Logger::kJson level.
|
||||
static void error(const char *fmt, ...); //!< Log a message with #Logger::kError level.
|
||||
static void warning(const char *fmt, ...); //!< Log a message with #Logger::kWarning level.
|
||||
static void info(const char *fmt, ...); //!< Log a message with #Logger::kInfo level.
|
||||
static void info2(const char *fmt, ...); //!< Log a message with #Logger::kInfo2 level.
|
||||
static void debug(const char *fmt, ...); //!< Log a message with #Logger::kDebug level.
|
||||
static void debug2(const char *fmt, ...); //!< Log a message with #Logger::kDebug2 level.
|
||||
//@}
|
||||
|
||||
protected:
|
||||
static Logger *s_logger; //!< The single global logger instance.
|
||||
|
||||
public:
|
||||
/*!
|
||||
* \brief Utility class to temporarily change the logging output level.
|
||||
*
|
||||
* This class will change the current logging output level of a given
|
||||
* logger instance. Then when it falls out of scope it will set the
|
||||
* level back to what it was originally.
|
||||
*
|
||||
* Use like this:
|
||||
* \code
|
||||
* // output level is some value here
|
||||
* {
|
||||
* Log::SetOutputLevel leveler(Logger::DEBUG);
|
||||
* // now output level is DEBUG
|
||||
* Log::log("my debug message 1");
|
||||
* Log::log("my debug message 2");
|
||||
* }
|
||||
* // output level is restored to previous value
|
||||
* \endcode
|
||||
*/
|
||||
class SetOutputLevel
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
//!
|
||||
//! Saves the current logging output level of the global logger,
|
||||
//! as managed by the Log class, and sets the new level to \a level.
|
||||
SetOutputLevel(Logger::log_level_t level)
|
||||
: m_logger(Log::getLogger())
|
||||
, m_saved(Logger::kInfo)
|
||||
{
|
||||
assert(m_logger);
|
||||
m_saved = m_logger->getOutputLevel();
|
||||
m_logger->setOutputLevel(level);
|
||||
}
|
||||
|
||||
//! \brief Constructor.
|
||||
//!
|
||||
//! Saves the current logging output level of \a logger and sets
|
||||
//! the new level to \a level.
|
||||
SetOutputLevel(Logger *logger, Logger::log_level_t level)
|
||||
: m_logger(logger)
|
||||
, m_saved(logger->getOutputLevel())
|
||||
{
|
||||
assert(m_logger);
|
||||
m_logger->setOutputLevel(level);
|
||||
}
|
||||
|
||||
//! \brief Destructor.
|
||||
//!
|
||||
//! Restores the saved logging output level.
|
||||
~SetOutputLevel() { m_logger->setOutputLevel(m_saved); }
|
||||
protected:
|
||||
Logger *m_logger; //!< The logger instance we're controlling.
|
||||
Logger::log_level_t m_saved; //!< Original logging output level.
|
||||
};
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Simple logger that writes to stdout.
|
||||
*/
|
||||
class StdoutLogger : public Logger
|
||||
{
|
||||
protected:
|
||||
//! \brief Logs the message to stdout.
|
||||
virtual void _log(const char *msg);
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Simple logger that writes to a file.
|
||||
*/
|
||||
class FileLogger : public Logger
|
||||
{
|
||||
public:
|
||||
FileLogger(const char *file_path);
|
||||
~FileLogger();
|
||||
|
||||
protected:
|
||||
//! \brief Logs the message to the file.
|
||||
virtual void _log(const char *msg);
|
||||
|
||||
//! \brief The name of the file, including the path, to log to.
|
||||
const std::string m_file_path;
|
||||
//! \brief The name of the file, including the path, to log to.
|
||||
std::ofstream m_logFile;
|
||||
};
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // _Logging_h_
|
||||
74
src/blfwk/OptionContext.h
Normal file
74
src/blfwk/OptionContext.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_OptionContext_h_)
|
||||
#define _OptionContext_h_
|
||||
|
||||
#include <string>
|
||||
#include "Value.h"
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* \brief Pure abstract interface class to a table of options.
|
||||
*/
|
||||
class OptionContext
|
||||
{
|
||||
public:
|
||||
//! @brief Force a virtual destructor.
|
||||
virtual ~OptionContext() {}
|
||||
//! \brief Detemine whether the named option is present in the table.
|
||||
//! \param name The name of the option to query.
|
||||
//! \retval true The option is present and has a value.
|
||||
//! \retval false No option with that name is in the table.
|
||||
virtual bool hasOption(const std::string &name) const = 0;
|
||||
|
||||
//! \brief Returns the option's value.
|
||||
//! \param name The name of the option.
|
||||
//! \return The value for the option named \a name.
|
||||
//! \retval NULL No option is in the table with that name.
|
||||
virtual const Value *getOption(const std::string &name) const = 0;
|
||||
|
||||
//! \brief Adds or changes an option's value.
|
||||
//!
|
||||
//! If the option was not already present in the table, it is added.
|
||||
//! Otherwise the old value is replaced.
|
||||
//!
|
||||
//! \param name The option's name.
|
||||
//! \param value New value for the option.
|
||||
virtual void setOption(const std::string &name, Value *value) = 0;
|
||||
|
||||
//! \brief Removes an option from the table.
|
||||
//! \param name The name of the option to remove.
|
||||
virtual void deleteOption(const std::string &name) = 0;
|
||||
};
|
||||
|
||||
}; // namespace blfwk
|
||||
|
||||
#endif // _OptionContext_h_
|
||||
129
src/blfwk/Packetizer.h
Normal file
129
src/blfwk/Packetizer.h
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _Packetizer_h_
|
||||
#define _Packetizer_h_
|
||||
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader/bl_peripheral.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
//! @addtogroup host_packetizers
|
||||
//! @{
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
// Forward declarations.
|
||||
class Peripheral;
|
||||
|
||||
//! @brief Packetizer status codes.
|
||||
enum _packetizer_status
|
||||
{
|
||||
kStatus_NoPingResponse = MAKE_STATUS(kStatusGroup_Packetizer, 0),
|
||||
kStatus_InvalidPacketType = MAKE_STATUS(kStatusGroup_Packetizer, 1),
|
||||
kStatus_InvalidCRC = MAKE_STATUS(kStatusGroup_Packetizer, 2),
|
||||
kStatus_NoCommandResponse = MAKE_STATUS(kStatusGroup_Packetizer, 3)
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Interface class for packetization of commands and data.
|
||||
*/
|
||||
class Packetizer
|
||||
{
|
||||
public:
|
||||
Packetizer(Peripheral *peripheral, uint32_t packetTimeoutMs)
|
||||
: m_peripheral(peripheral)
|
||||
, m_packetTimeoutMs(packetTimeoutMs)
|
||||
, m_version()
|
||||
, m_options(0)
|
||||
, m_isAbortEnabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Packetizer(){};
|
||||
|
||||
//! @brief Read a packet.
|
||||
virtual status_t readPacket(uint8_t **packet, uint32_t *packetLength, packet_type_t packetType) = 0;
|
||||
|
||||
//! @brief Write a packet.
|
||||
virtual status_t writePacket(const uint8_t *packet, uint32_t byteCount, packet_type_t packetType) = 0;
|
||||
|
||||
//! @brief Abort data phase.
|
||||
virtual void abortPacket() = 0;
|
||||
|
||||
//! @brief Send framing packet ack.
|
||||
virtual void sync() = 0;
|
||||
|
||||
//! @brief Finalize.
|
||||
virtual void finalize() = 0;
|
||||
|
||||
//! @brief Enable simulator command processor pump.
|
||||
virtual void enableSimulatorPump() = 0;
|
||||
|
||||
//! @brief Pump simulator command processor.
|
||||
virtual void pumpSimulator() = 0;
|
||||
|
||||
//! @brief Set aborted flag.
|
||||
//!
|
||||
//! Used for out-of-band flow control for simulator.
|
||||
virtual void setAborted(bool aborted) = 0;
|
||||
|
||||
//! @brief Return the max packet size.
|
||||
virtual uint32_t getMaxPacketSize() = 0;
|
||||
|
||||
//! @brief Peripheral accessor.
|
||||
virtual Peripheral *getPeripheral() { return m_peripheral; }
|
||||
//! @brief Get Framing Protocol Version
|
||||
standard_version_t getVersion() { return m_version; }
|
||||
//! @brief Get Framing Protocol Options
|
||||
uint16_t getOptions() { return m_options; }
|
||||
//! @brief Set abort packet check enable.
|
||||
void setAbortEnabled(bool isEnabled) { m_isAbortEnabled = isEnabled; }
|
||||
//! @biref Check if abort data phase is enabled.
|
||||
bool isAbortEnabled() { return m_isAbortEnabled; }
|
||||
protected:
|
||||
Peripheral *m_peripheral; //!< Peripheral to send/receive bytes on.
|
||||
standard_version_t m_version; //!< Framing protocol version.
|
||||
uint16_t m_options; //!< Framing protocol options bitfield.
|
||||
clock_t m_startTime; //!< Beginning time of packet transaction.
|
||||
uint32_t m_packetTimeoutMs;
|
||||
bool m_isAbortEnabled; //!< True if allowing abort packet. Not used by all packetizers.
|
||||
};
|
||||
|
||||
} // namespace blfwk
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // _Packetizer_h_
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
95
src/blfwk/Peripheral.h
Normal file
95
src/blfwk/Peripheral.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _Peripheral_h_
|
||||
#define _Peripheral_h_
|
||||
|
||||
#include "BusPal.h"
|
||||
#include "bootloader_common.h"
|
||||
#include <string>
|
||||
|
||||
//! @addtogroup host_peripherals
|
||||
//! @{
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* @brief Represents a peripheral.
|
||||
*
|
||||
* Interface class for objects that provide the source for commands or sink for responses.
|
||||
*/
|
||||
class Peripheral
|
||||
{
|
||||
public:
|
||||
enum _host_peripheral_types
|
||||
{
|
||||
kHostPeripheralType_None,
|
||||
kHostPeripheralType_UART,
|
||||
kHostPeripheralType_BUSPAL_UART,
|
||||
kHostPeripheralType_USB_HID,
|
||||
kHostPeripheralType_SIM
|
||||
};
|
||||
|
||||
struct PeripheralConfigData
|
||||
{
|
||||
_host_peripheral_types peripheralType;
|
||||
std::string comPortName;
|
||||
long comPortSpeed;
|
||||
uint32_t packetTimeoutMs;
|
||||
unsigned short usbHidVid;
|
||||
unsigned short usbHidPid;
|
||||
std::string usbHidSerialNumber;
|
||||
bool ping;
|
||||
BusPal::BusPalConfigData busPalConfig;
|
||||
};
|
||||
|
||||
virtual ~Peripheral(){};
|
||||
|
||||
//! @brief Read bytes.
|
||||
//!
|
||||
//! @param buffer Pointer to buffer
|
||||
//! @param requestedBytes Number of bytes to read
|
||||
//! @param timeoutMs Time in milliseconds to wait for read to complete.
|
||||
//! @param actualBytes Number of bytes actually read.
|
||||
virtual status_t read(uint8_t *buffer, uint32_t requestedBytes, uint32_t *actualBytes, uint32_t timeout) = 0;
|
||||
|
||||
//! @brief Write bytes.
|
||||
virtual status_t write(const uint8_t *buffer, uint32_t byteCount) = 0;
|
||||
};
|
||||
|
||||
} // namespace blfwk
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // _Peripheral_h_
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
56
src/blfwk/Random.h
Normal file
56
src/blfwk/Random.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* File: Random.h
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
|
||||
* See included license file for license details.
|
||||
*/
|
||||
#if !defined(_Random_h_)
|
||||
#define _Random_h_
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#ifdef WIN32
|
||||
/*!
|
||||
* This class is from the crypto++ library.
|
||||
*/
|
||||
class MicrosoftCryptoProvider
|
||||
{
|
||||
public:
|
||||
MicrosoftCryptoProvider();
|
||||
~MicrosoftCryptoProvider();
|
||||
#if defined(_WIN64)
|
||||
typedef unsigned __int64 ProviderHandle; // type HCRYPTPROV, avoid #include <windows.h>
|
||||
#else
|
||||
typedef unsigned long ProviderHandle;
|
||||
#endif
|
||||
ProviderHandle GetProviderHandle() const { return m_hProvider; }
|
||||
private:
|
||||
ProviderHandle m_hProvider;
|
||||
};
|
||||
|
||||
#pragma comment(lib, "advapi32.lib")
|
||||
#endif // WIN32
|
||||
|
||||
/*!
|
||||
* Encapsulates the Windows CryptoAPI's CryptGenRandom or /dev/urandom on Unix systems.
|
||||
*/
|
||||
class RandomNumberGenerator
|
||||
{
|
||||
public:
|
||||
RandomNumberGenerator();
|
||||
~RandomNumberGenerator();
|
||||
|
||||
uint8_t generateByte();
|
||||
void generateBlock(uint8_t *output, unsigned count);
|
||||
|
||||
protected:
|
||||
#ifdef WIN32
|
||||
#ifndef WORKAROUND_MS_BUG_Q258000
|
||||
MicrosoftCryptoProvider m_provider;
|
||||
#endif
|
||||
#else // WIN32
|
||||
int m_fd;
|
||||
#endif // WIN32
|
||||
};
|
||||
|
||||
#endif // _Random_h_
|
||||
60
src/blfwk/RijndaelCTR.h
Normal file
60
src/blfwk/RijndaelCTR.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* File: RijndaelCTR.h
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
|
||||
* See included license file for license details.
|
||||
*/
|
||||
#if !defined(_RijndaelCTR_h_)
|
||||
#define _RijndaelCTR_h_
|
||||
|
||||
#include "AESKey.h"
|
||||
#include "AESCounter.h"
|
||||
#include <string.h>
|
||||
|
||||
/*!
|
||||
* \brief Class to compute AES 128 CTR encryption/decryption.
|
||||
*
|
||||
* Currently only supports 128-bit keys and block sizes.
|
||||
*/
|
||||
class RijndaelCTR
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
BLOCK_SIZE = 16 //!< Number of bytes in one cipher block.
|
||||
};
|
||||
|
||||
//! The cipher block data type.
|
||||
typedef uint8_t block_t[BLOCK_SIZE];
|
||||
|
||||
public:
|
||||
//! \brief Constructor.
|
||||
RijndaelCTR(const AESKey<128> &key, const AESCounter<128> &counter);
|
||||
|
||||
//! \brief Encrypt data.
|
||||
void encrypt(const uint8_t *data, unsigned length, uint8_t *dest);
|
||||
|
||||
//! \brief Encrypt data.
|
||||
void decrypt(const uint8_t *data, unsigned length, uint8_t *dest);
|
||||
|
||||
//! \brief Assignment operator.
|
||||
RijndaelCTR &operator=(const RijndaelCTR &other)
|
||||
{
|
||||
m_key = other.m_key;
|
||||
m_counter = other.m_counter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
AESKey<128> m_key; //!< 128-bit key to use for encrypt/decrypt
|
||||
AESCounter<128> m_counter; //!< Counter value for encrypt/decrypt
|
||||
|
||||
void incrementCounter(AESCounter<128>::counter_t *counter);
|
||||
void baseProcess(const uint8_t *data, unsigned length, uint8_t *dest);
|
||||
|
||||
private:
|
||||
//! \brief inaccessible default constructor.
|
||||
RijndaelCTR() {}
|
||||
};
|
||||
|
||||
#endif // _RijndaelCTR_h_
|
||||
158
src/blfwk/SBSourceFile.h
Normal file
158
src/blfwk/SBSourceFile.h
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_SBSourceFile_h_)
|
||||
#define _SBSourceFile_h_
|
||||
|
||||
#include "blfwk/SourceFile.h"
|
||||
#include "blfwk/StELFFile.h"
|
||||
#include "blfwk/smart_ptr.h"
|
||||
#include "blfwk/DataSource.h"
|
||||
#include "blfwk/DataTarget.h"
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* \brief SB Format (SB) source file.
|
||||
*/
|
||||
class SBSourceFile : public BinarySourceFile
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
SBSourceFile(const std::string &path);
|
||||
|
||||
//! \brief Destructor.
|
||||
virtual ~SBSourceFile();
|
||||
|
||||
//! \brief Identifies whether the stream contains an SB file.
|
||||
static bool isSBFile(std::istream &stream);
|
||||
|
||||
//! \name Data source creation
|
||||
//@{
|
||||
//! \brief Creates an unmapped data source from the entire file.
|
||||
virtual DataSource *createDataSource();
|
||||
//@}
|
||||
|
||||
protected:
|
||||
//! An AES-128 cipher block is 16 bytes.
|
||||
typedef uint8_t cipher_block_t[16];
|
||||
|
||||
//! A SHA-1 digest is 160 bits, or 20 bytes.
|
||||
typedef uint8_t sha1_digest_t[20];
|
||||
|
||||
//! Unique identifier type for a section.
|
||||
typedef uint32_t section_id_t;
|
||||
|
||||
// All of these structures are packed to byte alignment in order to match
|
||||
// the structure on disk.
|
||||
#pragma pack(1)
|
||||
|
||||
//! Same version struct used for 3600 boot image.
|
||||
struct version_t
|
||||
{
|
||||
uint16_t m_major;
|
||||
uint16_t m_pad0;
|
||||
uint16_t m_minor;
|
||||
uint16_t m_pad1;
|
||||
uint16_t m_revision;
|
||||
uint16_t m_pad2;
|
||||
};
|
||||
|
||||
//! \brief Header for the entire boot image.
|
||||
//!
|
||||
//! Fields of this header are arranged so that those used by the bootloader ROM all come
|
||||
//! first. They are also set up so that all fields are not split across cipher block
|
||||
//! boundaries. The fields not used by the bootloader are not subject to this
|
||||
//! restraint.
|
||||
//!
|
||||
//! Image header size is always a round number of cipher blocks. The same also applies to
|
||||
//! the boot image itself. The padding, held in #blfwk::EncoreBootImage::boot_image_header_t::m_padding0
|
||||
//! and #blfwk::EncoreBootImage::boot_image_header_t::m_padding1 is filled with random bytes.
|
||||
//!
|
||||
//! The DEK dictionary, section table, and each section data region must all start on
|
||||
//! cipher block boundaries.
|
||||
//!
|
||||
//! This header is not encrypted in the image file.
|
||||
//!
|
||||
//! The m_digest field contains a SHA-1 digest of the fields of the header that follow it.
|
||||
//! It is the first field in the header so it doesn't change position or split the header
|
||||
//! in two if fields are added to the header.
|
||||
struct boot_image_header_t
|
||||
{
|
||||
union
|
||||
{
|
||||
sha1_digest_t m_digest; //!< SHA-1 digest of image header. Also used as the crypto IV.
|
||||
struct
|
||||
{
|
||||
cipher_block_t m_iv; //!< The first 16 bytes of the digest form the initialization vector.
|
||||
uint8_t m_extra[4]; //!< The leftover top four bytes of the SHA-1 digest.
|
||||
};
|
||||
};
|
||||
uint8_t m_signature[4]; //!< 'STMP', see #ROM_IMAGE_HEADER_SIGNATURE.
|
||||
uint8_t m_majorVersion; //!< Major version for the image format, see #ROM_BOOT_IMAGE_MAJOR_VERSION.
|
||||
uint8_t m_minorVersion; //!< Minor version of the boot image format, see #ROM_BOOT_IMAGE_MINOR_VERSION.
|
||||
uint16_t m_flags; //!< Flags or options associated with the entire image.
|
||||
uint32_t m_imageBlocks; //!< Size of entire image in blocks.
|
||||
uint32_t m_firstBootTagBlock; //!< Offset from start of file to the first boot tag, in blocks.
|
||||
section_id_t m_firstBootableSectionID; //!< ID of section to start booting from.
|
||||
uint16_t m_keyCount; //!< Number of entries in DEK dictionary.
|
||||
uint16_t m_keyDictionaryBlock; //!< Starting block number for the key dictionary.
|
||||
uint16_t m_headerBlocks; //!< Size of this header, including this size word, in blocks.
|
||||
uint16_t m_sectionCount; //!< Number of section headers in this table.
|
||||
uint16_t m_sectionHeaderSize; //!< Size in blocks of a section header.
|
||||
uint8_t m_padding0[2]; //!< Padding to align #m_timestamp to long word.
|
||||
uint8_t m_signature2[4]; //!< Second signature to distinguish this .sb format from the 36xx format, see
|
||||
//!#ROM_IMAGE_HEADER_SIGNATURE2.
|
||||
uint64_t m_timestamp; //!< Timestamp when image was generated in microseconds since 1-1-2000.
|
||||
version_t m_productVersion; //!< Product version.
|
||||
version_t m_componentVersion; //!< Component version.
|
||||
uint16_t m_driveTag; //!< Drive tag for the system drive which this boot image belongs to.
|
||||
uint8_t m_padding1[6]; //!< Padding to round up to next cipher block.
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
public:
|
||||
/*!
|
||||
* \brief Simple exception thrown to indicate an error in the input SB file format.
|
||||
*/
|
||||
class SBFileException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
SBFileException(const std::string &inMessage)
|
||||
: std::runtime_error(inMessage)
|
||||
{
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
}; // namespace blfwk
|
||||
|
||||
#endif // _SBSourceFile_h_
|
||||
104
src/blfwk/SRecordSourceFile.h
Normal file
104
src/blfwk/SRecordSourceFile.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_SRecordSourceFile_h_)
|
||||
#define _SRecordSourceFile_h_
|
||||
|
||||
#include "SourceFile.h"
|
||||
#include "StSRecordFile.h"
|
||||
#include "StExecutableImage.h"
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* \brief Executable file in the Motorola S-record format.
|
||||
*
|
||||
* Instead of presenting each S-record in the file separately, this class
|
||||
* builds up a memory image of all of the records. Records next to each other
|
||||
* in memory are coalesced into a single memory region. The data source that
|
||||
* is returned from createDataSource() exposes these regions as its segments.
|
||||
*
|
||||
* Because the S-record format does not support the concepts, no support is
|
||||
* provided for named sections or symbols.
|
||||
*/
|
||||
class SRecordSourceFile : public SourceFile
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
SRecordSourceFile(const std::string &path);
|
||||
|
||||
//! \brief Destructor.
|
||||
virtual ~SRecordSourceFile() {}
|
||||
//! \brief Test whether the \a stream contains a valid S-record file.
|
||||
static bool isSRecordFile(std::istream &stream);
|
||||
|
||||
//! \name Opening and closing
|
||||
//@{
|
||||
//! \brief Opens the file.
|
||||
virtual void open();
|
||||
|
||||
//! \brief Closes the file.
|
||||
virtual void close();
|
||||
//@}
|
||||
|
||||
//! \name Format capabilities
|
||||
//@{
|
||||
virtual bool supportsNamedSections() const { return false; }
|
||||
virtual bool supportsNamedSymbols() const { return false; }
|
||||
//@}
|
||||
|
||||
//! \name Data sources
|
||||
//@{
|
||||
//! \brief Returns data source for the entire file.
|
||||
virtual DataSource *createDataSource();
|
||||
//@}
|
||||
|
||||
//! \name Entry point
|
||||
//@{
|
||||
//! \brief Returns true if an entry point was set in the file.
|
||||
virtual bool hasEntryPoint();
|
||||
|
||||
//! \brief Returns the entry point address.
|
||||
virtual uint32_t getEntryPointAddress();
|
||||
//@}
|
||||
|
||||
protected:
|
||||
StSRecordFile *m_file; //!< S-record parser instance.
|
||||
StExecutableImage *m_image; //!< Memory image of the S-record file.
|
||||
bool m_hasEntryRecord; //!< Whether an S7,8,9 record was found.
|
||||
StSRecordFile::SRecord m_entryRecord; //!< Record for the entry point.
|
||||
|
||||
protected:
|
||||
//! \brief Build memory image of the S-record file.
|
||||
void buildMemoryImage();
|
||||
};
|
||||
|
||||
}; // namespace blfwk
|
||||
|
||||
#endif // _SRecordSourceFile_h_
|
||||
80
src/blfwk/SearchPath.h
Normal file
80
src/blfwk/SearchPath.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_searchpath_h_)
|
||||
#define _searchpath_h_
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
/*!
|
||||
* \brief Handles searching a list of paths for a file.
|
||||
*/
|
||||
class PathSearcher
|
||||
{
|
||||
public:
|
||||
//!
|
||||
enum _target_type
|
||||
{
|
||||
kFindFile,
|
||||
kFindDirectory
|
||||
};
|
||||
|
||||
//!
|
||||
typedef enum _target_type target_type_t;
|
||||
|
||||
protected:
|
||||
//! Global search object singleton.
|
||||
static PathSearcher *s_searcher;
|
||||
|
||||
public:
|
||||
//! \brief Access global path searching object.
|
||||
static PathSearcher &getGlobalSearcher();
|
||||
|
||||
public:
|
||||
//! \brief Constructor.
|
||||
PathSearcher() {}
|
||||
//! \brief Add a new search path to the end of the list.
|
||||
void addSearchPath(std::string &path);
|
||||
|
||||
//! \brief Attempts to locate a file by using the search paths.
|
||||
bool search(const std::string &base, target_type_t targetType, bool searchCwd, std::string &result);
|
||||
|
||||
protected:
|
||||
typedef std::list<std::string> string_list_t; //!< Linked list of strings.
|
||||
string_list_t m_paths; //!< Ordered list of paths to search.
|
||||
|
||||
//! \brief Returns whether \a path is absolute.
|
||||
bool isAbsolute(const std::string &path);
|
||||
|
||||
//! \brief Combines two paths into a single one.
|
||||
std::string joinPaths(const std::string &first, const std::string &second);
|
||||
};
|
||||
|
||||
#endif // _searchpath_h_
|
||||
169
src/blfwk/SerialPacketizer.h
Normal file
169
src/blfwk/SerialPacketizer.h
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _serial_packetizer_h_
|
||||
#define _serial_packetizer_h_
|
||||
|
||||
#include "Packetizer.h"
|
||||
#include "UartPeripheral.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "packet/serial_packet.h"
|
||||
|
||||
//! @addtogroup serial_packetizer
|
||||
//! @{
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
// Forward declarations.
|
||||
class Peripheral;
|
||||
|
||||
/*!
|
||||
* @brief Provides source and sink for packets that go over the serial peripherals.
|
||||
*/
|
||||
class SerialPacketizer : public Packetizer
|
||||
{
|
||||
public:
|
||||
//! @brief Constructor.
|
||||
SerialPacketizer(UartPeripheral *peripheral, uint32_t packetTimeoutMs);
|
||||
|
||||
//! @brief Destructor.
|
||||
virtual ~SerialPacketizer();
|
||||
|
||||
//! @brief Peripheral accessor.
|
||||
virtual UartPeripheral *getPeripheral() { return dynamic_cast<UartPeripheral *>(m_peripheral); }
|
||||
//! @brief Read a packet.
|
||||
//!
|
||||
//! Provides the address of a buffer containing the packet.
|
||||
//!
|
||||
//! @param packet Pointer location to write packet pointer
|
||||
//! @param packetLength Number of bytes in returned packet.
|
||||
virtual status_t readPacket(uint8_t **packet, uint32_t *packetLength, packet_type_t packetType);
|
||||
|
||||
//! @brief Write a packet.
|
||||
//!
|
||||
//! @param packet Pointer to packet to write.
|
||||
//! @param byteCount Number of bytes in packet.
|
||||
virtual status_t writePacket(const uint8_t *packet, uint32_t byteCount, packet_type_t packetType);
|
||||
|
||||
//! @brief Abort data phase.
|
||||
virtual void abortPacket();
|
||||
|
||||
//! @brief Send framing packet ack.
|
||||
virtual void sync();
|
||||
|
||||
//! @brief Finalize.
|
||||
virtual void finalize();
|
||||
|
||||
//! @brief Enable simulator command processor pump.
|
||||
virtual void enableSimulatorPump() {}
|
||||
//! @brief Pump simulator command processor.
|
||||
virtual void pumpSimulator() {}
|
||||
//! @brief Set aborted flag.
|
||||
virtual void setAborted(bool aborted) {}
|
||||
//! @brief Return the max packet size.
|
||||
virtual uint32_t getMaxPacketSize();
|
||||
|
||||
//! @brief Delay milliseconds.
|
||||
void host_delay(uint32_t milliseconds);
|
||||
|
||||
//! @brief Send a ping packet and receive an ack.
|
||||
//!
|
||||
//! This is a method for host only side pinging of the target. The reponse from the
|
||||
//! target to a ping packet is a ping response packet. Since the target may or may
|
||||
//! not be online there is optionally a series of retries to make the best attempt
|
||||
//! at communication possible
|
||||
//!
|
||||
//! @param retries The number of attempts that should be made.
|
||||
//! @param delay The time in milliseconds between each attempt.
|
||||
//! @param comSpeed The peripheral baud rate. Used in order to calculate the
|
||||
//! receive delay in the case of low com speeds such as 100 and 300 which need
|
||||
//! nearly a second to complete
|
||||
virtual status_t ping(int retries, unsigned int delay, ping_response_t *response, int comSpeed);
|
||||
|
||||
protected:
|
||||
//! @brief Send ACK if needed.
|
||||
status_t send_deferred_ack();
|
||||
|
||||
//! @brief Read packet using serial framing.
|
||||
//!
|
||||
//! On return, caller must call flow control method to send AckContinue or AckWait followed by Continue.
|
||||
status_t serial_packet_read(uint8_t **packet, uint32_t *packetLength, packet_type_t packetType);
|
||||
|
||||
//! @brief Write packet using serial framing.
|
||||
status_t serial_packet_write(const uint8_t *packet, uint32_t byteCount, packet_type_t packetType);
|
||||
|
||||
//! @brief Abort data phase.
|
||||
//!
|
||||
//! Respond to next host data packet with AckAbort instead of Ack
|
||||
//! (i.e. receiver data phase abort).
|
||||
void serial_packet_abort();
|
||||
|
||||
//! @brief Get max packet size.
|
||||
uint32_t serial_packet_get_max_packet_size();
|
||||
|
||||
//! @brief Send a sync packet of the specified type.
|
||||
status_t serial_packet_send_sync(uint8_t framingPacketType);
|
||||
|
||||
//! @brief Send a ping message back in response to a ping.
|
||||
status_t serial_send_ping_response();
|
||||
|
||||
//! @brief Wait for an ACK, handling NAKs as needed.
|
||||
status_t wait_for_ack_packet();
|
||||
|
||||
//! @brief Read from peripheral until entire data framing packet read.
|
||||
status_t read_data_packet(framing_data_packet_t *packet, uint8_t *data, packet_type_t packetType);
|
||||
|
||||
//! @brief Read from peripheral until start byte found.
|
||||
status_t read_start_byte(framing_header_t *header);
|
||||
|
||||
//! @brief Read from peripheral until packet header found.
|
||||
status_t read_header(framing_header_t *header);
|
||||
|
||||
//! @brief Read from peripheral until packet length found.
|
||||
status_t read_length(framing_data_packet_t *packet);
|
||||
|
||||
//! @brief Read from peripheral until crc16 is found.
|
||||
status_t read_crc16(framing_data_packet_t *packet);
|
||||
|
||||
//! @brief Calculate crc over framing data packet.
|
||||
uint16_t calculate_framing_crc16(framing_data_packet_t *packet, const uint8_t *data);
|
||||
|
||||
serial_data_t m_serialContext;
|
||||
};
|
||||
|
||||
} // namespace blfwk
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // _serial_packetizer_h_
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
109
src/blfwk/SimPacketizer.h
Normal file
109
src/blfwk/SimPacketizer.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _sim_packetizer_h_
|
||||
#define _sim_packetizer_h_
|
||||
|
||||
#include "Packetizer.h"
|
||||
#include "SimPeripheral.h"
|
||||
#include "packet/command_packet.h"
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
// Forward declarations.
|
||||
class Peripheral;
|
||||
|
||||
/*!
|
||||
* @brief Provides source and sink for packets in the simulator space.
|
||||
*/
|
||||
class SimPacketizer : public Packetizer
|
||||
{
|
||||
public:
|
||||
//! @brief Constants
|
||||
enum _simPacketizer_contants
|
||||
{
|
||||
kSimReadTimeoutMs = 5000
|
||||
};
|
||||
|
||||
public:
|
||||
//! @brief Default Constructor.
|
||||
SimPacketizer(SimPeripheral *peripheral);
|
||||
|
||||
//! @brief Destructor.
|
||||
virtual ~SimPacketizer();
|
||||
|
||||
//! @brief Peripheral accessor.
|
||||
virtual SimPeripheral *getPeripheral() { return dynamic_cast<SimPeripheral *>(m_peripheral); }
|
||||
//! @brief Read a packet.
|
||||
//!
|
||||
//! Provides the address of a buffer containing the packet.
|
||||
//!
|
||||
//! @param packet Pointer location to write packet pointer
|
||||
//! @param packetLength Number of bytes in returned packet.
|
||||
virtual status_t readPacket(uint8_t **packet, uint32_t *packetLength, packet_type_t packetType);
|
||||
|
||||
//! @brief Write a packet.
|
||||
//!
|
||||
//! @param packet Pointer to packet to write.
|
||||
//! @param byteCount Number of bytes in packet.
|
||||
virtual status_t writePacket(const uint8_t *packet, uint32_t byteCount, packet_type_t packetType);
|
||||
|
||||
//! @brief Abort data phase.
|
||||
virtual void abortPacket() { setAborted(true); }
|
||||
//! @brief Send framing packet ack.
|
||||
virtual void sync(){};
|
||||
|
||||
//! @brief Finalize.
|
||||
virtual void finalize();
|
||||
|
||||
//! @brief Enable simulator command processor pump.
|
||||
virtual void enableSimulatorPump() { m_isPumpEnabled = true; }
|
||||
//! @brief Pump simulator command processor.
|
||||
virtual void pumpSimulator();
|
||||
|
||||
//! @brief Set aborted flag.
|
||||
//!
|
||||
//! Used for out-of-band flow control for simulator.
|
||||
virtual void setAborted(bool aborted) { m_isAborted = aborted; }
|
||||
//! @brief Return the max packet size.
|
||||
virtual uint32_t getMaxPacketSize() { return kDefaultMaxPacketSize; }
|
||||
protected:
|
||||
bool m_isPumpEnabled; //!< True if simulator pump enabled.
|
||||
bool m_isAborted; //!< Data phase abort requested by receiver.
|
||||
uint8_t m_buffer[kDefaultMaxPacketSize]; //!< Buffer for bytes used to build read packet.
|
||||
};
|
||||
|
||||
} // namespace blfwk
|
||||
|
||||
#endif // _sim_packetizer_h_
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
80
src/blfwk/SimPeripheral.h
Normal file
80
src/blfwk/SimPeripheral.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _sim_peripheral_h_
|
||||
#define _sim_peripheral_h_
|
||||
|
||||
#include "blfwk/Peripheral.h"
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* @brief Peripheral that operates in the simulation space.
|
||||
*
|
||||
* Simulation peripherals are connected together using the streams provided to the init() method.
|
||||
* For example, to connect a "host" peripheral to a "device" peripheral, specify the host's output
|
||||
* stream as the device's input stream.
|
||||
*/
|
||||
class SimPeripheral : public Peripheral
|
||||
{
|
||||
public:
|
||||
//! @brief Default Constructor.
|
||||
SimPeripheral(uchar_deque_t *inStream, uchar_deque_t *outStream)
|
||||
: m_inStream(inStream)
|
||||
, m_outStream(outStream)
|
||||
{
|
||||
}
|
||||
|
||||
//! @brief Read bytes.
|
||||
//!
|
||||
//! @param buffer Pointer to buffer.
|
||||
//! @param requestedBytes Number of bytes to read.
|
||||
//! @param actualBytes Number of bytes actually read.
|
||||
//! @param timeoutMs Time in milliseconds to wait for read to complete.
|
||||
virtual status_t read(uint8_t *buffer, uint32_t requestedBytes, uint32_t *actualBytes, uint32_t timeoutMs);
|
||||
|
||||
//! @brief Write bytes.
|
||||
//!
|
||||
//! @param buffer Pointer to buffer to write
|
||||
//! @param byteCount Number of bytes to write
|
||||
virtual status_t write(const uint8_t *buffer, uint32_t byteCount);
|
||||
|
||||
protected:
|
||||
uchar_deque_t *m_inStream; //!< Writes go to this stream.
|
||||
uchar_deque_t *m_outStream; //!< Reads come from this stream.
|
||||
};
|
||||
|
||||
} // namespace blfwk
|
||||
|
||||
#endif // _sim_peripheral_h_
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
114
src/blfwk/Simulator.h
Normal file
114
src/blfwk/Simulator.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _Simulator_h_
|
||||
#define _Simulator_h_
|
||||
|
||||
#include "Bootloader.h"
|
||||
#include "Command.h"
|
||||
#include "SimulatorMemory.h"
|
||||
#include "SimPacketizer.h"
|
||||
#include "Peripheral.h"
|
||||
#include "Logging.h"
|
||||
|
||||
#include "bootloader/bl_command.h"
|
||||
#include "bootloader/bl_context.h"
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* @brief Represents the host bootloader.
|
||||
*
|
||||
* This class provides a convenient way to access other bootloader
|
||||
* framework objects.
|
||||
*/
|
||||
class Simulator : public Bootloader
|
||||
{
|
||||
public:
|
||||
//! @brief A vector of memory stores.
|
||||
typedef std::vector<blfwk::MemoryStore *> memory_vector_t;
|
||||
|
||||
//! @brief Get the singleton simulator object.
|
||||
static Simulator &getSimulator()
|
||||
{
|
||||
//! @brief Singleton object.
|
||||
static Simulator theSimulator;
|
||||
return theSimulator;
|
||||
}
|
||||
|
||||
//! @brief Destructor.
|
||||
virtual ~Simulator();
|
||||
|
||||
//! @brief Initialize.
|
||||
void init();
|
||||
|
||||
//! @brief Configure and open state files.
|
||||
//!
|
||||
//! Must be called to open or create state files.
|
||||
//!
|
||||
//! @param pathToDir Directory for state files.
|
||||
//! @param forceCreate True to re-create state files even if they exist.
|
||||
bool openStateFiles(const std::string &pathToDir, bool forceCreate);
|
||||
|
||||
//! @name Accessors.
|
||||
//@{
|
||||
|
||||
//! @brief Get the host packetizer.
|
||||
SimPacketizer *getHost() const { return dynamic_cast<SimPacketizer *>(m_hostPacketizer); }
|
||||
//! @brief Get the device packetizer.
|
||||
SimPacketizer *getDevice() const { return m_devicePacketizer; }
|
||||
//! @brief Get a device state memory store.
|
||||
//!
|
||||
//! index Index into memory map for the simulated device.
|
||||
MemoryStore *getMemoryStore(int index) const { return m_memoryStore[index]; }
|
||||
//@}
|
||||
|
||||
protected:
|
||||
//! @brief Constructor.
|
||||
Simulator();
|
||||
SimPacketizer *m_devicePacketizer; //!< Packet interface to recieve commands on.
|
||||
uchar_deque_t m_commandStream;
|
||||
uchar_deque_t m_responseStream;
|
||||
command_processor_data_t m_commandProcessor;
|
||||
bool m_areStateFilesOpen; //!< True if state files are in use
|
||||
memory_vector_t m_memoryStore; //!< Vector of memory stores, one per map entry.
|
||||
OptionsStore m_optionsStore; //!< Persistent options store.
|
||||
property_store_t m_propertyStore;
|
||||
peripheral_descriptor_t m_activePeripheral; //!< Descriptor for the active peripheral.
|
||||
FileLogger *m_logger; //!< Singleton logger instance.
|
||||
};
|
||||
|
||||
} // namespace blfwk
|
||||
|
||||
#endif // _Simulator_h_
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
294
src/blfwk/SimulatorMemory.h
Normal file
294
src/blfwk/SimulatorMemory.h
Normal file
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _Memory_h_
|
||||
#define _Memory_h_
|
||||
|
||||
#include "blfwk/host_types.h"
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* @brief Represents target device memory as a disk file.
|
||||
*/
|
||||
class MemoryStore
|
||||
{
|
||||
public:
|
||||
//! @brief Map indicies.
|
||||
enum
|
||||
{
|
||||
kMapIndexFlash = 0, //!< Flash memory
|
||||
kMapIndexSRAM = 1 //!< SRAM
|
||||
};
|
||||
|
||||
public:
|
||||
//! @brief Constructor that takes a map index.
|
||||
//!
|
||||
//! @param mapIndex Index into memory map array
|
||||
//! @param fillByte Optional byte erase value, default 0
|
||||
MemoryStore(int mapIndex, uint32_t fillByte = 0)
|
||||
: m_mapIndex(mapIndex)
|
||||
, m_fillByte(fillByte)
|
||||
, m_size(0)
|
||||
, m_startAddress(0)
|
||||
, m_memoryFile(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
//! @brief Open the store.
|
||||
//!
|
||||
//! @param pathToDir Directory for memory backing file.
|
||||
//! @param forceCreate True to re-create backing file even if it exists.
|
||||
bool open(const std::string &pathToDir, bool forceCreate);
|
||||
|
||||
//! @brief Close the store.
|
||||
void close()
|
||||
{
|
||||
if (m_memoryFile)
|
||||
{
|
||||
fclose(m_memoryFile);
|
||||
m_memoryFile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//! @brief Read from memory.
|
||||
//!
|
||||
//! The requested offset is adjusted by the store's start address to create a zero-based
|
||||
//! file offset.
|
||||
//!
|
||||
//! @param offset Offset into memory region
|
||||
//! @param size Number of bytes to read
|
||||
//! @param buffer Destination buffer
|
||||
//! @return Number of bytes read
|
||||
size_t read(long int offset, size_t size, unsigned char *buffer);
|
||||
|
||||
//! @brief Write to memory.
|
||||
//!
|
||||
//! The requested offset is adjusted by the store's start address to create a zero-based
|
||||
//! file offset.
|
||||
//!
|
||||
//! @param offset Offset into memory region
|
||||
//! @param size Number of bytes to write
|
||||
//! @param buffer Source buffer
|
||||
//! @return Number of bytes written
|
||||
size_t write(long int offset, size_t size, const unsigned char *buffer);
|
||||
|
||||
//! @brief Erase memory.
|
||||
//!
|
||||
//! The requested offset is adjusted by the store's start address to create a zero-based
|
||||
//! file offset.
|
||||
//!
|
||||
//! @param offset Offset into memory region
|
||||
//! @param size Number of bytes to erase
|
||||
void erase(long int offset, size_t size);
|
||||
|
||||
//! @brief Erase all memory.
|
||||
void erase() { erase(0, m_size); }
|
||||
protected:
|
||||
int m_mapIndex; //!< Index of memory map entry.
|
||||
uint8_t m_fillByte; //!< Erase value.
|
||||
size_t m_size; //!< Size of memory file.
|
||||
uint32_t m_startAddress; //!< Address address from map.
|
||||
FILE *m_memoryFile; //!< Handle to memory file.
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Represents target Flash memory.
|
||||
*/
|
||||
class FlashMemoryStore : public MemoryStore
|
||||
{
|
||||
public:
|
||||
//! @brief Default Constructor.
|
||||
FlashMemoryStore()
|
||||
: MemoryStore(MemoryStore::kMapIndexFlash, ~0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Represents target SRAM memory.
|
||||
*/
|
||||
class SramMemoryStore : public MemoryStore
|
||||
{
|
||||
public:
|
||||
//! @brief Default Constructor.
|
||||
SramMemoryStore()
|
||||
: MemoryStore(MemoryStore::kMapIndexSRAM)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Holds persistent options.
|
||||
*/
|
||||
class OptionsStore
|
||||
{
|
||||
public:
|
||||
//! @brief Constructor.
|
||||
OptionsStore()
|
||||
: m_optionsFile()
|
||||
{
|
||||
}
|
||||
|
||||
//! @brief Initialize the store.
|
||||
//!
|
||||
//! @param pathToDir Directory for options file.
|
||||
//! @param forceCreate True to re-create options file even if it exists.
|
||||
bool init(const std::string &pathToDir, bool forceCreate);
|
||||
|
||||
//! @brief Persist the store.
|
||||
void persist();
|
||||
|
||||
//! @name Accessors.
|
||||
//@{
|
||||
|
||||
//! @todo get/set for property store values
|
||||
|
||||
//@}
|
||||
|
||||
protected:
|
||||
std::string m_optionsFile; //!< Options file name.
|
||||
};
|
||||
|
||||
} // namespace blfwk
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Prototypes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
//! @brief Read from simulated flash memory.
|
||||
//!
|
||||
//! @param address Simulated address.
|
||||
//! @param length Number of bytes to read.
|
||||
//! @param buffer Destination buffer.
|
||||
//!
|
||||
//! @retval kStatusMemoryReadFailed
|
||||
//! @retval kStatus_Success
|
||||
status_t sim_flash_read(uint32_t address, uint32_t length, uint8_t *buffer);
|
||||
|
||||
//! @brief Write to simulated flash memory.
|
||||
//!
|
||||
//! @param address Simulated address.
|
||||
//! @param length Number of bytes to write.
|
||||
//! @param buffer Source buffer.
|
||||
//!
|
||||
//! @retval kStatusMemoryWriteFailed
|
||||
//! @retval kStatus_Success
|
||||
status_t sim_flash_write(uint32_t address, uint32_t length, const uint8_t *buffer);
|
||||
|
||||
//! @brief Fill simulated flash memory.
|
||||
//!
|
||||
//! @param address Simulated address.
|
||||
//! @param length Number of bytes to write.
|
||||
//! @param pattern 4-byte pattern.
|
||||
//!
|
||||
//! @retval kStatusMemoryWriteFailed
|
||||
//! @retval kStatus_Success
|
||||
status_t sim_flash_fill(uint32_t address, uint32_t length, uint32_t pattern);
|
||||
|
||||
//! @brief Erase simulated flash memory.
|
||||
//!
|
||||
//! @param address Simulated address.
|
||||
//! @param length Number of bytes to write.
|
||||
//!
|
||||
//! @retval kStatusMemoryWriteFailed
|
||||
//! @retval kStatus_Success
|
||||
status_t sim_flash_erase(uint32_t address, uint32_t length);
|
||||
|
||||
//! @brief Erase all simulated flash memory.
|
||||
//!
|
||||
//! @retval kStatusMemoryWriteFailed
|
||||
//! @retval kStatus_Success
|
||||
status_t sim_flash_erase_all(void);
|
||||
|
||||
//! @brief Read from simulated SRAM memory.
|
||||
//!
|
||||
//! @param address Simulated address.
|
||||
//! @param length Number of bytes to read.
|
||||
//! @param buffer Destination buffer.
|
||||
//!
|
||||
//! @retval kStatusMemoryReadFailed
|
||||
//! @retval kStatus_Success
|
||||
status_t sim_sram_mem_read(uint32_t address, uint32_t length, uint8_t *buffer);
|
||||
|
||||
//! @brief Write to simulated SRAM memory.
|
||||
//!
|
||||
//! @param address Simulated address.
|
||||
//! @param length Number of bytes to write.
|
||||
//! @param buffer Source buffer.
|
||||
//!
|
||||
//! @retval kStatusMemoryWriteFailed
|
||||
//! @retval kStatus_Success
|
||||
status_t sim_sram_mem_write(uint32_t address, uint32_t length, const uint8_t *buffer);
|
||||
|
||||
//! @brief Fill simulated SRAM memory.
|
||||
//!
|
||||
//! @param address Simulated address.
|
||||
//! @param length Number of bytes to write.
|
||||
//! @param pattern 4-byte pattern.
|
||||
//!
|
||||
//! @retval kStatusMemoryWriteFailed
|
||||
//! @retval kStatus_Success
|
||||
status_t sim_sram_mem_fill(uint32_t address, uint32_t length, uint32_t pattern);
|
||||
|
||||
//! Read from simulated device memory.
|
||||
//!
|
||||
//! Not supported.
|
||||
//!
|
||||
//! @retval kStatus_Success;
|
||||
status_t sim_device_mem_read(uint32_t address, uint32_t length, uint8_t *buffer);
|
||||
|
||||
//! Write to simulated device memory.
|
||||
//!
|
||||
//! Not supported.
|
||||
//!
|
||||
//! @retval kStatus_Success;
|
||||
status_t sim_device_mem_write(uint32_t address, uint32_t length, const uint8_t *buffer);
|
||||
|
||||
//! Fill simulated device memory.
|
||||
//!
|
||||
//! Not supported.
|
||||
//!
|
||||
//! @retval kStatus_Success;
|
||||
status_t sim_device_mem_fill(uint32_t address, uint32_t length, uint32_t pattern);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // _Memory_h_
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
204
src/blfwk/SourceFile.h
Normal file
204
src/blfwk/SourceFile.h
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_SourceFile_h_)
|
||||
#define _SourceFile_h_
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "smart_ptr.h"
|
||||
#include "DataSource.h"
|
||||
#include "DataTarget.h"
|
||||
#include "StringMatcher.h"
|
||||
#include "OptionContext.h"
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* \brief Abstract base class for a source file containing executable code.
|
||||
*
|
||||
* The purpose of this class cluster is to provide a common interface for
|
||||
* accessing the contents of different file formats. This is accomplished
|
||||
* through several small sets of methods along with the DataSource and
|
||||
* DataTarget classes.
|
||||
*
|
||||
* The primary interface for creating instances of SourceFile is the static
|
||||
* SourceFile::openFile() function. It will create the correct subclass of
|
||||
* SourceFile by inspecting the file to determine its type.
|
||||
*/
|
||||
class SourceFile
|
||||
{
|
||||
public:
|
||||
// \brief Factory function that creates the correct subclass of SourceFile.
|
||||
static SourceFile *openFile(const std::string &path);
|
||||
|
||||
//! Set of supported executable image file formats.
|
||||
enum source_file_t
|
||||
{
|
||||
kBinarySourceFile, //!< \see blfwk::BinarySourceFile
|
||||
kELFSourceFile, //!< \see blfwk::ELFSourceFile
|
||||
kIntelHexSourceFile, //!< \see blfwk::IntelHexSourceFile
|
||||
kSBSourceFile, //!< \see blfwk::SBSourceFile
|
||||
kSRecordSourceFile //!< \see blfwk::SRecordSourceFile
|
||||
};
|
||||
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
SourceFile(const std::string &path, source_file_t filetype);
|
||||
|
||||
//! \brief Destructor.
|
||||
virtual ~SourceFile();
|
||||
|
||||
//! \brief Set the option context.
|
||||
//!
|
||||
//! The source file will take ownership of the @a context and delete it
|
||||
//! when the source file is itself deleted.
|
||||
inline void setOptions(OptionContext *context) { m_options = context; }
|
||||
//! \brief Return the option context.
|
||||
inline const OptionContext *getOptions() const { return m_options; }
|
||||
//! \brief Return the file type.
|
||||
inline source_file_t getFileType() const { return m_filetype; }
|
||||
//! \brief Returns the path to the file.
|
||||
inline const std::string &getPath() const { return m_path; }
|
||||
//! \brief Get the size in bytes of the file.
|
||||
unsigned getSize() const { return m_size; }
|
||||
//! \name Opening and closing
|
||||
//@{
|
||||
//! \brief Opens the file.
|
||||
virtual void open();
|
||||
|
||||
//! \brief Closes the file.
|
||||
virtual void close();
|
||||
|
||||
//! \brief Returns whether the file is already open.
|
||||
virtual bool isOpen() const { return (bool)m_stream && const_cast<std::ifstream *>(m_stream.get())->is_open(); }
|
||||
//@}
|
||||
|
||||
//! \name Format capabilities
|
||||
//@{
|
||||
virtual bool supportsNamedSections() const = 0;
|
||||
virtual bool supportsNamedSymbols() const = 0;
|
||||
//@}
|
||||
|
||||
//! \name Data source creation
|
||||
//@{
|
||||
//! \brief Creates a data source from the entire file.
|
||||
virtual DataSource *createDataSource() = 0;
|
||||
|
||||
//! \brief Creates a data source out of one or more sections of the file.
|
||||
//!
|
||||
//! The \a selector object is used to perform the section name comparison.
|
||||
//! If the file does not support named sections, or if there is not a
|
||||
//! section with the given name, this method may return NULL.
|
||||
virtual DataSource *createDataSource(StringMatcher &matcher) { return NULL; }
|
||||
//! \brief Creates a data source out of one section of the file.
|
||||
virtual DataSource *createDataSource(const std::string §ion);
|
||||
//@}
|
||||
|
||||
//! \name Entry point
|
||||
//@{
|
||||
//! \brief Returns true if an entry point was set in the file.
|
||||
virtual bool hasEntryPoint() = 0;
|
||||
|
||||
//! \brief Returns the entry point address.
|
||||
virtual uint32_t getEntryPointAddress() { return 0; }
|
||||
//@}
|
||||
|
||||
//! \name Data target creation
|
||||
//@{
|
||||
virtual DataTarget *createDataTargetForSection(const std::string §ion) { return NULL; }
|
||||
virtual DataTarget *createDataTargetForSymbol(const std::string &symbol) { return NULL; }
|
||||
virtual DataTarget *createDataTargetForEntryPoint();
|
||||
//@}
|
||||
|
||||
//! \name Symbols
|
||||
//@{
|
||||
//! \brief Returns whether a symbol exists in the source file.
|
||||
virtual bool hasSymbol(const std::string &name) { return false; }
|
||||
//! \brief Returns the value of a symbol.
|
||||
virtual uint32_t getSymbolValue(const std::string &name) { return 0; }
|
||||
//! \brief Returns the size of a symbol.
|
||||
virtual unsigned getSymbolSize(const std::string &name) { return 0; }
|
||||
//@}
|
||||
|
||||
protected:
|
||||
std::string m_path; //!< Path to the file.
|
||||
smart_ptr<std::ifstream> m_stream; //!< File stream, or NULL if file is closed.
|
||||
smart_ptr<OptionContext> m_options; //!< Table of option values.
|
||||
source_file_t m_filetype; //!< Image file type.
|
||||
unsigned m_size; //!< The size in bytes of the file.
|
||||
|
||||
//! \brief Internal access to the input stream object.
|
||||
inline std::ifstream *getStream() { return m_stream; }
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Binary data file.
|
||||
*/
|
||||
class BinarySourceFile : public SourceFile
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
BinarySourceFile(const std::string &path, source_file_t sourceFileType = kBinarySourceFile);
|
||||
|
||||
//! \name Format capabilities
|
||||
//@{
|
||||
virtual bool supportsNamedSections() const { return false; }
|
||||
virtual bool supportsNamedSymbols() const { return false; }
|
||||
//@}
|
||||
|
||||
//! \name Data source creation
|
||||
//@{
|
||||
//! \brief Creates an unmapped data source from the entire file.
|
||||
virtual DataSource *createDataSource();
|
||||
//@}
|
||||
|
||||
//! \name Entry point
|
||||
//@{
|
||||
//! \brief Initialize entry point and stack pointer from assumed vetcor table
|
||||
//! at the beginning of the file.
|
||||
void guessEntryPointAndStackPointer();
|
||||
|
||||
//! \brief Returns true if an entry point was set in the file.
|
||||
virtual bool hasEntryPoint() { return m_entry_point != 0xffffffff; }
|
||||
//! \brief Returns the entry point address.
|
||||
virtual uint32_t getEntryPointAddress() { return m_entry_point; }
|
||||
//! \brief Returns the stack pointer.
|
||||
uint32_t getStackPointer() { return m_stack_pointer; }
|
||||
//@}
|
||||
|
||||
protected:
|
||||
uint32_t m_entry_point;
|
||||
uint32_t m_stack_pointer;
|
||||
};
|
||||
|
||||
}; // namespace blfwk
|
||||
|
||||
#endif // _SourceFile_h_
|
||||
219
src/blfwk/StELFFile.h
Normal file
219
src/blfwk/StELFFile.h
Normal file
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_StELFFile_h_)
|
||||
#define _StELFFile_h_
|
||||
|
||||
#include "blfwk/stdafx.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include "blfwk/ELF.h"
|
||||
|
||||
//! Variations of the ARM ELF format.
|
||||
typedef enum
|
||||
{
|
||||
eARMVariant = 1, //!< Standard ARM ELF specification.
|
||||
eGHSVariant, //!< Green Hills Software variant.
|
||||
eGCCVariant //!< GNU Compiler Collection variant.
|
||||
} ELFVariant_t;
|
||||
|
||||
//! Possible ARM ELF symbol types.
|
||||
typedef enum
|
||||
{
|
||||
eUnknownSymbol,
|
||||
eARMSymbol,
|
||||
eThumbSymbol,
|
||||
eDataSymbol
|
||||
} ARMSymbolType_t;
|
||||
|
||||
/*!
|
||||
* \brief Parser for Executable and Linking Format (ELF) files.
|
||||
*
|
||||
* The stream passed into the constructor needs to stay open for the life
|
||||
* of the object. This is because calls to getSectionDataAtIndex() and
|
||||
* getSegmentDataAtIndex() read the data directly from the input stream.
|
||||
*/
|
||||
class StELFFile
|
||||
{
|
||||
public:
|
||||
typedef std::vector<Elf32_Shdr>::const_iterator const_section_iterator;
|
||||
typedef std::vector<Elf32_Phdr>::const_iterator const_segment_iterator;
|
||||
|
||||
public:
|
||||
//! \brief Constructor.
|
||||
StELFFile(std::istream &inStream);
|
||||
|
||||
//! \brief Destructor.
|
||||
virtual ~StELFFile();
|
||||
|
||||
//! \name File format variant
|
||||
//@{
|
||||
//! \brief Return the ELF format variant to which this file is set.
|
||||
virtual ELFVariant_t ELFVariant() { return m_elfVariant; }
|
||||
//! \brief Set the ELF format variation to either #eARMVariant or #eGHSVariant.
|
||||
virtual void setELFVariant(ELFVariant_t variant) { m_elfVariant = variant; }
|
||||
//@}
|
||||
|
||||
//! \name File name
|
||||
//@{
|
||||
virtual void setName(const std::string &inName) { m_name = inName; }
|
||||
virtual std::string getName() const { return m_name; }
|
||||
//@}
|
||||
|
||||
//! \name ELF header
|
||||
//@{
|
||||
//! \brief Returns the ELF file header.
|
||||
inline const Elf32_Ehdr &getFileHeader() const { return m_header; }
|
||||
//@}
|
||||
|
||||
//! \name Sections
|
||||
//! Methods pertaining to the object file's sections.
|
||||
//@{
|
||||
//! \brief Returns the number of sections in the file.
|
||||
inline unsigned getSectionCount() const { return static_cast<unsigned>(m_sectionHeaders.size()); }
|
||||
//! \brief Returns a reference to section number \a inIndex.
|
||||
const Elf32_Shdr &getSectionAtIndex(unsigned inIndex) const;
|
||||
|
||||
inline const_section_iterator getSectionBegin() const { return m_sectionHeaders.begin(); }
|
||||
inline const_section_iterator getSectionEnd() const { return m_sectionHeaders.end(); }
|
||||
//! \brief Returns the index of the section with the name \a inName.
|
||||
unsigned getIndexOfSectionWithName(const std::string &inName);
|
||||
|
||||
//! \brief Returns the data for the section.
|
||||
uint8_t *getSectionDataAtIndex(unsigned inIndex);
|
||||
|
||||
//! \brief Returns the data for the section.
|
||||
uint8_t *getSectionData(const_section_iterator inSection);
|
||||
//@}
|
||||
|
||||
//! \name Segments
|
||||
//! Methods for accessing the file's program headers for segments.
|
||||
//@{
|
||||
//! \brief Returns the number of segments, or program headers, in the file.
|
||||
inline unsigned getSegmentCount() const { return static_cast<unsigned>(m_programHeaders.size()); }
|
||||
//! \brief Returns a reference to the given segment.
|
||||
const Elf32_Phdr &getSegmentAtIndex(unsigned inIndex) const;
|
||||
|
||||
inline const_segment_iterator getSegmentBegin() const { return m_programHeaders.begin(); }
|
||||
inline const_segment_iterator getSegmentEnd() const { return m_programHeaders.end(); }
|
||||
//! \brief Returns the data of the specified segment.
|
||||
uint8_t *getSegmentDataAtIndex(unsigned inIndex);
|
||||
|
||||
//! \brief Returns the data of the specified segment.
|
||||
uint8_t *getSegmentData(const_segment_iterator inSegment);
|
||||
//@}
|
||||
|
||||
//! \name String table
|
||||
//! Methods for accessing the string tables.
|
||||
//@{
|
||||
//! \brief Returns a string from the file's section name string table.
|
||||
std::string getSectionNameAtIndex(unsigned inIndex);
|
||||
|
||||
//! \brief Returns a string from any string table in the object file.
|
||||
std::string getStringAtIndex(unsigned inStringTableSectionIndex, unsigned inStringIndex);
|
||||
//@}
|
||||
|
||||
//! \name Symbol table
|
||||
//! Methods for accessing the object file's symbol table. Currently only
|
||||
//! a single symbol table with the section name ".symtab" is supported.
|
||||
//@{
|
||||
//! \brief Returns the number of symbols in the default ".symtab" symbol table.
|
||||
unsigned getSymbolCount();
|
||||
|
||||
//! \brief Returns the symbol with index \a inIndex.
|
||||
const Elf32_Sym &getSymbolAtIndex(unsigned inIndex);
|
||||
|
||||
//! \brief Returns the section index of the string table containing symbol names.
|
||||
unsigned getSymbolNameStringTableIndex() const;
|
||||
|
||||
//! \brief Returns the name of the symbol described by \a inSymbol.
|
||||
std::string getSymbolName(const Elf32_Sym &inSymbol);
|
||||
|
||||
unsigned getIndexOfSymbolAtAddress(uint32_t symbolAddress, bool strict = true);
|
||||
|
||||
ARMSymbolType_t getTypeOfSymbolAtIndex(unsigned symbolIndex);
|
||||
//@}
|
||||
|
||||
//! \name Debugging
|
||||
//@{
|
||||
void dumpSections();
|
||||
void dumpSymbolTable();
|
||||
//@}
|
||||
|
||||
protected:
|
||||
std::istream &m_stream; //!< The source stream for the ELF file.
|
||||
ELFVariant_t m_elfVariant; //!< Variant of the ARM ELF format specification.
|
||||
std::string m_name; //!< File name. (optional)
|
||||
Elf32_Ehdr m_header; //!< The ELF file header.
|
||||
std::vector<Elf32_Shdr> m_sectionHeaders; //!< All of the section headers.
|
||||
std::vector<Elf32_Phdr> m_programHeaders; //!< All of the program headers.
|
||||
unsigned m_symbolTableIndex; //!< Index of ".symtab" section, or #SHN_UNDEF if not present.
|
||||
|
||||
/*!
|
||||
* Little structure containing information about cached section data.
|
||||
*/
|
||||
struct SectionDataInfo
|
||||
{
|
||||
uint8_t *m_data; //!< Pointer to section data.
|
||||
unsigned m_size; //!< Section data size in bytes.
|
||||
bool m_swapped; //!< Has this section been byte swapped yet? Used for symbol table.
|
||||
};
|
||||
typedef std::map<unsigned, SectionDataInfo> SectionDataMap;
|
||||
SectionDataMap m_sectionDataCache; //!< Cached data of sections.
|
||||
|
||||
//! \brief Reads a section's data either from cache or from disk.
|
||||
SectionDataInfo &getCachedSectionData(unsigned inSectionIndex);
|
||||
|
||||
//! \brief Reads the file, section, and program headers into memory.
|
||||
void readFileHeaders();
|
||||
|
||||
uint8_t *readSectionData(const Elf32_Shdr &inHeader);
|
||||
uint8_t *readSegmentData(const Elf32_Phdr &inHeader);
|
||||
|
||||
//! \brief Byte swaps the symbol table data into host endianness.
|
||||
void byteSwapSymbolTable(const Elf32_Shdr &header, SectionDataInfo &info);
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Simple exception thrown to indicate an error in the input ELF file format.
|
||||
*/
|
||||
class StELFFileException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
StELFFileException(const std::string &inMessage)
|
||||
: std::runtime_error(inMessage)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _StELFFile_h_
|
||||
280
src/blfwk/StExecutableImage.h
Normal file
280
src/blfwk/StExecutableImage.h
Normal file
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_StExecutableImage_h_)
|
||||
#define _StExecutableImage_h_
|
||||
|
||||
#include "blfwk/stdafx.h"
|
||||
#include <list>
|
||||
|
||||
/*!
|
||||
* \brief Used to build a representation of memory regions.
|
||||
*
|
||||
* An intermediate representation of the memory regions and segments loaded
|
||||
* from an executable file. Also used to find contiguous segments that are
|
||||
* specified separately in the source file.
|
||||
*
|
||||
* When regions are added, an attempt is made to coalesce contiguous regions.
|
||||
* In order for this to succeed, the touching regions must be of the same
|
||||
* type and have the same permissions. Regions are also kept sorted by their
|
||||
* address range as they are added.
|
||||
*
|
||||
* \todo Implement alignment support.
|
||||
*/
|
||||
class StExecutableImage
|
||||
{
|
||||
public:
|
||||
//! Possible types of memory regions.
|
||||
typedef enum
|
||||
{
|
||||
TEXT_REGION, //!< A region containing data or instructions.
|
||||
FILL_REGION //!< Region to be initialized with zero bytes.
|
||||
} MemoryRegionType;
|
||||
|
||||
//! Memory region flag constants.
|
||||
enum
|
||||
{
|
||||
REGION_READ_FLAG = 1, //!< Region is readable.
|
||||
REGION_WRITE_FLAG = 2, //!< Region is writable.
|
||||
REGION_EXEC_FLAG = 4, //!< Region may contain executable code.
|
||||
|
||||
REGION_RW_FLAG = REGION_READ_FLAG | REGION_WRITE_FLAG, //!< Region is read-write.
|
||||
|
||||
//! Mask to access only permissions flags for a region.
|
||||
REGION_PERM_FLAG_MASK = 0x7
|
||||
};
|
||||
|
||||
/*!
|
||||
* Representation of a contiguous region of memory.
|
||||
*
|
||||
* \todo Add comparison operators so we can use the STL sort algorithm.
|
||||
*/
|
||||
struct MemoryRegion
|
||||
{
|
||||
MemoryRegionType m_type; //!< Memory region type.
|
||||
uint32_t m_address; //!< The 32-bit start address of this region.
|
||||
uint32_t m_length; //!< Number of bytes in this region.
|
||||
uint8_t *m_data; //!< Pointer to data. Will be NULL for FILL_REGION type.
|
||||
unsigned m_flags; //!< Flags for the region.
|
||||
|
||||
//! \brief Calculates the address of the last byte occupied by this region.
|
||||
inline uint32_t endAddress() const { return m_address + m_length - 1; }
|
||||
//! \brief Equality operator.
|
||||
bool operator==(const MemoryRegion &other) const;
|
||||
};
|
||||
|
||||
//! A list of #StExecutableImage::MemoryRegion objects.
|
||||
typedef std::list<MemoryRegion> MemoryRegionList;
|
||||
|
||||
//! The iterator type used to access #StExecutableImage::MemoryRegion objects. This type
|
||||
//! is used by the methods #getRegionBegin() and #getRegionEnd().
|
||||
typedef MemoryRegionList::const_iterator const_iterator;
|
||||
|
||||
//! The possible actions for regions matching an address filter range.
|
||||
typedef enum
|
||||
{
|
||||
ADDR_FILTER_NONE, //!< Do nothing.
|
||||
ADDR_FILTER_ERROR, //!< Raise an error exception.
|
||||
ADDR_FILTER_WARNING, //!< Raise a warning exception.
|
||||
ADDR_FILTER_CROP //!< Don't include the matching address range in the executable image.
|
||||
} AddressFilterAction;
|
||||
|
||||
/*!
|
||||
* An address filter consists of a single address range and an action. If a
|
||||
* memory region overlaps the filter's range then the action will be performed.
|
||||
* The possible filter actions are defined by the #AddressFilterAction enumeration.
|
||||
*/
|
||||
struct AddressFilter
|
||||
{
|
||||
AddressFilterAction m_action; //!< Action to be performed when the filter is matched.
|
||||
uint32_t m_fromAddress; //!< Start address of the filter. Should be lower than or equal to #m_toAddress.
|
||||
uint32_t m_toAddress; //!< End address of the filter. Should be higher than or equal to #m_fromAddress.
|
||||
unsigned m_priority; //!< Priority for this filter. Zero is the lowest priority.
|
||||
|
||||
//! \brief Constructor.
|
||||
AddressFilter(AddressFilterAction action, uint32_t from, uint32_t to, unsigned priority = 0)
|
||||
: m_action(action)
|
||||
, m_fromAddress(from)
|
||||
, m_toAddress(to)
|
||||
, m_priority(priority)
|
||||
{
|
||||
}
|
||||
|
||||
//! \brief Test routine.
|
||||
bool matchesMemoryRegion(const MemoryRegion ®ion) const;
|
||||
|
||||
//! \brief Compares two address filter objects.
|
||||
int compare(const AddressFilter &other) const;
|
||||
|
||||
//! \name Comparison operators
|
||||
//@{
|
||||
inline bool operator<(const AddressFilter &other) const { return compare(other) == -1; }
|
||||
inline bool operator>(const AddressFilter &other) const { return compare(other) == 1; }
|
||||
inline bool operator==(const AddressFilter &other) const { return compare(other) == 0; }
|
||||
inline bool operator<=(const AddressFilter &other) const { return compare(other) != 1; }
|
||||
inline bool operator>=(const AddressFilter &other) const { return compare(other) != -1; }
|
||||
//@}
|
||||
};
|
||||
|
||||
//! List of #StExecutableImage::AddressFilter objects.
|
||||
typedef std::list<AddressFilter> AddressFilterList;
|
||||
|
||||
//! The exception class raised for the #ADDR_FILTER_ERROR and #ADDR_FILTER_WARNING
|
||||
//! filter actions.
|
||||
class address_filter_exception
|
||||
{
|
||||
public:
|
||||
//! \brief Constructor.
|
||||
//!
|
||||
//! A local copy of \a matchingFilter is made, in case the image and/or filter
|
||||
//! are on the stack and would be disposed of when the exception is raised.
|
||||
address_filter_exception(bool isError, std::string &imageName, const AddressFilter &matchingFilter)
|
||||
: m_isError(isError)
|
||||
, m_imageName(imageName)
|
||||
, m_filter(matchingFilter)
|
||||
{
|
||||
}
|
||||
|
||||
//! \brief Returns true if the exception is an error. Otherwise the exception
|
||||
//! is for a warning.
|
||||
inline bool isError() const { return m_isError; }
|
||||
//! \brief
|
||||
inline std::string getImageName() const { return m_imageName; }
|
||||
//! \brief
|
||||
inline const AddressFilter &getMatchingFilter() const { return m_filter; }
|
||||
protected:
|
||||
bool m_isError;
|
||||
std::string m_imageName;
|
||||
AddressFilter m_filter;
|
||||
};
|
||||
|
||||
public:
|
||||
//! \brief Constructor.
|
||||
StExecutableImage(int inAlignment = 256);
|
||||
|
||||
//! \brief Copy constructor.
|
||||
StExecutableImage(const StExecutableImage &inOther);
|
||||
|
||||
//! \brief Destructor.
|
||||
virtual ~StExecutableImage();
|
||||
|
||||
//! \name Image name
|
||||
//! Methods for getting and setting the image name.
|
||||
//@{
|
||||
//! \brief Sets the image's name to \a inName.
|
||||
virtual void setName(const std::string &inName);
|
||||
|
||||
//! \brief Returns a copy of the image's name.
|
||||
virtual std::string getName() const;
|
||||
//@}
|
||||
|
||||
//! \name Regions
|
||||
//! Methods to add and access memory regions.
|
||||
//@{
|
||||
//! \brief Add a region to be filled with zeroes.
|
||||
virtual void addFillRegion(uint32_t inAddress, unsigned inLength);
|
||||
|
||||
//! \brief Add a region containing data to be loaded.
|
||||
virtual void addTextRegion(uint32_t inAddress, const uint8_t *inData, unsigned inLength);
|
||||
|
||||
//! \brief Returns the total number of regions.
|
||||
//!
|
||||
//! Note that this count may not be the same as the number of calls to
|
||||
//! addFillRegion() and addTextRegion() due to region coalescing.
|
||||
inline unsigned getRegionCount() const { return static_cast<unsigned>(m_image.size()); }
|
||||
//! \brief Returns a reference to the region specified by \a inIndex.
|
||||
const MemoryRegion &getRegionAtIndex(unsigned inIndex) const;
|
||||
|
||||
//! \brief Return an iterator to the first region.
|
||||
inline const_iterator getRegionBegin() const { return m_image.begin(); }
|
||||
//! \brief Return an iterator to the next-after-last region.
|
||||
inline const_iterator getRegionEnd() const { return m_image.end(); }
|
||||
//@}
|
||||
|
||||
//! \name Entry point
|
||||
//@{
|
||||
//! \brief Sets the entry point address.
|
||||
inline void setEntryPoint(uint32_t inEntryAddress)
|
||||
{
|
||||
m_entry = inEntryAddress;
|
||||
m_hasEntry = true;
|
||||
}
|
||||
|
||||
//! \brief Returns true if an entry point has been set.
|
||||
inline bool hasEntryPoint() const { return m_hasEntry; }
|
||||
//! \brief Returns the entry point address.
|
||||
inline uint32_t getEntryPoint() const { return hasEntryPoint() ? m_entry : 0; }
|
||||
//@}
|
||||
|
||||
//! \name Address filter
|
||||
//@{
|
||||
//! \brief Add a new address filter.
|
||||
virtual void addAddressFilter(const AddressFilter &filter);
|
||||
|
||||
//! \brief Add multiple address filters at once.
|
||||
//!
|
||||
//! The template argument \a _T must be an iterator or const iterator that
|
||||
//! dereferences to an StExecutableImage::AddressFilter reference. All filters
|
||||
//! from \a from to \a to will be added to the address filter list.
|
||||
template <typename _T>
|
||||
void addAddressFilters(_T from, _T to)
|
||||
{
|
||||
_T it = from;
|
||||
for (; it != to; ++it)
|
||||
{
|
||||
addAddressFilter(*it);
|
||||
}
|
||||
}
|
||||
|
||||
//! \brief Remove all active filters.
|
||||
virtual void clearAddressFilters();
|
||||
|
||||
//! \brief Process all active filters and perform associated actions.
|
||||
virtual void applyAddressFilters();
|
||||
//@}
|
||||
|
||||
protected:
|
||||
std::string m_name; //!< The name of the image (can be a file name, for instance).
|
||||
int m_alignment; //!< The required address alignment for each memory region.
|
||||
bool m_hasEntry; //!< True if an entry point has been set.
|
||||
uint32_t m_entry; //!< Entry point address.
|
||||
MemoryRegionList m_image; //!< The memory regions.
|
||||
AddressFilterList m_filters; //!< List of active address filters.
|
||||
|
||||
//! \brief Deletes the portion \a region that overlaps \a filter.
|
||||
void cropRegionToFilter(MemoryRegion ®ion, const AddressFilter &filter);
|
||||
|
||||
//! \brief Inserts the region in sorted order or merges with one already in the image.
|
||||
void insertOrMergeRegion(MemoryRegion &inRegion);
|
||||
|
||||
//! \brief Merges two memory regions into one.
|
||||
void mergeRegions(MemoryRegion &inOldRegion, MemoryRegion &inNewRegion);
|
||||
};
|
||||
|
||||
#endif // _StExecutableImage_h_
|
||||
178
src/blfwk/StIntelHexFile.h
Normal file
178
src/blfwk/StIntelHexFile.h
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (c) 2013-15, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_StIntelHexFile_h_)
|
||||
#define _StIntelHexFile_h_
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <istream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
|
||||
enum
|
||||
{
|
||||
//! The required first character of a Intel Hex
|
||||
INTELHEX_START_CHAR = ':',
|
||||
|
||||
//! The minimum length of a Hex. This is the start char (1) + datacount (2) +
|
||||
//! addr (4) + type (2) + check sum (2).
|
||||
INTELHEX_MIN_LENGTH = 11,
|
||||
|
||||
//! Index of the first character of the address field.
|
||||
INTELHEX_ADDRESS_START_CHAR_INDEX = 3,
|
||||
|
||||
//! Index of the first character of the record type field.
|
||||
INTELHEX_TYPE_START_CHAR_INDEX = 7,
|
||||
|
||||
//! Index of the first character of the record type field.
|
||||
INTELHEX_DATA_START_CHAR_INDEX = 9
|
||||
};
|
||||
|
||||
//! Intel Hex Record Type
|
||||
enum
|
||||
{
|
||||
//! Data Record, which contains data and a 16-bit start address for the data.
|
||||
INTELHEX_RECORD_DATA = 0x00,
|
||||
|
||||
//! End of File Record, which specifies the end of the hex file, and
|
||||
//! must occur exactly once per file in the last line of the file.
|
||||
INTELHEX_RECORD_END_OF_FILE = 0x01,
|
||||
|
||||
//! Extended Segment Address Record, which is used to specify bits 4- 19 of the Segment Base Address.
|
||||
INTELHEX_RECORD_EXTENDED_SEGMENT_ADDRESS = 0x02,
|
||||
|
||||
//! Start Segment Address Record, which is used to specify the execution start address for the object file.
|
||||
INTELHEX_RECORD_START_SEGMENT_ADDRESS = 0x03,
|
||||
|
||||
//! Extended Linear Address Record, which is used to specify bits 16- 31 of the Linear Base Address.
|
||||
INTELHEX_RECORD_EXTENDED_LINEAR_ADDRESS = 0x04,
|
||||
|
||||
//! Start Linear Address Record, which is used to specify the execution start address for the object file.
|
||||
INTELHEX_RECORD_START_LINEAR_ADDRESS = 0x05
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Intel Hex parser.
|
||||
*
|
||||
* This class takes an input stream and parses it as a Intel Hex file. While
|
||||
* the individual records that comprise the file are available for access, the
|
||||
* class also provides a higher-level view of the contents. It processes the
|
||||
* individual records and builds an image of what the memory touched by the
|
||||
* file looks like. Then you can access the contiguous sections of memory.
|
||||
*/
|
||||
class StIntelHexFile
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* Structure representing each individual line of the Intel Hex input data.
|
||||
*/
|
||||
struct IntelHex
|
||||
{
|
||||
unsigned m_dataCount; //!< The number of bytes in the data field.
|
||||
uint32_t m_address; //!< The address offset of the data.
|
||||
unsigned m_type; //!< Type of the data field. 00: Data
|
||||
//!< 01: End of File
|
||||
//!< 02: Extended Segment Address
|
||||
//!< 03: Start Segment Address
|
||||
//!< 04: Extended Linear Address
|
||||
//!< 05: Start Linear Address
|
||||
uint8_t *m_data; //!< Pointer to data, or NULL if no data for this record.
|
||||
uint8_t m_checksum; //!< The checksum byte used to verify the record.
|
||||
};
|
||||
|
||||
//! Iterator type.
|
||||
typedef std::vector<IntelHex>::const_iterator const_iterator;
|
||||
|
||||
public:
|
||||
//! \brief Constructor.
|
||||
StIntelHexFile(std::istream &inStream);
|
||||
|
||||
//! \brief Destructor.
|
||||
virtual ~StIntelHexFile();
|
||||
|
||||
//! \name File name
|
||||
//@{
|
||||
virtual void setName(const std::string &inName) { m_name = inName; }
|
||||
virtual std::string getName() const { return m_name; }
|
||||
//@}
|
||||
|
||||
//! \name Parsing
|
||||
//@{
|
||||
//! \brief Determine if the file is a Intel Hex file.
|
||||
virtual bool isIntelHexFile();
|
||||
|
||||
//! \brief Parse the entire IntelHex input stream.
|
||||
virtual void parse();
|
||||
//@}
|
||||
|
||||
//! \name Record access
|
||||
//@{
|
||||
//! \return the number of Intel Hex that have been parsed from the input stream.
|
||||
inline unsigned getRecordCount() const { return static_cast<unsigned>(m_records.size()); }
|
||||
//! \return iterator for
|
||||
inline const_iterator getBegin() const { return m_records.begin(); }
|
||||
inline const_iterator getEnd() const { return m_records.end(); }
|
||||
//@}
|
||||
|
||||
//! \name Operators
|
||||
//@{
|
||||
inline const IntelHex &operator[](unsigned inIndex) { return m_records[inIndex]; }
|
||||
//@}
|
||||
|
||||
protected:
|
||||
std::istream &m_stream; //!< The input stream for the Intel Hex data.
|
||||
std::vector<IntelHex> m_records; //!< Vector of Intel Hex in the input data.
|
||||
|
||||
std::string m_name; //!< File name. (optional)
|
||||
|
||||
//! \name Parsing utilities
|
||||
//@{
|
||||
virtual void parseLine(std::string &inLine);
|
||||
|
||||
bool isHexDigit(char c);
|
||||
int hexDigitToInt(char digit);
|
||||
int readHexByte(std::string &inString, int inIndex);
|
||||
//@}
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Simple exception thrown to indicate an error in the input Intel Hex data format.
|
||||
*/
|
||||
class StIntelHexParseException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
StIntelHexParseException(const std::string &inMessage)
|
||||
: std::runtime_error(inMessage)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _StIntelHexFile_h_
|
||||
145
src/blfwk/StSRecordFile.h
Normal file
145
src/blfwk/StSRecordFile.h
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_StSRecordFile_h_)
|
||||
#define _StSRecordFile_h_
|
||||
|
||||
//#include <stdint.h>
|
||||
#include "stdafx.h"
|
||||
#include <istream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
|
||||
enum
|
||||
{
|
||||
//! The required first character of an S-record.
|
||||
SRECORD_START_CHAR = 'S',
|
||||
|
||||
//! The minimum length of a S-record. This is the type (2) + count (2) + addr (4) + cksum (2).
|
||||
SRECORD_MIN_LENGTH = 10,
|
||||
|
||||
//! Index of the first character of the address field.
|
||||
SRECORD_ADDRESS_START_CHAR_INDEX = 4
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief S-record parser.
|
||||
*
|
||||
* This class takes an input stream and parses it as an S-record file. While
|
||||
* the individual records that comprise the file are available for access, the
|
||||
* class also provides a higher-level view of the contents. It processes the
|
||||
* individual records and builds an image of what the memory touched by the
|
||||
* file looks like. Then you can access the contiguous sections of memory.
|
||||
*/
|
||||
class StSRecordFile
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* Structure representing each individual line of the S-record input data.
|
||||
*/
|
||||
struct SRecord
|
||||
{
|
||||
unsigned m_type; //!< Record number type, such as 9 for "S9", 3 for "S3" and so on.
|
||||
unsigned m_count; //!< Number of character pairs (bytes) from address through checksum.
|
||||
uint32_t m_address; //!< The address specified as part of the S-record.
|
||||
unsigned m_dataCount; //!< Number of bytes of data.
|
||||
uint8_t *m_data; //!< Pointer to data, or NULL if no data for this record type.
|
||||
uint8_t m_checksum; //!< The checksum byte present in the S-record.
|
||||
};
|
||||
|
||||
//! Iterator type.
|
||||
typedef std::vector<SRecord>::const_iterator const_iterator;
|
||||
|
||||
public:
|
||||
//! \brief Constructor.
|
||||
StSRecordFile(std::istream &inStream);
|
||||
|
||||
//! \brief Destructor.
|
||||
virtual ~StSRecordFile();
|
||||
|
||||
//! \name File name
|
||||
//@{
|
||||
virtual void setName(const std::string &inName) { m_name = inName; }
|
||||
virtual std::string getName() const { return m_name; }
|
||||
//@}
|
||||
|
||||
//! \name Parsing
|
||||
//@{
|
||||
//! \brief Determine if the file is an S-record file.
|
||||
virtual bool isSRecordFile();
|
||||
|
||||
//! \brief Parses the entire S-record input stream.
|
||||
virtual void parse();
|
||||
//@}
|
||||
|
||||
//! \name Record access
|
||||
//@{
|
||||
//! \return the number of S-records that have been parsed from the input stream.
|
||||
inline unsigned getRecordCount() const { return static_cast<unsigned>(m_records.size()); }
|
||||
//! \return iterator for
|
||||
inline const_iterator getBegin() const { return m_records.begin(); }
|
||||
inline const_iterator getEnd() const { return m_records.end(); }
|
||||
//@}
|
||||
|
||||
//! \name Operators
|
||||
//@{
|
||||
inline const SRecord &operator[](unsigned inIndex) { return m_records[inIndex]; }
|
||||
//@}
|
||||
|
||||
protected:
|
||||
std::istream &m_stream; //!< The input stream for the S-record data.
|
||||
std::vector<SRecord> m_records; //!< Vector of S-records in the input data.
|
||||
|
||||
std::string m_name; //!< File name. (optional)
|
||||
|
||||
//! \name Parsing utilities
|
||||
//@{
|
||||
virtual void parseLine(std::string &inLine);
|
||||
|
||||
bool isHexDigit(char c);
|
||||
int hexDigitToInt(char digit);
|
||||
int readHexByte(std::string &inString, int inIndex);
|
||||
//@}
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Simple exception thrown to indicate an error in the input SRecord data format.
|
||||
*/
|
||||
class StSRecordParseException : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
StSRecordParseException(const std::string &inMessage)
|
||||
: std::runtime_error(inMessage)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _StSRecordFile_h_
|
||||
83
src/blfwk/StringMatcher.h
Normal file
83
src/blfwk/StringMatcher.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_StringMatcher_h_)
|
||||
#define _StringMatcher_h_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* \brief Abstract interface class used to select strings by name.
|
||||
*/
|
||||
class StringMatcher
|
||||
{
|
||||
public:
|
||||
//! \brief Performs a single string match test against testValue.
|
||||
//!
|
||||
//! \retval true The \a testValue argument matches.
|
||||
//! \retval false No match was made against the argument.
|
||||
virtual bool match(const std::string &testValue) = 0;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief String matcher subclass that matches all test strings.
|
||||
*/
|
||||
class WildcardMatcher : public StringMatcher
|
||||
{
|
||||
public:
|
||||
//! \brief Always returns true, indicating a positive match.
|
||||
virtual bool match(const std::string &testValue) { return true; }
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Simple string matcher that compares against a fixed value.
|
||||
*/
|
||||
class FixedMatcher : public StringMatcher
|
||||
{
|
||||
public:
|
||||
//! \brief Constructor. Sets the string to compare against to be \a fixedValue.
|
||||
FixedMatcher(const std::string &fixedValue)
|
||||
: m_value(fixedValue)
|
||||
{
|
||||
}
|
||||
|
||||
//! \brief Returns whether \a testValue is the same as the value passed to the constructor.
|
||||
//!
|
||||
//! \retval true The \a testValue argument matches the fixed compare value.
|
||||
//! \retval false The argument is not the same as the compare value.
|
||||
virtual bool match(const std::string &testValue) { return testValue == m_value; }
|
||||
protected:
|
||||
const std::string &m_value; //!< The section name to look for.
|
||||
};
|
||||
|
||||
}; // namespace blfwk
|
||||
|
||||
#endif // _StringMatcher_h_
|
||||
114
src/blfwk/UartPeripheral.h
Normal file
114
src/blfwk/UartPeripheral.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _uart_peripheral_h_
|
||||
#define _uart_peripheral_h_
|
||||
|
||||
#include "Peripheral.h"
|
||||
#include "packet/command_packet.h"
|
||||
|
||||
//! @addtogroup uart_peripheral
|
||||
//! @{
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* @brief Peripheral that talks to the target device over COM port hardware.
|
||||
*/
|
||||
class UartPeripheral : public Peripheral
|
||||
{
|
||||
public:
|
||||
//! @breif Constants.
|
||||
enum _uart_peripheral_constants
|
||||
{
|
||||
// The read() implementation for the UartPeripheral does not use this the timeout parameter.
|
||||
kUartPeripheral_UnusedTimeout = 0,
|
||||
// Serial timeout is set to this default during init().
|
||||
kUartPeripheral_DefaultReadTimeoutMs = 1000,
|
||||
kUartPeripheral_DefaultBaudRate = 9600
|
||||
};
|
||||
|
||||
public:
|
||||
//! @brief Parameterized constructor that opens the serial port.
|
||||
//!
|
||||
//! Opens and configures the port. Throws exception if port configuration fails.
|
||||
//!
|
||||
//! Note: following COM port configuration is assumed: 8 bits, 1 stop bit, no parity.
|
||||
//!
|
||||
//! @param port OS file path for COM port. For example "COM1" on Windows.
|
||||
//! @param speed Port speed, e.g. 9600.
|
||||
UartPeripheral(const char *port, long speed = kUartPeripheral_DefaultBaudRate);
|
||||
|
||||
//! @brief Destructor.
|
||||
virtual ~UartPeripheral();
|
||||
|
||||
//! @brief Flush.
|
||||
//!
|
||||
//! should be called on an open COM port in order to flush any remaining data in the UART RX buffer
|
||||
void flushRX();
|
||||
|
||||
//! @brief Read bytes.
|
||||
//!
|
||||
//! @param buffer Pointer to buffer.
|
||||
//! @param requestedBytes Number of bytes to read.
|
||||
//! @param actualBytes Number of bytes actually read.
|
||||
//! @param timeoutMs Time in milliseconds to wait for read to complete.
|
||||
virtual status_t read(uint8_t *buffer, uint32_t requestedBytes, uint32_t *actualBytes, uint32_t unused_timeoutMs);
|
||||
|
||||
//! @brief Write bytes.
|
||||
//!
|
||||
//! @param buffer Pointer to buffer to write
|
||||
//! @param byteCount Number of bytes to write
|
||||
virtual status_t write(const uint8_t *buffer, uint32_t byteCount);
|
||||
|
||||
protected:
|
||||
//! @brief Initialize.
|
||||
//!
|
||||
//! Opens and configures the port.
|
||||
//!
|
||||
//! Note: following COM port configuration is assumed: 8 bits, 1 stop bit, no parity.
|
||||
//!
|
||||
//! @param port OS file path for COM port. For example "COM1" on Windows.
|
||||
//! @param speed Port speed, e.g. 9600.
|
||||
bool init(const char *port, long speed);
|
||||
|
||||
int m_fileDescriptor; //!< Port file descriptor.
|
||||
uint8_t m_buffer[kDefaultMaxPacketSize]; //!< Buffer for bytes used to build read packet.
|
||||
};
|
||||
|
||||
} // namespace blfwk
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // _uart_peripheral_h_
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
324
src/blfwk/Updater.h
Normal file
324
src/blfwk/Updater.h
Normal file
@@ -0,0 +1,324 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_Updater_h_)
|
||||
#define _Updater_h_
|
||||
|
||||
#include "Bootloader.h"
|
||||
#include "SourceFile.h"
|
||||
|
||||
//! @addtogroup host_updater
|
||||
//! @{
|
||||
|
||||
using namespace blfwk;
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
//! @name Updater states with descriptions.
|
||||
//@{
|
||||
struct updater_enum_t
|
||||
{
|
||||
uint32_t value;
|
||||
std::string description;
|
||||
|
||||
updater_enum_t()
|
||||
: value(0)
|
||||
, description("")
|
||||
{
|
||||
}
|
||||
|
||||
updater_enum_t(uint32_t value, const char *description)
|
||||
: value(value)
|
||||
, description(description)
|
||||
{
|
||||
}
|
||||
|
||||
updater_enum_t(const updater_enum_t &old_enum)
|
||||
{
|
||||
value = old_enum.value;
|
||||
description = old_enum.description.c_str();
|
||||
}
|
||||
};
|
||||
const updater_enum_t kUpdaterState_NotReady(0, "Not ready");
|
||||
const updater_enum_t kUpdaterState_Ready(1, "Ready");
|
||||
const updater_enum_t kUpdaterState_Working(2, "Working");
|
||||
const updater_enum_t kUpdaterState_Idle(3, "Idle");
|
||||
const updater_enum_t kUpdaterState_Complete(4, "Complete");
|
||||
//@}
|
||||
|
||||
//! @name Updater tasks with descriptions.
|
||||
//@{
|
||||
const updater_enum_t kUpdaterTask_Erasing(0, "Erasing");
|
||||
const updater_enum_t kUpdaterTask_Flashing(1, "Writing");
|
||||
const updater_enum_t kUpdaterTask_Reseting(2, "Reseting");
|
||||
const updater_enum_t kUpdaterTask_Executing(3, "Jumping");
|
||||
|
||||
struct updater_task_t
|
||||
{
|
||||
updater_enum_t task_desc;
|
||||
uint32_t current;
|
||||
uint32_t total;
|
||||
|
||||
updater_task_t(const updater_enum_t &task_desc, uint32_t total)
|
||||
: task_desc(task_desc)
|
||||
, current(0)
|
||||
, total(total)
|
||||
{
|
||||
}
|
||||
|
||||
updater_task_t()
|
||||
: task_desc()
|
||||
, current(0)
|
||||
, total(0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::vector<updater_task_t> updater_task_vector_t;
|
||||
|
||||
//! @name Updater operations with descriptions.
|
||||
//@{
|
||||
const updater_enum_t kUpdaterOperation_Update(0, "Update");
|
||||
|
||||
//! @name Updater operation.
|
||||
//@{
|
||||
struct updater_operation_t
|
||||
{
|
||||
updater_enum_t operation_desc;
|
||||
updater_task_vector_t tasks;
|
||||
uint32_t current_task;
|
||||
bool user_stopped;
|
||||
|
||||
uint32_t current()
|
||||
{
|
||||
uint32_t current = 0;
|
||||
|
||||
for (uint32_t i = 0; i < current_task; ++i)
|
||||
{
|
||||
current += tasks[i].total;
|
||||
}
|
||||
|
||||
current += tasks[current_task].current;
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
uint32_t total()
|
||||
{
|
||||
uint32_t total = 0;
|
||||
for (uint32_t i = 0; i < tasks.size(); ++i)
|
||||
{
|
||||
total += tasks[i].total;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
updater_operation_t(updater_enum_t operation_desc)
|
||||
: operation_desc(operation_desc)
|
||||
, tasks()
|
||||
, current_task(0)
|
||||
, user_stopped(false)
|
||||
{
|
||||
}
|
||||
|
||||
updater_operation_t(uint32_t value, const char *description)
|
||||
: operation_desc(value, description)
|
||||
, tasks()
|
||||
, current_task(0)
|
||||
, user_stopped(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
//@}
|
||||
|
||||
/*!
|
||||
* \brief Update class contains the functionality necessary to update the
|
||||
* firmware on a device running Bootloader.
|
||||
*
|
||||
* The purpose of this class is to provide a common interface for
|
||||
* updating any device running the Kinetis Bootloader from several different file formats.
|
||||
*/
|
||||
class Updater : public Bootloader
|
||||
{
|
||||
public:
|
||||
//! \brief Default constructor.
|
||||
Updater(const Peripheral::PeripheralConfigData &config);
|
||||
|
||||
//! \brief Destructor.
|
||||
virtual ~Updater();
|
||||
|
||||
//! \name Update API.
|
||||
//@{
|
||||
//! @brief Type for the progress callback routine.
|
||||
typedef void (*progress_callback_t)(updater_operation_t *op);
|
||||
|
||||
//! @brief Struct used to monitor the Operation progress.
|
||||
updater_operation_t m_operation;
|
||||
|
||||
//! \brief Set the user-defined function to call on progress events.
|
||||
//!
|
||||
//! \param callback The function to callback with the progress data.
|
||||
void setCallback(progress_callback_t callback) { m_progressCallback = callback; }
|
||||
//! \brief Set callback for progress and abort control.
|
||||
//!
|
||||
//! \param callback The function to callback with the progress data.
|
||||
//! \param abort The variable used for abort phase control.
|
||||
void registerCallback(void (*callback)(int, int, int), bool *abort)
|
||||
{
|
||||
m_progress.registerCallback(callback, abort);
|
||||
}
|
||||
|
||||
//! \brief Program flash on the device.
|
||||
//!
|
||||
//! \exception std::runtime_error Raised if the file could not be opened successfully.
|
||||
//!
|
||||
//! \param filename The file to program into the device.
|
||||
//! \param base_address The address on the device where the file wiill be written.
|
||||
status_t flashFirmware(const char *filename, uint32_t base_address);
|
||||
|
||||
//! \brief Erase all flash blocks and release MCU security
|
||||
//!
|
||||
//! \exception std::runtime_error Raised if the FlashEraseAllUnsecure command does not
|
||||
//! return success.
|
||||
//! Raised if the FlashEraseAllUnsecure command is not
|
||||
//! supported.
|
||||
void eraseAllUnsecure();
|
||||
|
||||
//! \brief Release security using BackdoorKey
|
||||
//!
|
||||
//! \exception std::runtime_error Raised if the FlashSecurityDisable command does not
|
||||
//! return success.
|
||||
//! Raised if the FlashSecurityDisable command is not
|
||||
//! supported.
|
||||
//! Raised if the parameter is illegal
|
||||
//! \param backdoor_key The 16 hex digitals used to release the security
|
||||
void unlock(string backdoor_key);
|
||||
|
||||
//! \brief Checks if Kinetis Bootloader device supports a given command.
|
||||
//!
|
||||
//! \exception std::runtime_error Thrown if an error occurred while sending the
|
||||
//! GetProperty(kProperty_AvailableCommands) bootloader command.
|
||||
//!
|
||||
//! \param command The command to check.
|
||||
//!
|
||||
//! \return true if command is supported, false if not.
|
||||
bool isCommandSupported(const cmd_t &command);
|
||||
//@}
|
||||
//
|
||||
|
||||
//! \brief get Device's property by using get-property command.
|
||||
//!
|
||||
//! \exception std::runtime_error Thrown if an error occurred while sending the
|
||||
//! GetProperty(property) bootloader command.
|
||||
//!
|
||||
//! \param property tag
|
||||
//!
|
||||
//! \return vector of the response values.
|
||||
uint32_vector_t getProperty(property_t tag);
|
||||
|
||||
//! \brief get Device's flash sector size.
|
||||
//!
|
||||
//! \return the value of sector size.
|
||||
uint32_t getSectorSize() { return m_sector_size; };
|
||||
//! \brief get Device's flash size.
|
||||
//!
|
||||
//! \return the value of flash size.
|
||||
uint32_t getFlshSize() { return m_flashSize; };
|
||||
//! \brief Execute the FlashEraseRegion bootloader command.
|
||||
//!
|
||||
//! \exception std::runtime_error Thrown if an error occurred while sending the
|
||||
//! FlashEraseRegion(start, length) bootloader command.
|
||||
//!
|
||||
//! \param start The beginning address of the memory region to be erased.
|
||||
//!
|
||||
//! \param length The length in bytes of the memory region to be erased.
|
||||
void eraseFlashRegion(uint32_t start, uint32_t length);
|
||||
|
||||
//! \brief Execute the FlashEraseAll bootloader command.
|
||||
//!
|
||||
//! \exception std::runtime_error Thrown if an error occurred while sending the
|
||||
//! FlashEraseAll bootloader command.
|
||||
void eraseFlashAll(uint32_t memoryId);
|
||||
|
||||
//! \brief Execute the FlashProgramOnce bootloader command.
|
||||
//!
|
||||
//! \exception std::runtime_error Thrown if an error occurred while sending the
|
||||
//! FlashEraseAll bootloader command.
|
||||
//!
|
||||
//! \param index The index of a specific program once field.
|
||||
//!
|
||||
//! \param byteCount The length in bytes of a specific program once field.
|
||||
//!
|
||||
//! \param data The 8/16 hex digitals to write.
|
||||
void programOnce(uint32_t index, uint32_t byteCount, string data);
|
||||
//@}
|
||||
//
|
||||
|
||||
protected:
|
||||
//! \name Bootloader commands
|
||||
//@{
|
||||
|
||||
//! \brief Execute the write-memory bootloader command.
|
||||
//!
|
||||
//! \exception std::runtime_error Thrown if an error occurred while sending the
|
||||
//! WriteMemory(segment) bootloader command.
|
||||
//!
|
||||
//! \param [in,out] segment The DatSource::Segment that represents the data to be written to the device.
|
||||
void writeMemory(DataSource::Segment *segment);
|
||||
|
||||
//! \brief Execute the write-memory bootloader command.
|
||||
//!
|
||||
//! \exception std::runtime_error Thrown if an error occurred while sending the
|
||||
//! WriteMemory(vector<uint8_t) bootloader command.
|
||||
//!
|
||||
//! \param [in] data A vector<uchar> refernce that contains the data to be written to the device.
|
||||
//! \param [in] address The address on the device where the data will be written.
|
||||
void writeMemory(uint32_t address, const uchar_vector_t &data);
|
||||
|
||||
//! \brief Program flash procedure for SourceFile types.
|
||||
status_t flashFromSourceFile();
|
||||
|
||||
//! \brief Program flash procedure for SB files.
|
||||
status_t flashFromSBFile(const char *filename);
|
||||
|
||||
protected:
|
||||
uint32_t m_base_address; //!< Base address of the image.
|
||||
uint32_t m_sector_size; //!< Sector size of the flash on the device.
|
||||
uint32_t m_flashStart; //!< Start address of the flash on the device.
|
||||
uint32_t m_flashSize; //!< The flash size (in bytes) of the device.
|
||||
SourceFile *m_sourceFile; //!< SourceFile object.
|
||||
progress_callback_t m_progressCallback; //!< Callback used to report update progress.
|
||||
Progress m_progress; //!< Progress control.
|
||||
};
|
||||
|
||||
}; // namespace blfwk
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // _Updater_h_
|
||||
130
src/blfwk/UsbHidPacketizer.h
Normal file
130
src/blfwk/UsbHidPacketizer.h
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _usb_hid_packetizer_h_
|
||||
#define _usb_hid_packetizer_h_
|
||||
|
||||
#include "Packetizer.h"
|
||||
#include "UsbHidPeripheral.h"
|
||||
#include "hidapi.h"
|
||||
|
||||
#include "bootloader_common.h"
|
||||
|
||||
#include "bootloader_hid_report_ids.h"
|
||||
|
||||
//! @addtogroup usb_hid_packetizer
|
||||
//! @{
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* @brief Provides source and sink for packets that go over USB HID class.
|
||||
*/
|
||||
class UsbHidPacketizer : public Packetizer
|
||||
{
|
||||
public:
|
||||
//! @brief Constants
|
||||
enum _usbhid_contants
|
||||
{
|
||||
kReadFlushTimeoutMs = 100000,
|
||||
#if defined(BL_WITHOUT_RECEIVE_SB_FILE_CMD)
|
||||
kPollAbortTimeoutMs = 0,
|
||||
#else
|
||||
kPollAbortTimeoutMs = 10,
|
||||
#endif
|
||||
kPollPacketMaxRetryCnt = 50,
|
||||
kContinuousReadMargin = 2,
|
||||
};
|
||||
public:
|
||||
//! @brief Default Constructor.
|
||||
UsbHidPacketizer(UsbHidPeripheral *peripheral, uint32_t readPacketTimeoutMs);
|
||||
|
||||
//! @brief Destructor.
|
||||
virtual ~UsbHidPacketizer();
|
||||
|
||||
//! @brief Read a packet.
|
||||
//!
|
||||
//! Provides the address of a buffer containing the packet.
|
||||
//!
|
||||
//! @param packet Pointer location to write packet pointer
|
||||
//! @param packetLength Number of bytes in returned packet
|
||||
virtual status_t readPacket(uint8_t **packet, uint32_t *packetLength, packet_type_t packetType);
|
||||
|
||||
//! @brief Write a packet.
|
||||
//!
|
||||
//! @param packet Pointer to packet to write
|
||||
//! @param byteCount Number of bytes in packet
|
||||
virtual status_t writePacket(const uint8_t *packet, uint32_t byteCount, packet_type_t packetType);
|
||||
|
||||
//! @brief Abort data phase.
|
||||
virtual void abortPacket();
|
||||
|
||||
//! @brief Send framing packet ack/nak.
|
||||
virtual void sync(){};
|
||||
|
||||
//! @brief Finalize.
|
||||
virtual void finalize(){};
|
||||
|
||||
//! @brief Enable simulator command processor pump.
|
||||
virtual void enableSimulatorPump() {}
|
||||
//! @brief Pump simulator command processor.
|
||||
virtual void pumpSimulator() {}
|
||||
//! @brief Set aborted flag.
|
||||
virtual void setAborted(bool aborted) {}
|
||||
//! @brief Returns the max packet size supported
|
||||
virtual uint32_t getMaxPacketSize();
|
||||
|
||||
//! @brief Peripheral accessor.
|
||||
virtual UsbHidPeripheral *getPeripheral() { return (UsbHidPeripheral *)m_peripheral; }
|
||||
protected:
|
||||
//! @brief Flush input from device.
|
||||
virtual void flushInput();
|
||||
|
||||
//! @brief Poll overlapped read for receiver data phase abort.
|
||||
bool pollForAbortPacket();
|
||||
|
||||
protected:
|
||||
bl_hid_report_t m_report; //!< Used for building and receiving the report.
|
||||
bl_hid_report_t m_abortReport; //!< Used for received abort report.
|
||||
|
||||
private:
|
||||
uint32_t
|
||||
m_continuousReadCount; //!< Used for distinguish abort report for write-memory/receive-sb-file or read-memory
|
||||
};
|
||||
|
||||
} // namespace blfwk
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // _usb_hid_packetizer_h_
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
118
src/blfwk/UsbHidPeripheral.h
Normal file
118
src/blfwk/UsbHidPeripheral.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _UsbHidPeripheral_h_
|
||||
#define _UsbHidPeripheral_h_
|
||||
|
||||
#include "Peripheral.h"
|
||||
#include "hidapi.h"
|
||||
|
||||
//! @addtogroup host_usb_hid_peripheral
|
||||
//! @{
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* @brief Represents a USB HID peripheral.
|
||||
*
|
||||
* Interface class for objects that provide the source for commands or sink for responses.
|
||||
*/
|
||||
class UsbHidPeripheral : public Peripheral
|
||||
{
|
||||
public:
|
||||
//! @brief Constants
|
||||
enum _usbhid_contants
|
||||
{
|
||||
kDefault_Vid = 0x15a2, //!< Freescale VID
|
||||
kDefault_Pid = 0x0073, //!< PID for KL25Z48M
|
||||
};
|
||||
|
||||
public:
|
||||
//! @brief Default constructor.
|
||||
//!
|
||||
//! Uses vendor_id = kDefault_Vid and product_id = kDefault_Pid.
|
||||
UsbHidPeripheral();
|
||||
|
||||
//! @brief Parameterized constructor.
|
||||
//!
|
||||
//! @param vendor_id The Vendor ID of the USB HID device.
|
||||
//! @param product_id The Product ID of the USB HID device.
|
||||
//! @param serial_number The Serial Number of the USB HID device.
|
||||
UsbHidPeripheral(unsigned short vendor_id, unsigned short product_id, const char *serial_number);
|
||||
|
||||
//! @brief Destructor.
|
||||
virtual ~UsbHidPeripheral();
|
||||
|
||||
//! @brief Read bytes.
|
||||
//!
|
||||
//! @param buffer Pointer to buffer
|
||||
//! @param requestedBytes Number of bytes to read
|
||||
//! @param timeoutMs Time in milliseconds to wait for read to complete.
|
||||
//! @param actualBytes Number of bytes actually read.
|
||||
virtual status_t read(uint8_t *buffer, uint32_t requestedBytes, uint32_t *actualBytes, uint32_t timeoutMS);
|
||||
|
||||
//! @brief Write bytes. This is a do nothing function implemented here to satisfy abstract base class
|
||||
//! requirements. This function is not used. The write(buffer, count, timeout) function is used
|
||||
//! in this child class instead of the write(buffer, cout) function declared in the base class.
|
||||
virtual status_t write(const uint8_t *buffer, uint32_t byteCount) { return kStatus_Success; }
|
||||
//! @brief Write bytes.
|
||||
//!
|
||||
//! @param buffer Pointer to buffer to write
|
||||
//! @param byteCount Number of bytes to write
|
||||
//! @param timeoutMs Time in milliseconds to wait for write to complete.
|
||||
status_t write(const uint8_t *buffer, uint32_t byteCount, uint32_t timeoutMS);
|
||||
|
||||
//! @brief Return USB Vendor ID
|
||||
unsigned short getVendorId() { return m_vendor_id; }
|
||||
//! @brief Return USB Product ID
|
||||
unsigned short getProductId() { return m_product_id; }
|
||||
//! @brief Return USB Serial Number
|
||||
const wchar_t *getSerialNumber() { return m_serial_number.c_str(); }
|
||||
private:
|
||||
//! @brief Initialize.
|
||||
//!
|
||||
//! Opens the HID device.
|
||||
bool init();
|
||||
|
||||
unsigned short m_vendor_id;
|
||||
unsigned short m_product_id;
|
||||
std::wstring m_serial_number;
|
||||
hid_device *m_device; //!< Device handle.
|
||||
};
|
||||
|
||||
} // namespace blfwk
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // _UsbHidPeripheral_h_
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
229
src/blfwk/Value.h
Normal file
229
src/blfwk/Value.h
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_Value_h_)
|
||||
#define _Value_h_
|
||||
|
||||
#include <string>
|
||||
#include "blfwk/stdafx.h"
|
||||
#include "blfwk/int_size.h"
|
||||
#include "blfwk/Blob.h"
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
/*!
|
||||
* \brief Abstract base class for values of arbitrary types.
|
||||
*/
|
||||
class Value
|
||||
{
|
||||
public:
|
||||
Value() {}
|
||||
virtual ~Value() {}
|
||||
virtual std::string getTypeName() const = 0;
|
||||
virtual size_t getSize() const = 0;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief 32-bit signed integer value.
|
||||
*/
|
||||
class IntegerValue : public Value
|
||||
{
|
||||
public:
|
||||
IntegerValue()
|
||||
: m_value(0)
|
||||
{
|
||||
}
|
||||
IntegerValue(uint32_t value)
|
||||
: m_value(value)
|
||||
{
|
||||
}
|
||||
IntegerValue(const IntegerValue &other)
|
||||
: m_value(other.m_value)
|
||||
{
|
||||
}
|
||||
|
||||
virtual std::string getTypeName() const { return "integer"; }
|
||||
virtual size_t getSize() const { return sizeof(m_value); }
|
||||
inline uint32_t getValue() const { return m_value; }
|
||||
inline operator uint32_t() const { return m_value; }
|
||||
inline IntegerValue &operator=(uint32_t value)
|
||||
{
|
||||
m_value = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
uint32_t m_value; //!< The integer value.
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Adds a word size attribute to IntegerValue.
|
||||
*
|
||||
* The word size really only acts as an attribute that is carried along
|
||||
* with the integer value. It doesn't affect the actual value at all.
|
||||
* However, you can use the getWordSizeMask() method to mask off bits
|
||||
* that should not be there.
|
||||
*
|
||||
* The word size defaults to a 32-bit word.
|
||||
*/
|
||||
class SizedIntegerValue : public IntegerValue
|
||||
{
|
||||
public:
|
||||
SizedIntegerValue()
|
||||
: IntegerValue()
|
||||
, m_size(kWordSize)
|
||||
{
|
||||
}
|
||||
SizedIntegerValue(uint32_t value, int_size_t size = kWordSize)
|
||||
: IntegerValue(value)
|
||||
, m_size(size)
|
||||
{
|
||||
}
|
||||
SizedIntegerValue(uint16_t value)
|
||||
: IntegerValue(value)
|
||||
, m_size(kHalfWordSize)
|
||||
{
|
||||
}
|
||||
SizedIntegerValue(uint8_t value)
|
||||
: IntegerValue(value)
|
||||
, m_size(kByteSize)
|
||||
{
|
||||
}
|
||||
SizedIntegerValue(const SizedIntegerValue &other)
|
||||
: IntegerValue(other)
|
||||
, m_size(other.m_size)
|
||||
{
|
||||
}
|
||||
|
||||
virtual std::string getTypeName() const { return "sized integer"; }
|
||||
virtual size_t getSize() const;
|
||||
|
||||
inline int_size_t getWordSize() const { return m_size; }
|
||||
inline void setWordSize(int_size_t size) { m_size = size; }
|
||||
//! \brief Returns a 32-bit mask value dependant on the word size attribute.
|
||||
uint32_t getWordSizeMask() const;
|
||||
|
||||
//! \name Assignment operators
|
||||
//! These operators set the word size as well as the integer value.
|
||||
//@{
|
||||
SizedIntegerValue &operator=(uint8_t value)
|
||||
{
|
||||
m_value = value;
|
||||
m_size = kByteSize;
|
||||
return *this;
|
||||
}
|
||||
SizedIntegerValue &operator=(uint16_t value)
|
||||
{
|
||||
m_value = value;
|
||||
m_size = kHalfWordSize;
|
||||
return *this;
|
||||
}
|
||||
SizedIntegerValue &operator=(uint32_t value)
|
||||
{
|
||||
m_value = value;
|
||||
m_size = kWordSize;
|
||||
return *this;
|
||||
}
|
||||
//@}
|
||||
|
||||
protected:
|
||||
int_size_t m_size; //!< Size of the integer.
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief String value.
|
||||
*
|
||||
* Simply wraps the STL std::string class.
|
||||
*/
|
||||
class StringValue : public Value
|
||||
{
|
||||
public:
|
||||
StringValue()
|
||||
: m_value()
|
||||
{
|
||||
}
|
||||
StringValue(const std::string &value)
|
||||
: m_value(value)
|
||||
{
|
||||
}
|
||||
StringValue(const std::string *value)
|
||||
: m_value(*value)
|
||||
{
|
||||
}
|
||||
StringValue(const StringValue &other)
|
||||
: m_value(other.m_value)
|
||||
{
|
||||
}
|
||||
|
||||
virtual std::string getTypeName() const { return "string"; }
|
||||
virtual size_t getSize() const { return m_value.size(); }
|
||||
operator const char *() const { return m_value.c_str(); }
|
||||
operator const std::string &() const { return m_value; }
|
||||
operator std::string &() { return m_value; }
|
||||
operator const std::string *() { return &m_value; }
|
||||
operator std::string *() { return &m_value; }
|
||||
StringValue &operator=(const StringValue &other)
|
||||
{
|
||||
m_value = other.m_value;
|
||||
return *this;
|
||||
}
|
||||
StringValue &operator=(const std::string &value)
|
||||
{
|
||||
m_value = value;
|
||||
return *this;
|
||||
}
|
||||
StringValue &operator=(const char *value)
|
||||
{
|
||||
m_value = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string m_value;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Binary object value of arbitrary size.
|
||||
*/
|
||||
class BinaryValue : public Value, public Blob
|
||||
{
|
||||
public:
|
||||
BinaryValue()
|
||||
: Value()
|
||||
, Blob()
|
||||
{
|
||||
}
|
||||
|
||||
virtual std::string getTypeName() const { return "binary"; }
|
||||
virtual size_t getSize() const { return getLength(); }
|
||||
};
|
||||
|
||||
}; // namespace blfwk
|
||||
|
||||
#endif // _Value_h_
|
||||
48
src/blfwk/bootloader_config.h
Normal file
48
src/blfwk/bootloader_config.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef __BOOTLOADER_CONFIG_H__
|
||||
#define __BOOTLOADER_CONFIG_H__
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Definitions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// Bootloader configuration options
|
||||
//
|
||||
|
||||
#define BL_HAS_QSPI_MODULE (0)
|
||||
|
||||
#define BL_FEATURE_ENCRYPTION (0)
|
||||
|
||||
#endif // __BOOTLOADER_CONFIG_H__
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
41
src/blfwk/format_string.h
Normal file
41
src/blfwk/format_string.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_format_string_h_)
|
||||
#define _format_string_h_
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
/*!
|
||||
* \brief Returns a formatted STL string using printf format strings.
|
||||
*/
|
||||
std::string format_string(const char *fmt, ...);
|
||||
|
||||
#endif // _format_string_h_
|
||||
395
src/blfwk/hidapi.h
Normal file
395
src/blfwk/hidapi.h
Normal file
@@ -0,0 +1,395 @@
|
||||
/*******************************************************
|
||||
HIDAPI - Multi-Platform library for
|
||||
communication with HID devices.
|
||||
|
||||
Alan Ott
|
||||
Signal 11 Software
|
||||
|
||||
8/22/2009
|
||||
|
||||
Copyright 2009, All Rights Reserved.
|
||||
|
||||
At the discretion of the user of this library,
|
||||
this software may be licensed under the terms of the
|
||||
GNU General Public License v3, a BSD-Style license, or the
|
||||
original HIDAPI license as outlined in the LICENSE.txt,
|
||||
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
|
||||
files located at the root of the source distribution.
|
||||
These files may also be found in the public source
|
||||
code repository located at:
|
||||
http://github.com/signal11/hidapi .
|
||||
********************************************************/
|
||||
|
||||
/** @file
|
||||
* @defgroup API hidapi API
|
||||
*/
|
||||
|
||||
#ifndef HIDAPI_H__
|
||||
#define HIDAPI_H__
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define HID_API_EXPORT __declspec(dllexport)
|
||||
#define HID_API_CALL
|
||||
#else
|
||||
#define HID_API_EXPORT /**< API export macro */
|
||||
#define HID_API_CALL /**< API call macro */
|
||||
#endif
|
||||
|
||||
#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
struct hid_device_;
|
||||
typedef struct hid_device_ hid_device; /**< opaque hidapi structure */
|
||||
|
||||
/** hidapi info structure */
|
||||
struct hid_device_info
|
||||
{
|
||||
/** Platform-specific device path */
|
||||
char *path;
|
||||
/** Device Vendor ID */
|
||||
unsigned short vendor_id;
|
||||
/** Device Product ID */
|
||||
unsigned short product_id;
|
||||
/** Serial Number */
|
||||
wchar_t *serial_number;
|
||||
/** Device Release Number in binary-coded decimal,
|
||||
also known as Device Version Number */
|
||||
unsigned short release_number;
|
||||
/** Manufacturer String */
|
||||
wchar_t *manufacturer_string;
|
||||
/** Product string */
|
||||
wchar_t *product_string;
|
||||
/** Usage Page for this Device/Interface
|
||||
(Windows/Mac only). */
|
||||
unsigned short usage_page;
|
||||
/** Usage for this Device/Interface
|
||||
(Windows/Mac only).*/
|
||||
unsigned short usage;
|
||||
/** The USB interface which this logical device
|
||||
represents. Valid on both Linux implementations
|
||||
in all cases, and valid on the Windows implementation
|
||||
only if the device contains more than one interface. */
|
||||
int interface_number;
|
||||
|
||||
/** Pointer to the next device */
|
||||
struct hid_device_info *next;
|
||||
};
|
||||
|
||||
/** @brief Initialize the HIDAPI library.
|
||||
|
||||
This function initializes the HIDAPI library. Calling it is not
|
||||
strictly necessary, as it will be called automatically by
|
||||
hid_enumerate() and any of the hid_open_*() functions if it is
|
||||
needed. This function should be called at the beginning of
|
||||
execution however, if there is a chance of HIDAPI handles
|
||||
being opened by different threads simultaneously.
|
||||
|
||||
@ingroup API
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_init(void);
|
||||
|
||||
/** @brief Finalize the HIDAPI library.
|
||||
|
||||
This function frees all of the static data associated with
|
||||
HIDAPI. It should be called at the end of execution to avoid
|
||||
memory leaks.
|
||||
|
||||
@ingroup API
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_exit(void);
|
||||
|
||||
/** @brief Enumerate the HID Devices.
|
||||
|
||||
This function returns a linked list of all the HID devices
|
||||
attached to the system which match vendor_id and product_id.
|
||||
If @p vendor_id is set to 0 then any vendor matches.
|
||||
If @p product_id is set to 0 then any product matches.
|
||||
If @p vendor_id and @p product_id are both set to 0, then
|
||||
all HID devices will be returned.
|
||||
|
||||
@ingroup API
|
||||
@param vendor_id The Vendor ID (VID) of the types of device
|
||||
to open.
|
||||
@param product_id The Product ID (PID) of the types of
|
||||
device to open.
|
||||
|
||||
@returns
|
||||
This function returns a pointer to a linked list of type
|
||||
struct #hid_device, containing information about the HID devices
|
||||
attached to the system, or NULL in the case of failure. Free
|
||||
this linked list by calling hid_free_enumeration().
|
||||
*/
|
||||
struct hid_device_info HID_API_EXPORT *HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id);
|
||||
|
||||
/** @brief Free an enumeration Linked List
|
||||
|
||||
This function frees a linked list created by hid_enumerate().
|
||||
|
||||
@ingroup API
|
||||
@param devs Pointer to a list of struct_device returned from
|
||||
hid_enumerate().
|
||||
*/
|
||||
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs);
|
||||
|
||||
/** @brief Open a HID device using a Vendor ID (VID), Product ID
|
||||
(PID) and optionally a serial number.
|
||||
|
||||
If @p serial_number is NULL, the first device with the
|
||||
specified VID and PID is opened.
|
||||
|
||||
@ingroup API
|
||||
@param vendor_id The Vendor ID (VID) of the device to open.
|
||||
@param product_id The Product ID (PID) of the device to open.
|
||||
@param serial_number The Serial Number of the device to open
|
||||
(Optionally NULL).
|
||||
|
||||
@returns
|
||||
This function returns a pointer to a #hid_device object on
|
||||
success or NULL on failure.
|
||||
*/
|
||||
HID_API_EXPORT hid_device *HID_API_CALL hid_open(unsigned short vendor_id,
|
||||
unsigned short product_id,
|
||||
const wchar_t *serial_number);
|
||||
|
||||
/** @brief Open a HID device by its path name.
|
||||
|
||||
The path name be determined by calling hid_enumerate(), or a
|
||||
platform-specific path name can be used (eg: /dev/hidraw0 on
|
||||
Linux).
|
||||
|
||||
@ingroup API
|
||||
@param path The path name of the device to open
|
||||
|
||||
@returns
|
||||
This function returns a pointer to a #hid_device object on
|
||||
success or NULL on failure.
|
||||
*/
|
||||
HID_API_EXPORT hid_device *HID_API_CALL hid_open_path(const char *path);
|
||||
|
||||
/** @brief Write an Output report to a HID device.
|
||||
|
||||
The first byte of @p data[] must contain the Report ID. For
|
||||
devices which only support a single report, this must be set
|
||||
to 0x0. The remaining bytes contain the report data. Since
|
||||
the Report ID is mandatory, calls to hid_write() will always
|
||||
contain one more byte than the report contains. For example,
|
||||
if a hid report is 16 bytes long, 17 bytes must be passed to
|
||||
hid_write(), the Report ID (or 0x0, for devices with a
|
||||
single report), followed by the report data (16 bytes). In
|
||||
this example, the length passed in would be 17.
|
||||
|
||||
hid_write() will send the data on the first OUT endpoint, if
|
||||
one exists. If it does not, it will send the data through
|
||||
the Control Endpoint (Endpoint 0).
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param data The data to send, including the report number as
|
||||
the first byte.
|
||||
@param length The length in bytes of the data to send.
|
||||
|
||||
@returns
|
||||
This function returns the actual number of bytes written and
|
||||
-1 on error.
|
||||
*/
|
||||
#ifdef LINUX
|
||||
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length);
|
||||
#else
|
||||
int HID_API_EXPORT HID_API_CALL hid_write_timeout(hid_device *device,
|
||||
const unsigned char *data,
|
||||
size_t length,
|
||||
int milliseconds);
|
||||
#endif
|
||||
|
||||
/** @brief Read an Input report from a HID device with timeout.
|
||||
|
||||
Input reports are returned
|
||||
to the host through the INTERRUPT IN endpoint. The first byte will
|
||||
contain the Report number if the device uses numbered reports.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param data A buffer to put the read data into.
|
||||
@param length The number of bytes to read. For devices with
|
||||
multiple reports, make sure to read an extra byte for
|
||||
the report number.
|
||||
@param milliseconds timeout in milliseconds or -1 for blocking wait.
|
||||
|
||||
@returns
|
||||
This function returns the actual number of bytes read and
|
||||
-1 on error. If no packet was available to be read within
|
||||
the timeout period, this function returns 0.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds);
|
||||
|
||||
/** @brief Read an Input report from a HID device.
|
||||
|
||||
Input reports are returned
|
||||
to the host through the INTERRUPT IN endpoint. The first byte will
|
||||
contain the Report number if the device uses numbered reports.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param data A buffer to put the read data into.
|
||||
@param length The number of bytes to read. For devices with
|
||||
multiple reports, make sure to read an extra byte for
|
||||
the report number.
|
||||
|
||||
@returns
|
||||
This function returns the actual number of bytes read and
|
||||
-1 on error. If no packet was available to be read and
|
||||
the handle is in non-blocking mode, this function returns 0.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length);
|
||||
|
||||
/** @brief Set the device handle to be non-blocking.
|
||||
|
||||
In non-blocking mode calls to hid_read() will return
|
||||
immediately with a value of 0 if there is no data to be
|
||||
read. In blocking mode, hid_read() will wait (block) until
|
||||
there is data to read before returning.
|
||||
|
||||
Nonblocking can be turned on and off at any time.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param nonblock enable or not the nonblocking reads
|
||||
- 1 to enable nonblocking
|
||||
- 0 to disable nonblocking.
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock);
|
||||
|
||||
/** @brief Send a Feature report to the device.
|
||||
|
||||
Feature reports are sent over the Control endpoint as a
|
||||
Set_Report transfer. The first byte of @p data[] must
|
||||
contain the Report ID. For devices which only support a
|
||||
single report, this must be set to 0x0. The remaining bytes
|
||||
contain the report data. Since the Report ID is mandatory,
|
||||
calls to hid_send_feature_report() will always contain one
|
||||
more byte than the report contains. For example, if a hid
|
||||
report is 16 bytes long, 17 bytes must be passed to
|
||||
hid_send_feature_report(): the Report ID (or 0x0, for
|
||||
devices which do not use numbered reports), followed by the
|
||||
report data (16 bytes). In this example, the length passed
|
||||
in would be 17.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param data The data to send, including the report number as
|
||||
the first byte.
|
||||
@param length The length in bytes of the data to send, including
|
||||
the report number.
|
||||
|
||||
@returns
|
||||
This function returns the actual number of bytes written and
|
||||
-1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length);
|
||||
|
||||
/** @brief Get a feature report from a HID device.
|
||||
|
||||
Make sure to set the first byte of @p data[] to the Report
|
||||
ID of the report to be read. Make sure to allow space for
|
||||
this extra byte in @p data[].
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param data A buffer to put the read data into, including
|
||||
the Report ID. Set the first byte of @p data[] to the
|
||||
Report ID of the report to be read.
|
||||
@param length The number of bytes to read, including an
|
||||
extra byte for the report ID. The buffer can be longer
|
||||
than the actual report.
|
||||
|
||||
@returns
|
||||
This function returns the number of bytes read and
|
||||
-1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length);
|
||||
|
||||
/** @brief Close a HID device.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
*/
|
||||
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device);
|
||||
|
||||
/** @brief Get The Manufacturer String from a HID device.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param string A wide string buffer to put the data into.
|
||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen);
|
||||
|
||||
/** @brief Get The Product String from a HID device.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param string A wide string buffer to put the data into.
|
||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen);
|
||||
|
||||
/** @brief Get The Serial Number String from a HID device.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param string A wide string buffer to put the data into.
|
||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen);
|
||||
|
||||
/** @brief Get a string from a HID device, based on its string index.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
@param string_index The index of the string to get.
|
||||
@param string A wide string buffer to put the data into.
|
||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
||||
|
||||
@returns
|
||||
This function returns 0 on success and -1 on error.
|
||||
*/
|
||||
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen);
|
||||
|
||||
/** @brief Get a string describing the last error which occurred.
|
||||
|
||||
@ingroup API
|
||||
@param device A device handle returned from hid_open().
|
||||
|
||||
@returns
|
||||
This function returns a string containing the last error
|
||||
which occurred or NULL if none has occurred.
|
||||
*/
|
||||
HID_API_EXPORT const wchar_t *HID_API_CALL hid_error(hid_device *device);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
57
src/blfwk/host_types.h
Normal file
57
src/blfwk/host_types.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _host_types_h_
|
||||
#define _host_types_h_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
|
||||
//! @brief An array of strings.
|
||||
typedef std::vector<std::string> string_vector_t;
|
||||
|
||||
//! @brief An array of bytes.
|
||||
typedef std::vector<unsigned char> uchar_vector_t;
|
||||
|
||||
//! @brief An array of uint32_t's.
|
||||
typedef std::vector<uint32_t> uint32_vector_t;
|
||||
|
||||
//! @brief A stream of bytes.
|
||||
typedef std::deque<unsigned char> uchar_deque_t;
|
||||
|
||||
#endif // _host_types_h_
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
45
src/blfwk/int_size.h
Normal file
45
src/blfwk/int_size.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_int_size_h_)
|
||||
#define _int_size_h_
|
||||
|
||||
namespace blfwk
|
||||
{
|
||||
//! Supported sizes of integers.
|
||||
typedef enum
|
||||
{
|
||||
kWordSize, //!< 32-bit word.
|
||||
kHalfWordSize, //!< 16-bit half word.
|
||||
kByteSize //!< 8-bit byte.
|
||||
} int_size_t;
|
||||
|
||||
}; // namespace blfwk
|
||||
|
||||
#endif // _int_size_h_
|
||||
1739
src/blfwk/json.h
Normal file
1739
src/blfwk/json.h
Normal file
File diff suppressed because it is too large
Load Diff
473
src/blfwk/options.h
Normal file
473
src/blfwk/options.h
Normal file
@@ -0,0 +1,473 @@
|
||||
// COPY/REUSE POLICY
|
||||
// =================
|
||||
// Permission is hereby granted to freely copy and redistribute this
|
||||
// software, provided that the author is clearly credited in all copies
|
||||
// and derivations. Neither the names of the authors nor that of their
|
||||
// employers may be used to endorse or promote products derived from this
|
||||
// software without specific written permission.
|
||||
//
|
||||
//
|
||||
// DISCLAIMER
|
||||
// ==========
|
||||
// This software is provided ``As Is'' and without any express or implied
|
||||
// warranties. Neither the authors nor any of their employers (including
|
||||
// any of their subsidiaries and subdivisions) are responsible for maintaining
|
||||
// or supporting this software or for any consequences resulting from the
|
||||
// use of this software, no matter how awful, even if they arise from flaws
|
||||
// in the software.
|
||||
// ****************************************************************************
|
||||
// ^FILE: options.h - option parsing classes
|
||||
//
|
||||
// ^DESCRIPTION:
|
||||
// This file defines classes used to parse command-line options.
|
||||
// Options may be parsed from an array of strings, or from any structure
|
||||
// for which a corresponding option-iterator exists.
|
||||
//
|
||||
// ^HISTORY:
|
||||
// 03/06/92 Brad Appleton <bradapp@enteract.com> Created
|
||||
//
|
||||
// 03/23/93 Brad Appleton <bradapp@enteract.com>
|
||||
// - Added OptIstreamIter class
|
||||
//
|
||||
// 03/08/94 Brad Appleton <bradapp@enteract.com>
|
||||
// - Added Options::reset() member function
|
||||
//
|
||||
// 07/31/97 Brad Appleton <bradapp@enteract.com>
|
||||
// - Added PARSE_POS control flag and POSITIONAL return value
|
||||
//
|
||||
// 04/30/06 Chris Reed
|
||||
// - Updated to modern C++ and STL
|
||||
// - Converted comments to doxygen style
|
||||
// ^^**************************************************************************
|
||||
|
||||
#ifndef _options_h
|
||||
#define _options_h
|
||||
|
||||
#ifdef USE_STDIO
|
||||
#include <stdio.h>
|
||||
#else
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
//! Abstract class to iterate through options/arguments
|
||||
//!
|
||||
class OptIter
|
||||
{
|
||||
public:
|
||||
OptIter(void) {}
|
||||
virtual ~OptIter(void);
|
||||
|
||||
//! curr() returns the current item in the iterator without
|
||||
//! advancing on to the next item. If we are at the end of items
|
||||
//! then NULL is returned.
|
||||
virtual const char *curr(void) = 0;
|
||||
|
||||
//! next() advances to the next item.
|
||||
virtual void next(void) = 0;
|
||||
|
||||
//! operator() returns the current item in the iterator and then
|
||||
//! advances on to the next item. If we are at the end of items
|
||||
//! then NULL is returned.
|
||||
virtual const char *operator()(void);
|
||||
};
|
||||
|
||||
//! Abstract class for a rewindable OptIter
|
||||
//!
|
||||
class OptIterRwd : public OptIter
|
||||
{
|
||||
public:
|
||||
OptIterRwd(void);
|
||||
|
||||
virtual ~OptIterRwd(void);
|
||||
|
||||
virtual const char *curr(void) = 0;
|
||||
|
||||
virtual void next(void) = 0;
|
||||
|
||||
virtual const char *operator()(void) = 0;
|
||||
|
||||
//! rewind() resets the "current-element" to the first one in the "list"
|
||||
virtual void rewind(void) = 0;
|
||||
};
|
||||
|
||||
//! Class to iterate through an array of tokens. The array may be terminated
|
||||
//! by NULL or a count containing the number of tokens may be given.
|
||||
//!
|
||||
class OptArgvIter : public OptIterRwd
|
||||
{
|
||||
private:
|
||||
int ndx; // index of current arg
|
||||
int ac; // arg count
|
||||
const char *const *av; // arg vector
|
||||
|
||||
public:
|
||||
OptArgvIter(const char *const argv[])
|
||||
: av(argv)
|
||||
, ac(-1)
|
||||
, ndx(0)
|
||||
{
|
||||
}
|
||||
|
||||
OptArgvIter(int argc, const char *const argv[])
|
||||
: av(argv)
|
||||
, ac(argc)
|
||||
, ndx(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~OptArgvIter(void);
|
||||
|
||||
virtual const char *curr(void);
|
||||
|
||||
virtual void next(void);
|
||||
|
||||
virtual const char *operator()(void);
|
||||
|
||||
virtual void rewind(void);
|
||||
|
||||
//! index returns the current index to use for argv[]
|
||||
int index(void) { return ndx; }
|
||||
};
|
||||
|
||||
//! Class to iterate through a string containing delimiter-separated tokens
|
||||
//!
|
||||
class OptStrTokIter : public OptIterRwd
|
||||
{
|
||||
private:
|
||||
unsigned len; // length of token-string
|
||||
const char *str; // the token-string
|
||||
const char *seps; // delimiter-set (separator-characters)
|
||||
const char *cur; // current token
|
||||
char *tokstr; // our copy of the token-string
|
||||
|
||||
static const char *default_delims; // default delimiters = whitespace
|
||||
|
||||
public:
|
||||
OptStrTokIter(const char *tokens, const char *delimiters = 0);
|
||||
|
||||
virtual ~OptStrTokIter(void);
|
||||
|
||||
virtual const char *curr(void);
|
||||
|
||||
virtual void next(void);
|
||||
|
||||
virtual const char *operator()(void);
|
||||
|
||||
virtual void rewind(void);
|
||||
|
||||
//! delimiters() with NO arguments returns the current set of delimiters,
|
||||
//! If an argument is given then it is used as the new set of delimiters.
|
||||
const char *delimiters(void) { return seps; }
|
||||
void delimiters(const char *delims) { seps = (delims) ? delims : default_delims; }
|
||||
};
|
||||
|
||||
//! OptIstreamIter is a class for iterating over arguments that come
|
||||
//! from an input stream. Each line of the input stream is considered
|
||||
//! to be a set of white-space separated tokens. If the the first
|
||||
//! non-white character on a line is '#' ('!' for VMS systems) then
|
||||
//! the line is considered a comment and is ignored.
|
||||
//!
|
||||
//! \note If a line is more than 1022 characters in length then we
|
||||
//! treat it as if it were several lines of length 1022 or less.
|
||||
//!
|
||||
//! \note The string tokens returned by this iterator are pointers
|
||||
//! to temporary buffers which may not necessarily stick around
|
||||
//! for too long after the call to curr() or operator(), hence
|
||||
//! if you need the string value to persist - you will need to
|
||||
//! make a copy.
|
||||
//!
|
||||
class OptIstreamIter : public OptIter
|
||||
{
|
||||
private:
|
||||
std::istream &is;
|
||||
OptStrTokIter *tok_iter;
|
||||
|
||||
void fill(void);
|
||||
|
||||
public:
|
||||
static const unsigned MAX_LINE_LEN;
|
||||
|
||||
OptIstreamIter(std::istream &input);
|
||||
|
||||
virtual ~OptIstreamIter(void);
|
||||
|
||||
virtual const char *curr(void);
|
||||
|
||||
virtual void next(void);
|
||||
|
||||
virtual const char *operator()(void);
|
||||
};
|
||||
|
||||
//! \brief parse command-line options
|
||||
//!
|
||||
//! \section Synopsis
|
||||
//! \code
|
||||
//! #include <options.h>
|
||||
//!
|
||||
//! Options opts(cmdname, optv);
|
||||
//! char cmdname[], *optv[];
|
||||
//! \endcode
|
||||
//! \section Description
|
||||
//! The Options constructor expects a command-name (usually argv[0]) and
|
||||
//! a pointer to an array of strings. The last element in this array MUST
|
||||
//! be NULL. Each non-NULL string in the array must have the following format:
|
||||
//!
|
||||
//! The 1st character must be the option-name ('c' for a -c option).
|
||||
//!
|
||||
//! The 2nd character must be one of '|', '?', ':', '*', or '+'.
|
||||
//! '|' -- indicates that the option takes NO argument;
|
||||
//! '?' -- indicates that the option takes an OPTIONAL argument;
|
||||
//! ':' -- indicates that the option takes a REQUIRED argument;
|
||||
//! '*' -- indicates that the option takes 0 or more arguments;
|
||||
//! '+' -- indicates that the option takes 1 or more arguments;
|
||||
//!
|
||||
//! The remainder of the string must be the long-option name.
|
||||
//!
|
||||
//! If desired, the long-option name may be followed by one or more
|
||||
//! spaces and then by the name of the option value. This name will
|
||||
//! be used when printing usage messages. If the option-value-name
|
||||
//! is not given then the string "<value>" will be used in usage
|
||||
//! messages.
|
||||
//!
|
||||
//! One may use a space to indicate that a particular option does not
|
||||
//! have a corresponding long-option. For example, "c: " (or "c:")
|
||||
//! means the -c option takes a value & has NO corresponding long-option.
|
||||
//!
|
||||
//! To specify a long-option that has no corresponding single-character
|
||||
//! option is a bit trickier: Options::operator() still needs an "option-
|
||||
//! character" to return when that option is matched. One may use a whitespace
|
||||
//! character or a non-printable character as the single-character option
|
||||
//! in such a case. (hence " |hello" would only match "--hello").
|
||||
//!
|
||||
//! \section Exceptions Exceptions to the above
|
||||
//! If the 1st character of the string is '-', then the rest of the
|
||||
//! string must correspond to the above format, and the option is
|
||||
//! considered to be a hidden-option. This means it will be parsed
|
||||
//! when actually matching options from the command-line, but will
|
||||
//! NOT show-up if a usage message is printed using the usage() member
|
||||
//! function. Such an example might be "-h|hidden". If you want to
|
||||
//! use any "dummy" options (options that are not parsed, but that
|
||||
//! to show up in the usage message), you can specify them along with
|
||||
//! any positional parameters to the usage() member function.
|
||||
//!
|
||||
//! If the 2nd character of the string is '\0' then it is assumed
|
||||
//! that there is no corresponding long-option and that the option
|
||||
//! takes no argument (hence "f", and "f| " are equivalent).
|
||||
//!
|
||||
//! \code
|
||||
//! const char * optv[] = {
|
||||
//! "c:count <number>",
|
||||
//! "s?str <string>",
|
||||
//! "x",
|
||||
//! " |hello",
|
||||
//! "g+groups <newsgroup>",
|
||||
//! NULL
|
||||
//! } ;
|
||||
//! \endcode
|
||||
//! optv[] now corresponds to the following:
|
||||
//!
|
||||
//! usage: cmdname [-c|--count <number>] [-s|--str [<string>]]
|
||||
//! [-x] [--hello] [-g|--groups <newsgroup> ...]
|
||||
//!
|
||||
//! Long-option names are matched case-insensitive and only a unique prefix
|
||||
//! of the name needs to be specified.
|
||||
//!
|
||||
//! Option-name characters are case-sensitive!
|
||||
//!
|
||||
//! \section Caveat
|
||||
//! Because of the way in which multi-valued options and options with optional
|
||||
//! values are handled, it is NOT possible to supply a value to an option in
|
||||
//! a separate argument (different argv[] element) if the value is OPTIONAL
|
||||
//! and begins with a '-'. What this means is that if an option "-s" takes an
|
||||
//! optional value value and you wish to supply a value of "-foo" then you must
|
||||
//! specify this on the command-line as "-s-foo" instead of "-s -foo" because
|
||||
//! "-s -foo" will be considered to be two separate sets of options.
|
||||
//!
|
||||
//! A multi-valued option is terminated by another option or by the end-of
|
||||
//! options. The following are all equivalent (if "-l" is a multi-valued
|
||||
//! option and "-x" is an option that takes no value):
|
||||
//!
|
||||
//! cmdname -x -l item1 item2 item3 -- arg1 arg2 arg3
|
||||
//! cmdname -x -litem1 -litem2 -litem3 -- arg1 arg2 arg3
|
||||
//! cmdname -l item1 item2 item3 -x arg1 arg2 arg3
|
||||
//!
|
||||
//!
|
||||
//! \code
|
||||
//! #include <options.h>
|
||||
//!
|
||||
//! static const char * optv[] = {
|
||||
//! "H|help",
|
||||
//! "c:count <number>",
|
||||
//! "s?str <string>",
|
||||
//! "x",
|
||||
//! " |hello",
|
||||
//! "g+groups <newsgroup>",
|
||||
//! NULL
|
||||
//! } ;
|
||||
//!
|
||||
//! main(int argc, char * argv[]) {
|
||||
//! int optchar;
|
||||
//! const char * optarg;
|
||||
//! const char * str = "default_string";
|
||||
//! int count = 0, xflag = 0, hello = 0;
|
||||
//! int errors = 0, ngroups = 0;
|
||||
//!
|
||||
//! Options opts(*argv, optv);
|
||||
//! OptArgvIter iter(--argc, ++argv);
|
||||
//!
|
||||
//! while( optchar = opts(iter, optarg) ) {
|
||||
//! switch (optchar) {
|
||||
//! case 'H' :
|
||||
//! opts.usage(cout, "files ...");
|
||||
//! exit(0);
|
||||
//! break;
|
||||
//! case 'g' :
|
||||
//! ++ngroups; break; //! the groupname is in "optarg"
|
||||
//! case 's' :
|
||||
//! str = optarg; break;
|
||||
//! case 'x' :
|
||||
//! ++xflag; break;
|
||||
//! case ' ' :
|
||||
//! ++hello; break;
|
||||
//! case 'c' :
|
||||
//! if (optarg == NULL) ++errors;
|
||||
//! else count = (int) atol(optarg);
|
||||
//! break;
|
||||
//! default : ++errors; break;
|
||||
//! } //!switch
|
||||
//! }
|
||||
//!
|
||||
//! if (errors || (iter.index() == argc)) {
|
||||
//! if (! errors) {
|
||||
//! cerr << opts.name() << ": no filenames given." << endl ;
|
||||
//! }
|
||||
//! opts.usage(cerr, "files ...");
|
||||
//! exit(1);
|
||||
//! }
|
||||
//!
|
||||
//! cout << "xflag=" << ((xflag) ? "ON" : "OFF") << endl
|
||||
//! << "hello=" << ((hello) ? "YES" : "NO") << endl
|
||||
//! << "count=" << count << endl
|
||||
//! << "str=\"" << ((str) ? str : "No value given!") << "\"" << endl
|
||||
//! << "ngroups=" << ngroups << endl ;
|
||||
//!
|
||||
//! if (iter.index() < argc) {
|
||||
//! cout << "files=" ;
|
||||
//! for (int i = iter.index() ; i < argc ; i++) {
|
||||
//! cout << "\"" << argv[i] << "\" " ;
|
||||
//! }
|
||||
//! cout << endl ;
|
||||
//! }
|
||||
//! }
|
||||
//! \endcode
|
||||
class Options
|
||||
{
|
||||
private:
|
||||
unsigned explicit_end : 1; //!< were we terminated because of "--"?
|
||||
unsigned optctrls : 7; //!< control settings (a set of OptCtrl masks)
|
||||
const char *const *optvec; //!< vector of option-specifications (last=NULL)
|
||||
const char *nextchar; //!< next option-character to process
|
||||
const char *listopt; //!< last list-option we matched
|
||||
const char *cmdname; //!< name of the command
|
||||
|
||||
void check_syntax(void) const;
|
||||
|
||||
const char *match_opt(char opt, int ignore_case = 0) const;
|
||||
|
||||
const char *match_longopt(const char *opt, int len, int &ambiguous) const;
|
||||
|
||||
int parse_opt(OptIter &iter, const char *&optarg);
|
||||
|
||||
int parse_longopt(OptIter &iter, const char *&optarg);
|
||||
|
||||
public:
|
||||
enum OptCtrl
|
||||
{
|
||||
DEFAULT = 0x00, //!< Default setting
|
||||
ANYCASE = 0x01, //!< Ignore case when matching short-options
|
||||
QUIET = 0x02, //!< Dont print error messages
|
||||
PLUS = 0x04, //!< Allow "+" as a long-option prefix
|
||||
SHORT_ONLY = 0x08, //!< Dont accept long-options
|
||||
LONG_ONLY = 0x10, //!< Dont accept short-options
|
||||
//!< (also allows "-" as a long-option prefix).
|
||||
NOGUESSING = 0x20, //!< Normally, when we see a short (long) option
|
||||
//!< on the command line that doesnt match any
|
||||
//!< known short (long) options, then we try to
|
||||
//!< "guess" by seeing if it will match any known
|
||||
//!< long (short) option. Setting this mask prevents
|
||||
//!< this "guessing" from occurring.
|
||||
PARSE_POS = 0x40 //!< By default, Options will not present positional
|
||||
//!< command-line arguments to the user and will
|
||||
//!< instead stop parsing when the first positonal
|
||||
//!< argument has been encountered. If this flag
|
||||
//!< is given, Options will present positional
|
||||
//!< arguments to the user with a return code of
|
||||
//!< POSITIONAL; ENDOPTS will be returned only
|
||||
//!< when the end of the argument list is reached.
|
||||
};
|
||||
|
||||
//! Error return values for operator()
|
||||
//!
|
||||
enum OptRC
|
||||
{
|
||||
ENDOPTS = 0,
|
||||
BADCHAR = -1,
|
||||
BADKWD = -2,
|
||||
AMBIGUOUS = -3,
|
||||
POSITIONAL = -4
|
||||
};
|
||||
|
||||
Options(const char *name, const char *const optv[]);
|
||||
|
||||
virtual ~Options(void);
|
||||
|
||||
//! name() returns the command name
|
||||
const char *name(void) const { return cmdname; }
|
||||
//! ctrls() (with no arguments) returns the existing control settings
|
||||
unsigned ctrls(void) const { return optctrls; }
|
||||
//! ctrls() (with 1 argument) sets new control settings
|
||||
void ctrls(unsigned newctrls) { optctrls = newctrls; }
|
||||
//! reset for another pass to parse for options
|
||||
void reset(void) { nextchar = listopt = NULL; }
|
||||
//! usage() prints options usage (followed by any positional arguments
|
||||
//! listed in the parameter "positionals") on the given outstream
|
||||
void usage(std::ostream &os, const char *positionals) const;
|
||||
|
||||
//! operator() iterates through the arguments as necessary (using the
|
||||
//! given iterator) and returns the character value of the option
|
||||
//! (or long-option) that it matched. If the option has a value
|
||||
//! then the value given may be found in optarg (otherwise optarg
|
||||
//! will be NULL).
|
||||
//!
|
||||
//! 0 is returned upon end-of-options. At this point, "iter" may
|
||||
//! be used to process any remaining positional parameters. If the
|
||||
//! PARSE_POS control-flag is set then 0 is returned only when all
|
||||
//! arguments in "iter" have been exhausted.
|
||||
//!
|
||||
//! If an invalid option is found then BADCHAR is returned and *optarg
|
||||
//! is the unrecognized option character.
|
||||
//!
|
||||
//! If an invalid long-option is found then BADKWD is returned and optarg
|
||||
//! points to the bad long-option.
|
||||
//!
|
||||
//! If an ambiguous long-option is found then AMBIGUOUS is returned and
|
||||
//! optarg points to the ambiguous long-option.
|
||||
//!
|
||||
//! If the PARSE_POS control-flag is set then POSITIONAL is returned
|
||||
//! when a positional argument is encountered and optarg points to
|
||||
//! the positonal argument (and "iter" is advanced to the next argument
|
||||
//! in the iterator).
|
||||
//!
|
||||
//! Unless Options::QUIET is used, missing option-arguments and
|
||||
//! invalid options (and the like) will automatically cause error
|
||||
//! messages to be issued to cerr.
|
||||
int operator()(OptIter &iter, const char *&optarg);
|
||||
|
||||
//! Call this member function after operator() has returned 0
|
||||
//! if you want to know whether or not options were explicitly
|
||||
//! terminated because "--" appeared on the command-line.
|
||||
//!
|
||||
int explicit_endopts() const { return explicit_end; }
|
||||
};
|
||||
|
||||
#endif /* _options_h */
|
||||
180
src/blfwk/rijndael.h
Normal file
180
src/blfwk/rijndael.h
Normal file
@@ -0,0 +1,180 @@
|
||||
#ifndef _RIJNDAEL_H_
|
||||
#define _RIJNDAEL_H_
|
||||
|
||||
//
|
||||
// File : rijndael.h
|
||||
// Creation date : Sun Nov 5 2000 03:21:05 CEST
|
||||
// Author : Szymon Stefanek (stefanek@tin.it)
|
||||
//
|
||||
// Another implementation of the Rijndael cipher.
|
||||
// This is intended to be an easily usable library file.
|
||||
// This code is public domain.
|
||||
// Based on the Vincent Rijmen and K.U.Leuven implementation 2.4.
|
||||
//
|
||||
|
||||
//
|
||||
// Original Copyright notice:
|
||||
//
|
||||
// rijndael-alg-fst.c v2.4 April '2000
|
||||
// rijndael-alg-fst.h
|
||||
// rijndael-api-fst.c
|
||||
// rijndael-api-fst.h
|
||||
//
|
||||
// Optimised ANSI C code
|
||||
//
|
||||
// authors: v1.0: Antoon Bosselaers
|
||||
// v2.0: Vincent Rijmen, K.U.Leuven
|
||||
// v2.3: Paulo Barreto
|
||||
// v2.4: Vincent Rijmen, K.U.Leuven
|
||||
//
|
||||
// This code is placed in the public domain.
|
||||
//
|
||||
|
||||
//
|
||||
// This implementation works on 128 , 192 , 256 bit keys
|
||||
// and on 128 bit blocks
|
||||
//
|
||||
|
||||
//
|
||||
// Example of usage:
|
||||
//
|
||||
// // Input data
|
||||
// unsigned char key[32]; // The key
|
||||
// initializeYour256BitKey(); // Obviously initialized with sth
|
||||
// const unsigned char * plainText = getYourPlainText(); // Your plain text
|
||||
// int plainTextLen = strlen(plainText); // Plain text length
|
||||
//
|
||||
// // Encrypting
|
||||
// Rijndael rin;
|
||||
// unsigned char output[plainTextLen + 16];
|
||||
//
|
||||
// rin.init(Rijndael::CBC,Rijndael::Encrypt,key,Rijndael::Key32Bytes);
|
||||
// // It is a good idea to check the error code
|
||||
// int len = rin.padEncrypt(plainText,len,output);
|
||||
// if(len >= 0)useYourEncryptedText();
|
||||
// else encryptError(len);
|
||||
//
|
||||
// // Decrypting: we can reuse the same object
|
||||
// unsigned char output2[len];
|
||||
// rin.init(Rijndael::CBC,Rijndael::Decrypt,key,Rijndael::Key32Bytes));
|
||||
// len = rin.padDecrypt(output,len,output2);
|
||||
// if(len >= 0)useYourDecryptedText();
|
||||
// else decryptError(len);
|
||||
//
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define _MAX_KEY_COLUMNS (256 / 32)
|
||||
#define _MAX_ROUNDS 14
|
||||
#define MAX_IV_SIZE 16
|
||||
|
||||
// We assume that unsigned int is 32 bits long....
|
||||
// typedef unsigned char uint8_t;
|
||||
// typedef unsigned int uint32_t;
|
||||
// typedef unsigned short uint16_t;
|
||||
|
||||
// Error codes
|
||||
#define RIJNDAEL_SUCCESS 0
|
||||
#define RIJNDAEL_UNSUPPORTED_MODE -1
|
||||
#define RIJNDAEL_UNSUPPORTED_DIRECTION -2
|
||||
#define RIJNDAEL_UNSUPPORTED_KEY_LENGTH -3
|
||||
#define RIJNDAEL_BAD_KEY -4
|
||||
#define RIJNDAEL_NOT_INITIALIZED -5
|
||||
#define RIJNDAEL_BAD_DIRECTION -6
|
||||
#define RIJNDAEL_CORRUPTED_DATA -7
|
||||
|
||||
class Rijndael
|
||||
{
|
||||
public:
|
||||
enum Direction
|
||||
{
|
||||
Encrypt,
|
||||
Decrypt
|
||||
};
|
||||
enum Mode
|
||||
{
|
||||
ECB,
|
||||
CBC,
|
||||
CFB1
|
||||
};
|
||||
enum KeyLength
|
||||
{
|
||||
Key16Bytes,
|
||||
Key24Bytes,
|
||||
Key32Bytes
|
||||
};
|
||||
//
|
||||
// Creates a Rijndael cipher object
|
||||
// You have to call init() before you can encrypt or decrypt stuff
|
||||
//
|
||||
Rijndael();
|
||||
~Rijndael();
|
||||
|
||||
protected:
|
||||
// Internal stuff
|
||||
enum State
|
||||
{
|
||||
Valid,
|
||||
Invalid
|
||||
};
|
||||
|
||||
State m_state;
|
||||
Mode m_mode;
|
||||
Direction m_direction;
|
||||
uint8_t m_initVector[MAX_IV_SIZE];
|
||||
uint32_t m_uRounds;
|
||||
uint8_t m_expandedKey[_MAX_ROUNDS + 1][4][4];
|
||||
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// API
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// init(): Initializes the crypt session
|
||||
// Returns RIJNDAEL_SUCCESS or an error code
|
||||
// mode : Rijndael::ECB, Rijndael::CBC or Rijndael::CFB1
|
||||
// You have to use the same mode for encrypting and decrypting
|
||||
// dir : Rijndael::Encrypt or Rijndael::Decrypt
|
||||
// A cipher instance works only in one direction
|
||||
// (Well , it could be easily modified to work in both
|
||||
// directions with a single init() call, but it looks
|
||||
// useless to me...anyway , it is a matter of generating
|
||||
// two expanded keys)
|
||||
// key : array of unsigned octets , it can be 16 , 24 or 32 bytes long
|
||||
// this CAN be binary data (it is not expected to be null terminated)
|
||||
// keyLen : Rijndael::Key16Bytes , Rijndael::Key24Bytes or Rijndael::Key32Bytes
|
||||
// initVector: initialization vector, you will usually use 0 here
|
||||
int init(Mode mode, Direction dir, const uint8_t *key, KeyLength keyLen, uint8_t *initVector = 0);
|
||||
// Encrypts the input array (can be binary data)
|
||||
// The input array length must be a multiple of 16 bytes, the remaining part
|
||||
// is DISCARDED.
|
||||
// so it actually encrypts inputLen / 128 blocks of input and puts it in outBuffer
|
||||
// Input len is in BITS!
|
||||
// outBuffer must be at least inputLen / 8 bytes long.
|
||||
// Returns the encrypted buffer length in BITS or an error code < 0 in case of error
|
||||
int blockEncrypt(const uint8_t *input, int inputLen, uint8_t *outBuffer);
|
||||
// Encrypts the input array (can be binary data)
|
||||
// The input array can be any length , it is automatically padded on a 16 byte boundary.
|
||||
// Input len is in BYTES!
|
||||
// outBuffer must be at least (inputLen + 16) bytes long
|
||||
// Returns the encrypted buffer length in BYTES or an error code < 0 in case of error
|
||||
int padEncrypt(const uint8_t *input, int inputOctets, uint8_t *outBuffer);
|
||||
// Decrypts the input vector
|
||||
// Input len is in BITS!
|
||||
// outBuffer must be at least inputLen / 8 bytes long
|
||||
// Returns the decrypted buffer length in BITS and an error code < 0 in case of error
|
||||
int blockDecrypt(const uint8_t *input, int inputLen, uint8_t *outBuffer);
|
||||
// Decrypts the input vector
|
||||
// Input len is in BYTES!
|
||||
// outBuffer must be at least inputLen bytes long
|
||||
// Returns the decrypted buffer length in BYTES and an error code < 0 in case of error
|
||||
int padDecrypt(const uint8_t *input, int inputOctets, uint8_t *outBuffer);
|
||||
|
||||
protected:
|
||||
void keySched(uint8_t key[_MAX_KEY_COLUMNS][4]);
|
||||
void keyEncToDec();
|
||||
void encrypt(const uint8_t a[16], uint8_t b[16]);
|
||||
void decrypt(const uint8_t a[16], uint8_t b[16]);
|
||||
};
|
||||
|
||||
#endif // _RIJNDAEL_H_
|
||||
70
src/blfwk/serial.h
Normal file
70
src/blfwk/serial.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This file is part of the Bus Pirate project (http://code.google.com/p/the-bus-pirate/).
|
||||
*
|
||||
* Written and maintained by the Bus Pirate project and http://dangerousprototypes.com
|
||||
*
|
||||
* To the extent possible under law, the project has
|
||||
* waived all copyright and related or neighboring rights to Bus Pirate. This
|
||||
* work is published from United States.
|
||||
*
|
||||
* For details see: http://creativecommons.org/publicdomain/zero/1.0/.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
/*
|
||||
* OS independent serial interface
|
||||
*
|
||||
* Heavily based on Pirate-Loader:
|
||||
* http://the-bus-pirate.googlecode.com/svn/trunk/bootloader-v4/pirate-loader/source/pirate-loader.c
|
||||
*
|
||||
*/
|
||||
#ifndef MYSERIAL_H_
|
||||
#define MYSERIAL_H_
|
||||
|
||||
#ifdef MACOSX
|
||||
#include <IOKit/serial/ioss.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#define B1500000 1500000
|
||||
#define B1000000 1000000
|
||||
#define B921600 921600
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <time.h>
|
||||
|
||||
#define B115200 115200
|
||||
#define B921600 921600
|
||||
|
||||
typedef long speed_t;
|
||||
#else
|
||||
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#endif
|
||||
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int serial_setup(int fd, speed_t speed);
|
||||
int serial_set_read_timeout(int fd, uint32_t timeoutMs);
|
||||
int serial_write(int fd, char *buf, int size);
|
||||
int serial_read(int fd, char *buf, int size);
|
||||
int serial_open(char *port);
|
||||
int serial_close(int fd);
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
238
src/blfwk/smart_ptr.h
Normal file
238
src/blfwk/smart_ptr.h
Normal file
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#if !defined(_smart_ptr_h_)
|
||||
#define _smart_ptr_h_
|
||||
|
||||
//! @addtogroup smart_pointer
|
||||
//! @{
|
||||
|
||||
/*!
|
||||
* \brief Simple, standard smart pointer class.
|
||||
*
|
||||
* This class only supports the single-owner paradigm.
|
||||
*/
|
||||
template <typename T>
|
||||
class smart_ptr
|
||||
{
|
||||
public:
|
||||
typedef T data_type;
|
||||
typedef T *ptr_type;
|
||||
typedef const T *const_ptr_type;
|
||||
typedef T &ref_type;
|
||||
typedef const T &const_ref_type;
|
||||
|
||||
//! Default constuctor. Initialises with no pointer set.
|
||||
smart_ptr()
|
||||
: _p(0)
|
||||
{
|
||||
}
|
||||
|
||||
//! This constructor takes a pointer to the object to be deleted.
|
||||
smart_ptr(ptr_type p)
|
||||
: _p(p)
|
||||
{
|
||||
}
|
||||
|
||||
//! Destructor. If an object (pointer) has been set, it will be deleted.
|
||||
//! Deletes the object using safe_delete().
|
||||
virtual ~smart_ptr() { safe_delete(); }
|
||||
//! Return the current pointer value.
|
||||
ptr_type get() { return _p; }
|
||||
//! Return the const form of the current pointer value.
|
||||
const_ptr_type get() const { return _p; }
|
||||
//! Change the pointer value, or set if if the default constructor was used.
|
||||
//! If a pointer had previously been associated with the object, and \a p is
|
||||
//! different than that previous pointer, it will be deleted before taking
|
||||
//! ownership of \a p. If this is not desired, call reset() beforehand.
|
||||
void set(ptr_type p)
|
||||
{
|
||||
if (_p && p != _p)
|
||||
{
|
||||
safe_delete();
|
||||
}
|
||||
_p = p;
|
||||
}
|
||||
|
||||
//! Dissociates any previously set pointer value without deleting it.
|
||||
void reset() { _p = 0; }
|
||||
//! Dissociates a previously set pointer value, deleting it at the same time.
|
||||
void clear() { safe_delete(); }
|
||||
//! Forces immediate deletion of the object. If you are planning on using
|
||||
//! this method, think about just using a normal pointer. It probably makes
|
||||
//! more sense.
|
||||
virtual void safe_delete()
|
||||
{
|
||||
if (_p)
|
||||
{
|
||||
delete _p;
|
||||
_p = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//! \name Operators
|
||||
//@{
|
||||
|
||||
//! Makes the object transparent as the template type.
|
||||
operator ptr_type() { return _p; }
|
||||
//! Const version of the pointer operator.
|
||||
operator const_ptr_type() const { return _p; }
|
||||
//! Makes the object transparent as a reference of the template type.
|
||||
operator ref_type() { return *_p; }
|
||||
//! Const version of the reference operator.
|
||||
operator const_ref_type() const { return *_p; }
|
||||
//! Returns a boolean indicating whether the object has a pointer set or not.
|
||||
operator bool() const { return _p != 0; }
|
||||
//! To allow setting the pointer directly. Equivalent to a call to set().
|
||||
smart_ptr<T> &operator=(const_ptr_type p)
|
||||
{
|
||||
set(const_cast<ptr_type>(p));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Another operator to allow you to treat the object just like a pointer.
|
||||
ptr_type operator->() { return _p; }
|
||||
//! Another operator to allow you to treat the object just like a pointer.
|
||||
const_ptr_type operator->() const { return _p; }
|
||||
// //! Pointer dereferencing operator.
|
||||
// ref_type operator * () const { return *_p; }
|
||||
//
|
||||
// //! Const version of the pointer dereference operator.
|
||||
// const_ref_type operator * () const { return *_p; }
|
||||
|
||||
//@}
|
||||
|
||||
protected:
|
||||
ptr_type _p; //!< The wrapped pointer.
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Simple, standard smart pointer class that uses the array delete operator.
|
||||
*
|
||||
* This class only supports the single-owner paradigm.
|
||||
*
|
||||
* This is almost entirely a copy of smart_ptr since the final C++ specification
|
||||
* does not allow template subclass members to access members of the parent that
|
||||
* do not depend on the template parameter.
|
||||
*/
|
||||
template <typename T>
|
||||
class smart_array_ptr
|
||||
{
|
||||
public:
|
||||
typedef T data_type;
|
||||
typedef T *ptr_type;
|
||||
typedef const T *const_ptr_type;
|
||||
typedef T &ref_type;
|
||||
typedef const T &const_ref_type;
|
||||
|
||||
//! Default constuctor. Initialises with no pointer set.
|
||||
smart_array_ptr()
|
||||
: _p(0)
|
||||
{
|
||||
}
|
||||
|
||||
//! This constructor takes a pointer to the object to be deleted.
|
||||
smart_array_ptr(ptr_type p)
|
||||
: _p(p)
|
||||
{
|
||||
}
|
||||
|
||||
//! Destructor. If an array has been set, it will be deleted.
|
||||
//! Deletes the array using safe_delete().
|
||||
virtual ~smart_array_ptr() { safe_delete(); }
|
||||
//! Return the current pointer value.
|
||||
ptr_type get() { return _p; }
|
||||
//! Return the const form of the current pointer value.
|
||||
const_ptr_type get() const { return _p; }
|
||||
//! Change the pointer value, or set if if the default constructor was used.
|
||||
//! If a pointer had previously been associated with the object, and \a p is
|
||||
//! different than that previous pointer, it will be deleted before taking
|
||||
//! ownership of \a p. If this is not desired, call reset() beforehand.
|
||||
void set(ptr_type p)
|
||||
{
|
||||
if (_p && p != _p)
|
||||
{
|
||||
safe_delete();
|
||||
}
|
||||
_p = p;
|
||||
}
|
||||
|
||||
//! Dissociates any previously set pointer value without deleting it.
|
||||
void reset() { _p = 0; }
|
||||
//! Dissociates a previously set pointer value, deleting it at the same time.
|
||||
void clear() { safe_delete(); }
|
||||
//! Forces immediate deletion of the object. If you are planning on using
|
||||
//! this method, think about just using a normal pointer. It probably makes
|
||||
//! more sense.
|
||||
virtual void safe_delete()
|
||||
{
|
||||
if (_p)
|
||||
{
|
||||
delete[] _p;
|
||||
_p = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//! \name Operators
|
||||
//@{
|
||||
|
||||
//! Makes the object transparent as the template type.
|
||||
operator ptr_type() { return _p; }
|
||||
//! Const version of the pointer operator.
|
||||
operator const_ptr_type() const { return _p; }
|
||||
//! Makes the object transparent as a reference of the template type.
|
||||
operator ref_type() { return *_p; }
|
||||
//! Const version of the reference operator.
|
||||
operator const_ref_type() const { return *_p; }
|
||||
//! Returns a boolean indicating whether the object has a pointer set or not.
|
||||
operator bool() const { return _p != 0; }
|
||||
//! To allow setting the pointer directly. Equivalent to a call to set().
|
||||
smart_array_ptr<T> &operator=(const_ptr_type p)
|
||||
{
|
||||
set(const_cast<ptr_type>(p));
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Another operator to allow you to treat the object just like a pointer.
|
||||
ptr_type operator->() { return _p; }
|
||||
//! Another operator to allow you to treat the object just like a pointer.
|
||||
const_ptr_type operator->() const { return _p; }
|
||||
//! Indexing operator.
|
||||
ref_type operator[](unsigned index) { return _p[index]; }
|
||||
//! Indexing operator.
|
||||
const_ref_type operator[](unsigned index) const { return _p[index]; }
|
||||
//@}
|
||||
|
||||
protected:
|
||||
ptr_type _p; //!< The wrapped pointer.
|
||||
};
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // _smart_ptr_h_
|
||||
76
src/blfwk/src/AESCounter.cpp
Normal file
76
src/blfwk/src/AESCounter.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* File: AESCounter.cpp
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
|
||||
* See included license file for license details.
|
||||
*/
|
||||
|
||||
#include "blfwk/AESCounter.h"
|
||||
#include <stdexcept>
|
||||
#include "blfwk/smart_ptr.h"
|
||||
#include "blfwk/HexValues.h"
|
||||
#include <ctype.h>
|
||||
|
||||
//! The data from the stream is expected to be hex encoded. Each two characters
|
||||
//! from the stream encode a single result byte. All non-hexadecimal characters
|
||||
//! are ignored, including newlines. Every two hexadecimal characters form
|
||||
//! an encoded byte. This is true even if the two characters representing the
|
||||
//! upper and lower nibbles are separated by whitespace or other characters.
|
||||
//!
|
||||
//! \post The stream read head is left pointing just after the last encoded byte.
|
||||
//!
|
||||
//! \param stream Input stream to read from.
|
||||
//! \param bytes Number of encoded bytes to read. This is the number of \e
|
||||
//! result bytes, not the count of bytes to read from the stream.
|
||||
//! \param[out] buffer Pointer to the buffer where decoded data is written.
|
||||
//!
|
||||
//! \exception std::runtime_error This exception will be thrown if less
|
||||
//! data than required is available from \a stream, or if some other
|
||||
//! error occurs while reading from \a stream.
|
||||
void AESCounterBase::_readFromStream(std::istream &stream, unsigned bytes, uint8_t *buffer)
|
||||
{
|
||||
char temp[2];
|
||||
char c;
|
||||
char n = 0;
|
||||
|
||||
while (bytes)
|
||||
{
|
||||
if (stream.get(c).fail())
|
||||
{
|
||||
throw std::runtime_error("not enough data in stream");
|
||||
}
|
||||
|
||||
if (isHexDigit(c))
|
||||
{
|
||||
temp[n++] = c;
|
||||
if (n == 2)
|
||||
{
|
||||
*buffer++ = hexByteToInt(temp);
|
||||
bytes--;
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Counter data is written to \a stream as a sequence of hex encoded octets, each two
|
||||
//! characters long. No spaces or newlines are inserted between the encoded octets
|
||||
//! or at the end of the sequence.
|
||||
//!
|
||||
//! \exception std::runtime_error Thrown if the \a stream reports an error while
|
||||
//! writing the key data.
|
||||
void AESCounterBase::_writeToStream(std::ostream &stream, unsigned bytes, const uint8_t *buffer) const
|
||||
{
|
||||
const char hexChars[] = "0123456789ABCDEF";
|
||||
while (bytes--)
|
||||
{
|
||||
uint8_t thisByte = *buffer++;
|
||||
char byteString[2];
|
||||
byteString[0] = hexChars[(thisByte & 0xf0) >> 4];
|
||||
byteString[1] = hexChars[thisByte & 0x0f];
|
||||
if (stream.write(byteString, 2).bad())
|
||||
{
|
||||
throw std::runtime_error("error while writing to stream");
|
||||
}
|
||||
}
|
||||
}
|
||||
76
src/blfwk/src/AESKey.cpp
Normal file
76
src/blfwk/src/AESKey.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* File: AESKey.cpp
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
|
||||
* See included license file for license details.
|
||||
*/
|
||||
|
||||
#include "blfwk/AESKey.h"
|
||||
#include <stdexcept>
|
||||
#include "blfwk/smart_ptr.h"
|
||||
#include "blfwk/HexValues.h"
|
||||
#include <ctype.h>
|
||||
|
||||
//! The data from the stream is expected to be hex encoded. Each two characters
|
||||
//! from the stream encode a single result byte. All non-hexadecimal characters
|
||||
//! are ignored, including newlines. Every two hexadecimal characters form
|
||||
//! an encoded byte. This is true even if the two characters representing the
|
||||
//! upper and lower nibbles are separated by whitespace or other characters.
|
||||
//!
|
||||
//! \post The stream read head is left pointing just after the last encoded byte.
|
||||
//!
|
||||
//! \param stream Input stream to read from.
|
||||
//! \param bytes Number of encoded bytes to read. This is the number of \e
|
||||
//! result bytes, not the count of bytes to read from the stream.
|
||||
//! \param[out] buffer Pointer to the buffer where decoded data is written.
|
||||
//!
|
||||
//! \exception std::runtime_error This exception will be thrown if less
|
||||
//! data than required is available from \a stream, or if some other
|
||||
//! error occurs while reading from \a stream.
|
||||
void AESKeyBase::_readFromStream(std::istream &stream, unsigned bytes, uint8_t *buffer) const
|
||||
{
|
||||
char temp[2];
|
||||
char c;
|
||||
char n = 0;
|
||||
|
||||
while (bytes)
|
||||
{
|
||||
if (stream.get(c).fail())
|
||||
{
|
||||
throw std::runtime_error("not enough data in stream");
|
||||
}
|
||||
|
||||
if (isHexDigit(c))
|
||||
{
|
||||
temp[n++] = c;
|
||||
if (n == 2)
|
||||
{
|
||||
*buffer++ = hexByteToInt(temp);
|
||||
bytes--;
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Key data is written to \a stream as a sequence of hex encoded octets, each two
|
||||
//! characters long. No spaces or newlines are inserted between the encoded octets
|
||||
//! or at the end of the sequence.
|
||||
//!
|
||||
//! \exception std::runtime_error Thrown if the \a stream reports an error while
|
||||
//! writing the key data.
|
||||
void AESKeyBase::_writeToStream(std::ostream &stream, unsigned bytes, const uint8_t *buffer) const
|
||||
{
|
||||
const char hexChars[] = "0123456789ABCDEF";
|
||||
while (bytes--)
|
||||
{
|
||||
uint8_t thisByte = *buffer++;
|
||||
char byteString[2];
|
||||
byteString[0] = hexChars[(thisByte & 0xf0) >> 4];
|
||||
byteString[1] = hexChars[thisByte & 0x0f];
|
||||
if (stream.write(byteString, 2).bad())
|
||||
{
|
||||
throw std::runtime_error("error while writing to stream");
|
||||
}
|
||||
}
|
||||
}
|
||||
122
src/blfwk/src/Blob.cpp
Normal file
122
src/blfwk/src/Blob.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* File: Blob.cpp
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
|
||||
* See included license file for license details.
|
||||
*/
|
||||
|
||||
#include "blfwk/Blob.h"
|
||||
#include <stdexcept>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
Blob::Blob()
|
||||
: m_data(0)
|
||||
, m_length(0)
|
||||
{
|
||||
}
|
||||
|
||||
//! Makes a local copy of the \a data argument.
|
||||
//!
|
||||
Blob::Blob(const uint8_t *data, unsigned length)
|
||||
: m_data(0)
|
||||
, m_length(length)
|
||||
{
|
||||
m_data = reinterpret_cast<uint8_t *>(malloc(length));
|
||||
memcpy(m_data, data, length);
|
||||
}
|
||||
|
||||
//! Makes a local copy of the data owned by \a other.
|
||||
//!
|
||||
Blob::Blob(const Blob &other)
|
||||
: m_data(0)
|
||||
, m_length(other.m_length)
|
||||
{
|
||||
m_data = reinterpret_cast<uint8_t *>(malloc(m_length));
|
||||
memcpy(m_data, other.m_data, m_length);
|
||||
}
|
||||
|
||||
//! Disposes of the binary data associated with this object.
|
||||
Blob::~Blob()
|
||||
{
|
||||
if (m_data)
|
||||
{
|
||||
free(m_data);
|
||||
}
|
||||
}
|
||||
|
||||
//! Copies \a data onto the blob's data. The blob does not assume ownership
|
||||
//! of \a data.
|
||||
//!
|
||||
//! \param data Pointer to a buffer containing the data which will be copied
|
||||
//! into the blob.
|
||||
//! \param length Number of bytes pointed to by \a data.
|
||||
void Blob::setData(const uint8_t *data, unsigned length)
|
||||
{
|
||||
setLength(length);
|
||||
memcpy(m_data, data, length);
|
||||
}
|
||||
|
||||
//! Sets the #m_length member variable to \a length and resizes #m_data to
|
||||
//! the new length. The contents of #m_data past any previous contents are undefined.
|
||||
//! If the new \a length is 0 then the data will be freed and a subsequent call
|
||||
//! to getData() will return NULL.
|
||||
//!
|
||||
//! \param length New length of the blob's data in bytes.
|
||||
void Blob::setLength(unsigned length)
|
||||
{
|
||||
if (length == 0)
|
||||
{
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate new block.
|
||||
if (!m_data)
|
||||
{
|
||||
m_data = reinterpret_cast<uint8_t *>(malloc(length));
|
||||
if (!m_data)
|
||||
{
|
||||
throw std::runtime_error("failed to allocate memory");
|
||||
}
|
||||
}
|
||||
// Reallocate previous block.
|
||||
else
|
||||
{
|
||||
void *newBlob = realloc(m_data, length);
|
||||
if (!newBlob)
|
||||
{
|
||||
throw std::runtime_error("failed to reallocate memory");
|
||||
}
|
||||
m_data = reinterpret_cast<uint8_t *>(newBlob);
|
||||
}
|
||||
|
||||
// Set length.
|
||||
m_length = length;
|
||||
}
|
||||
|
||||
void Blob::append(const uint8_t *newData, unsigned newDataLength)
|
||||
{
|
||||
unsigned oldLength = m_length;
|
||||
|
||||
setLength(m_length + newDataLength);
|
||||
|
||||
memcpy(m_data + oldLength, newData, newDataLength);
|
||||
}
|
||||
|
||||
void Blob::clear()
|
||||
{
|
||||
if (m_data)
|
||||
{
|
||||
free(m_data);
|
||||
m_data = NULL;
|
||||
}
|
||||
|
||||
m_length = 0;
|
||||
}
|
||||
|
||||
void Blob::relinquish()
|
||||
{
|
||||
m_data = NULL;
|
||||
m_length = 0;
|
||||
}
|
||||
277
src/blfwk/src/Bootloader.cpp
Normal file
277
src/blfwk/src/Bootloader.cpp
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "blfwk/Bootloader.h"
|
||||
#include "blfwk/BusPalPeripheral.h"
|
||||
#include "blfwk/SerialPacketizer.h"
|
||||
#include "blfwk/UartPeripheral.h"
|
||||
#include "blfwk/UsbHidPacketizer.h"
|
||||
#include "blfwk/UsbHidPeripheral.h"
|
||||
#include "blfwk/format_string.h"
|
||||
#include "blfwk/utils.h"
|
||||
#include "blfwk/json.h"
|
||||
#include "packet/serial_packet.h"
|
||||
|
||||
using namespace blfwk;
|
||||
using namespace std;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Definitions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
enum
|
||||
{
|
||||
kBuspalReadRetries = 3
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Code
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// See host_bootloader.h for documentation of this method.
|
||||
Bootloader::Bootloader()
|
||||
: m_hostPacketizer(NULL)
|
||||
, m_logger(NULL)
|
||||
{
|
||||
// create logger instance
|
||||
if (Log::getLogger() == NULL)
|
||||
{
|
||||
this->m_logger = new FileLogger("bootloader.log");
|
||||
this->m_logger->setFilterLevel(Logger::kDebug2 /*Logger::kInfo*/);
|
||||
Log::setLogger(this->m_logger);
|
||||
}
|
||||
}
|
||||
|
||||
// See host_bootloader.h for documentation of this method.
|
||||
Bootloader::Bootloader(const Peripheral::PeripheralConfigData &config)
|
||||
: m_hostPacketizer(NULL)
|
||||
, m_logger(NULL)
|
||||
{
|
||||
// create logger instance
|
||||
if (Log::getLogger() == NULL)
|
||||
{
|
||||
this->m_logger = new FileLogger("bootloader.log");
|
||||
this->m_logger->setFilterLevel(Logger::kDebug2 /*Logger::kInfo*/);
|
||||
Log::setLogger(this->m_logger);
|
||||
}
|
||||
|
||||
switch (config.peripheralType)
|
||||
{
|
||||
case Peripheral::kHostPeripheralType_UART:
|
||||
{
|
||||
UartPeripheral *peripheral = new UartPeripheral(config.comPortName.c_str(), config.comPortSpeed);
|
||||
m_hostPacketizer = new SerialPacketizer(peripheral, config.packetTimeoutMs);
|
||||
|
||||
if (config.ping)
|
||||
{
|
||||
// Send initial ping.
|
||||
try
|
||||
{
|
||||
ping(0, 0, config.comPortSpeed);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
delete m_hostPacketizer;
|
||||
m_hostPacketizer = NULL;
|
||||
throw std::runtime_error(format_string("Error: Initial ping failure: %s", e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case Peripheral::kHostPeripheralType_USB_HID:
|
||||
{
|
||||
UsbHidPeripheral *peripheral =
|
||||
new UsbHidPeripheral(config.usbHidVid, config.usbHidPid, config.usbHidSerialNumber.c_str());
|
||||
m_hostPacketizer = new UsbHidPacketizer(peripheral, config.packetTimeoutMs);
|
||||
|
||||
break;
|
||||
}
|
||||
case Peripheral::kHostPeripheralType_BUSPAL_UART:
|
||||
{
|
||||
BusPalUartPeripheral *peripheral =
|
||||
new BusPalUartPeripheral(config.comPortName.c_str(), config.comPortSpeed, config.busPalConfig);
|
||||
m_hostPacketizer = new SerialPacketizer(peripheral, config.packetTimeoutMs);
|
||||
|
||||
// Send initial ping.
|
||||
// Bus pal peripheral interface will take care of the delays for us.
|
||||
if (config.ping)
|
||||
{
|
||||
uint32_t buspalReadRetries;
|
||||
#if defined(DEBUG)
|
||||
buspalReadRetries = 0;
|
||||
#else
|
||||
buspalReadRetries = kBuspalReadRetries;
|
||||
#endif
|
||||
try
|
||||
{
|
||||
ping(buspalReadRetries, 0, 0);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
throw std::runtime_error(format_string("Error: Initial ping failure: %s", e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error(format_string("Error: Unsupported peripheral type(%d).", config.peripheralType));
|
||||
}
|
||||
}
|
||||
|
||||
// See host_bootloader.h for documentation of this method.
|
||||
Bootloader::~Bootloader()
|
||||
{
|
||||
flush();
|
||||
|
||||
// Delete packetizer should close handles and free memory on Peripheral.
|
||||
delete m_hostPacketizer;
|
||||
m_hostPacketizer = NULL;
|
||||
}
|
||||
|
||||
// See host_bootloader.h for documentation of this method.
|
||||
void Bootloader::flush()
|
||||
{
|
||||
// Finalize the packet interface.
|
||||
if (m_hostPacketizer)
|
||||
{
|
||||
m_hostPacketizer->finalize();
|
||||
}
|
||||
}
|
||||
|
||||
// See host_bootloader.h for documentation of this method.
|
||||
void Bootloader::execute(uint32_t entry_point, uint32_t param, uint32_t stack_pointer)
|
||||
{
|
||||
// Inject the execute(start_address, param, stack_pointer) command.
|
||||
Execute cmd(entry_point, param, stack_pointer);
|
||||
Log::info("Inject command '%s'\n", cmd.getName().c_str());
|
||||
this->inject(cmd);
|
||||
|
||||
uint32_t fw_status = cmd.getResponseValues()->at(0);
|
||||
std::string fw_msg = cmd.getStatusMessage(fw_status);
|
||||
|
||||
// Check the command status
|
||||
if (fw_status != kStatus_Success)
|
||||
{
|
||||
throw std::runtime_error(fw_msg);
|
||||
}
|
||||
}
|
||||
|
||||
// See host_bootloader.h for documentation of this method.
|
||||
void Bootloader::reset()
|
||||
{
|
||||
// Inject the reset command.
|
||||
Reset cmd;
|
||||
Log::info("Inject command '%s'\n", cmd.getName().c_str());
|
||||
this->inject(cmd);
|
||||
|
||||
uint32_t fw_status = cmd.getResponseValues()->at(0);
|
||||
std::string fw_msg = cmd.getStatusMessage(fw_status);
|
||||
|
||||
// Check the command status
|
||||
if (fw_status != kStatus_Success)
|
||||
{
|
||||
throw std::runtime_error(fw_msg);
|
||||
}
|
||||
}
|
||||
|
||||
// See host_bootloader.h for documentation of this method.
|
||||
standard_version_t Bootloader::getVersion()
|
||||
{
|
||||
// Inject the reset command.
|
||||
GetProperty cmd(kProperty_CurrentVersion);
|
||||
Log::info("inject command '%s'\n", cmd.getName().c_str());
|
||||
this->inject(cmd);
|
||||
|
||||
uint32_t fw_status = cmd.getResponseValues()->at(0);
|
||||
std::string fw_msg = cmd.getStatusMessage(fw_status);
|
||||
|
||||
// Check the command status
|
||||
if (fw_status != kStatus_Success)
|
||||
{
|
||||
throw std::runtime_error(fw_msg);
|
||||
}
|
||||
|
||||
return standard_version_t(cmd.getResponseValues()->at(1));
|
||||
}
|
||||
|
||||
// See host_bootloader.h for documentation of this method.
|
||||
uint32_t Bootloader::getSecurityState()
|
||||
{
|
||||
// Inject the reset command.
|
||||
GetProperty cmd(kProperty_FlashSecurityState);
|
||||
Log::info("inject command '%s'\n", cmd.getName().c_str());
|
||||
this->inject(cmd);
|
||||
|
||||
uint32_t fw_status = cmd.getResponseValues()->at(0);
|
||||
std::string fw_msg = cmd.getStatusMessage(fw_status);
|
||||
|
||||
// Check the command status
|
||||
if (fw_status != kStatus_Success)
|
||||
{
|
||||
throw std::runtime_error(fw_msg);
|
||||
}
|
||||
|
||||
return cmd.getResponseValues()->at(1);
|
||||
}
|
||||
|
||||
// See host_bootloader.h for documentation of this method.
|
||||
void Bootloader::ping(int retries, unsigned int delay, int comSpeed)
|
||||
{
|
||||
this->flush();
|
||||
|
||||
SerialPacketizer *pPacketizer = dynamic_cast<SerialPacketizer *>(m_hostPacketizer);
|
||||
if (pPacketizer)
|
||||
{
|
||||
status_t status = pPacketizer->ping(retries, delay, NULL, comSpeed);
|
||||
if (status != kStatus_Success)
|
||||
{
|
||||
this->flush();
|
||||
|
||||
Reset cmd; // dummy command to get access to status text.
|
||||
// report ping failure in JSON output mode.
|
||||
Json::Value root;
|
||||
root["command"] = "ping";
|
||||
root["status"] = Json::Value(Json::objectValue);
|
||||
root["status"]["value"] = static_cast<int32_t>(status);
|
||||
root["status"]["description"] =
|
||||
format_string("%d (0x%X) %s", status, status, cmd.getStatusMessage(status).c_str());
|
||||
root["response"] = Json::Value(Json::arrayValue);
|
||||
|
||||
Json::StyledWriter writer;
|
||||
Log::json(writer.write(root).c_str());
|
||||
|
||||
throw std::runtime_error(cmd.getStatusMessage(status));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
1185
src/blfwk/src/BusPal.cpp
Normal file
1185
src/blfwk/src/BusPal.cpp
Normal file
File diff suppressed because it is too large
Load Diff
243
src/blfwk/src/BusPalPeripheral.cpp
Normal file
243
src/blfwk/src/BusPalPeripheral.cpp
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "blfwk/BusPalPeripheral.h"
|
||||
#include "blfwk/Logging.h"
|
||||
#include "blfwk/format_string.h"
|
||||
|
||||
using namespace blfwk;
|
||||
using namespace std;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Variables
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Code
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// See BusPalUartPeripheral.h for documentation of this method.
|
||||
BusPalUartPeripheral::BusPalUartPeripheral(const char *port, long speed, const BusPal::BusPalConfigData &config)
|
||||
: UartPeripheral(port, speed)
|
||||
{
|
||||
m_busPal = new BusPal(m_fileDescriptor);
|
||||
if (m_busPal->enterBitBangMode())
|
||||
{
|
||||
configure(config);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete m_busPal;
|
||||
m_busPal = NULL;
|
||||
throw std::runtime_error(format_string("Error: BusPalUartPeripheral() cannot enter BitBang Mode."));
|
||||
}
|
||||
}
|
||||
|
||||
// See BusPalUartPeripheral.h for documentation of this method.
|
||||
BusPalUartPeripheral::~BusPalUartPeripheral()
|
||||
{
|
||||
}
|
||||
|
||||
// See BusPalUartPeripheral.h for documentation of this method.
|
||||
void BusPalUartPeripheral::configure(const BusPal::BusPalConfigData &config)
|
||||
{
|
||||
switch (config.function)
|
||||
{
|
||||
case BusPal::kBusPalFunction_SPI:
|
||||
if (!m_busPal->enterSpiMode())
|
||||
{
|
||||
throw std::runtime_error(format_string("Error: BusPalUartPeripheral() cannot enter SPI Mode."));
|
||||
}
|
||||
|
||||
if (!m_busPal->setSpiSpeed(config.spiSpeedKHz))
|
||||
{
|
||||
throw std::runtime_error(
|
||||
format_string("Error: BusPalUartPeripheral() cannot set SPI speed(%d kHz).", config.spiSpeedKHz));
|
||||
}
|
||||
|
||||
if (!m_busPal->setSpiConfig(config.spiPolarity, config.spiPhase, config.spiDirection))
|
||||
{
|
||||
throw std::runtime_error(format_string(
|
||||
"Error: BusPalUartPeripheral() cannot set SPI polarity(%s(%d)), phase(%s(%d)), and "
|
||||
"direction(%s(%d)).",
|
||||
config.spiPolarity == BusPal::kSpiClockPolarity_ActiveHigh ? "ActiveHigh" : "ActiveLow",
|
||||
config.spiPolarity,
|
||||
config.spiPhase == BusPal::kSpiClockPhase_FirstEdge ? "FirstEdge" : "SecondEdge", config.spiPhase,
|
||||
config.spiDirection == BusPal::kSpiLsbFirst ? "LsbFirst" : "MsbFirst", config.spiDirection));
|
||||
}
|
||||
break;
|
||||
|
||||
case BusPal::kBusPalFunction_CAN:
|
||||
if (!m_busPal->enterCanMode())
|
||||
{
|
||||
throw std::runtime_error(format_string("Error: BusPalUartPeripheral() cannot enter CAN Mode."));
|
||||
}
|
||||
|
||||
if (!m_busPal->setCanSpeed(config.canSpeed))
|
||||
{
|
||||
throw std::runtime_error(
|
||||
format_string("Error: BusPalUartPeripheral() cannot set CAN speed(%d).", config.canSpeed));
|
||||
}
|
||||
|
||||
if (!m_busPal->setCanTxid(config.canTxid))
|
||||
{
|
||||
throw std::runtime_error(
|
||||
format_string("Error: BusPalUartPeripheral() cannot set CAN txid(0x%x).", config.canTxid));
|
||||
}
|
||||
|
||||
if (!m_busPal->setCanRxid(config.canRxid))
|
||||
{
|
||||
throw std::runtime_error(
|
||||
format_string("Error: BusPalUartPeripheral() cannot set CAN rxid(0x%x).", config.canTxid));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case BusPal::kBusPalFunction_I2C:
|
||||
if (!m_busPal->enterI2cMode())
|
||||
{
|
||||
throw std::runtime_error(format_string("Error: BusPalUartPeripheral() cannot enter I2C Mode."));
|
||||
}
|
||||
if (!m_busPal->setI2cAddress(config.i2cAddress))
|
||||
{
|
||||
throw std::runtime_error(
|
||||
format_string("Error: BusPalUartPeripheral() cannot set I2C address %02X.", config.i2cAddress));
|
||||
}
|
||||
|
||||
if (!m_busPal->setI2cSpeed(config.i2cSpeedKHz))
|
||||
{
|
||||
throw std::runtime_error(
|
||||
format_string("Error: BusPalUartPeripheral() cannot set I2C speed(%d KHz).", config.i2cSpeedKHz));
|
||||
}
|
||||
break;
|
||||
|
||||
case BusPal::kBusPalFunction_GPIO_CONFIG:
|
||||
if (!m_busPal->enterBitBangMode())
|
||||
{
|
||||
throw std::runtime_error(
|
||||
format_string("Error: BusPalUartPeripheral() cannot enter Bitbang mode for GPIO setting."));
|
||||
}
|
||||
if (!m_busPal->rawConfigurePins(config.gpioPort, config.gpioPinNum, config.gpioMux))
|
||||
{
|
||||
throw std::runtime_error(
|
||||
format_string("Error: BusPalUartPeripheral() cannot configure GPIO %c,%02X,%02X", config.gpioPort,
|
||||
config.gpioPinNum, config.gpioMux));
|
||||
}
|
||||
break;
|
||||
|
||||
case BusPal::kBusPalFunction_GPIO_SET:
|
||||
if (!m_busPal->enterBitBangMode())
|
||||
{
|
||||
throw std::runtime_error(
|
||||
format_string("Error: BusPalUartPeripheral() cannot enter Bitbang mode for GPIO setting."));
|
||||
}
|
||||
if (!m_busPal->rawSetPins(config.gpioPort, config.gpioPinNum, config.gpioLevel))
|
||||
{
|
||||
throw std::runtime_error(format_string("Error: BusPalUartPeripheral() cannot set GPIO %c,%02X,%02X",
|
||||
config.gpioPort, config.gpioPinNum, config.gpioLevel));
|
||||
}
|
||||
break;
|
||||
|
||||
case BusPal::kBusPalFunction_FPGA_CLOCK_SET:
|
||||
if (!m_busPal->enterBitBangMode())
|
||||
{
|
||||
throw std::runtime_error(
|
||||
format_string("Error: BusPalUartPeripheral() cannot enter Bitbang mode for FPGA clock setting."));
|
||||
}
|
||||
if (!m_busPal->setFPGAClock(config.fpgaClockMhz))
|
||||
{
|
||||
throw std::runtime_error(format_string("Error: BusPalUartPeripheral() cannot set FPGA clock to %2d MHz",
|
||||
config.fpgaClockMhz));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::runtime_error("Unsupported BusPal function type");
|
||||
}
|
||||
}
|
||||
|
||||
// See BusPalUartPeripheral.h for documentation of this method.
|
||||
status_t BusPalUartPeripheral::read(uint8_t *buffer, uint32_t requestedBytes, uint32_t *actualBytes, uint32_t timeoutMs)
|
||||
{
|
||||
assert(buffer);
|
||||
|
||||
// Read the requested number of bytes.
|
||||
int count = m_busPal->read(buffer, requestedBytes);
|
||||
if (actualBytes)
|
||||
{
|
||||
*actualBytes = count;
|
||||
}
|
||||
|
||||
if (count < (int)requestedBytes)
|
||||
{
|
||||
// Anything less than requestedBytes is a timeout error.
|
||||
Log::error("Error: Bus Pal read returned 0\n");
|
||||
return kStatus_Timeout;
|
||||
}
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
// See BusPalUartPeripheral.h for documentation of this method.
|
||||
status_t BusPalUartPeripheral::write(const uint8_t *buffer, uint32_t byteCount)
|
||||
{
|
||||
assert(buffer);
|
||||
|
||||
const int maxBulk = BusPal::kBulkTransferMax;
|
||||
int numBulk = (byteCount / maxBulk);
|
||||
int remaining = byteCount - (numBulk * maxBulk);
|
||||
bool rc = true;
|
||||
|
||||
// Send buffer in max bulk transfer size chunks.
|
||||
for (int i = 0; i < numBulk; ++i)
|
||||
{
|
||||
rc = m_busPal->write(&buffer[i * maxBulk], maxBulk);
|
||||
if (!rc)
|
||||
{
|
||||
return kStatus_Fail;
|
||||
}
|
||||
}
|
||||
|
||||
// Send the last OR partial chunk.
|
||||
if (rc && remaining)
|
||||
{
|
||||
rc = m_busPal->write(&buffer[numBulk * maxBulk], remaining);
|
||||
if (!rc)
|
||||
{
|
||||
return kStatus_Fail;
|
||||
}
|
||||
}
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
2132
src/blfwk/src/Command.cpp
Normal file
2132
src/blfwk/src/Command.cpp
Normal file
File diff suppressed because it is too large
Load Diff
67
src/blfwk/src/Crc.cpp
Normal file
67
src/blfwk/src/Crc.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2013-15, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "blfwk/Crc.h"
|
||||
#include "bootloader/bootloader.h"
|
||||
#include "crc/crc32.h"
|
||||
|
||||
using namespace blfwk;
|
||||
|
||||
// See Crc.h for documentation of this method.
|
||||
uint32_t Crc::calculate_application_crc32(const uint8_t *start, uint32_t length)
|
||||
{
|
||||
uint32_t crc32;
|
||||
|
||||
// Initialize the CRC32 information
|
||||
crc32_data_t crcInfo;
|
||||
crc32_init(&crcInfo);
|
||||
|
||||
// Run CRC, Considering skip crcExpectedValue address
|
||||
const bootloader_configuration_data_t *config =
|
||||
NULL; // Just used for calculate the offset, must not change the region it points to.
|
||||
uint32_t bypassStartAddress = 0x3C0 + ((uint32_t)&config->crcExpectedValue - (uint32_t)&config->tag);
|
||||
uint32_t bypassEndAddress = bypassStartAddress + sizeof(config->crcExpectedValue);
|
||||
|
||||
if (length <= bypassStartAddress)
|
||||
{
|
||||
crc32_update(&crcInfo, (uint8_t *)start, length);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assume that crcExpectedValue address (4 byte) resides in crc addresses completely
|
||||
crc32_update(&crcInfo, (uint8_t *)start, bypassStartAddress);
|
||||
crc32_update(&crcInfo, (uint8_t *)(start + bypassEndAddress), length - bypassEndAddress);
|
||||
}
|
||||
|
||||
// Finalize the CRC calculations
|
||||
crc32_finalize(&crcInfo, &crc32);
|
||||
|
||||
return crc32;
|
||||
}
|
||||
280
src/blfwk/src/DataSource.cpp
Normal file
280
src/blfwk/src/DataSource.cpp
Normal file
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "blfwk/DataSource.h"
|
||||
#include "blfwk/DataTarget.h"
|
||||
|
||||
using namespace blfwk;
|
||||
|
||||
#pragma warning(disable : 4068) /* disable unknown pragma warnings */
|
||||
#pragma mark *** DataSource::PatternSegment ***
|
||||
|
||||
DataSource::PatternSegment::PatternSegment(DataSource &source)
|
||||
: DataSource::Segment(source)
|
||||
, m_pattern()
|
||||
{
|
||||
}
|
||||
|
||||
DataSource::PatternSegment::PatternSegment(DataSource &source, const SizedIntegerValue &pattern)
|
||||
: DataSource::Segment(source)
|
||||
, m_pattern(pattern)
|
||||
{
|
||||
}
|
||||
|
||||
DataSource::PatternSegment::PatternSegment(DataSource &source, uint8_t pattern)
|
||||
: DataSource::Segment(source)
|
||||
, m_pattern(static_cast<uint8_t>(pattern))
|
||||
{
|
||||
}
|
||||
|
||||
DataSource::PatternSegment::PatternSegment(DataSource &source, uint16_t pattern)
|
||||
: DataSource::Segment(source)
|
||||
, m_pattern(static_cast<uint16_t>(pattern))
|
||||
{
|
||||
}
|
||||
|
||||
DataSource::PatternSegment::PatternSegment(DataSource &source, uint32_t pattern)
|
||||
: DataSource::Segment(source)
|
||||
, m_pattern(static_cast<uint32_t>(pattern))
|
||||
{
|
||||
}
|
||||
|
||||
unsigned DataSource::PatternSegment::getData(unsigned offset, unsigned maxBytes, uint8_t *buffer)
|
||||
{
|
||||
memset(buffer, 0, maxBytes);
|
||||
|
||||
return maxBytes;
|
||||
}
|
||||
|
||||
//! The pattern segment's length is a function of the data target. If the
|
||||
//! target is bounded, then the segment's length is simply the target's
|
||||
//! length. Otherwise, if no target has been set or the target is unbounded,
|
||||
//! then the length returned is 0.
|
||||
unsigned DataSource::PatternSegment::getLength()
|
||||
{
|
||||
DataTarget *target = m_source.getTarget();
|
||||
if (!target)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t length;
|
||||
if (target->isBounded())
|
||||
{
|
||||
length = target->getEndAddress() - target->getBeginAddress();
|
||||
}
|
||||
else
|
||||
{
|
||||
length = m_pattern.getSize();
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
#pragma mark *** PatternSource ***
|
||||
|
||||
PatternSource::PatternSource()
|
||||
: DataSource()
|
||||
, DataSource::PatternSegment((DataSource &)*this)
|
||||
{
|
||||
}
|
||||
|
||||
PatternSource::PatternSource(const SizedIntegerValue &value)
|
||||
: DataSource()
|
||||
, DataSource::PatternSegment((DataSource &)*this, value)
|
||||
{
|
||||
}
|
||||
|
||||
#pragma mark *** UnmappedDataSource ***
|
||||
|
||||
UnmappedDataSource::UnmappedDataSource()
|
||||
: DataSource()
|
||||
, DataSource::Segment((DataSource &)*this)
|
||||
, m_data()
|
||||
, m_length(0)
|
||||
{
|
||||
}
|
||||
|
||||
UnmappedDataSource::UnmappedDataSource(const uint8_t *data, unsigned length)
|
||||
: DataSource()
|
||||
, DataSource::Segment((DataSource &)*this)
|
||||
, m_data()
|
||||
, m_length(0)
|
||||
{
|
||||
setData(data, length);
|
||||
}
|
||||
|
||||
//! Makes a copy of \a data that is freed when the data source is
|
||||
//! destroyed. The caller does not have to maintain \a data after this call
|
||||
//! returns.
|
||||
void UnmappedDataSource::setData(const uint8_t *data, unsigned length)
|
||||
{
|
||||
m_data.safe_delete();
|
||||
|
||||
uint8_t *dataCopy = new uint8_t[length];
|
||||
memcpy(dataCopy, data, length);
|
||||
m_data = dataCopy;
|
||||
m_length = length;
|
||||
}
|
||||
|
||||
unsigned UnmappedDataSource::getData(unsigned offset, unsigned maxBytes, uint8_t *buffer)
|
||||
{
|
||||
assert(offset < m_length);
|
||||
unsigned copyBytes = std::min<unsigned>(m_length - offset, maxBytes);
|
||||
memcpy(buffer, &m_data[offset], copyBytes);
|
||||
return copyBytes;
|
||||
}
|
||||
|
||||
//! The unmapped datasource as segment's base address is a function of the data target.
|
||||
//! If the target is not NULL, then the segment's base address is simply the target's
|
||||
//! beginAddress. Otherwise, if no target has been set, then the base address returned is 0.
|
||||
uint32_t UnmappedDataSource::getBaseAddress()
|
||||
{
|
||||
return getTarget() == NULL ? 0 : getTarget()->getBeginAddress();
|
||||
}
|
||||
|
||||
#pragma mark *** MemoryImageDataSource ***
|
||||
|
||||
MemoryImageDataSource::MemoryImageDataSource(StExecutableImage *image)
|
||||
: DataSource()
|
||||
, m_image(image)
|
||||
{
|
||||
// reserve enough room for all segments
|
||||
m_segments.reserve(m_image->getRegionCount());
|
||||
}
|
||||
|
||||
MemoryImageDataSource::~MemoryImageDataSource()
|
||||
{
|
||||
segment_array_t::iterator it = m_segments.begin();
|
||||
for (; it != m_segments.end(); ++it)
|
||||
{
|
||||
// delete this segment if it has been created
|
||||
if (*it)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned MemoryImageDataSource::getSegmentCount()
|
||||
{
|
||||
return m_image->getRegionCount();
|
||||
}
|
||||
|
||||
DataSource::Segment *MemoryImageDataSource::getSegmentAt(unsigned index)
|
||||
{
|
||||
// return previously created segment
|
||||
if (index < m_segments.size() && m_segments[index])
|
||||
{
|
||||
return m_segments[index];
|
||||
}
|
||||
|
||||
// extend array out to this index
|
||||
if (index >= m_segments.size() && index < m_image->getRegionCount())
|
||||
{
|
||||
m_segments.resize(index + 1, NULL);
|
||||
}
|
||||
|
||||
// create the new segment object
|
||||
DataSource::Segment *newSegment;
|
||||
const StExecutableImage::MemoryRegion ®ion = m_image->getRegionAtIndex(index);
|
||||
if (region.m_type == StExecutableImage::TEXT_REGION)
|
||||
{
|
||||
newSegment = new TextSegment(*this, m_image, index);
|
||||
}
|
||||
else if (region.m_type == StExecutableImage::FILL_REGION)
|
||||
{
|
||||
newSegment = new FillSegment(*this, m_image, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
newSegment = NULL;
|
||||
}
|
||||
|
||||
m_segments[index] = newSegment;
|
||||
return newSegment;
|
||||
}
|
||||
|
||||
#pragma mark *** MemoryImageDataSource::TextSegment ***
|
||||
|
||||
MemoryImageDataSource::TextSegment::TextSegment(MemoryImageDataSource &source, StExecutableImage *image, unsigned index)
|
||||
: DataSource::Segment(source)
|
||||
, m_image(image)
|
||||
, m_index(index)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned MemoryImageDataSource::TextSegment::getData(unsigned offset, unsigned maxBytes, uint8_t *buffer)
|
||||
{
|
||||
const StExecutableImage::MemoryRegion ®ion = m_image->getRegionAtIndex(m_index);
|
||||
assert(region.m_type == StExecutableImage::TEXT_REGION);
|
||||
|
||||
unsigned copyBytes = std::min<unsigned>(region.m_length - offset, maxBytes);
|
||||
memcpy(buffer, ®ion.m_data[offset], copyBytes);
|
||||
|
||||
return copyBytes;
|
||||
}
|
||||
|
||||
unsigned MemoryImageDataSource::TextSegment::getLength()
|
||||
{
|
||||
const StExecutableImage::MemoryRegion ®ion = m_image->getRegionAtIndex(m_index);
|
||||
return region.m_length;
|
||||
}
|
||||
|
||||
uint32_t MemoryImageDataSource::TextSegment::getBaseAddress()
|
||||
{
|
||||
const StExecutableImage::MemoryRegion ®ion = m_image->getRegionAtIndex(m_index);
|
||||
return region.m_address;
|
||||
}
|
||||
|
||||
#pragma mark *** MemoryImageDataSource::FillSegment ***
|
||||
|
||||
MemoryImageDataSource::FillSegment::FillSegment(MemoryImageDataSource &source, StExecutableImage *image, unsigned index)
|
||||
: DataSource::PatternSegment(source)
|
||||
, m_image(image)
|
||||
, m_index(index)
|
||||
{
|
||||
SizedIntegerValue zero(0, kWordSize);
|
||||
setPattern(zero);
|
||||
}
|
||||
|
||||
unsigned MemoryImageDataSource::FillSegment::getLength()
|
||||
{
|
||||
const StExecutableImage::MemoryRegion ®ion = m_image->getRegionAtIndex(m_index);
|
||||
return region.m_length;
|
||||
}
|
||||
|
||||
uint32_t MemoryImageDataSource::FillSegment::getBaseAddress()
|
||||
{
|
||||
const StExecutableImage::MemoryRegion ®ion = m_image->getRegionAtIndex(m_index);
|
||||
return region.m_address;
|
||||
}
|
||||
142
src/blfwk/src/DataSourceImager.cpp
Normal file
142
src/blfwk/src/DataSourceImager.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* File: DataSourceImager.cpp
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
|
||||
* See included license file for license details.
|
||||
*/
|
||||
|
||||
#include "blfwk/DataSourceImager.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
using namespace blfwk;
|
||||
|
||||
DataSourceImager::DataSourceImager()
|
||||
: Blob()
|
||||
, m_fill(0)
|
||||
, m_baseAddress(0)
|
||||
, m_isBaseAddressSet(false)
|
||||
{
|
||||
}
|
||||
|
||||
void DataSourceImager::setBaseAddress(uint32_t address)
|
||||
{
|
||||
m_baseAddress = address;
|
||||
m_isBaseAddressSet = true;
|
||||
}
|
||||
|
||||
void DataSourceImager::setFillPattern(uint8_t pattern)
|
||||
{
|
||||
m_fill = pattern;
|
||||
}
|
||||
|
||||
void DataSourceImager::reset()
|
||||
{
|
||||
clear();
|
||||
|
||||
m_fill = 0;
|
||||
m_baseAddress = 0;
|
||||
m_isBaseAddressSet = false;
|
||||
}
|
||||
|
||||
//! \param dataSource Pointer to an instance of a concrete data source subclass.
|
||||
//!
|
||||
void DataSourceImager::addDataSource(DataSource *source)
|
||||
{
|
||||
unsigned segmentCount = source->getSegmentCount();
|
||||
unsigned index = 0;
|
||||
for (; index < segmentCount; ++index)
|
||||
{
|
||||
addDataSegment(source->getSegmentAt(index));
|
||||
}
|
||||
}
|
||||
|
||||
//! \param segment The segment to add. May be any type of data segment, including
|
||||
//! a pattern segment.
|
||||
void DataSourceImager::addDataSegment(DataSource::Segment *segment)
|
||||
{
|
||||
DataSource::PatternSegment *patternSegment = dynamic_cast<DataSource::PatternSegment *>(segment);
|
||||
|
||||
unsigned segmentLength = segment->getLength();
|
||||
bool segmentHasLocation = segment->hasNaturalLocation();
|
||||
uint32_t segmentAddress = segment->getBaseAddress();
|
||||
|
||||
uint8_t *toPtr = NULL;
|
||||
unsigned addressDelta;
|
||||
unsigned newLength;
|
||||
|
||||
// If a pattern segment's length is 0 then make it as big as the fill pattern.
|
||||
// This needs to be done before the buffer is adjusted.
|
||||
if (patternSegment && segmentLength == 0)
|
||||
{
|
||||
SizedIntegerValue &pattern = patternSegment->getPattern();
|
||||
segmentLength = pattern.getSize();
|
||||
}
|
||||
|
||||
if (segmentLength)
|
||||
{
|
||||
if (segmentHasLocation)
|
||||
{
|
||||
// Make sure a base address is set.
|
||||
if (!m_isBaseAddressSet)
|
||||
{
|
||||
m_baseAddress = segmentAddress;
|
||||
m_isBaseAddressSet = true;
|
||||
}
|
||||
|
||||
// The segment is located before our buffer's first address.
|
||||
// toPtr is not set in this if, but in the else branch of the next if.
|
||||
// Unless the segment completely overwrite the current data.
|
||||
if (segmentAddress < m_baseAddress)
|
||||
{
|
||||
addressDelta = m_baseAddress - segmentAddress;
|
||||
|
||||
uint8_t *newData = (uint8_t *)malloc(m_length + addressDelta);
|
||||
memcpy(&newData[addressDelta], m_data, m_length);
|
||||
free(m_data);
|
||||
|
||||
m_data = newData;
|
||||
m_length += addressDelta;
|
||||
m_baseAddress = segmentAddress;
|
||||
}
|
||||
|
||||
// This segment is located or extends outside of our buffer.
|
||||
if (segmentAddress + segmentLength > m_baseAddress + m_length)
|
||||
{
|
||||
newLength = segmentAddress + segmentLength - m_baseAddress;
|
||||
|
||||
m_data = (uint8_t *)realloc(m_data, newLength);
|
||||
|
||||
// Clear any bytes between the old data and the new segment.
|
||||
addressDelta = segmentAddress - (m_baseAddress + m_length);
|
||||
if (addressDelta)
|
||||
{
|
||||
memset(m_data + m_length, 0, addressDelta);
|
||||
}
|
||||
|
||||
toPtr = m_data + (segmentAddress - m_baseAddress);
|
||||
m_length = newLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
toPtr = m_data + (segmentAddress - m_baseAddress);
|
||||
}
|
||||
}
|
||||
// Segment has no natural location, so just append it to the end of our buffer.
|
||||
else
|
||||
{
|
||||
newLength = m_length + segmentLength;
|
||||
m_data = (uint8_t *)realloc(m_data, newLength);
|
||||
toPtr = m_data + m_length;
|
||||
m_length = newLength;
|
||||
}
|
||||
}
|
||||
|
||||
// A loop is used because getData() may fill in less than the requested
|
||||
// number of bytes per call.
|
||||
unsigned offset = 0;
|
||||
while (offset < segmentLength)
|
||||
{
|
||||
offset += segment->getData(offset, segmentLength - offset, toPtr + offset);
|
||||
}
|
||||
}
|
||||
82
src/blfwk/src/DataTarget.cpp
Normal file
82
src/blfwk/src/DataTarget.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "blfwk/DataTarget.h"
|
||||
#include "blfwk/DataSource.h"
|
||||
#include "blfwk/BlfwkErrors.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace blfwk;
|
||||
|
||||
//! \exception blfwk::semantic_error Thrown if the source has multiple segments.
|
||||
DataTarget::AddressRange ConstantDataTarget::getRangeForSegment(DataSource &source, DataSource::Segment &segment)
|
||||
{
|
||||
// can't handle multi-segment data sources
|
||||
if (source.getSegmentCount() > 1)
|
||||
{
|
||||
throw semantic_error("constant targets only support single-segment sources");
|
||||
}
|
||||
|
||||
// always relocate the segment to our begin address
|
||||
AddressRange range;
|
||||
range.m_begin = m_begin;
|
||||
|
||||
if (isBounded())
|
||||
{
|
||||
// we have an end address. trim the result range to the segment size
|
||||
// or let the end address crop the segment.
|
||||
range.m_end = std::min<uint32_t>(m_end, m_begin + segment.getLength());
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have no end address, so the segment size determines it.
|
||||
range.m_end = m_begin + segment.getLength();
|
||||
}
|
||||
|
||||
return range;
|
||||
}
|
||||
|
||||
//! If the \a segment has a natural location, the returned address range extends
|
||||
//! from the segment's base address to its base address plus its length.
|
||||
//!
|
||||
//! \exception blfwk::semantic_error This exception is thrown if the \a segment
|
||||
//! does not have a natural location associated with it.
|
||||
DataTarget::AddressRange NaturalDataTarget::getRangeForSegment(DataSource &source, DataSource::Segment &segment)
|
||||
{
|
||||
if (!segment.hasNaturalLocation())
|
||||
{
|
||||
throw semantic_error("source has no natural location");
|
||||
}
|
||||
|
||||
AddressRange range;
|
||||
range.m_begin = segment.getBaseAddress();
|
||||
range.m_end = segment.getBaseAddress() + segment.getLength();
|
||||
return range;
|
||||
}
|
||||
632
src/blfwk/src/ELFSourceFile.cpp
Normal file
632
src/blfwk/src/ELFSourceFile.cpp
Normal file
File diff suppressed because it is too large
Load Diff
87
src/blfwk/src/ExcludesListMatcher.cpp
Normal file
87
src/blfwk/src/ExcludesListMatcher.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* File: ExcludesListMatcher.cpp
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
|
||||
* See included license file for license details.
|
||||
*/
|
||||
|
||||
#include "blfwk/ExcludesListMatcher.h"
|
||||
|
||||
using namespace blfwk;
|
||||
|
||||
ExcludesListMatcher::ExcludesListMatcher()
|
||||
: GlobMatcher("")
|
||||
{
|
||||
}
|
||||
|
||||
ExcludesListMatcher::~ExcludesListMatcher()
|
||||
{
|
||||
}
|
||||
|
||||
//! \param isInclude True if this pattern is an include, false if it is an exclude.
|
||||
//! \param pattern String containing the glob pattern.
|
||||
void ExcludesListMatcher::addPattern(bool isInclude, const std::string &pattern)
|
||||
{
|
||||
glob_list_item_t item;
|
||||
item.m_isInclude = isInclude;
|
||||
item.m_glob = pattern;
|
||||
|
||||
// add to end of list
|
||||
m_patterns.push_back(item);
|
||||
}
|
||||
|
||||
//! If there are no entries in the match list, the match fails.
|
||||
//!
|
||||
//! \param testValue The string to match against the pattern list.
|
||||
//! \retval true The \a testValue argument matches.
|
||||
//! \retval false No match was made against the argument.
|
||||
bool ExcludesListMatcher::match(const std::string &testValue)
|
||||
{
|
||||
if (!m_patterns.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Iterate over the match list. Includes act as an OR operator, while
|
||||
// excludes act as an AND operator.
|
||||
bool didMatch = false;
|
||||
bool isFirstItem = true;
|
||||
glob_list_t::iterator it = m_patterns.begin();
|
||||
for (; it != m_patterns.end(); ++it)
|
||||
{
|
||||
glob_list_item_t &item = *it;
|
||||
|
||||
// if this pattern is an include and it doesn't match, or
|
||||
// if this pattern is an exclude and it does match, then the match fails
|
||||
bool didItemMatch = globMatch(testValue.c_str(), item.m_glob.c_str());
|
||||
|
||||
if (item.m_isInclude)
|
||||
{
|
||||
// Include
|
||||
if (isFirstItem)
|
||||
{
|
||||
didMatch = didItemMatch;
|
||||
}
|
||||
else
|
||||
{
|
||||
didMatch = didMatch || didItemMatch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Exclude
|
||||
if (isFirstItem)
|
||||
{
|
||||
didMatch = !didItemMatch;
|
||||
}
|
||||
else
|
||||
{
|
||||
didMatch = didMatch && !didItemMatch;
|
||||
}
|
||||
}
|
||||
|
||||
isFirstItem = false;
|
||||
}
|
||||
|
||||
return didMatch;
|
||||
}
|
||||
103
src/blfwk/src/GHSSecInfo.cpp
Normal file
103
src/blfwk/src/GHSSecInfo.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* File: GHSSecInfo.cpp
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
|
||||
* See included license file for license details.
|
||||
*/
|
||||
|
||||
#include "blfwk/GHSSecInfo.h"
|
||||
#include <stdexcept>
|
||||
#include "blfwk/Logging.h"
|
||||
#include "blfwk/EndianUtilities.h"
|
||||
|
||||
//! The name of the GHS-specific section info table ELF section.
|
||||
const char *const kSecInfoSectionName = ".secinfo";
|
||||
|
||||
using namespace blfwk;
|
||||
|
||||
//! The ELF file passed into this constructor as the \a elf argument must remain
|
||||
//! valid for the life of this object.
|
||||
//!
|
||||
//! \param elf The ELF file parser. An assertion is raised if this is NULL.
|
||||
GHSSecInfo::GHSSecInfo(StELFFile *elf)
|
||||
: m_elf(elf)
|
||||
, m_hasInfo(false)
|
||||
, m_info(0)
|
||||
, m_entryCount(0)
|
||||
{
|
||||
assert(elf);
|
||||
|
||||
// look up the section. if it's not there just leave m_info and m_entryCount to 0
|
||||
unsigned sectionIndex = m_elf->getIndexOfSectionWithName(kSecInfoSectionName);
|
||||
if (sectionIndex == SHN_UNDEF)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// get the section data
|
||||
const Elf32_Shdr &secInfo = m_elf->getSectionAtIndex(sectionIndex);
|
||||
if (secInfo.sh_type != SHT_PROGBITS)
|
||||
{
|
||||
// .secinfo section isn't the right type, so something is wrong
|
||||
return;
|
||||
}
|
||||
|
||||
m_hasInfo = true;
|
||||
m_info = (ghs_secinfo_t *)m_elf->getSectionDataAtIndex(sectionIndex);
|
||||
m_entryCount = secInfo.sh_size / sizeof(ghs_secinfo_t);
|
||||
}
|
||||
|
||||
//! Looks up \a addr for \a length in the .secinfo array. Only if that address is in the
|
||||
//! .secinfo array does this section need to be filled. If the section is found but the
|
||||
//! length does not match the \a length argument, a message is logged at the
|
||||
//! #Logger::kWarning level.
|
||||
//!
|
||||
//! If the .secinfo section is not present in the ELF file, this method always returns
|
||||
//! true.
|
||||
//!
|
||||
//! \param addr The start address of the section to query.
|
||||
//! \param length The length of the section. If a section with a start address matching
|
||||
//! \a addr is found, its length must match \a length to be considered.
|
||||
//!
|
||||
//! \retval true The section matching \a addr and \a length was found and should be filled.
|
||||
//! True is also returned when the ELF file does not have a .secinfo section.
|
||||
//! \retval false The section was not found and should not be filled.
|
||||
bool GHSSecInfo::isSectionFilled(uint32_t addr, uint32_t length)
|
||||
{
|
||||
if (!m_hasInfo)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < m_entryCount; ++i)
|
||||
{
|
||||
// byte swap these values into host endianness
|
||||
uint32_t clearAddr = ENDIAN_LITTLE_TO_HOST_U32(m_info[i].m_clearAddr);
|
||||
uint32_t numBytesToClear = ENDIAN_LITTLE_TO_HOST_U32(m_info[i].m_numBytesToClear);
|
||||
|
||||
// we only consider non-zero length clear regions
|
||||
if ((addr == clearAddr) && (numBytesToClear != 0))
|
||||
{
|
||||
// it is an error if the address matches but the length does not
|
||||
if (length != numBytesToClear)
|
||||
{
|
||||
Log::log(Logger::kWarning, "ELF Error: Size mismatch @ sect=%u, .secinfo=%u at addr 0x%08X\n", length,
|
||||
numBytesToClear, addr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Simply calls through to isSectionFilled(uint32_t, uint32_t) to determine
|
||||
//! if \a section should be filled.
|
||||
//!
|
||||
//! If the .secinfo section is not present in the ELF file, this method always returns
|
||||
//! true.
|
||||
bool GHSSecInfo::isSectionFilled(const Elf32_Shdr §ion)
|
||||
{
|
||||
return isSectionFilled(section.sh_addr, section.sh_size);
|
||||
}
|
||||
135
src/blfwk/src/GlobMatcher.cpp
Normal file
135
src/blfwk/src/GlobMatcher.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* File: GlobMatcher.cpp
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
|
||||
* See included license file for license details.
|
||||
*/
|
||||
|
||||
#include "blfwk/GlobMatcher.h"
|
||||
|
||||
#ifndef NEGATE
|
||||
#define NEGATE '^' // std cset negation char
|
||||
#endif
|
||||
|
||||
using namespace blfwk;
|
||||
|
||||
//! The glob pattern must match the \e entire test value argument in order
|
||||
//! for the match to be considered successful. Thus, even if, for example,
|
||||
//! the pattern matches all but the last character the result will be false.
|
||||
//!
|
||||
//! \retval true The test value does match the glob pattern.
|
||||
//! \retval false The test value does not match the glob pattern.
|
||||
bool GlobMatcher::match(const std::string &testValue)
|
||||
{
|
||||
return globMatch(testValue.c_str(), m_pattern.c_str());
|
||||
}
|
||||
|
||||
//! \note This glob implementation was originally written by ozan s. yigit in
|
||||
//! December 1994. This is public domain source code.
|
||||
bool GlobMatcher::globMatch(const char *str, const char *p)
|
||||
{
|
||||
int negate;
|
||||
int match;
|
||||
int c;
|
||||
|
||||
while (*p)
|
||||
{
|
||||
if (!*str && *p != '*')
|
||||
return false;
|
||||
|
||||
switch (c = *p++)
|
||||
{
|
||||
case '*':
|
||||
while (*p == '*')
|
||||
p++;
|
||||
|
||||
if (!*p)
|
||||
return true;
|
||||
|
||||
if (*p != '?' && *p != '[' && *p != '\\')
|
||||
while (*str && *p != *str)
|
||||
str++;
|
||||
|
||||
while (*str)
|
||||
{
|
||||
if (globMatch(str, p))
|
||||
return true;
|
||||
str++;
|
||||
}
|
||||
return false;
|
||||
|
||||
case '?':
|
||||
if (*str)
|
||||
break;
|
||||
return false;
|
||||
|
||||
// set specification is inclusive, that is [a-z] is a, z and
|
||||
// everything in between. this means [z-a] may be interpreted
|
||||
// as a set that contains z, a and nothing in between.
|
||||
case '[':
|
||||
if (*p != NEGATE)
|
||||
negate = false;
|
||||
else
|
||||
{
|
||||
negate = true;
|
||||
p++;
|
||||
}
|
||||
|
||||
match = false;
|
||||
|
||||
while (!match && (c = *p++))
|
||||
{
|
||||
if (!*p)
|
||||
return false;
|
||||
if (*p == '-')
|
||||
{ // c-c
|
||||
if (!*++p)
|
||||
return false;
|
||||
if (*p != ']')
|
||||
{
|
||||
if (*str == c || *str == *p || (*str > c && *str < *p))
|
||||
match = true;
|
||||
}
|
||||
else
|
||||
{ // c-]
|
||||
if (*str >= c)
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // cc or c]
|
||||
if (c == *str)
|
||||
match = true;
|
||||
if (*p != ']')
|
||||
{
|
||||
if (*p == *str)
|
||||
match = true;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (negate == match)
|
||||
return false;
|
||||
// if there is a match, skip past the cset and continue on
|
||||
while (*p && *p != ']')
|
||||
p++;
|
||||
if (!*p++) // oops!
|
||||
return false;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
if (*p)
|
||||
c = *p++;
|
||||
default:
|
||||
if (c != *str)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
str++;
|
||||
}
|
||||
|
||||
return !*str;
|
||||
}
|
||||
35
src/blfwk/src/HexValues.cpp
Normal file
35
src/blfwk/src/HexValues.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* File: HexValues.cpp
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
|
||||
* See included license file for license details.
|
||||
*/
|
||||
|
||||
#include "blfwk/HexValues.h"
|
||||
#include <cctype>
|
||||
|
||||
bool isHexDigit(char c)
|
||||
{
|
||||
return isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
||||
}
|
||||
|
||||
//! \return The integer equivalent to \a c.
|
||||
//! \retval -1 The character \a c is not a hex character.
|
||||
uint8_t hexCharToInt(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
return c - 'a' + 10;
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
return c - 'A' + 10;
|
||||
else
|
||||
return static_cast<uint8_t>(-1);
|
||||
}
|
||||
|
||||
//! \param encodedByte Must point to at least two ASCII hex characters.
|
||||
//!
|
||||
uint8_t hexByteToInt(const char *encodedByte)
|
||||
{
|
||||
return (hexCharToInt(encodedByte[0]) << 4) | hexCharToInt(encodedByte[1]);
|
||||
}
|
||||
246
src/blfwk/src/IntelHexSourceFile.cpp
Normal file
246
src/blfwk/src/IntelHexSourceFile.cpp
Normal file
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright (c) 2013-15, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "blfwk/smart_ptr.h"
|
||||
#include "blfwk/IntelHexSourceFile.h"
|
||||
#include "blfwk/Logging.h"
|
||||
|
||||
enum
|
||||
{
|
||||
//! Size in bytes of the buffer used to collect Intel Hex data records
|
||||
//! before adding them to the executable image.
|
||||
//! The address field in each record is 2 bytes, so set the buffer to 64KB.
|
||||
COLLECTION_BUFFER_SIZE = 64 * 1024
|
||||
};
|
||||
|
||||
using namespace blfwk;
|
||||
|
||||
IntelHexSourceFile::IntelHexSourceFile(const std::string &path)
|
||||
: SourceFile(path, kIntelHexSourceFile)
|
||||
, m_image(0)
|
||||
, m_hasEntryRecord(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool IntelHexSourceFile::isIntelHexFile(std::istream &stream)
|
||||
{
|
||||
StIntelHexFile hex(stream);
|
||||
return hex.isIntelHexFile();
|
||||
}
|
||||
|
||||
void IntelHexSourceFile::open()
|
||||
{
|
||||
SourceFile::open();
|
||||
|
||||
// create file parser and examine file
|
||||
m_file = new StIntelHexFile(*m_stream);
|
||||
m_file->parse();
|
||||
|
||||
// build an image of the file
|
||||
m_image = new StExecutableImage();
|
||||
buildMemoryImage();
|
||||
|
||||
// dispose of file parser object
|
||||
delete m_file;
|
||||
m_file = 0;
|
||||
}
|
||||
|
||||
void IntelHexSourceFile::close()
|
||||
{
|
||||
assert(m_image);
|
||||
|
||||
SourceFile::close();
|
||||
|
||||
// dispose of memory image
|
||||
delete m_image;
|
||||
m_image = 0;
|
||||
}
|
||||
|
||||
//! \pre The file must be open before this method can be called.
|
||||
//!
|
||||
DataSource *IntelHexSourceFile::createDataSource()
|
||||
{
|
||||
assert(m_image);
|
||||
return new MemoryImageDataSource(m_image);
|
||||
}
|
||||
|
||||
//! \retval true The file has an 03 or 05 record.
|
||||
//! \retval false No entry point is available.
|
||||
bool IntelHexSourceFile::hasEntryPoint()
|
||||
{
|
||||
return m_hasEntryRecord;
|
||||
}
|
||||
|
||||
//! If no entry point is available then 0 is returned instead.
|
||||
//!
|
||||
//! \return Entry point address.
|
||||
//! \retval 0 No entry point is available.
|
||||
uint32_t IntelHexSourceFile::getEntryPointAddress()
|
||||
{
|
||||
if (m_hasEntryRecord)
|
||||
{
|
||||
// the address in the record is the entry point
|
||||
uint32_t address = (m_entryRecord.m_data[0] << 24) | (m_entryRecord.m_data[1] << 16) |
|
||||
(m_entryRecord.m_data[2] << 8) | (m_entryRecord.m_data[3]);
|
||||
Log::log(Logger::kDebug2, "entry point address is 0x%08x\n", address);
|
||||
return address;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Scans the Intel Hex of the file looking for data records(00 records). The
|
||||
//! contents of these records are added to an StExecutableImage object, which
|
||||
//! coalesces the individual records into contiguous regions of memory.
|
||||
//!
|
||||
//! Also looks for 03 and 05 records that contain the entry point. The first
|
||||
//! match of one of these records is saved off into the #m_entryRecord member.
|
||||
//!
|
||||
//! Also looks for 02 and 04 records that contain the extended address. The
|
||||
//! address in the StExecutableImage object is the combination of extended
|
||||
//! address and offset in data record.
|
||||
//!
|
||||
//! If 01 record, the file end record is detected, the left records would not
|
||||
//! be handled.
|
||||
//!
|
||||
//! \pre The #m_file member must be valid.
|
||||
//! \pre The #m_image member variable must have been instantiated.
|
||||
void IntelHexSourceFile::buildMemoryImage()
|
||||
{
|
||||
assert(m_file);
|
||||
assert(m_image);
|
||||
|
||||
// Clear the entry point.
|
||||
m_hasEntryRecord = false;
|
||||
memset(&m_entryRecord, 0, sizeof(m_entryRecord));
|
||||
|
||||
// Allocate buffer to hold data before adding it to the executable image.
|
||||
// Contiguous records are added to this buffer. When overflowed or when a
|
||||
// non-contiguous record is encountered the buffer is added to the executable
|
||||
// image where it will be coalesced further. We don't add records individually
|
||||
// to the image because coalescing record by record is very slow.
|
||||
smart_array_ptr<uint8_t> buffer = new uint8_t[COLLECTION_BUFFER_SIZE];
|
||||
|
||||
unsigned baseAddress = 0;
|
||||
unsigned startAddress = 0;
|
||||
unsigned nextAddress = 0;
|
||||
unsigned dataLength = 0;
|
||||
|
||||
// process IntelHexs
|
||||
StIntelHexFile::const_iterator it = m_file->getBegin();
|
||||
for (; it != m_file->getEnd(); it++)
|
||||
{
|
||||
const StIntelHexFile::IntelHex &theRecord = *it;
|
||||
|
||||
bool isDataRecord = theRecord.m_type == INTELHEX_RECORD_DATA;
|
||||
bool isEntryRecord = (theRecord.m_type == INTELHEX_RECORD_START_SEGMENT_ADDRESS) ||
|
||||
(theRecord.m_type == INTELHEX_RECORD_START_LINEAR_ADDRESS);
|
||||
bool isAddressRecord = (theRecord.m_type == INTELHEX_RECORD_EXTENDED_SEGMENT_ADDRESS) ||
|
||||
(theRecord.m_type == INTELHEX_RECORD_EXTENDED_LINEAR_ADDRESS);
|
||||
bool isFileEndRecord = theRecord.m_type == INTELHEX_RECORD_END_OF_FILE;
|
||||
// handle 00 data record
|
||||
if (isDataRecord)
|
||||
{
|
||||
// If this record's data would overflow the collection buffer, or if the
|
||||
// record is not contiguous with the rest of the data in the collection
|
||||
// buffer, then flush the buffer to the executable image and restart.
|
||||
if (dataLength &&
|
||||
((dataLength + theRecord.m_dataCount > COLLECTION_BUFFER_SIZE) || (theRecord.m_address != nextAddress)))
|
||||
{
|
||||
m_image->addTextRegion(startAddress + baseAddress, buffer, dataLength);
|
||||
|
||||
dataLength = 0;
|
||||
}
|
||||
|
||||
// Capture addresses when starting an empty buffer.
|
||||
if (dataLength == 0)
|
||||
{
|
||||
startAddress = theRecord.m_address;
|
||||
nextAddress = startAddress;
|
||||
}
|
||||
|
||||
// Copy record data into place in the collection buffer and update
|
||||
// size and address.
|
||||
memcpy(&buffer[dataLength], theRecord.m_data, theRecord.m_dataCount);
|
||||
dataLength += theRecord.m_dataCount;
|
||||
nextAddress += theRecord.m_dataCount;
|
||||
}
|
||||
// handle 02, 04 record
|
||||
else if (isAddressRecord)
|
||||
{
|
||||
// If there are data in the collection buffer, then flush the buffer to the executable image.
|
||||
if (dataLength != 0)
|
||||
{
|
||||
m_image->addTextRegion(startAddress + baseAddress, buffer, dataLength);
|
||||
dataLength = 0;
|
||||
}
|
||||
|
||||
// extended address stored at data field.
|
||||
baseAddress = (theRecord.m_data[0] << 8) | theRecord.m_data[1];
|
||||
if (theRecord.m_type == INTELHEX_RECORD_EXTENDED_SEGMENT_ADDRESS)
|
||||
{
|
||||
baseAddress <<= 4; // Extended Segment Address Record, left shift 4 bits.
|
||||
}
|
||||
else
|
||||
{
|
||||
baseAddress <<= 16; // Extended Linear Address Record, left shitf 16 bits.
|
||||
}
|
||||
}
|
||||
// handle 03, 05 record
|
||||
else if (isEntryRecord)
|
||||
{
|
||||
if (!m_hasEntryRecord)
|
||||
{
|
||||
// save off the entry point record so we don't have to scan again
|
||||
memcpy(&m_entryRecord, &theRecord, sizeof(m_entryRecord));
|
||||
m_hasEntryRecord = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// throw an exception when detecting a second entry record
|
||||
throw StIntelHexParseException("multiple entry record detected");
|
||||
}
|
||||
}
|
||||
// handle 01 record
|
||||
else if (isFileEndRecord)
|
||||
{
|
||||
// if the file end record is detected, stop handling the records.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add any leftover data in the collection buffer to the executable image.
|
||||
if (dataLength)
|
||||
{
|
||||
m_image->addTextRegion(startAddress + baseAddress, buffer, dataLength);
|
||||
}
|
||||
}
|
||||
234
src/blfwk/src/Logging.cpp
Normal file
234
src/blfwk/src/Logging.cpp
Normal file
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "blfwk/Logging.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// init global logger to null
|
||||
Logger *Log::s_logger = NULL;
|
||||
|
||||
void Logger::log(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
log(m_level, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void Logger::log(log_level_t level, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
log(level, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void Logger::log(const char *fmt, va_list args)
|
||||
{
|
||||
log(m_level, fmt, args);
|
||||
}
|
||||
|
||||
//! Allocates a temporary 1KB buffer which is used to hold the
|
||||
//! formatted string.
|
||||
void Logger::log(log_level_t level, const char *fmt, va_list args)
|
||||
{
|
||||
if (level <= m_filter)
|
||||
{
|
||||
char *buffer = NULL;
|
||||
|
||||
#if WIN32
|
||||
int l = _vscprintf(fmt, args); // Does not include final NULL char.
|
||||
buffer = reinterpret_cast<char *>(malloc(l + 1));
|
||||
if (!buffer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
vsprintf(buffer, fmt, args);
|
||||
#else // WIN32
|
||||
vasprintf(&buffer, fmt, args);
|
||||
#endif // WIN32
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
_log(buffer);
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Log::log(const char *fmt, ...)
|
||||
{
|
||||
if (s_logger)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
s_logger->log(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::log(const std::string &msg)
|
||||
{
|
||||
if (s_logger)
|
||||
{
|
||||
s_logger->log(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::log(Logger::log_level_t level, const char *fmt, ...)
|
||||
{
|
||||
if (s_logger)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
s_logger->log(level, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::log(Logger::log_level_t level, const std::string &msg)
|
||||
{
|
||||
if (s_logger)
|
||||
{
|
||||
s_logger->log(level, msg);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::urgent(const char *fmt, ...)
|
||||
{
|
||||
if (s_logger)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
s_logger->log(Logger::kUrgent, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::json(const char *fmt, ...)
|
||||
{
|
||||
if (s_logger && s_logger->getFilterLevel() == Logger::kJson)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
s_logger->log(Logger::kJson, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::error(const char *fmt, ...)
|
||||
{
|
||||
if (s_logger)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
s_logger->log(Logger::kError, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::warning(const char *fmt, ...)
|
||||
{
|
||||
if (s_logger)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
s_logger->log(Logger::kWarning, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::info(const char *fmt, ...)
|
||||
{
|
||||
if (s_logger)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
s_logger->log(Logger::kInfo, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::info2(const char *fmt, ...)
|
||||
{
|
||||
if (s_logger)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
s_logger->log(Logger::kInfo2, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::debug(const char *fmt, ...)
|
||||
{
|
||||
if (s_logger)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
s_logger->log(Logger::kDebug, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::debug2(const char *fmt, ...)
|
||||
{
|
||||
if (s_logger)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
s_logger->log(Logger::kDebug2, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
void StdoutLogger::_log(const char *msg)
|
||||
{
|
||||
printf("%s", msg);
|
||||
}
|
||||
|
||||
FileLogger::FileLogger(const char *file_path)
|
||||
: m_file_path(file_path)
|
||||
, m_logFile(file_path)
|
||||
{
|
||||
}
|
||||
|
||||
FileLogger::~FileLogger()
|
||||
{
|
||||
m_logFile.close();
|
||||
}
|
||||
|
||||
void FileLogger::_log(const char *msg)
|
||||
{
|
||||
m_logFile << msg;
|
||||
m_logFile.flush();
|
||||
}
|
||||
81
src/blfwk/src/Random.cpp
Normal file
81
src/blfwk/src/Random.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* File: Random.cpp
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
|
||||
* See included license file for license details.
|
||||
*/
|
||||
|
||||
#include "blfwk/Random.h"
|
||||
#include <stdexcept>
|
||||
|
||||
#ifdef WIN32
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0400
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
#else // WIN32
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#endif // WIN32
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
MicrosoftCryptoProvider::MicrosoftCryptoProvider()
|
||||
{
|
||||
if (!CryptAcquireContext(&m_hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
|
||||
{
|
||||
throw std::runtime_error("CryptAcquireContext");
|
||||
}
|
||||
}
|
||||
|
||||
MicrosoftCryptoProvider::~MicrosoftCryptoProvider()
|
||||
{
|
||||
CryptReleaseContext(m_hProvider, 0);
|
||||
}
|
||||
|
||||
#endif // WIN32
|
||||
|
||||
RandomNumberGenerator::RandomNumberGenerator()
|
||||
{
|
||||
#ifndef WIN32
|
||||
m_fd = open("/dev/urandom", O_RDONLY);
|
||||
if (m_fd == -1)
|
||||
{
|
||||
throw std::runtime_error("open /dev/urandom");
|
||||
}
|
||||
#endif // WIN32
|
||||
}
|
||||
|
||||
RandomNumberGenerator::~RandomNumberGenerator()
|
||||
{
|
||||
#ifndef WIN32
|
||||
close(m_fd);
|
||||
#endif // WIN32
|
||||
}
|
||||
|
||||
uint8_t RandomNumberGenerator::generateByte()
|
||||
{
|
||||
uint8_t result;
|
||||
generateBlock(&result, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
void RandomNumberGenerator::generateBlock(uint8_t *output, unsigned count)
|
||||
{
|
||||
#ifdef WIN32
|
||||
#ifdef WORKAROUND_MS_BUG_Q258000
|
||||
static MicrosoftCryptoProvider m_provider;
|
||||
#endif
|
||||
if (!CryptGenRandom(m_provider.GetProviderHandle(), count, output))
|
||||
{
|
||||
throw std::runtime_error("CryptGenRandom");
|
||||
}
|
||||
#else // WIN32
|
||||
if (read(m_fd, output, count) != count)
|
||||
{
|
||||
throw std::runtime_error("read /dev/urandom");
|
||||
}
|
||||
#endif // WIN32
|
||||
}
|
||||
77
src/blfwk/src/RijndaelCTR.cpp
Normal file
77
src/blfwk/src/RijndaelCTR.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* File: RijndaelCTR.cpp
|
||||
*
|
||||
* Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
|
||||
* See included license file for license details.
|
||||
*/
|
||||
|
||||
#include "blfwk/RijndaelCTR.h"
|
||||
#include "blfwk/rijndael.h"
|
||||
#include <assert.h>
|
||||
#include "blfwk/Logging.h"
|
||||
|
||||
void logHexArray(Logger::log_level_t level, const uint8_t *bytes, unsigned count);
|
||||
|
||||
//! \param key The key to use
|
||||
//! \param counter The counter to use
|
||||
RijndaelCTR::RijndaelCTR(const AESKey<128> &key, const AESCounter<128> &counter)
|
||||
: m_key(key)
|
||||
, m_counter(counter)
|
||||
{
|
||||
}
|
||||
|
||||
void RijndaelCTR::decrypt(const uint8_t *data, unsigned length, uint8_t *dest)
|
||||
{
|
||||
baseProcess(data, length, dest);
|
||||
}
|
||||
|
||||
void RijndaelCTR::encrypt(const uint8_t *data, unsigned length, uint8_t *dest)
|
||||
{
|
||||
baseProcess(data, length, dest);
|
||||
}
|
||||
|
||||
void RijndaelCTR::baseProcess(const uint8_t *data, unsigned length, uint8_t *dest)
|
||||
{
|
||||
Rijndael cipher;
|
||||
unsigned blocks = length / BLOCK_SIZE;
|
||||
block_t remainder;
|
||||
AESCounter<128>::counter_t currentCounter;
|
||||
|
||||
cipher.init(Rijndael::ECB, Rijndael::Encrypt, m_key, Rijndael::Key16Bytes);
|
||||
|
||||
while (blocks--)
|
||||
{
|
||||
m_counter.getCounter(¤tCounter);
|
||||
|
||||
cipher.blockEncrypt(currentCounter, BLOCK_SIZE * 8, currentCounter);
|
||||
|
||||
for (int i = 0; i < BLOCK_SIZE; i++)
|
||||
{
|
||||
dest[i] = data[i] ^ currentCounter[i];
|
||||
}
|
||||
|
||||
data += BLOCK_SIZE;
|
||||
dest += BLOCK_SIZE;
|
||||
|
||||
m_counter.incrementCounter(BLOCK_SIZE);
|
||||
}
|
||||
|
||||
if (length % sizeof(block_t))
|
||||
{
|
||||
m_counter.getCounter(¤tCounter);
|
||||
|
||||
memset(remainder, 0, sizeof(remainder));
|
||||
memcpy(remainder, data, length % sizeof(block_t));
|
||||
|
||||
cipher.blockEncrypt(currentCounter, BLOCK_SIZE * 8, currentCounter);
|
||||
|
||||
for (unsigned int i = 0; i < length % sizeof(block_t); i++)
|
||||
{
|
||||
remainder[i] = data[i] ^ currentCounter[i];
|
||||
}
|
||||
|
||||
memcpy(dest, remainder, length % sizeof(block_t));
|
||||
|
||||
m_counter.incrementCounter(BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
102
src/blfwk/src/SBSourceFile.cpp
Normal file
102
src/blfwk/src/SBSourceFile.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <algorithm>
|
||||
#include "string.h"
|
||||
#include "blfwk/stdafx.h"
|
||||
#include "blfwk/EndianUtilities.h"
|
||||
#include "blfwk/GHSSecInfo.h"
|
||||
#include "blfwk/Logging.h"
|
||||
#include "blfwk/SBSourceFile.h"
|
||||
|
||||
using namespace blfwk;
|
||||
|
||||
SBSourceFile::SBSourceFile(const std::string &path)
|
||||
: BinarySourceFile(path, kSBSourceFile)
|
||||
{
|
||||
}
|
||||
|
||||
SBSourceFile::~SBSourceFile()
|
||||
{
|
||||
}
|
||||
|
||||
bool SBSourceFile::isSBFile(std::istream &stream)
|
||||
{
|
||||
try
|
||||
{
|
||||
boot_image_header_t header; //!< Header from the SB boot image.
|
||||
|
||||
// readImageHeader
|
||||
// seek to beginning of the stream/file and read the plaintext header
|
||||
stream.seekg(0, std::ios_base::beg);
|
||||
if (stream.read((char *)&header, sizeof(header)).bad())
|
||||
{
|
||||
throw SBFileException("failed to read SB image header");
|
||||
}
|
||||
|
||||
header.m_flags = ENDIAN_LITTLE_TO_HOST_U16(header.m_flags);
|
||||
header.m_imageBlocks = ENDIAN_LITTLE_TO_HOST_U32(header.m_imageBlocks);
|
||||
header.m_firstBootTagBlock = ENDIAN_LITTLE_TO_HOST_U32(header.m_firstBootTagBlock);
|
||||
header.m_firstBootableSectionID = ENDIAN_LITTLE_TO_HOST_U32(header.m_firstBootableSectionID);
|
||||
header.m_keyCount = ENDIAN_LITTLE_TO_HOST_U16(header.m_keyCount);
|
||||
header.m_keyDictionaryBlock = ENDIAN_LITTLE_TO_HOST_U16(header.m_keyDictionaryBlock);
|
||||
header.m_headerBlocks = ENDIAN_LITTLE_TO_HOST_U16(header.m_headerBlocks);
|
||||
header.m_sectionCount = ENDIAN_LITTLE_TO_HOST_U16(header.m_sectionCount);
|
||||
header.m_sectionHeaderSize = ENDIAN_LITTLE_TO_HOST_U16(header.m_sectionHeaderSize);
|
||||
header.m_timestamp = ENDIAN_LITTLE_TO_HOST_U64(header.m_timestamp);
|
||||
|
||||
// check header signature 1
|
||||
if (header.m_signature[0] != 'S' || header.m_signature[1] != 'T' || header.m_signature[2] != 'M' ||
|
||||
header.m_signature[3] != 'P')
|
||||
{
|
||||
throw SBFileException("invalid SB signature 1");
|
||||
}
|
||||
|
||||
// check header signature 2 for version 1.1 and greater
|
||||
if ((header.m_majorVersion > 1 || (header.m_majorVersion == 1 && header.m_minorVersion >= 1)) &&
|
||||
(header.m_signature2[0] != 's' || header.m_signature2[1] != 'g' || header.m_signature2[2] != 't' ||
|
||||
header.m_signature2[3] != 'l'))
|
||||
{
|
||||
Log::log(Logger::kWarning, "warning: invalid SB signature 2\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
DataSource *SBSourceFile::createDataSource()
|
||||
{
|
||||
throw std::runtime_error("SBSourceFile::createDataSource() has not been implemented.");
|
||||
}
|
||||
202
src/blfwk/src/SRecordSourceFile.cpp
Normal file
202
src/blfwk/src/SRecordSourceFile.cpp
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "blfwk/smart_ptr.h"
|
||||
#include "blfwk/SRecordSourceFile.h"
|
||||
#include "blfwk/Logging.h"
|
||||
|
||||
enum
|
||||
{
|
||||
//! Size in bytes of the buffer used to collect S-record data records
|
||||
//! before adding them to the executable image. Currently 64KB.
|
||||
COLLECTION_BUFFER_SIZE = 64 * 1024
|
||||
};
|
||||
|
||||
using namespace blfwk;
|
||||
|
||||
SRecordSourceFile::SRecordSourceFile(const std::string &path)
|
||||
: SourceFile(path, kSRecordSourceFile)
|
||||
, m_image(0)
|
||||
, m_hasEntryRecord(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool SRecordSourceFile::isSRecordFile(std::istream &stream)
|
||||
{
|
||||
StSRecordFile srec(stream);
|
||||
return srec.isSRecordFile();
|
||||
}
|
||||
|
||||
void SRecordSourceFile::open()
|
||||
{
|
||||
SourceFile::open();
|
||||
|
||||
// create file parser and examine file
|
||||
m_file = new StSRecordFile(*m_stream);
|
||||
m_file->parse();
|
||||
|
||||
// build an image of the file
|
||||
m_image = new StExecutableImage();
|
||||
buildMemoryImage();
|
||||
|
||||
// dispose of file parser object
|
||||
delete m_file;
|
||||
m_file = 0;
|
||||
}
|
||||
|
||||
void SRecordSourceFile::close()
|
||||
{
|
||||
assert(m_image);
|
||||
|
||||
SourceFile::close();
|
||||
|
||||
// dispose of memory image
|
||||
delete m_image;
|
||||
m_image = 0;
|
||||
}
|
||||
|
||||
//! \pre The file must be open before this method can be called.
|
||||
//!
|
||||
DataSource *SRecordSourceFile::createDataSource()
|
||||
{
|
||||
assert(m_image);
|
||||
return new MemoryImageDataSource(m_image);
|
||||
}
|
||||
|
||||
//! \retval true The file has an S7, S8, or S9 record.
|
||||
//! \retval false No entry point is available.
|
||||
bool SRecordSourceFile::hasEntryPoint()
|
||||
{
|
||||
return m_hasEntryRecord;
|
||||
}
|
||||
|
||||
//! If no entry point is available then 0 is returned instead. The method scans
|
||||
//! the records in the file looking for S7, S8, or S9 records. Thus, 16-bit,
|
||||
//! 24-bit, and 32-bit entry point records are supported.
|
||||
//!
|
||||
//! \return Entry point address.
|
||||
//! \retval 0 No entry point is available.
|
||||
uint32_t SRecordSourceFile::getEntryPointAddress()
|
||||
{
|
||||
if (m_hasEntryRecord)
|
||||
{
|
||||
// the address in the record is the entry point
|
||||
Log::log(Logger::kDebug2, "entry point address is 0x%08x\n", m_entryRecord.m_address);
|
||||
return m_entryRecord.m_address;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Scans the S-records of the file looking for data records. These are S3, S2, or
|
||||
//! S1 records. The contents of these records are added to an StExecutableImage
|
||||
//! object, which coalesces the individual records into contiguous regions of
|
||||
//! memory.
|
||||
//!
|
||||
//! Also looks for S7, S8, or S9 records that contain the entry point. The first
|
||||
//! match of one of these records is saved off into the #m_entryRecord member.
|
||||
//!
|
||||
//! \pre The #m_file member must be valid.
|
||||
//! \pre The #m_image member variable must have been instantiated.
|
||||
void SRecordSourceFile::buildMemoryImage()
|
||||
{
|
||||
assert(m_file);
|
||||
assert(m_image);
|
||||
|
||||
// Clear the entry point related members.
|
||||
m_hasEntryRecord = false;
|
||||
memset(&m_entryRecord, 0, sizeof(m_entryRecord));
|
||||
|
||||
// Allocate buffer to hold data before adding it to the executable image.
|
||||
// Contiguous records are added to this buffer. When overflowed or when a
|
||||
// non-contiguous record is encountered the buffer is added to the executable
|
||||
// image where it will be coalesced further. We don't add records individually
|
||||
// to the image because coalescing record by record is very slow.
|
||||
smart_array_ptr<uint8_t> buffer = new uint8_t[COLLECTION_BUFFER_SIZE];
|
||||
unsigned startAddress = 0;
|
||||
unsigned nextAddress = 0;
|
||||
unsigned dataLength = 0;
|
||||
|
||||
// process SRecords
|
||||
StSRecordFile::const_iterator it = m_file->getBegin();
|
||||
for (; it != m_file->getEnd(); it++)
|
||||
{
|
||||
const StSRecordFile::SRecord &theRecord = *it;
|
||||
|
||||
// only handle S3,2,1 records
|
||||
bool isDataRecord = theRecord.m_type == 3 || theRecord.m_type == 2 || theRecord.m_type == 1;
|
||||
bool hasData = theRecord.m_data && theRecord.m_dataCount;
|
||||
if (isDataRecord && hasData)
|
||||
{
|
||||
// If this record's data would overflow the collection buffer, or if the
|
||||
// record is not contiguous with the rest of the data in the collection
|
||||
// buffer, then flush the buffer to the executable image and restart.
|
||||
if (dataLength &&
|
||||
((dataLength + theRecord.m_dataCount > COLLECTION_BUFFER_SIZE) || (theRecord.m_address != nextAddress)))
|
||||
{
|
||||
m_image->addTextRegion(startAddress, buffer, dataLength);
|
||||
|
||||
dataLength = 0;
|
||||
}
|
||||
|
||||
// Capture addresses when starting an empty buffer.
|
||||
if (dataLength == 0)
|
||||
{
|
||||
startAddress = theRecord.m_address;
|
||||
nextAddress = startAddress;
|
||||
}
|
||||
|
||||
// Copy record data into place in the collection buffer and update
|
||||
// size and address.
|
||||
memcpy(&buffer[dataLength], theRecord.m_data, theRecord.m_dataCount);
|
||||
dataLength += theRecord.m_dataCount;
|
||||
nextAddress += theRecord.m_dataCount;
|
||||
}
|
||||
else if (!m_hasEntryRecord)
|
||||
{
|
||||
// look for S7,8,9 records
|
||||
bool isEntryPointRecord = theRecord.m_type == 7 || theRecord.m_type == 8 || theRecord.m_type == 9;
|
||||
if (isEntryPointRecord)
|
||||
{
|
||||
// save off the entry point record so we don't have to scan again
|
||||
memcpy(&m_entryRecord, &theRecord, sizeof(m_entryRecord));
|
||||
m_hasEntryRecord = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add any leftover data in the collection buffer to the executable image.
|
||||
if (dataLength)
|
||||
{
|
||||
m_image->addTextRegion(startAddress, buffer, dataLength);
|
||||
}
|
||||
}
|
||||
144
src/blfwk/src/SearchPath.cpp
Normal file
144
src/blfwk/src/SearchPath.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "blfwk/SearchPath.h"
|
||||
|
||||
#if defined(WIN32)
|
||||
#define PATH_SEP_CHAR '\\'
|
||||
#define PATH_SEP_STRING "\\"
|
||||
#else
|
||||
#define PATH_SEP_CHAR '/'
|
||||
#define PATH_SEP_STRING "/"
|
||||
#endif
|
||||
|
||||
PathSearcher *PathSearcher::s_searcher = NULL;
|
||||
|
||||
//! This function will create the global path search object if it has
|
||||
//! not already been created.
|
||||
PathSearcher &PathSearcher::getGlobalSearcher()
|
||||
{
|
||||
if (!s_searcher)
|
||||
{
|
||||
s_searcher = new PathSearcher;
|
||||
}
|
||||
|
||||
return *s_searcher;
|
||||
}
|
||||
|
||||
void PathSearcher::addSearchPath(std::string &path)
|
||||
{
|
||||
m_paths.push_back(path);
|
||||
}
|
||||
|
||||
//! The \a base path argument can be either a relative or absolute path. If the path
|
||||
//! is relative, then it is joined with search paths one after another until a matching
|
||||
//! file is located or all search paths are exhausted. If the \a base is absolute,
|
||||
//! only that path is tested and if invalid false is returned.
|
||||
//!
|
||||
//! \param base A path to the file that is to be found.
|
||||
//! \param targetType Currently ignored. In the future it will let you select whether to
|
||||
//! find a file or directory.
|
||||
//! \param searchCwd If set to true, the current working directory is searched before using
|
||||
//! any of the search paths. Otherwise only the search paths are considered.
|
||||
//! \param[out] result When true is returned this string is set to the first path at which
|
||||
//! a valid file was found.
|
||||
//!
|
||||
//! \retval true A matching file was found among the search paths. The contents of \a result
|
||||
//! are a valid path.
|
||||
//! \retval false No match could be made. \a result has been left unmodified.
|
||||
bool PathSearcher::search(const std::string &base, target_type_t targetType, bool searchCwd, std::string &result)
|
||||
{
|
||||
FILE *tempFile;
|
||||
bool absolute = isAbsolute(base);
|
||||
|
||||
// Try cwd first if requested. Same process applies to absolute paths.
|
||||
if (absolute || searchCwd)
|
||||
{
|
||||
tempFile = fopen(base.c_str(), "r");
|
||||
if (tempFile)
|
||||
{
|
||||
fclose(tempFile);
|
||||
result = base;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If the base path is absolute and the previous test failed, then we don't go any further.
|
||||
if (absolute)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Iterate over all search paths.
|
||||
string_list_t::const_iterator it = m_paths.begin();
|
||||
for (; it != m_paths.end(); ++it)
|
||||
{
|
||||
std::string searchPath = joinPaths(*it, base);
|
||||
|
||||
tempFile = fopen(searchPath.c_str(), "r");
|
||||
if (tempFile)
|
||||
{
|
||||
fclose(tempFile);
|
||||
result = searchPath;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't find anything matching the base path.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PathSearcher::isAbsolute(const std::string &path)
|
||||
{
|
||||
#if __WIN32__
|
||||
return path.size() >= 3 && path[1] == ':' && path[2] == '\\';
|
||||
#else
|
||||
return path.size() >= 1 && path[0] == '/';
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string PathSearcher::joinPaths(const std::string &first, const std::string &second)
|
||||
{
|
||||
// Start with first string.
|
||||
std::string result = first;
|
||||
|
||||
// Add path separator if needed
|
||||
if ((first[first.size() - 1] != PATH_SEP_CHAR) && (second[0] != PATH_SEP_CHAR))
|
||||
{
|
||||
result += PATH_SEP_STRING;
|
||||
}
|
||||
|
||||
// Append the second string.
|
||||
result += second;
|
||||
|
||||
// And return the whole mess.
|
||||
return result;
|
||||
}
|
||||
672
src/blfwk/src/SerialPacketizer.cpp
Normal file
672
src/blfwk/src/SerialPacketizer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
135
src/blfwk/src/SimPacketizer.cpp
Normal file
135
src/blfwk/src/SimPacketizer.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "blfwk/SimPacketizer.h"
|
||||
#include "blfwk/Logging.h"
|
||||
#include "bootloader/bl_command.h"
|
||||
#include "bootloader/bootloader.h"
|
||||
|
||||
using namespace blfwk;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Code
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// See SimPacketizer.h for documentation of this method.
|
||||
SimPacketizer::SimPacketizer(SimPeripheral *peripheral)
|
||||
: Packetizer(dynamic_cast<Peripheral *>(peripheral), kSimReadTimeoutMs)
|
||||
, m_isPumpEnabled(false)
|
||||
, m_isAborted(false)
|
||||
{
|
||||
}
|
||||
|
||||
// See SimPacketizer.h for documentation of this method.
|
||||
SimPacketizer::~SimPacketizer()
|
||||
{
|
||||
delete m_peripheral;
|
||||
}
|
||||
|
||||
// See SimPacketizer.h for documentation of this method.
|
||||
void SimPacketizer::finalize()
|
||||
{
|
||||
}
|
||||
|
||||
// See SimPacketizer.h for documentation of this method.
|
||||
status_t SimPacketizer::writePacket(const uint8_t *packet, uint32_t byteCount, packet_type_t packetType)
|
||||
{
|
||||
assert(packet);
|
||||
|
||||
// Check for receiver data phase abort.
|
||||
if (m_isAborted)
|
||||
{
|
||||
m_isAborted = false;
|
||||
return kStatus_AbortDataPhase;
|
||||
}
|
||||
|
||||
// Write framing packet header.
|
||||
uint8_t buffer = (uint8_t)byteCount;
|
||||
status_t status = m_peripheral->write(&buffer, 1);
|
||||
|
||||
// Write the packet.
|
||||
if (byteCount && (status == kStatus_Success))
|
||||
{
|
||||
status = m_peripheral->write(packet, byteCount);
|
||||
}
|
||||
|
||||
pumpSimulator();
|
||||
return status;
|
||||
}
|
||||
|
||||
// See SimPacketizer.h for documentation of this method.
|
||||
status_t SimPacketizer::readPacket(uint8_t **packet, uint32_t *packetLength, packet_type_t packetType)
|
||||
{
|
||||
assert(packet);
|
||||
assert(packetLength);
|
||||
*packet = NULL;
|
||||
*packetLength = 0;
|
||||
|
||||
// Read framing packet header.
|
||||
uint8_t buffer;
|
||||
status_t status = m_peripheral->read(&buffer, 1, NULL, 0);
|
||||
if (status != kStatus_Success)
|
||||
{
|
||||
// fatal error in sumulator
|
||||
Log::error("Error: no data for readPacket\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
// Read the packet.
|
||||
int length = (int)(buffer);
|
||||
if (length == 0)
|
||||
{
|
||||
// zero length packet
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
status = m_peripheral->read(m_buffer, length, NULL, 0);
|
||||
if (status != kStatus_Success)
|
||||
{
|
||||
Log::error("Error: malformed packet\n");
|
||||
return kStatus_Fail;
|
||||
}
|
||||
|
||||
*packet = m_buffer;
|
||||
*packetLength = length;
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
void SimPacketizer::pumpSimulator()
|
||||
{
|
||||
if (m_isPumpEnabled)
|
||||
{
|
||||
bootloader_command_pump();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
108
src/blfwk/src/SimPeripheral.cpp
Normal file
108
src/blfwk/src/SimPeripheral.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "blfwk/SimPeripheral.h"
|
||||
#include "blfwk/Logging.h"
|
||||
|
||||
using namespace blfwk;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Code
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// See sim_peripheral.h for documentation of this method.
|
||||
status_t SimPeripheral::read(uint8_t *buffer, uint32_t requestedBytes, uint32_t *actualBytes, uint32_t timeoutMs)
|
||||
{
|
||||
if (m_inStream->empty())
|
||||
return kStatus_Fail;
|
||||
|
||||
uint32_t bytesRead = 0;
|
||||
for (int i = 0; i < (int)requestedBytes; ++i)
|
||||
{
|
||||
if (m_inStream->empty())
|
||||
break;
|
||||
unsigned char val = m_inStream->front();
|
||||
m_inStream->pop_front();
|
||||
buffer[i] = val;
|
||||
++bytesRead;
|
||||
}
|
||||
|
||||
if (actualBytes)
|
||||
{
|
||||
*actualBytes = bytesRead;
|
||||
}
|
||||
|
||||
if (Log::getLogger()->getFilterLevel() == Logger::kDebug2)
|
||||
{
|
||||
// Log bytes read in hex
|
||||
Log::debug2("<");
|
||||
for (int i = 0; i < (int)bytesRead; i++)
|
||||
{
|
||||
Log::debug2("%02x", buffer[i]);
|
||||
if (i != (bytesRead - 1))
|
||||
{
|
||||
Log::debug2(" ");
|
||||
}
|
||||
}
|
||||
Log::debug2(">\n");
|
||||
}
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
// See sim_peripheral.h for documentation of this method.
|
||||
status_t SimPeripheral::write(const uint8_t *buffer, uint32_t byteCount)
|
||||
{
|
||||
if (Log::getLogger()->getFilterLevel() == Logger::kDebug2)
|
||||
{
|
||||
// Log bytes written in hex
|
||||
Log::debug2("[");
|
||||
for (int i = 0; i < (int)byteCount; i++)
|
||||
{
|
||||
Log::debug2("%02x", buffer[i]);
|
||||
if (i != (byteCount - 1))
|
||||
{
|
||||
Log::debug2(" ");
|
||||
}
|
||||
}
|
||||
Log::debug2("]\n");
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)byteCount; ++i)
|
||||
{
|
||||
m_outStream->push_back(buffer[i]);
|
||||
}
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
263
src/blfwk/src/Simulator.cpp
Normal file
263
src/blfwk/src/Simulator.cpp
Normal file
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "blfwk/Simulator.h"
|
||||
|
||||
#include "bootloader/bl_version.h"
|
||||
#include "memory/memory.h"
|
||||
#include "packet/serial_packet.h"
|
||||
#include "property/property.h"
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
using namespace blfwk;
|
||||
using namespace std;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Definitions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Code
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// See host_peripheral.h for documentation of this method.
|
||||
status_t host_peripheral_read(const peripheral_descriptor_t *self, uint8_t *buffer, uint32_t requestedBytes)
|
||||
{
|
||||
Simulator &sim = Simulator::getSimulator();
|
||||
Peripheral *device = sim.getHost()->getPeripheral();
|
||||
return device->read(buffer, requestedBytes, NULL, 0);
|
||||
}
|
||||
|
||||
// See host_peripheral.h for documentation of this method.
|
||||
status_t host_peripheral_write(const peripheral_descriptor_t *self, const uint8_t *buffer, uint32_t byteCount)
|
||||
{
|
||||
Simulator &sim = Simulator::getSimulator();
|
||||
Peripheral *device = sim.getHost()->getPeripheral();
|
||||
device->write(buffer, byteCount);
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
// See host_peripheral.h for documentation of this method.
|
||||
status_t device_peripheral_read(const peripheral_descriptor_t *self, uint8_t *buffer, uint32_t requestedBytes)
|
||||
{
|
||||
Simulator &sim = Simulator::getSimulator();
|
||||
Peripheral *device = sim.getDevice()->getPeripheral();
|
||||
device->read(buffer, requestedBytes, NULL, 0);
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
// See host_peripheral.h for documentation of this method.
|
||||
status_t device_peripheral_write(const peripheral_descriptor_t *self, const uint8_t *buffer, uint32_t byteCount)
|
||||
{
|
||||
Simulator &sim = Simulator::getSimulator();
|
||||
Peripheral *device = sim.getDevice()->getPeripheral();
|
||||
device->write(buffer, byteCount);
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
// See host_packetizer.h for documentation of this method.
|
||||
status_t host_packet_read(const peripheral_descriptor_t *self,
|
||||
uint8_t **packet,
|
||||
uint32_t *packetLength,
|
||||
packet_type_t packetType)
|
||||
{
|
||||
Simulator &sim = Simulator::getSimulator();
|
||||
Packetizer *device = sim.getDevice();
|
||||
return device->readPacket(packet, packetLength, packetType);
|
||||
}
|
||||
|
||||
// See host_packetizer.h for documentation of this method.
|
||||
status_t host_packet_write(const peripheral_descriptor_t *self,
|
||||
const uint8_t *packet,
|
||||
uint32_t byteCount,
|
||||
packet_type_t packetType)
|
||||
{
|
||||
Simulator &sim = Simulator::getSimulator();
|
||||
Packetizer *device = sim.getDevice();
|
||||
return device->writePacket(packet, byteCount, packetType);
|
||||
}
|
||||
|
||||
// See host_packetizer.h for documentation of this method.
|
||||
void host_packet_abort(const peripheral_descriptor_t *self)
|
||||
{
|
||||
Simulator &sim = Simulator::getSimulator();
|
||||
Packetizer *host = sim.getHost();
|
||||
host->setAborted(true);
|
||||
}
|
||||
|
||||
// See host_packetizer.h for documentation of this method.
|
||||
status_t host_packet_finalize(const peripheral_descriptor_t *self)
|
||||
{
|
||||
Simulator &sim = Simulator::getSimulator();
|
||||
Packetizer *host = sim.getHost();
|
||||
host->finalize();
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
uint32_t host_get_max_packet_size(const peripheral_descriptor_t *self)
|
||||
{
|
||||
Simulator &sim = Simulator::getSimulator();
|
||||
Packetizer *host = sim.getHost();
|
||||
return host->getMaxPacketSize();
|
||||
}
|
||||
|
||||
void host_delay(uint32_t milliseconds)
|
||||
{
|
||||
// @todo implement for non-win32
|
||||
#ifdef WIN32
|
||||
Sleep(milliseconds);
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Variables
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! @brief Bootloader global context data.
|
||||
//!
|
||||
//! Referenced by both the simulated host and simulated device sides.
|
||||
bootloader_context_t g_bootloaderContext = {
|
||||
&g_memoryInterface, // Memory interface.
|
||||
g_memoryMap, // Memory map.
|
||||
&g_propertyInterface, // Property store interface.
|
||||
&g_commandInterface, // Command processor interface.
|
||||
NULL, // Flash driver interface - not used on host
|
||||
NULL, // Peripheral array - filled in at run-time.
|
||||
NULL, // Active peripheral - filled in at run-time.
|
||||
0 // Flash driver state - typed to a u32 and unused for host
|
||||
};
|
||||
|
||||
//! @brief Interface to host peripheral operations.
|
||||
const peripheral_byte_inteface_t g_hostPeripheralInterface = {
|
||||
NULL, // init
|
||||
host_peripheral_read, // read
|
||||
host_peripheral_write // write
|
||||
};
|
||||
|
||||
//! @brief Interface to device peripheral operations.
|
||||
const peripheral_byte_inteface_t g_devicePeripheralInterface = {
|
||||
NULL, // init
|
||||
device_peripheral_read, // read
|
||||
device_peripheral_write // write
|
||||
};
|
||||
|
||||
//! @brief Interface to host packet operations.
|
||||
const peripheral_packet_interface_t g_hostPacketInterface = {
|
||||
NULL, // init
|
||||
host_packet_read, // readPacket
|
||||
host_packet_write, // writePacket
|
||||
host_packet_abort, // abortPacket
|
||||
host_packet_finalize, // finalize
|
||||
host_get_max_packet_size, // getMaxPacketSize
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Code
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// See host_bootloader.h for documentation of this method.
|
||||
Simulator::Simulator()
|
||||
: Bootloader()
|
||||
, m_devicePacketizer(NULL)
|
||||
{
|
||||
// Create host peripheral and packetizer.
|
||||
SimPeripheral *hostPeripheral = new SimPeripheral(&m_responseStream, &m_commandStream);
|
||||
m_hostPacketizer = new SimPacketizer(hostPeripheral);
|
||||
|
||||
// Enable the host packetizer to pump the simulator state machine as necessary.
|
||||
((SimPacketizer *)m_hostPacketizer)->enableSimulatorPump();
|
||||
|
||||
// Create device peripheral and packetizer.
|
||||
SimPeripheral *devicePeripheral = new SimPeripheral(&m_commandStream, &m_responseStream);
|
||||
m_devicePacketizer = new SimPacketizer(devicePeripheral);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
// See host_bootloader.h for documentation of this method.
|
||||
Simulator::~Simulator()
|
||||
{
|
||||
// Delete packetizer should close handles and free memory on Peripheral.
|
||||
delete m_devicePacketizer;
|
||||
|
||||
// Delete all memory stores that were new'd in init().
|
||||
m_memoryStore.clear();
|
||||
}
|
||||
|
||||
// See host_bootloader.h for documentation of this method.
|
||||
void Simulator::init()
|
||||
{
|
||||
// Initialize the property store component.
|
||||
bootloader_property_init();
|
||||
|
||||
g_bootloaderContext.activePeripheral = &m_activePeripheral;
|
||||
|
||||
// Create all memory stores.
|
||||
// Stores are never deleted because bootloader is a singleton.
|
||||
FlashMemoryStore *flash = new FlashMemoryStore;
|
||||
m_memoryStore.push_back(flash);
|
||||
SramMemoryStore *sram = new SramMemoryStore;
|
||||
m_memoryStore.push_back(sram);
|
||||
|
||||
// Initialize the command processor component.
|
||||
bootloader_command_init();
|
||||
m_commandProcessor.state = kCommandState_CommandPhase;
|
||||
|
||||
// Use the host peripheral and packet interfaces.
|
||||
m_activePeripheral.byteInterface = &g_hostPeripheralInterface;
|
||||
m_activePeripheral.packetInterface = &g_hostPacketInterface;
|
||||
}
|
||||
|
||||
// See host_bootloader.h for documentation of this method.
|
||||
bool Simulator::openStateFiles(const string &pathToDir, bool forceCreate)
|
||||
{
|
||||
// Open all memory stores.
|
||||
memory_vector_t::iterator it = m_memoryStore.begin();
|
||||
for (; it != m_memoryStore.end(); ++it)
|
||||
{
|
||||
if (!(*it)->open(pathToDir, forceCreate))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_optionsStore.init(pathToDir, forceCreate))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_areStateFilesOpen = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
455
src/blfwk/src/SimulatorMemory.cpp
Normal file
455
src/blfwk/src/SimulatorMemory.cpp
Normal file
@@ -0,0 +1,455 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "blfwk/Simulator.h"
|
||||
#include "blfwk/SimulatorMemory.h"
|
||||
#include "blfwk/Logging.h"
|
||||
#include "memory/memory.h"
|
||||
//#include "fsl_platform_status.h"
|
||||
//#include <string.h>
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#elif LINUX
|
||||
#include <linux/limits.h>
|
||||
#include "sys/stat.h"
|
||||
#include <string.h>
|
||||
#else
|
||||
#include "sys/stat.h"
|
||||
#endif
|
||||
|
||||
using namespace blfwk;
|
||||
using namespace std;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Variables
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//! @brief Interface to simulator memory operations.
|
||||
const memory_region_interface_t g_flashMemoryInterface = { NULL, sim_flash_read, sim_flash_write,
|
||||
sim_flash_fill, NULL, NULL };
|
||||
|
||||
//! @brief Interface to simulator SRAM memory operations.
|
||||
const memory_region_interface_t g_sramMemoryInterface = {
|
||||
NULL, sim_sram_mem_read, sim_sram_mem_write, sim_sram_mem_fill, NULL, NULL
|
||||
};
|
||||
|
||||
//! @brief Interface to simulator device peripheral memory operations.
|
||||
const memory_region_interface_t g_deviceMemoryInterface = {
|
||||
NULL, sim_device_mem_read, sim_device_mem_write, sim_device_mem_fill, NULL, NULL
|
||||
};
|
||||
|
||||
//! @brief Memory map for KL25Z128.
|
||||
memory_map_entry_t g_memoryMap[] = {
|
||||
{ 0x00000000, 0x0001ffff, &g_flashMemoryInterface }, // Flash array
|
||||
{ 0x1ffff000, 0x20002fff, &g_sramMemoryInterface }, // SRAM_L + SRAM_U
|
||||
{ 0x40000000, 0x4007ffff, &g_deviceMemoryInterface }, // AIPS peripherals
|
||||
{ 0x400ff000, 0x400fffff, &g_deviceMemoryInterface }, // GPIO
|
||||
{ 0x44000000, 0x5fffffff, &g_deviceMemoryInterface }, // BME
|
||||
{ 0xe0000000, 0xe00fffff, &g_deviceMemoryInterface }, // M0+ private peripherals
|
||||
{ 0xf0003000, 0xf0003fff, &g_deviceMemoryInterface }, // MCM
|
||||
{ 0xf8000000, 0xffffffff, &g_deviceMemoryInterface }, // IOPORT (single-cycle GPIO)
|
||||
{ 0 } // Terminator
|
||||
};
|
||||
|
||||
#ifdef WIN32
|
||||
//! @brief File separator character.
|
||||
static const string k_fileSeparator("\\");
|
||||
static const unsigned k_maxPath = MAX_PATH;
|
||||
#else
|
||||
static const string k_fileSeparator("/");
|
||||
static const unsigned k_maxPath = PATH_MAX;
|
||||
#endif
|
||||
|
||||
//! @brief Options state file name.
|
||||
static const string k_optionsFileName = "state_init.dat";
|
||||
|
||||
//! @brief Memory state file name.
|
||||
static const string k_memoryFileName = "state_mem0.dat";
|
||||
|
||||
// Forward function declarations
|
||||
static status_t sim_mem_read(int mapIndex, uint32_t address, uint32_t length, uint8_t *buffer);
|
||||
static status_t sim_mem_write(int mapIndex, uint32_t address, uint32_t length, const uint8_t *buffer);
|
||||
static status_t sim_mem_fill(int mapIndex, uint32_t address, uint32_t length, uint32_t pattern);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Code
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//@brief Create all directories in a path if they don't exist.
|
||||
//!
|
||||
//! Errors are ignored.
|
||||
//!
|
||||
//! @param path Directory path, must end with a separator.
|
||||
static void createPath(const char *path)
|
||||
{
|
||||
char folder[k_maxPath] = { 0 };
|
||||
const char *end = strchr(path, k_fileSeparator[0]);
|
||||
|
||||
while (end != NULL)
|
||||
{
|
||||
strncpy(folder, path, end - path + 1);
|
||||
#ifdef WIN32
|
||||
CreateDirectory(folder, NULL);
|
||||
#else
|
||||
mkdir(folder, 0755);
|
||||
#endif
|
||||
end = strchr(++end, k_fileSeparator[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// See host_memory.h for documentation of this method.
|
||||
bool MemoryStore::open(const string &pathToDir, bool forceCreate)
|
||||
{
|
||||
// Create all directories in the path if they don't exist.
|
||||
// Errors will be caught by trying to open the file below.
|
||||
string path(pathToDir);
|
||||
path += k_fileSeparator;
|
||||
createPath(path.c_str());
|
||||
|
||||
// Create the file name, replacing the '0' with the actual map index.
|
||||
path += k_memoryFileName;
|
||||
size_t pos = path.find_last_of('0');
|
||||
path.replace(pos, 1, 1, static_cast<char>(m_mapIndex + '0'));
|
||||
|
||||
close();
|
||||
m_memoryFile = NULL;
|
||||
bool doFill = false;
|
||||
|
||||
if (!forceCreate)
|
||||
{
|
||||
// Try to open existing file.
|
||||
m_memoryFile = fopen(path.c_str(), "r+b");
|
||||
}
|
||||
|
||||
if (!m_memoryFile)
|
||||
{
|
||||
// Create new file.
|
||||
m_memoryFile = fopen(path.c_str(), "w+b");
|
||||
doFill = true;
|
||||
}
|
||||
|
||||
if (m_memoryFile)
|
||||
{
|
||||
m_startAddress = g_memoryMap[m_mapIndex].startAddress;
|
||||
m_size = (g_memoryMap[m_mapIndex].endAddress + 1) - m_startAddress;
|
||||
if (doFill)
|
||||
{
|
||||
erase();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("Error: cannot open or create memory file '%s'\n", path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// See host_memory.h for documentation of this method.
|
||||
size_t MemoryStore::read(long int offset, size_t size, unsigned char *buffer)
|
||||
{
|
||||
if (m_memoryFile)
|
||||
{
|
||||
fseek(m_memoryFile, offset - m_startAddress, SEEK_SET);
|
||||
return fread(buffer, 1, size, m_memoryFile);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// See host_memory.h for documentation of this method.
|
||||
size_t MemoryStore::write(long int offset, size_t size, const unsigned char *buffer)
|
||||
{
|
||||
if (m_memoryFile)
|
||||
{
|
||||
fseek(m_memoryFile, offset - m_startAddress, SEEK_SET);
|
||||
return fwrite(buffer, 1, size, m_memoryFile);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// See host_memory.h for documentation of this method.
|
||||
void MemoryStore::erase(long int offset, size_t size)
|
||||
{
|
||||
if (m_memoryFile)
|
||||
{
|
||||
unsigned char *fill = new unsigned char[size];
|
||||
memset(fill, m_fillByte, size);
|
||||
fseek(m_memoryFile, offset - m_startAddress, SEEK_SET);
|
||||
fwrite(fill, 1, size, m_memoryFile);
|
||||
delete[] fill;
|
||||
}
|
||||
}
|
||||
|
||||
//! @brief Read from simulated memory.
|
||||
//!
|
||||
//! @param mapIndex Index into memory map array
|
||||
//! @param address Simulated address
|
||||
//! @param length Number of bytes to read
|
||||
//! @param buffer Destination buffer
|
||||
//!
|
||||
//! @retval kStatusMemoryReadFailed
|
||||
//! @retval kStatus_Success
|
||||
static status_t sim_mem_read(int mapIndex, uint32_t address, uint32_t length, uint8_t *buffer)
|
||||
{
|
||||
Simulator &sim = Simulator::getSimulator();
|
||||
MemoryStore *mem = sim.getMemoryStore(mapIndex);
|
||||
if (mem->read(address, length, buffer) != length)
|
||||
{
|
||||
return kStatusMemoryReadFailed;
|
||||
}
|
||||
else
|
||||
{
|
||||
return kStatus_Success;
|
||||
}
|
||||
}
|
||||
|
||||
//! @brief Write to simulated memory.
|
||||
//!
|
||||
//! @param mapIndex Index into memory map array
|
||||
//! @param address Simulated address
|
||||
//! @param length Number of bytes to write
|
||||
//! @param buffer Source buffer
|
||||
//!
|
||||
//! @retval kStatusMemoryWriteFailed
|
||||
//! @retval kStatus_Success
|
||||
static status_t sim_mem_write(int mapIndex, uint32_t address, uint32_t length, const uint8_t *buffer)
|
||||
{
|
||||
Simulator &sim = Simulator::getSimulator();
|
||||
MemoryStore *mem = sim.getMemoryStore(mapIndex);
|
||||
if (mem->write(address, length, buffer) != length)
|
||||
{
|
||||
return kStatusMemoryWriteFailed;
|
||||
}
|
||||
else
|
||||
{
|
||||
return kStatus_Success;
|
||||
}
|
||||
}
|
||||
|
||||
//! @brief Fill simulated memory.
|
||||
//!
|
||||
//! Pattern is a 4-byte pattern that can be written at any byte alignment.
|
||||
//! Pattern must contain all bytes to write. To fill every byte
|
||||
//! with the same value, the value must be repeat in the word.
|
||||
//! For example, pattern=0x55555555.
|
||||
//!
|
||||
//! @param mapIndex Index into memory map array
|
||||
//! @param address Simulated address
|
||||
//! @param length Number of bytes to write
|
||||
//! @param pattern 4-byte pattern to write
|
||||
//!
|
||||
//! @retval kStatusMemoryWriteFailed
|
||||
//! @retval kStatus_Success
|
||||
static status_t sim_mem_fill(int mapIndex, uint32_t address, uint32_t length, uint32_t pattern)
|
||||
{
|
||||
Simulator &sim = Simulator::getSimulator();
|
||||
MemoryStore *mem = sim.getMemoryStore(mapIndex);
|
||||
unsigned char b3 = (unsigned char)((pattern >> 24) & 0xff);
|
||||
unsigned char b2 = (unsigned char)((pattern >> 16) & 0xff);
|
||||
unsigned char b1 = (unsigned char)((pattern >> 8) & 0xff);
|
||||
unsigned char b0 = (unsigned char)(pattern & 0xff);
|
||||
while (length)
|
||||
{
|
||||
if (mem->write(address++, 1, &b0) != 1)
|
||||
{
|
||||
Log::error("Error: memory write failed\n");
|
||||
return kStatusMemoryWriteFailed;
|
||||
}
|
||||
if (--length == 0)
|
||||
break;
|
||||
|
||||
if (mem->write(address++, 1, &b1) != 1)
|
||||
{
|
||||
Log::error("Error: memory write failed\n");
|
||||
return kStatusMemoryWriteFailed;
|
||||
}
|
||||
if (--length == 0)
|
||||
break;
|
||||
|
||||
if (mem->write(address++, 1, &b2) != 1)
|
||||
{
|
||||
Log::error("Error: memory write failed\n");
|
||||
return kStatusMemoryWriteFailed;
|
||||
}
|
||||
if (--length == 0)
|
||||
break;
|
||||
|
||||
if (mem->write(address++, 1, &b3) != 1)
|
||||
{
|
||||
Log::error("Error: memory write failed\n");
|
||||
return kStatusMemoryWriteFailed;
|
||||
}
|
||||
--length;
|
||||
}
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
// See host_memory.h for documentation of this method.
|
||||
status_t sim_flash_read(uint32_t address, uint32_t length, uint8_t *buffer)
|
||||
{
|
||||
return sim_mem_read(MemoryStore::kMapIndexFlash, address, length, buffer);
|
||||
}
|
||||
|
||||
// See host_memory.h for documentation of this method.
|
||||
status_t sim_flash_write(uint32_t address, uint32_t length, const uint8_t *buffer)
|
||||
{
|
||||
return sim_mem_write(MemoryStore::kMapIndexFlash, address, length, buffer);
|
||||
}
|
||||
|
||||
// See host_memory.h for documentation of this method.
|
||||
status_t sim_flash_fill(uint32_t address, uint32_t length, uint32_t pattern)
|
||||
{
|
||||
return sim_mem_fill(MemoryStore::kMapIndexFlash, address, length, pattern);
|
||||
}
|
||||
|
||||
// See host_memory.h for documentation of this method.
|
||||
status_t sim_flash_erase(uint32_t address, uint32_t length)
|
||||
{
|
||||
host_flash_erase_region(address, length);
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
// See host_memory.h for documentation of this method.
|
||||
status_t sim_flash_erase_all(void)
|
||||
{
|
||||
host_flash_erase_all();
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
// See host_memory.h for documentation of this method.
|
||||
status_t sim_sram_mem_read(uint32_t address, uint32_t length, uint8_t *buffer)
|
||||
{
|
||||
return sim_mem_read(MemoryStore::kMapIndexSRAM, address, length, buffer);
|
||||
}
|
||||
|
||||
// See host_memory.h for documentation of this method.
|
||||
status_t sim_sram_mem_write(uint32_t address, uint32_t length, const uint8_t *buffer)
|
||||
{
|
||||
return sim_mem_write(MemoryStore::kMapIndexSRAM, address, length, buffer);
|
||||
}
|
||||
|
||||
// See host_memory.h for documentation of this method.
|
||||
status_t sim_sram_mem_fill(uint32_t address, uint32_t length, uint32_t pattern)
|
||||
{
|
||||
return sim_mem_fill(MemoryStore::kMapIndexSRAM, address, length, pattern);
|
||||
}
|
||||
|
||||
// See host_memory.h for documentation of this method.
|
||||
status_t sim_device_mem_read(uint32_t address, uint32_t length, uint8_t *buffer)
|
||||
{
|
||||
Log::warning("Warning: device peripheral memory not simulated\n");
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
// See host_memory.h for documentation of this method.
|
||||
status_t sim_device_mem_write(uint32_t address, uint32_t length, const uint8_t *buffer)
|
||||
{
|
||||
Log::warning("Warning: device peripheral memory not simulated\n");
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
// See host_memory.h for documentation of this method.
|
||||
status_t sim_device_mem_fill(uint32_t address, uint32_t length, uint32_t pattern)
|
||||
{
|
||||
Log::warning("Warning: device peripheral memory not simulated\n");
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
// See memory.h for documentation of this method.
|
||||
void host_flash_erase_all()
|
||||
{
|
||||
Simulator &sim = Simulator::getSimulator();
|
||||
MemoryStore *mem = sim.getMemoryStore(MemoryStore::kMapIndexFlash);
|
||||
mem->erase();
|
||||
}
|
||||
|
||||
// See memory.h for documentation of this method.
|
||||
void host_flash_erase_all_unsecure()
|
||||
{
|
||||
host_flash_erase_all();
|
||||
}
|
||||
|
||||
// See memory.h for documentation of this method.
|
||||
void host_flash_erase_region(uint32_t address, uint32_t count)
|
||||
{
|
||||
Simulator &sim = Simulator::getSimulator();
|
||||
MemoryStore *mem = sim.getMemoryStore(MemoryStore::kMapIndexFlash);
|
||||
mem->erase(address, count);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Options Store operations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// See host_memory.h for documentation of this method.
|
||||
bool OptionsStore::init(const string &pathToDir, bool forceCreate)
|
||||
{
|
||||
m_optionsFile.assign(pathToDir);
|
||||
m_optionsFile += k_fileSeparator + k_optionsFileName;
|
||||
|
||||
// Do nothing if forceCreate requested - file will be created by persist().
|
||||
if (!forceCreate)
|
||||
{
|
||||
FILE *options = fopen(m_optionsFile.c_str(), "r");
|
||||
if (options)
|
||||
{
|
||||
// Read property store values.
|
||||
fread(g_bootloaderContext.propertyInterface->store, sizeof(*(g_bootloaderContext.propertyInterface->store)),
|
||||
1, options);
|
||||
|
||||
fclose(options);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// See host_memory.h for documentation of this method.
|
||||
void OptionsStore::persist()
|
||||
{
|
||||
FILE *options = fopen(m_optionsFile.c_str(), "w");
|
||||
if (!options)
|
||||
{
|
||||
Log::error("Error: cannot create options file '%s'\n", m_optionsFile.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Write property store values.
|
||||
fwrite(g_bootloaderContext.propertyInterface->store, sizeof(*(g_bootloaderContext.propertyInterface->store)), 1,
|
||||
options);
|
||||
|
||||
fclose(options);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
225
src/blfwk/src/SourceFile.cpp
Normal file
225
src/blfwk/src/SourceFile.cpp
Normal file
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "blfwk/SourceFile.h"
|
||||
#include "blfwk/SearchPath.h"
|
||||
#include "blfwk/ELFSourceFile.h"
|
||||
#include "blfwk/EndianUtilities.h"
|
||||
#include "blfwk/SRecordSourceFile.h"
|
||||
#include "blfwk/SBSourceFile.h"
|
||||
#include "blfwk/IntelHexSourceFile.h"
|
||||
#include "blfwk/format_string.h"
|
||||
|
||||
using namespace blfwk;
|
||||
|
||||
//! The supported file types are currently:
|
||||
//! - ELF files
|
||||
//! - Motorola S-record files
|
||||
//! - Binary files
|
||||
//! - SB files
|
||||
//! - Intel Hex files
|
||||
//!
|
||||
//! Any file that is not picked up by the other subclasses will result in a
|
||||
//! an instance of BinaryDataFile.
|
||||
//!
|
||||
//! \return An instance of the correct subclass of SourceFile for the given path.
|
||||
//!
|
||||
//! \exception std::runtime_error Thrown if the file cannot be opened.
|
||||
//!
|
||||
//! \see blfwk::ELFSourceFile
|
||||
//! \see blfwk::SRecordSourceFile
|
||||
//! \see blfwk::BinarySourceFile
|
||||
//! \see blfwk::SBSourceFile
|
||||
//! \see blfwk::IntelHexSourceFile
|
||||
SourceFile *SourceFile::openFile(const std::string &path)
|
||||
{
|
||||
// Search for file using search paths
|
||||
std::string actualPath;
|
||||
bool found = PathSearcher::getGlobalSearcher().search(path, PathSearcher::kFindFile, true, actualPath);
|
||||
if (!found)
|
||||
{
|
||||
throw std::runtime_error(format_string("unable to find file %s\n", path.c_str()));
|
||||
}
|
||||
|
||||
std::ifstream testStream(actualPath.c_str(), std::ios_base::in | std::ios_base::binary);
|
||||
if (!testStream.is_open())
|
||||
{
|
||||
throw std::runtime_error(format_string("failed to open file: %s", actualPath.c_str()));
|
||||
}
|
||||
|
||||
// catch exceptions so we can close the file stream
|
||||
try
|
||||
{
|
||||
if (ELFSourceFile::isELFFile(testStream))
|
||||
{
|
||||
testStream.close();
|
||||
return new ELFSourceFile(actualPath);
|
||||
}
|
||||
else if (SRecordSourceFile::isSRecordFile(testStream))
|
||||
{
|
||||
testStream.close();
|
||||
return new SRecordSourceFile(actualPath);
|
||||
}
|
||||
else if (SBSourceFile::isSBFile(testStream))
|
||||
{
|
||||
testStream.close();
|
||||
return new SBSourceFile(actualPath);
|
||||
}
|
||||
else if (IntelHexSourceFile::isIntelHexFile(testStream))
|
||||
{
|
||||
testStream.close();
|
||||
return new IntelHexSourceFile(actualPath);
|
||||
}
|
||||
|
||||
// treat it as a binary file
|
||||
testStream.close();
|
||||
return new BinarySourceFile(actualPath);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
testStream.close();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
SourceFile::SourceFile(const std::string &path, source_file_t filetype)
|
||||
: m_path(path)
|
||||
, m_filetype(filetype)
|
||||
, m_stream()
|
||||
{
|
||||
// Initialize m_size
|
||||
open();
|
||||
assert(m_stream);
|
||||
m_stream->seekg(0, std::ios_base::end);
|
||||
m_size = (unsigned)m_stream->tellg();
|
||||
close();
|
||||
}
|
||||
|
||||
//! The file is closed if it had been left opened.
|
||||
//!
|
||||
SourceFile::~SourceFile()
|
||||
{
|
||||
if (isOpen())
|
||||
{
|
||||
m_stream->close();
|
||||
}
|
||||
}
|
||||
|
||||
//! \exception std::runtime_error Raised if the file could not be opened successfully.
|
||||
void SourceFile::open()
|
||||
{
|
||||
assert(!isOpen());
|
||||
m_stream = new std::ifstream(m_path.c_str(), std::ios_base::in | std::ios_base::binary);
|
||||
if (!m_stream->is_open())
|
||||
{
|
||||
throw std::runtime_error(format_string("failed to open file: %s", m_path.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
void SourceFile::close()
|
||||
{
|
||||
assert(isOpen());
|
||||
|
||||
m_stream->close();
|
||||
m_stream.safe_delete();
|
||||
}
|
||||
|
||||
//! If the file does not support named sections, or if there is not a
|
||||
//! section with the given name, this method may return NULL.
|
||||
//!
|
||||
//! This method is just a small wrapper that creates an
|
||||
//! FixedMatcher string matcher instance and uses the createDataSource()
|
||||
//! that takes a reference to a StringMatcher.
|
||||
DataSource *SourceFile::createDataSource(const std::string §ion)
|
||||
{
|
||||
FixedMatcher matcher(section);
|
||||
return createDataSource(matcher);
|
||||
}
|
||||
|
||||
DataTarget *SourceFile::createDataTargetForEntryPoint()
|
||||
{
|
||||
if (!hasEntryPoint())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new ConstantDataTarget(getEntryPointAddress());
|
||||
}
|
||||
|
||||
BinarySourceFile::BinarySourceFile(const std::string &path, source_file_t sourceFileType)
|
||||
: SourceFile(path, sourceFileType)
|
||||
, m_entry_point(0xffffffff)
|
||||
, m_stack_pointer(0xffffffff)
|
||||
{
|
||||
}
|
||||
|
||||
void BinarySourceFile::guessEntryPointAndStackPointer()
|
||||
{
|
||||
open();
|
||||
|
||||
uint32_t data[] = { 0xffffffff, 0xffffffff };
|
||||
|
||||
// seek to beginning of the stream/file and read the plaintext header
|
||||
m_stream->seekg(0, std::ios_base::beg);
|
||||
if (m_stream->read((char *)&data, sizeof(data)).bad())
|
||||
{
|
||||
close();
|
||||
throw std::runtime_error(format_string("failed to read image header from file: %s", m_path.c_str()));
|
||||
}
|
||||
|
||||
close();
|
||||
|
||||
m_stack_pointer = ENDIAN_LITTLE_TO_HOST_U32(data[0]);
|
||||
m_entry_point = ENDIAN_LITTLE_TO_HOST_U32(data[1]);
|
||||
}
|
||||
|
||||
DataSource *BinarySourceFile::createDataSource()
|
||||
{
|
||||
std::istream *fileStream = getStream();
|
||||
assert(fileStream);
|
||||
|
||||
// get stream size
|
||||
fileStream->seekg(0, std::ios_base::end);
|
||||
int length = (int)fileStream->tellg();
|
||||
|
||||
// allocate buffer
|
||||
smart_array_ptr<uint8_t> data = new uint8_t[length];
|
||||
|
||||
// read entire file into the buffer
|
||||
fileStream->seekg(0, std::ios_base::beg);
|
||||
if (fileStream->read((char *)data.get(), length).bad())
|
||||
{
|
||||
throw std::runtime_error(format_string("unexpected end of file: %s", m_path.c_str()));
|
||||
}
|
||||
|
||||
// create the data source. the buffer is copied, so we can dispose of it.
|
||||
return new UnmappedDataSource(data, length);
|
||||
}
|
||||
556
src/blfwk/src/StELFFile.cpp
Normal file
556
src/blfwk/src/StELFFile.cpp
Normal file
File diff suppressed because it is too large
Load Diff
487
src/blfwk/src/StExecutableImage.cpp
Normal file
487
src/blfwk/src/StExecutableImage.cpp
Normal file
@@ -0,0 +1,487 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "blfwk/StExecutableImage.h"
|
||||
|
||||
StExecutableImage::StExecutableImage(int inAlignment)
|
||||
: m_alignment(inAlignment)
|
||||
, m_hasEntry(false)
|
||||
, m_entry(0)
|
||||
{
|
||||
}
|
||||
|
||||
//! Makes a duplicate of each memory region.
|
||||
StExecutableImage::StExecutableImage(const StExecutableImage &inOther)
|
||||
: m_name(inOther.m_name)
|
||||
, m_alignment(inOther.m_alignment)
|
||||
, m_hasEntry(inOther.m_hasEntry)
|
||||
, m_entry(inOther.m_entry)
|
||||
, m_filters(inOther.m_filters)
|
||||
{
|
||||
const_iterator it = inOther.getRegionBegin();
|
||||
for (; it != inOther.getRegionEnd(); ++it)
|
||||
{
|
||||
const MemoryRegion ®ion = *it;
|
||||
|
||||
MemoryRegion regionCopy(region);
|
||||
if (region.m_type == FILL_REGION && region.m_data != NULL)
|
||||
{
|
||||
regionCopy.m_data = new uint8_t[region.m_length];
|
||||
memcpy(regionCopy.m_data, region.m_data, region.m_length);
|
||||
}
|
||||
|
||||
m_image.push_back(regionCopy);
|
||||
}
|
||||
}
|
||||
|
||||
//! Disposes of memory allocated for each region.
|
||||
StExecutableImage::~StExecutableImage()
|
||||
{
|
||||
MemoryRegionList::iterator it;
|
||||
for (it = m_image.begin(); it != m_image.end(); ++it)
|
||||
{
|
||||
if (it->m_data)
|
||||
{
|
||||
delete[] it->m_data;
|
||||
it->m_data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! A copy of \a inName is made, so the original may be disposed of by the caller
|
||||
//! after this method returns.
|
||||
void StExecutableImage::setName(const std::string &inName)
|
||||
{
|
||||
m_name = inName;
|
||||
}
|
||||
|
||||
std::string StExecutableImage::getName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
// The region is added with read and write flags set.
|
||||
//! \exception std::runtime_error will be thrown if the new overlaps an
|
||||
//! existing region.
|
||||
void StExecutableImage::addFillRegion(uint32_t inAddress, unsigned inLength)
|
||||
{
|
||||
MemoryRegion region;
|
||||
region.m_type = FILL_REGION;
|
||||
region.m_address = inAddress;
|
||||
region.m_data = NULL;
|
||||
region.m_length = inLength;
|
||||
region.m_flags = REGION_RW_FLAG;
|
||||
|
||||
insertOrMergeRegion(region);
|
||||
}
|
||||
|
||||
//! A copy of \a inData is made before returning. The copy will be deleted when
|
||||
//! the executable image is destructed. Currently, the text region is created with
|
||||
//! read, write, and executable flags set.
|
||||
//! \exception std::runtime_error will be thrown if the new overlaps an
|
||||
//! existing region.
|
||||
//! \exception std::bad_alloc is thrown if memory for the copy of \a inData
|
||||
//! cannot be allocated.
|
||||
void StExecutableImage::addTextRegion(uint32_t inAddress, const uint8_t *inData, unsigned inLength)
|
||||
{
|
||||
MemoryRegion region;
|
||||
region.m_type = TEXT_REGION;
|
||||
region.m_address = inAddress;
|
||||
region.m_flags = REGION_RW_FLAG | REGION_EXEC_FLAG;
|
||||
|
||||
// copy the data
|
||||
region.m_data = new uint8_t[inLength];
|
||||
region.m_length = inLength;
|
||||
memcpy(region.m_data, inData, inLength);
|
||||
|
||||
insertOrMergeRegion(region);
|
||||
}
|
||||
|
||||
//! \exception std::out_of_range is thrown if \a inIndex is out of range.
|
||||
//!
|
||||
const StExecutableImage::MemoryRegion &StExecutableImage::getRegionAtIndex(unsigned inIndex) const
|
||||
{
|
||||
// check bounds
|
||||
if (inIndex >= m_image.size())
|
||||
throw std::out_of_range("inIndex");
|
||||
|
||||
// find region by index
|
||||
MemoryRegionList::const_iterator it = m_image.begin();
|
||||
unsigned i = 0;
|
||||
for (; it != m_image.end(); ++it, ++i)
|
||||
{
|
||||
if (i == inIndex)
|
||||
break;
|
||||
}
|
||||
return *it;
|
||||
}
|
||||
|
||||
//! The list of address filters is kept sorted as filters are added.
|
||||
//!
|
||||
void StExecutableImage::addAddressFilter(const AddressFilter &filter)
|
||||
{
|
||||
m_filters.push_back(filter);
|
||||
m_filters.sort();
|
||||
}
|
||||
|
||||
//!
|
||||
void StExecutableImage::clearAddressFilters()
|
||||
{
|
||||
m_filters.clear();
|
||||
}
|
||||
|
||||
//! \exception StExecutableImage::address_filter_exception Raised when a filter
|
||||
//! with the type #ADDR_FILTER_ERROR or #ADDR_FILTER_WARNING is matched.
|
||||
//!
|
||||
//! \todo Build a list of all matching filters and then execute them at once.
|
||||
//! For the warning and error filters, a single exception should be raised
|
||||
//! that identifies all the overlapping errors. Currently the user will only
|
||||
//! see the first (lowest address) overlap.
|
||||
void StExecutableImage::applyAddressFilters()
|
||||
{
|
||||
restart_loops:
|
||||
// Iterate over filters.
|
||||
AddressFilterList::const_iterator fit = m_filters.begin();
|
||||
for (; fit != m_filters.end(); ++fit)
|
||||
{
|
||||
const AddressFilter &filter = *fit;
|
||||
|
||||
// Iterator over regions.
|
||||
MemoryRegionList::iterator rit = m_image.begin();
|
||||
for (; rit != m_image.end(); ++rit)
|
||||
{
|
||||
MemoryRegion ®ion = *rit;
|
||||
|
||||
if (filter.matchesMemoryRegion(region))
|
||||
{
|
||||
switch (filter.m_action)
|
||||
{
|
||||
case ADDR_FILTER_NONE:
|
||||
// Do nothing.
|
||||
break;
|
||||
|
||||
case ADDR_FILTER_ERROR:
|
||||
// throw error exception
|
||||
throw address_filter_exception(true, m_name, filter);
|
||||
break;
|
||||
|
||||
case ADDR_FILTER_WARNING:
|
||||
// throw warning exception
|
||||
throw address_filter_exception(false, m_name, filter);
|
||||
break;
|
||||
|
||||
case ADDR_FILTER_CROP:
|
||||
// Delete the offending portion of the region and restart
|
||||
// the iteration loops.
|
||||
cropRegionToFilter(region, filter);
|
||||
goto restart_loops;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! There are several possible cases here:
|
||||
//! - No overlap at all. Nothing is done.
|
||||
//!
|
||||
//! - All of the memory region is matched by the \a filter. The region is
|
||||
//! removed from #StExecutableImage::m_image and its data memory freed.
|
||||
//!
|
||||
//! - The remaining portion of the region is one contiguous chunk. In this
|
||||
//! case, \a region is simply modified.
|
||||
//!
|
||||
//! - The region is split in the middle by the filter. The original \a region
|
||||
//! is modified to match the first remaining chunk. And a new #StExecutableImage::MemoryRegion
|
||||
//! instance is created to hold the other leftover piece.
|
||||
void StExecutableImage::cropRegionToFilter(MemoryRegion ®ion, const AddressFilter &filter)
|
||||
{
|
||||
uint32_t firstByte = region.m_address; // first byte occupied by this region
|
||||
uint32_t lastByte = region.endAddress(); // last used byte in this region
|
||||
|
||||
// compute new address range
|
||||
uint32_t cropFrom = filter.m_fromAddress;
|
||||
if (cropFrom < firstByte)
|
||||
{
|
||||
cropFrom = firstByte;
|
||||
}
|
||||
|
||||
uint32_t cropTo = filter.m_toAddress;
|
||||
if (cropTo > lastByte)
|
||||
{
|
||||
cropTo = lastByte;
|
||||
}
|
||||
|
||||
// is there actually a match?
|
||||
if (cropFrom > filter.m_toAddress || cropTo < filter.m_fromAddress)
|
||||
{
|
||||
// nothing to do, so bail
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Deleting region 0x%08x-0x%08x\n", cropFrom, cropTo);
|
||||
|
||||
// handle if the entire region is to be deleted
|
||||
if (cropFrom == firstByte && cropTo == lastByte)
|
||||
{
|
||||
delete[] region.m_data;
|
||||
region.m_data = NULL;
|
||||
m_image.remove(region);
|
||||
}
|
||||
|
||||
// there is at least a little of the original region remaining
|
||||
uint32_t newLength = cropTo - cropFrom + 1;
|
||||
uint32_t leftoverLength = lastByte - cropTo;
|
||||
uint8_t *oldData = region.m_data;
|
||||
|
||||
// update the region
|
||||
region.m_address = cropFrom;
|
||||
region.m_length = newLength;
|
||||
|
||||
// crop data buffer for text regions
|
||||
if (region.m_type == TEXT_REGION && oldData)
|
||||
{
|
||||
region.m_data = new uint8_t[newLength];
|
||||
memcpy(region.m_data, &oldData[cropFrom - firstByte], newLength);
|
||||
|
||||
// dispose of old data
|
||||
delete[] oldData;
|
||||
}
|
||||
|
||||
// create a new region for any part of the original region that was past
|
||||
// the crop to address. this will happen if the filter range falls in the
|
||||
// middle of the region.
|
||||
if (leftoverLength)
|
||||
{
|
||||
MemoryRegion newRegion;
|
||||
newRegion.m_type = region.m_type;
|
||||
newRegion.m_flags = region.m_flags;
|
||||
newRegion.m_address = cropTo + 1;
|
||||
newRegion.m_length = leftoverLength;
|
||||
|
||||
if (region.m_type == TEXT_REGION && oldData)
|
||||
{
|
||||
newRegion.m_data = new uint8_t[leftoverLength];
|
||||
memcpy(newRegion.m_data, &oldData[cropTo - firstByte + 1], leftoverLength);
|
||||
}
|
||||
|
||||
insertOrMergeRegion(newRegion);
|
||||
}
|
||||
}
|
||||
|
||||
//! \exception std::runtime_error will be thrown if \a inRegion overlaps an
|
||||
//! existing region.
|
||||
//!
|
||||
//! \todo Need to investigate if we can use the STL sort algorithm at all. Even
|
||||
//! though we're doing merges too, we could sort first then examine the list
|
||||
//! for merges.
|
||||
void StExecutableImage::insertOrMergeRegion(MemoryRegion &inRegion)
|
||||
{
|
||||
uint32_t newStart = inRegion.m_address;
|
||||
uint32_t newEnd = newStart + inRegion.m_length;
|
||||
|
||||
MemoryRegionList::iterator it = m_image.begin();
|
||||
|
||||
for (; it != m_image.end(); ++it)
|
||||
{
|
||||
MemoryRegion ®ion = *it;
|
||||
uint32_t thisStart = region.m_address;
|
||||
uint32_t thisEnd = thisStart + region.m_length;
|
||||
|
||||
// keep track of where to insert it to retain sort order
|
||||
if (thisStart >= newEnd)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// region types and flags must match in order to merge
|
||||
if (region.m_type == inRegion.m_type && region.m_flags == inRegion.m_flags)
|
||||
{
|
||||
if (newStart == thisEnd || newEnd == thisStart)
|
||||
{
|
||||
mergeRegions(region, inRegion);
|
||||
return;
|
||||
}
|
||||
else if ((newStart >= thisStart && newStart < thisEnd) || (newEnd >= thisStart && newEnd < thisEnd))
|
||||
{
|
||||
throw std::runtime_error("new region overlaps existing region");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// not merged, so just insert it in the sorted position
|
||||
m_image.insert(it, inRegion);
|
||||
}
|
||||
|
||||
//! Extends \a inNewRegion to include the data in \a inOldRegion. It is
|
||||
//! assumed that the two regions are compatible. The new region may come either
|
||||
//! before or after the old region in memory. Note that while the two regions
|
||||
//! don't necessarily have to be touching, it's probably a good idea. That's
|
||||
//! because any data between the regions will be set to 0.
|
||||
//!
|
||||
//! For TEXT_REGION types, the two original regions will have their data deleted
|
||||
//! during the merge. Thus, this method is not safe if any outside callers may
|
||||
//! be accessing the region's data.
|
||||
void StExecutableImage::mergeRegions(MemoryRegion &inOldRegion, MemoryRegion &inNewRegion)
|
||||
{
|
||||
bool isOldBefore = inOldRegion.m_address < inNewRegion.m_address;
|
||||
uint32_t oldEnd = inOldRegion.m_address + inOldRegion.m_length;
|
||||
uint32_t newEnd = inNewRegion.m_address + inNewRegion.m_length;
|
||||
|
||||
switch (inOldRegion.m_type)
|
||||
{
|
||||
case TEXT_REGION:
|
||||
{
|
||||
// calculate new length
|
||||
unsigned newLength;
|
||||
if (isOldBefore)
|
||||
{
|
||||
newLength = newEnd - inOldRegion.m_address;
|
||||
}
|
||||
else
|
||||
{
|
||||
newLength = oldEnd - inNewRegion.m_address;
|
||||
}
|
||||
|
||||
// alloc memory
|
||||
uint8_t *newData = new uint8_t[newLength];
|
||||
memset(newData, 0, newLength);
|
||||
|
||||
// copy data from the two regions into new block
|
||||
if (isOldBefore)
|
||||
{
|
||||
memcpy(newData, inOldRegion.m_data, inOldRegion.m_length);
|
||||
memcpy(&newData[newLength - inNewRegion.m_length], inNewRegion.m_data, inNewRegion.m_length);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(newData, inNewRegion.m_data, inNewRegion.m_length);
|
||||
memcpy(&newData[newLength - inOldRegion.m_length], inOldRegion.m_data, inOldRegion.m_length);
|
||||
|
||||
inOldRegion.m_address = inNewRegion.m_address;
|
||||
}
|
||||
|
||||
// replace old region's data
|
||||
delete[] inOldRegion.m_data;
|
||||
inOldRegion.m_data = newData;
|
||||
inOldRegion.m_length = newLength;
|
||||
|
||||
// delete new region's data
|
||||
delete[] inNewRegion.m_data;
|
||||
inNewRegion.m_data = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
case FILL_REGION:
|
||||
{
|
||||
if (isOldBefore)
|
||||
{
|
||||
inOldRegion.m_length = newEnd - inOldRegion.m_address;
|
||||
}
|
||||
else
|
||||
{
|
||||
inOldRegion.m_length = oldEnd - inNewRegion.m_address;
|
||||
inOldRegion.m_address = inNewRegion.m_address;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Used when we remove a region from the region list by value. Because this
|
||||
//! operator compares the #m_data member, it will only return true for either an
|
||||
//! exact copy or a reference to the original.
|
||||
bool StExecutableImage::MemoryRegion::operator==(const MemoryRegion &other) const
|
||||
{
|
||||
return (m_type == other.m_type) && (m_address == other.m_address) && (m_length == other.m_length) &&
|
||||
(m_flags == other.m_flags) && (m_data == other.m_data);
|
||||
}
|
||||
|
||||
//! Returns true if the address filter overlaps \a region.
|
||||
bool StExecutableImage::AddressFilter::matchesMemoryRegion(const MemoryRegion ®ion) const
|
||||
{
|
||||
uint32_t firstByte = region.m_address; // first byte occupied by this region
|
||||
uint32_t lastByte = region.endAddress(); // last used byte in this region
|
||||
return (firstByte >= m_fromAddress && firstByte <= m_toAddress) ||
|
||||
(lastByte >= m_fromAddress && lastByte <= m_toAddress);
|
||||
}
|
||||
|
||||
//! The comparison does \em not take the action into account. It only looks at the
|
||||
//! priority and address ranges of each filter. Priority is considered only if the two
|
||||
//! filters overlap. Lower priority filters will come after higher priority ones.
|
||||
//!
|
||||
//! \retval -1 This filter is less than filter \a b.
|
||||
//! \retval 0 This filter is equal to filter \a b.
|
||||
//! \retval 1 This filter is greater than filter \a b.
|
||||
int StExecutableImage::AddressFilter::compare(const AddressFilter &other) const
|
||||
{
|
||||
if (m_priority != other.m_priority &&
|
||||
((m_fromAddress >= other.m_fromAddress && m_fromAddress <= other.m_toAddress) ||
|
||||
(m_toAddress >= other.m_fromAddress && m_toAddress <= other.m_toAddress)))
|
||||
{
|
||||
// we know the priorities are not equal
|
||||
if (m_priority > other.m_priority)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_fromAddress == other.m_fromAddress)
|
||||
{
|
||||
if (m_toAddress == other.m_toAddress)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (m_toAddress < other.m_toAddress)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (m_fromAddress < other.m_fromAddress)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
232
src/blfwk/src/StIntelHexFile.cpp
Normal file
232
src/blfwk/src/StIntelHexFile.cpp
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Copyright (c) 2013-15, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "blfwk/stdafx.h"
|
||||
#include "blfwk/StIntelHexFile.h"
|
||||
#ifdef LINUX
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
StIntelHexFile::StIntelHexFile(std::istream &inStream)
|
||||
: m_stream(inStream)
|
||||
{
|
||||
}
|
||||
|
||||
//! Frees any data allocated as part of an Intel Hex.
|
||||
StIntelHexFile::~StIntelHexFile()
|
||||
{
|
||||
const_iterator it;
|
||||
for (it = m_records.begin(); it != m_records.end(); it++)
|
||||
{
|
||||
IntelHex &theRecord = (IntelHex &)*it;
|
||||
if (theRecord.m_data)
|
||||
{
|
||||
delete[] theRecord.m_data;
|
||||
theRecord.m_data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Just looks for ":" as the first characters of the file followed by two digit characters.
|
||||
bool StIntelHexFile::isIntelHexFile()
|
||||
{
|
||||
int savePosition = (int)m_stream.tellg();
|
||||
m_stream.seekg(0, std::ios_base::beg);
|
||||
|
||||
char buffer[3];
|
||||
m_stream.read(buffer, 3);
|
||||
bool isIntelHex = (buffer[0] == ':' && isHexDigit(buffer[1]) && isHexDigit(buffer[2]));
|
||||
|
||||
m_stream.seekg(savePosition, std::ios_base::beg);
|
||||
|
||||
return isIntelHex;
|
||||
}
|
||||
|
||||
//! Extract records one line at a time and hand them to the parseLine()
|
||||
//! method. Either CR, LF, or CRLF line endings are supported. The input
|
||||
//! stream is read until EOF or an file end record detected.
|
||||
//! The parse() method must be called after the object has been constructed
|
||||
//! before any of the records will become accessible.
|
||||
//! \exception StIntelHexParseException will be thrown if any error occurs while
|
||||
//! parsing the input.
|
||||
void StIntelHexFile::parse()
|
||||
{
|
||||
// back to start of stream
|
||||
m_stream.seekg(0, std::ios_base::beg);
|
||||
|
||||
std::string thisLine;
|
||||
|
||||
do
|
||||
{
|
||||
char thisChar;
|
||||
m_stream.get(thisChar);
|
||||
|
||||
if (thisChar == '\r' || thisChar == '\n')
|
||||
{
|
||||
// skip the LF in a CRLF
|
||||
if (thisChar == '\r' && m_stream.peek() == '\n')
|
||||
m_stream.ignore();
|
||||
|
||||
// parse line if it's not empty
|
||||
if (!thisLine.empty())
|
||||
{
|
||||
parseLine(thisLine);
|
||||
|
||||
// reset line
|
||||
thisLine.clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
thisLine += thisChar;
|
||||
}
|
||||
} while (!m_stream.eof());
|
||||
}
|
||||
|
||||
bool StIntelHexFile::isHexDigit(char c)
|
||||
{
|
||||
return (isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
|
||||
}
|
||||
|
||||
int StIntelHexFile::hexDigitToInt(char digit)
|
||||
{
|
||||
if (isdigit(digit))
|
||||
return digit - '0';
|
||||
else if (digit >= 'a' && digit <= 'f')
|
||||
return 10 + digit - 'a';
|
||||
else if (digit >= 'A' && digit <= 'F')
|
||||
return 10 + digit - 'A';
|
||||
|
||||
// unknow char
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! \exception StIntelHexParseException is thrown if either of the nibble characters
|
||||
//! is not a valid hex digit.
|
||||
int StIntelHexFile::readHexByte(std::string &inString, int inIndex)
|
||||
{
|
||||
char nibbleCharHi = inString[inIndex];
|
||||
char nibbleCharLo = inString[inIndex + 1];
|
||||
|
||||
// must be hex digits
|
||||
if (!(isHexDigit(nibbleCharHi) && isHexDigit(nibbleCharLo)))
|
||||
{
|
||||
throw StIntelHexParseException("invalid hex digit");
|
||||
}
|
||||
|
||||
return (hexDigitToInt(nibbleCharHi) << 4) | hexDigitToInt(nibbleCharLo);
|
||||
}
|
||||
|
||||
//! \brief Parses individual Intel Hex.
|
||||
//!
|
||||
//! Takes a single Intel Hex line as input and appends a new IntelHex struct
|
||||
//! to the m_records vector.
|
||||
//! \exception StIntelHexParseException will be thrown if any error occurs while
|
||||
//! parsing \a inLine.
|
||||
void StIntelHexFile::parseLine(std::string &inLine)
|
||||
{
|
||||
int checksum = 0;
|
||||
IntelHex newRecord;
|
||||
memset(&newRecord, 0, sizeof(newRecord));
|
||||
|
||||
// must be at least a certain length
|
||||
if (inLine.length() < INTELHEX_MIN_LENGTH)
|
||||
{
|
||||
throw StIntelHexParseException("invalid record length");
|
||||
}
|
||||
|
||||
// start char must be ':'
|
||||
if (inLine[0] != INTELHEX_START_CHAR)
|
||||
{
|
||||
throw StIntelHexParseException("invalid record start char");
|
||||
}
|
||||
|
||||
// parse count field
|
||||
newRecord.m_dataCount = readHexByte(inLine, 1);
|
||||
checksum += newRecord.m_dataCount;
|
||||
|
||||
// verify the record length now that we know the count
|
||||
if (inLine.length() != 11 + newRecord.m_dataCount * 2)
|
||||
{
|
||||
throw StIntelHexParseException("invalid record length");
|
||||
}
|
||||
|
||||
// read address field.
|
||||
int address = 0;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
int addressByte = readHexByte(inLine, INTELHEX_ADDRESS_START_CHAR_INDEX + i * 2);
|
||||
address = (address << 8) | addressByte;
|
||||
checksum += addressByte;
|
||||
}
|
||||
newRecord.m_address = address;
|
||||
|
||||
// handle data type.;
|
||||
newRecord.m_type = readHexByte(inLine, INTELHEX_TYPE_START_CHAR_INDEX);
|
||||
checksum += newRecord.m_type;
|
||||
switch (newRecord.m_type)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
break;
|
||||
default:
|
||||
throw StIntelHexParseException("unknown Intel Hex record type");
|
||||
break;
|
||||
}
|
||||
|
||||
// read data
|
||||
if (newRecord.m_dataCount)
|
||||
{
|
||||
uint8_t *data = new uint8_t[newRecord.m_dataCount];
|
||||
for (unsigned i = 0; i < newRecord.m_dataCount; ++i)
|
||||
{
|
||||
int dataByte = readHexByte(inLine, INTELHEX_DATA_START_CHAR_INDEX + i * 2);
|
||||
data[i] = dataByte;
|
||||
checksum += dataByte;
|
||||
}
|
||||
|
||||
newRecord.m_data = data;
|
||||
}
|
||||
|
||||
// read and compare checksum byte
|
||||
checksum = (~checksum + 1) & 0xff; // low byte of one's complement of sum of other bytes
|
||||
newRecord.m_checksum = readHexByte(inLine, (int)inLine.length() - 2);
|
||||
if (checksum != newRecord.m_checksum)
|
||||
{
|
||||
throw StIntelHexParseException("invalid checksum");
|
||||
}
|
||||
|
||||
// now save the new Intel Hex record
|
||||
m_records.push_back(newRecord);
|
||||
}
|
||||
266
src/blfwk/src/StSRecordFile.cpp
Normal file
266
src/blfwk/src/StSRecordFile.cpp
Normal file
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "blfwk/stdafx.h"
|
||||
#include "blfwk/StSRecordFile.h"
|
||||
#ifdef LINUX
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
StSRecordFile::StSRecordFile(std::istream &inStream)
|
||||
: m_stream(inStream)
|
||||
{
|
||||
}
|
||||
|
||||
//! Frees any data allocated as part of an S-record.
|
||||
StSRecordFile::~StSRecordFile()
|
||||
{
|
||||
const_iterator it;
|
||||
for (it = m_records.begin(); it != m_records.end(); it++)
|
||||
{
|
||||
SRecord &theRecord = (SRecord &)*it;
|
||||
if (theRecord.m_data)
|
||||
{
|
||||
delete[] theRecord.m_data;
|
||||
theRecord.m_data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Just looks for "S[0-9]" as the first two characters of the file.
|
||||
bool StSRecordFile::isSRecordFile()
|
||||
{
|
||||
int savePosition = (int)m_stream.tellg();
|
||||
m_stream.seekg(0, std::ios_base::beg);
|
||||
|
||||
char buffer[2];
|
||||
m_stream.read(buffer, 2);
|
||||
bool isSRecord = (buffer[0] == 'S' && isdigit(buffer[1]));
|
||||
|
||||
m_stream.seekg(savePosition, std::ios_base::beg);
|
||||
|
||||
return isSRecord;
|
||||
}
|
||||
|
||||
//! Extract records one line at a time and hand them to the parseLine()
|
||||
//! method. Either CR, LF, or CRLF line endings are supported. The input
|
||||
//! stream is read until EOF.
|
||||
//! The parse() method must be called after the object has been constructed
|
||||
//! before any of the records will become accessible.
|
||||
//! \exception StSRecordParseException will be thrown if any error occurs while
|
||||
//! parsing the input.
|
||||
void StSRecordFile::parse()
|
||||
{
|
||||
// back to start of stream
|
||||
m_stream.seekg(0, std::ios_base::beg);
|
||||
|
||||
std::string thisLine;
|
||||
|
||||
do
|
||||
{
|
||||
char thisChar;
|
||||
m_stream.get(thisChar);
|
||||
|
||||
if (thisChar == '\r' || thisChar == '\n')
|
||||
{
|
||||
// skip the LF in a CRLF
|
||||
if (thisChar == '\r' && m_stream.peek() == '\n')
|
||||
m_stream.ignore();
|
||||
|
||||
// parse line if it's not empty
|
||||
if (!thisLine.empty())
|
||||
{
|
||||
parseLine(thisLine);
|
||||
|
||||
// reset line
|
||||
thisLine.clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
thisLine += thisChar;
|
||||
}
|
||||
} while (!m_stream.eof());
|
||||
}
|
||||
|
||||
bool StSRecordFile::isHexDigit(char c)
|
||||
{
|
||||
return (isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
|
||||
}
|
||||
|
||||
int StSRecordFile::hexDigitToInt(char digit)
|
||||
{
|
||||
if (isdigit(digit))
|
||||
return digit - '0';
|
||||
else if (digit >= 'a' && digit <= 'f')
|
||||
return 10 + digit - 'a';
|
||||
else if (digit >= 'A' && digit <= 'F')
|
||||
return 10 + digit - 'A';
|
||||
|
||||
// unknow char
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! \exception StSRecordParseException is thrown if either of the nibble characters
|
||||
//! is not a valid hex digit.
|
||||
int StSRecordFile::readHexByte(std::string &inString, int inIndex)
|
||||
{
|
||||
char nibbleCharHi = inString[inIndex];
|
||||
char nibbleCharLo = inString[inIndex + 1];
|
||||
|
||||
// must be hex digits
|
||||
if (!(isHexDigit(nibbleCharHi) && isHexDigit(nibbleCharLo)))
|
||||
{
|
||||
throw StSRecordParseException("invalid hex digit");
|
||||
}
|
||||
|
||||
return (hexDigitToInt(nibbleCharHi) << 4) | hexDigitToInt(nibbleCharLo);
|
||||
}
|
||||
|
||||
//! \brief Parses individual S-records.
|
||||
//!
|
||||
//! Takes a single S-record line as input and appends a new SRecord struct
|
||||
//! to the m_records vector.
|
||||
//! \exception StSRecordParseException will be thrown if any error occurs while
|
||||
//! parsing \a inLine.
|
||||
void StSRecordFile::parseLine(std::string &inLine)
|
||||
{
|
||||
int checksum = 0;
|
||||
SRecord newRecord;
|
||||
memset(&newRecord, 0, sizeof(newRecord));
|
||||
|
||||
// must be at least a certain length
|
||||
if (inLine.length() < SRECORD_MIN_LENGTH)
|
||||
{
|
||||
throw StSRecordParseException("invalid record length");
|
||||
}
|
||||
|
||||
// start char must be 'S'
|
||||
if (inLine[0] != SRECORD_START_CHAR)
|
||||
{
|
||||
throw StSRecordParseException("invalid record start char");
|
||||
}
|
||||
|
||||
// parse type field
|
||||
if (!isdigit(inLine[1]))
|
||||
{
|
||||
throw StSRecordParseException("invalid S-record type");
|
||||
}
|
||||
newRecord.m_type = inLine[1] - '0';
|
||||
|
||||
// parse count field
|
||||
newRecord.m_count = readHexByte(inLine, 2);
|
||||
checksum += newRecord.m_count;
|
||||
|
||||
// verify the record length now that we know the count
|
||||
if (inLine.length() != 4 + newRecord.m_count * 2)
|
||||
{
|
||||
throw StSRecordParseException("invalid record length");
|
||||
}
|
||||
|
||||
// get address length
|
||||
int addressLength = 0; // len in bytes
|
||||
bool hasData = false;
|
||||
switch (newRecord.m_type)
|
||||
{
|
||||
case 0: // contains header information
|
||||
addressLength = 2;
|
||||
hasData = true;
|
||||
break;
|
||||
case 1: // data record with 2-byte address
|
||||
addressLength = 2;
|
||||
hasData = true;
|
||||
break;
|
||||
case 2: // data record with 3-byte address
|
||||
addressLength = 3;
|
||||
hasData = true;
|
||||
break;
|
||||
case 3: // data record with 4-byte address
|
||||
addressLength = 4;
|
||||
hasData = true;
|
||||
break;
|
||||
case 5: // the 2-byte address field contains a count of all prior S1, S2, and S3 records
|
||||
addressLength = 2;
|
||||
break;
|
||||
case 7: // entry point record with 4-byte address
|
||||
addressLength = 4;
|
||||
break;
|
||||
case 8: // entry point record with 3-byte address
|
||||
addressLength = 3;
|
||||
break;
|
||||
case 9: // entry point record with 2-byte address
|
||||
addressLength = 2;
|
||||
break;
|
||||
default:
|
||||
// unrecognized type
|
||||
throw StSRecordParseException("unknown S-record type");
|
||||
break;
|
||||
}
|
||||
|
||||
// read address
|
||||
int address = 0;
|
||||
int i;
|
||||
for (i = 0; i < addressLength; ++i)
|
||||
{
|
||||
int addressByte = readHexByte(inLine, SRECORD_ADDRESS_START_CHAR_INDEX + i * 2);
|
||||
address = (address << 8) | addressByte;
|
||||
checksum += addressByte;
|
||||
}
|
||||
newRecord.m_address = address;
|
||||
|
||||
// read data
|
||||
if (hasData)
|
||||
{
|
||||
int dataStartCharIndex = 4 + addressLength * 2;
|
||||
int dataLength = newRecord.m_count - addressLength - 1; // total rem - addr - cksum (in bytes)
|
||||
uint8_t *data = new uint8_t[dataLength];
|
||||
|
||||
for (i = 0; i < dataLength; ++i)
|
||||
{
|
||||
int dataByte = readHexByte(inLine, dataStartCharIndex + i * 2);
|
||||
data[i] = dataByte;
|
||||
checksum += dataByte;
|
||||
}
|
||||
|
||||
newRecord.m_data = data;
|
||||
newRecord.m_dataCount = dataLength;
|
||||
}
|
||||
|
||||
// read and compare checksum byte
|
||||
checksum = (~checksum) & 0xff; // low byte of one's complement of sum of other bytes
|
||||
newRecord.m_checksum = readHexByte(inLine, (int)inLine.length() - 2);
|
||||
if (checksum != newRecord.m_checksum)
|
||||
{
|
||||
throw StSRecordParseException("invalid checksum");
|
||||
}
|
||||
|
||||
// now save the new S-record
|
||||
m_records.push_back(newRecord);
|
||||
}
|
||||
172
src/blfwk/src/UartPeripheral.cpp
Normal file
172
src/blfwk/src/UartPeripheral.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "blfwk/UartPeripheral.h"
|
||||
#include "blfwk/Logging.h"
|
||||
#include "blfwk/format_string.h"
|
||||
#include "blfwk/serial.h"
|
||||
|
||||
using namespace blfwk;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Code
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// See uart_peripheral.h for documentation of this method.
|
||||
UartPeripheral::UartPeripheral(const char *port, long speed)
|
||||
: m_fileDescriptor(-1)
|
||||
{
|
||||
if (!init(port, speed))
|
||||
{
|
||||
throw std::runtime_error(
|
||||
format_string("Error: UartPeripheral() cannot open PC UART port(%s), speed(%d Hz).", port, speed));
|
||||
}
|
||||
}
|
||||
|
||||
// See uart_peripheral.h for documentation of this method.
|
||||
bool UartPeripheral::init(const char *port, long speed)
|
||||
{
|
||||
assert(port);
|
||||
|
||||
// Open the port.
|
||||
m_fileDescriptor = serial_open(const_cast<char *>(port));
|
||||
if (m_fileDescriptor == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
serial_setup(m_fileDescriptor, speed);
|
||||
|
||||
// Flush garbage from receive buffer before setting read timeout.
|
||||
flushRX();
|
||||
|
||||
// Set host serial timeout to 10 milliseconds. Higherlevel timeouts are implemented in
|
||||
// SerialPacketizer.cpp
|
||||
serial_set_read_timeout(m_fileDescriptor, kUartPeripheral_DefaultReadTimeoutMs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// See host_peripheral.h for documentation of this method.
|
||||
UartPeripheral::~UartPeripheral()
|
||||
{
|
||||
if (m_fileDescriptor != -1)
|
||||
{
|
||||
serial_close(m_fileDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
// See host_peripheral.h for documentation of this method.
|
||||
status_t UartPeripheral::read(uint8_t *buffer,
|
||||
uint32_t requestedBytes,
|
||||
uint32_t *actualBytes,
|
||||
uint32_t unused_timeoutMs)
|
||||
{
|
||||
assert(buffer);
|
||||
|
||||
// Read the requested number of bytes.
|
||||
int count = serial_read(m_fileDescriptor, reinterpret_cast<char *>(buffer), requestedBytes);
|
||||
if (actualBytes)
|
||||
{
|
||||
*actualBytes = count;
|
||||
}
|
||||
|
||||
if (Log::getLogger()->getFilterLevel() == Logger::kDebug2)
|
||||
{
|
||||
// Log bytes read in hex
|
||||
Log::debug2("<");
|
||||
for (int i = 0; i < (int)count; i++)
|
||||
{
|
||||
Log::debug2("%02x", buffer[i]);
|
||||
if (i != (count - 1))
|
||||
{
|
||||
Log::debug2(" ");
|
||||
}
|
||||
}
|
||||
Log::debug2(">\n");
|
||||
}
|
||||
|
||||
if (count < (int)requestedBytes)
|
||||
{
|
||||
// Anything less than requestedBytes is a timeout error.
|
||||
return kStatus_Timeout;
|
||||
}
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
// See uart_peripheral.h for documentation of this method.
|
||||
void UartPeripheral::flushRX()
|
||||
{
|
||||
// An attempt was made on win32 to use a serial_flush function
|
||||
// which would call PurgeComm(hCom, PURGE_RXABORT | PURGE_TXABORT | PURGE_RXCLEAR | PURGE_TXCLEAR)
|
||||
// even though the function returned success there were still errant data in the RX buffer. Using reads
|
||||
// to empty the RX buffer has worked
|
||||
|
||||
// This read loop never exits on the Mac, and doesn't appear to be necessary.
|
||||
#if (defined(WIN32) || defined(LINUX))
|
||||
// Read up to the requested number of bytes.
|
||||
char *readBuf = reinterpret_cast<char *>(m_buffer);
|
||||
while (serial_read(m_fileDescriptor, readBuf, 16))
|
||||
{
|
||||
readBuf = reinterpret_cast<char *>(m_buffer);
|
||||
}
|
||||
#endif // defined(WIN32) || defined(LINUX)
|
||||
}
|
||||
|
||||
// See host_peripheral.h for documentation of this method.
|
||||
status_t UartPeripheral::write(const uint8_t *buffer, uint32_t byteCount)
|
||||
{
|
||||
assert(buffer);
|
||||
|
||||
if (Log::getLogger()->getFilterLevel() == Logger::kDebug2)
|
||||
{
|
||||
// Log bytes written in hex
|
||||
Log::debug2("[");
|
||||
for (int i = 0; i < (int)byteCount; i++)
|
||||
{
|
||||
Log::debug2("%02x", buffer[i]);
|
||||
if (i != (byteCount - 1))
|
||||
{
|
||||
Log::debug2(" ");
|
||||
}
|
||||
}
|
||||
Log::debug2("]\n");
|
||||
}
|
||||
|
||||
if (serial_write(m_fileDescriptor, reinterpret_cast<char *>(const_cast<uint8_t *>(buffer)), byteCount) == byteCount)
|
||||
return kStatus_Success;
|
||||
else
|
||||
return kStatus_Fail;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
403
src/blfwk/src/Updater.cpp
Normal file
403
src/blfwk/src/Updater.cpp
Normal file
@@ -0,0 +1,403 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "blfwk/Updater.h"
|
||||
#include "bootloader/bootloader.h"
|
||||
|
||||
using namespace blfwk;
|
||||
|
||||
Updater::Updater(const Peripheral::PeripheralConfigData &config)
|
||||
: Bootloader(config)
|
||||
, m_sector_size(0)
|
||||
, m_sourceFile(NULL)
|
||||
, m_operation(kUpdaterOperation_Update)
|
||||
, m_progressCallback(NULL)
|
||||
{
|
||||
//
|
||||
// Get the sector size of the device so we can compute the
|
||||
// address of the Bootloader COnfiguration Block and align
|
||||
// erase regions.
|
||||
//
|
||||
// Inject the get-property(flash-sector-size) command.
|
||||
GetProperty cmdGetSectorSize(kProperty_FlashSectorSize);
|
||||
Log::info("inject command '%s'\n", cmdGetSectorSize.getName().c_str());
|
||||
inject(cmdGetSectorSize);
|
||||
|
||||
uint32_t fw_status = cmdGetSectorSize.getResponseValues()->at(0);
|
||||
if (fw_status != kStatus_Success)
|
||||
{
|
||||
throw std::runtime_error(cmdGetSectorSize.getStatusMessage(fw_status));
|
||||
}
|
||||
|
||||
m_sector_size = cmdGetSectorSize.getResponseValues()->at(1);
|
||||
|
||||
//
|
||||
// Get the flash start address of the device
|
||||
//
|
||||
// Inject the get-property(flash-start-address) command.
|
||||
GetProperty cmdGetFlashStartAddress(kProperty_FlashStartAddress);
|
||||
Log::info("inject command '%s'\n", cmdGetFlashStartAddress.getName().c_str());
|
||||
inject(cmdGetFlashStartAddress);
|
||||
|
||||
fw_status = cmdGetFlashStartAddress.getResponseValues()->at(0);
|
||||
if (fw_status != kStatus_Success)
|
||||
{
|
||||
throw std::runtime_error(cmdGetFlashStartAddress.getStatusMessage(fw_status));
|
||||
}
|
||||
|
||||
m_flashStart = cmdGetFlashStartAddress.getResponseValues()->at(1);
|
||||
|
||||
//
|
||||
// Get the flash size of the device
|
||||
//
|
||||
// Inject the get-property(flash-size-in-bytes) command.
|
||||
GetProperty cmdGetFlashSize(kProperty_FlashSizeInBytes);
|
||||
Log::info("inject command '%s'\n", cmdGetFlashSize.getName().c_str());
|
||||
inject(cmdGetFlashSize);
|
||||
|
||||
fw_status = cmdGetFlashSize.getResponseValues()->at(0);
|
||||
if (fw_status != kStatus_Success)
|
||||
{
|
||||
throw std::runtime_error(cmdGetFlashSize.getStatusMessage(fw_status));
|
||||
}
|
||||
|
||||
m_flashSize = cmdGetFlashSize.getResponseValues()->at(1);
|
||||
}
|
||||
|
||||
Updater::~Updater()
|
||||
{
|
||||
}
|
||||
|
||||
// See Updater.h for documentation of this method.
|
||||
status_t Updater::flashFirmware(const char *filename, uint32_t base_address)
|
||||
{
|
||||
m_base_address = base_address;
|
||||
// Create the SourceFile
|
||||
m_sourceFile = SourceFile::openFile(filename);
|
||||
|
||||
// Initialize the Operation structure.
|
||||
m_operation.tasks.push_back(updater_task_t(kUpdaterTask_Erasing, m_sourceFile->getSize()));
|
||||
m_operation.tasks.push_back(updater_task_t(kUpdaterTask_Flashing, m_sourceFile->getSize()));
|
||||
m_operation.current_task = 0;
|
||||
|
||||
if (m_sourceFile->getFileType() == SourceFile::source_file_t::kSBSourceFile &&
|
||||
isCommandSupported(kCommand_ReceiveSbFile))
|
||||
{
|
||||
return flashFromSBFile(filename);
|
||||
}
|
||||
else if (m_sourceFile->getFileType() == SourceFile::source_file_t::kELFSourceFile)
|
||||
{
|
||||
throw std::runtime_error("ELF files are not yet supported.");
|
||||
}
|
||||
else
|
||||
{
|
||||
return flashFromSourceFile();
|
||||
}
|
||||
}
|
||||
|
||||
// See Updater.h for documentation of this method.
|
||||
void Updater::eraseAllUnsecure()
|
||||
{
|
||||
if (!isCommandSupported(kCommand_FlashEraseAllUnsecure))
|
||||
{
|
||||
throw std::runtime_error("FlashEraseAllUnsecure isn't supported!");
|
||||
}
|
||||
|
||||
FlashEraseAllUnsecure cmd;
|
||||
Log::info("inject command '%s'\n", cmd.getName().c_str());
|
||||
inject(cmd);
|
||||
|
||||
uint32_t fw_status = cmd.getResponseValues()->at(0);
|
||||
std::string fw_msg = cmd.getStatusMessage(fw_status);
|
||||
|
||||
// Check the command status
|
||||
if (fw_status != kStatus_Success)
|
||||
{
|
||||
throw std::runtime_error(fw_msg);
|
||||
}
|
||||
}
|
||||
|
||||
// See Updater.h for documentation of this method.
|
||||
void Updater::unlock(string backdoor_key)
|
||||
{
|
||||
if (!isCommandSupported(kCommand_FlashSecurityDisable))
|
||||
{
|
||||
throw std::runtime_error("FlashSecurityDisable isn't supported!");
|
||||
}
|
||||
if (backdoor_key.length() != 16)
|
||||
{
|
||||
throw std::runtime_error("Illegal BackdoorKey");
|
||||
}
|
||||
|
||||
FlashSecurityDisable cmd(strtoul(backdoor_key.substr(8, 8).c_str(), NULL, 16),
|
||||
strtoul(backdoor_key.substr(0, 8).c_str(), NULL, 16));
|
||||
Log::info("inject command '%s'\n", cmd.getName().c_str());
|
||||
inject(cmd);
|
||||
|
||||
uint32_t fw_status = cmd.getResponseValues()->at(0);
|
||||
std::string fw_msg = cmd.getStatusMessage(fw_status);
|
||||
|
||||
// Check the command status
|
||||
if (fw_status != kStatus_Success)
|
||||
{
|
||||
throw std::runtime_error(fw_msg);
|
||||
}
|
||||
}
|
||||
|
||||
// See Updater.h for documentation of this method.
|
||||
bool Updater::isCommandSupported(const cmd_t &command)
|
||||
{
|
||||
// Inject the get-property(available-commands) command.
|
||||
GetProperty cmd(kProperty_AvailableCommands);
|
||||
Log::info("inject command '%s'\n", cmd.getName().c_str());
|
||||
inject(cmd);
|
||||
|
||||
uint32_t fw_status = cmd.getResponseValues()->at(0);
|
||||
uint32_t fw_response = cmd.getResponseValues()->at(1);
|
||||
std::string fw_msg = cmd.getStatusMessage(fw_status);
|
||||
|
||||
// Check the command status
|
||||
if (fw_status != kStatus_Success)
|
||||
{
|
||||
throw std::runtime_error(fw_msg);
|
||||
}
|
||||
|
||||
// See if the command is supported.
|
||||
return ((fw_response & command.mask) == command.mask);
|
||||
}
|
||||
|
||||
uint32_vector_t Updater::getProperty(property_t tag)
|
||||
{
|
||||
// Inject the get-property(tag) command.
|
||||
GetProperty cmd(tag);
|
||||
Log::info("inject command '%s'\n", cmd.getName().c_str());
|
||||
inject(cmd);
|
||||
|
||||
uint32_t fw_status = cmd.getResponseValues()->at(0);
|
||||
std::string fw_msg = cmd.getStatusMessage(fw_status);
|
||||
|
||||
// Check the command status
|
||||
if (fw_status != kStatus_Success)
|
||||
{
|
||||
throw std::runtime_error(fw_msg);
|
||||
}
|
||||
|
||||
return *cmd.getResponseValues();
|
||||
}
|
||||
// See Updater.h for documentation of this method.
|
||||
void Updater::eraseFlashRegion(uint32_t start, uint32_t length)
|
||||
{
|
||||
// Align the length to a sector boundary.
|
||||
uint32_t alignedLength = (-(-static_cast<int>(length) & -(static_cast<int>(m_sector_size))));
|
||||
|
||||
// Inject the flash-erase-region(start, length) command.
|
||||
FlashEraseRegion cmd(start, alignedLength);
|
||||
Log::info("inject command '%s'\n", cmd.getName().c_str());
|
||||
inject(cmd);
|
||||
|
||||
uint32_t fw_status = cmd.getResponseValues()->at(0);
|
||||
std::string fw_msg = cmd.getStatusMessage(fw_status);
|
||||
|
||||
// Check the command status
|
||||
if (fw_status != kStatus_Success)
|
||||
{
|
||||
throw std::runtime_error(fw_msg);
|
||||
}
|
||||
}
|
||||
|
||||
// See Updater.h for documentation of this method.
|
||||
void Updater::eraseFlashAll(uint32_t memoryId)
|
||||
{
|
||||
// Inject the flash-erase-all command.
|
||||
FlashEraseAll cmd(memoryId);
|
||||
Log::info("inject command '%s'\n", cmd.getName().c_str());
|
||||
inject(cmd);
|
||||
|
||||
uint32_t fw_status = cmd.getResponseValues()->at(0);
|
||||
std::string fw_msg = cmd.getStatusMessage(fw_status);
|
||||
|
||||
// Check the command status
|
||||
if (fw_status != kStatus_Success)
|
||||
{
|
||||
throw std::runtime_error(fw_msg);
|
||||
}
|
||||
}
|
||||
|
||||
// See Updater.h for documentation of this method.
|
||||
void Updater::programOnce(uint32_t index, uint32_t byteCount, string data)
|
||||
{
|
||||
if (!isCommandSupported(kCommand_FlashProgramOnce))
|
||||
{
|
||||
throw std::runtime_error("FlashProgramOnce isn't supported!");
|
||||
}
|
||||
if ((byteCount != 4) && (byteCount != 8))
|
||||
{
|
||||
throw std::runtime_error("Illegal byteCount! Must be 4 or 8");
|
||||
}
|
||||
if ((data.length() != 8) && (data.length() != 16))
|
||||
{
|
||||
throw std::runtime_error("Illegal data length. Must hex digits with no leading 0x");
|
||||
}
|
||||
|
||||
FlashProgramOnce cmd(index, byteCount, strtoul(data.substr(0, 8).c_str(), NULL, 16),
|
||||
strtoul(data.substr(8, 8).c_str(), NULL, 16));
|
||||
Log::info("inject command '%s'\n", cmd.getName().c_str());
|
||||
inject(cmd);
|
||||
|
||||
uint32_t fw_status = cmd.getResponseValues()->at(0);
|
||||
std::string fw_msg = cmd.getStatusMessage(fw_status);
|
||||
|
||||
// Check the command status
|
||||
if (fw_status != kStatus_Success)
|
||||
{
|
||||
throw std::runtime_error(fw_msg);
|
||||
}
|
||||
}
|
||||
|
||||
// See Updater.h for documentation of this method.
|
||||
void Updater::writeMemory(DataSource::Segment *segment)
|
||||
{
|
||||
// Inject the write-memory(segment) command.
|
||||
WriteMemory cmd(segment);
|
||||
cmd.registerProgress(&m_progress);
|
||||
Log::info("inject command '%s'\n", cmd.getName().c_str());
|
||||
inject(cmd);
|
||||
|
||||
uint32_t fw_status = cmd.getResponseValues()->at(0);
|
||||
std::string fw_msg = cmd.getStatusMessage(fw_status);
|
||||
|
||||
// Check the command status
|
||||
if (fw_status != kStatus_Success)
|
||||
{
|
||||
throw std::runtime_error(fw_msg);
|
||||
}
|
||||
}
|
||||
|
||||
// See Updater.h for documentation of this method.
|
||||
void Updater::writeMemory(uint32_t address, const uchar_vector_t &data)
|
||||
{
|
||||
// Inject the write-memory(segment) command.
|
||||
WriteMemory cmd(address, data);
|
||||
Log::info("inject command '%s'\n", cmd.getName().c_str());
|
||||
inject(cmd);
|
||||
|
||||
uint32_t fw_status = cmd.getResponseValues()->at(0);
|
||||
std::string fw_msg = cmd.getStatusMessage(fw_status);
|
||||
|
||||
// Check the command status
|
||||
if (fw_status != kStatus_Success)
|
||||
{
|
||||
throw std::runtime_error(fw_msg);
|
||||
}
|
||||
}
|
||||
|
||||
// See Updater.h for documentation of this method.
|
||||
status_t Updater::flashFromSourceFile()
|
||||
{
|
||||
m_sourceFile->open();
|
||||
|
||||
DataSource *dataSource = m_sourceFile->createDataSource();
|
||||
|
||||
m_progress.m_segmentCount = dataSource->getSegmentCount();
|
||||
|
||||
for (uint32_t index = 0; index < dataSource->getSegmentCount(); ++index)
|
||||
{
|
||||
DataSource::Segment *segment = dataSource->getSegmentAt(index);
|
||||
|
||||
if (segment->hasNaturalLocation())
|
||||
{
|
||||
dataSource->setTarget(new NaturalDataTarget());
|
||||
}
|
||||
else
|
||||
{
|
||||
dataSource->setTarget(new ConstantDataTarget(m_base_address));
|
||||
}
|
||||
|
||||
// If base address is in flash, do erase operation to erase the necessary flash.
|
||||
if ((segment->getBaseAddress() >= m_flashStart) && (segment->getBaseAddress() < m_flashStart + m_flashSize))
|
||||
{
|
||||
m_operation.current_task = 0;
|
||||
m_operation.tasks[m_operation.current_task].current += segment->getLength();
|
||||
if (m_progressCallback)
|
||||
{
|
||||
m_progressCallback(&m_operation);
|
||||
}
|
||||
|
||||
eraseFlashRegion(segment->getBaseAddress(), segment->getLength());
|
||||
}
|
||||
}
|
||||
for (uint32_t index = 0; index < dataSource->getSegmentCount(); ++index)
|
||||
{
|
||||
DataSource::Segment *segment = dataSource->getSegmentAt(index);
|
||||
|
||||
// Write the file to the base address.
|
||||
m_operation.current_task = 1;
|
||||
m_operation.tasks[m_operation.current_task].current += segment->getLength();
|
||||
if (m_progressCallback)
|
||||
{
|
||||
m_progressCallback(&m_operation);
|
||||
}
|
||||
m_progress.m_segmentIndex = index + 1;
|
||||
writeMemory(segment);
|
||||
}
|
||||
|
||||
delete dataSource;
|
||||
m_sourceFile->close();
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
// See Updater.h for documentation of this method.
|
||||
status_t Updater::flashFromSBFile(const char *filename)
|
||||
{
|
||||
// Inject the receive-sb-file command.
|
||||
m_operation.current_task = 1;
|
||||
if (m_progressCallback)
|
||||
{
|
||||
m_progressCallback(&m_operation);
|
||||
}
|
||||
ReceiveSbFile cmd(filename);
|
||||
cmd.registerProgress(&m_progress);
|
||||
Log::info("inject command '%s'\n", cmd.getName().c_str());
|
||||
inject(cmd);
|
||||
|
||||
// print command response values using the Logger.
|
||||
cmd.logResponses();
|
||||
|
||||
uint32_t fw_status = cmd.getResponseValues()->at(0);
|
||||
std::string fw_msg = cmd.getStatusMessage(fw_status);
|
||||
|
||||
// Check the command status
|
||||
if ((fw_status != kStatus_Success) && (fw_status != kStatus_AbortDataPhase))
|
||||
{
|
||||
throw std::runtime_error(fw_msg);
|
||||
}
|
||||
return fw_status;
|
||||
}
|
||||
239
src/blfwk/src/UsbHidPacketizer.cpp
Normal file
239
src/blfwk/src/UsbHidPacketizer.cpp
Normal file
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "blfwk/UsbHidPacketizer.h"
|
||||
#include "blfwk/Logging.h"
|
||||
#include "blfwk/smart_ptr.h"
|
||||
#include "blfwk/utils.h"
|
||||
#include "bootloader/bootloader.h"
|
||||
#ifdef LINUX
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
using namespace blfwk;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Code
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// See usb_hid_packetizer.h for documentation of this method.
|
||||
UsbHidPacketizer::UsbHidPacketizer(UsbHidPeripheral *peripheral, uint32_t packetTimeoutMs)
|
||||
: Packetizer(peripheral, packetTimeoutMs)
|
||||
{
|
||||
m_continuousReadCount = 0;
|
||||
}
|
||||
|
||||
// See usb_hid_packetizer.h for documentation of this method.
|
||||
UsbHidPacketizer::~UsbHidPacketizer()
|
||||
{
|
||||
delete m_peripheral;
|
||||
}
|
||||
|
||||
// See usb_hid_packetizer.h for documentation of this method.
|
||||
status_t UsbHidPacketizer::writePacket(const uint8_t *packet, uint32_t byteCount, packet_type_t packetType)
|
||||
{
|
||||
assert(m_peripheral);
|
||||
if (byteCount)
|
||||
{
|
||||
assert(packet);
|
||||
}
|
||||
|
||||
// Determine report ID based on packet type.
|
||||
uint8_t reportID;
|
||||
switch (packetType)
|
||||
{
|
||||
case kPacketType_Command:
|
||||
reportID = kBootloaderReportID_CommandOut;
|
||||
break;
|
||||
case kPacketType_Data:
|
||||
reportID = kBootloaderReportID_DataOut;
|
||||
break;
|
||||
default:
|
||||
Log::error("usbhid: unsupported packet type %d\n", (int)packetType);
|
||||
return kStatus_Fail;
|
||||
};
|
||||
|
||||
if (m_isAbortEnabled && (reportID == kBootloaderReportID_DataOut))
|
||||
{
|
||||
// Check if the target has sent an abort report.
|
||||
if (pollForAbortPacket())
|
||||
{
|
||||
Log::info("usb hid detected receiver data abort\n");
|
||||
return kStatus_AbortDataPhase;
|
||||
}
|
||||
}
|
||||
|
||||
// Construct report contents.
|
||||
memset(&m_report, 0, sizeof(m_report));
|
||||
m_report.header.reportID = reportID;
|
||||
m_report.header.packetLengthLsb = byteCount & 0xff;
|
||||
m_report.header.packetLengthMsb = (byteCount >> 8) & 0xff;
|
||||
|
||||
// If not a zero-length report, copy in packet data.
|
||||
if (byteCount)
|
||||
{
|
||||
memcpy(m_report.packet, packet, byteCount);
|
||||
}
|
||||
|
||||
m_continuousReadCount = 0;
|
||||
|
||||
return getPeripheral()->write((uint8_t *)&m_report, sizeof(m_report), m_packetTimeoutMs);
|
||||
}
|
||||
|
||||
// See usb_hid_packetizer.h for documentation of this method.
|
||||
status_t UsbHidPacketizer::readPacket(uint8_t **packet, uint32_t *packetLength, packet_type_t packetType)
|
||||
{
|
||||
assert(m_peripheral);
|
||||
assert(packet);
|
||||
assert(packetLength);
|
||||
*packet = NULL;
|
||||
*packetLength = 0;
|
||||
|
||||
// Determine report ID based on packet type.
|
||||
uint8_t reportID;
|
||||
switch (packetType)
|
||||
{
|
||||
case kPacketType_Command:
|
||||
reportID = kBootloaderReportID_CommandIn;
|
||||
break;
|
||||
case kPacketType_Data:
|
||||
reportID = kBootloaderReportID_DataIn;
|
||||
break;
|
||||
default:
|
||||
Log::error("usbhid: unsupported packet type %d\n", (int)packetType);
|
||||
return kStatus_Fail;
|
||||
};
|
||||
|
||||
// Read report.
|
||||
uint32_t actualBytes = 0;
|
||||
uint16_t lengthInPacket = 0;
|
||||
uint32_t retryCnt = 0;
|
||||
do
|
||||
{
|
||||
status_t retVal =
|
||||
m_peripheral->read((unsigned char *)&m_report, sizeof(m_report), &actualBytes, m_packetTimeoutMs);
|
||||
if (retVal != kStatus_Success)
|
||||
{
|
||||
return retVal;
|
||||
}
|
||||
|
||||
if (!retryCnt)
|
||||
{
|
||||
m_continuousReadCount++;
|
||||
}
|
||||
|
||||
// Check the report ID.
|
||||
if (m_report.header.reportID != reportID)
|
||||
{
|
||||
Log::error("usbhid: received unexpected report=%x\n", m_report.header.reportID);
|
||||
return kStatus_Fail;
|
||||
}
|
||||
|
||||
// Extract the packet length encoded as bytes 1 and 2 of the report. The packet length
|
||||
// is transferred in little endian byte order.
|
||||
lengthInPacket = m_report.header.packetLengthLsb | (m_report.header.packetLengthMsb << 8);
|
||||
|
||||
// See if we received the data abort packet,
|
||||
// if the data abort packet was received, try to read pending generic response packet.
|
||||
if (lengthInPacket == 0)
|
||||
{
|
||||
Log::info("usbhid: received data phase abort\n");
|
||||
|
||||
// If continuous read occurs, that means this is a read-memory command,
|
||||
// host tool shouldn't wait for pending packet because there are no pending packets.
|
||||
if (m_continuousReadCount >= kContinuousReadMargin)
|
||||
{
|
||||
break;
|
||||
}
|
||||
retryCnt++;
|
||||
}
|
||||
} while (actualBytes && !lengthInPacket && retryCnt < kPollPacketMaxRetryCnt);
|
||||
|
||||
// Make sure we got all of the packet. Target will send the maximum
|
||||
// report size, so there may be extra trailing bytes.
|
||||
if ((actualBytes - sizeof(m_report.header)) < lengthInPacket)
|
||||
{
|
||||
Log::error("usbhid: received only %d bytes of packet with length %d\n", actualBytes - sizeof(m_report.header),
|
||||
lengthInPacket);
|
||||
return kStatus_Fail;
|
||||
}
|
||||
|
||||
// Return results.
|
||||
*packet = m_report.packet;
|
||||
*packetLength = lengthInPacket;
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
// See usb_hid_packetizer.h for documentation of this method.
|
||||
void UsbHidPacketizer::flushInput()
|
||||
{
|
||||
uint32_t actualBytes = 0;
|
||||
do
|
||||
{
|
||||
m_peripheral->read((unsigned char *)&m_report, sizeof(m_report), &actualBytes, m_packetTimeoutMs);
|
||||
} while (actualBytes > 0);
|
||||
}
|
||||
|
||||
// See usb_hid_packetizer.h for documentation of this method.
|
||||
void UsbHidPacketizer::abortPacket()
|
||||
{
|
||||
// Abort data phase by writing a zero-length command packet.
|
||||
writePacket(NULL, 0, kPacketType_Command);
|
||||
flushInput();
|
||||
}
|
||||
|
||||
bool UsbHidPacketizer::pollForAbortPacket()
|
||||
{
|
||||
// Just check to see if there is data to be read from hid device.
|
||||
// No reason to wait (milliseconds = 0), because we aren't really expecting anything.
|
||||
uint32_t actualBytes = 0;
|
||||
m_peripheral->read((unsigned char *)&m_abortReport, sizeof(m_abortReport), &actualBytes, kPollAbortTimeoutMs);
|
||||
if (actualBytes == 0)
|
||||
{
|
||||
// No abort packet
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Got an abort packet
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// See usb_hid_packetizer.h for documentation of this method.
|
||||
uint32_t UsbHidPacketizer::getMaxPacketSize()
|
||||
{
|
||||
return kMinPacketBufferSize;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
187
src/blfwk/src/UsbHidPeripheral.cpp
Normal file
187
src/blfwk/src/UsbHidPeripheral.cpp
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "blfwk/UsbHidPeripheral.h"
|
||||
#include "blfwk/format_string.h"
|
||||
#include "blfwk/smart_ptr.h"
|
||||
#include "blfwk/Logging.h"
|
||||
|
||||
#include "bootloader_hid_report_ids.h"
|
||||
|
||||
using namespace blfwk;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Code
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// See UsbHidPeripheral.h for documentation of this method.
|
||||
UsbHidPeripheral::UsbHidPeripheral()
|
||||
: m_vendor_id(kDefault_Vid)
|
||||
, m_product_id(kDefault_Pid)
|
||||
{
|
||||
if (!init())
|
||||
{
|
||||
throw std::runtime_error(
|
||||
format_string("Error: UsbHidPeripheral() cannot open USB HID device (vid=0x%04x, pid=0x%04x).", m_vendor_id,
|
||||
m_product_id));
|
||||
}
|
||||
}
|
||||
|
||||
// See UsbHidPeripheral.h for documentation of this method.
|
||||
UsbHidPeripheral::UsbHidPeripheral(unsigned short vendor_id, unsigned short product_id, const char *serial_number)
|
||||
: m_vendor_id(vendor_id)
|
||||
, m_product_id(product_id)
|
||||
{
|
||||
// Convert to a wchar_t*
|
||||
std::string s(serial_number);
|
||||
m_serial_number.assign(s.begin(), s.end());
|
||||
|
||||
if (!init())
|
||||
{
|
||||
throw std::runtime_error(
|
||||
format_string("Error: UsbHidPeripheral() cannot open USB HID device (vid=0x%04x, pid=0x%04x, sn=%s).",
|
||||
vendor_id, product_id, s.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
// See UsbHidPeripheral.h for documentation of this method.
|
||||
bool UsbHidPeripheral::init()
|
||||
{
|
||||
// Open the device using the VID, PID,
|
||||
// and optionally the Serial number.
|
||||
m_device = hid_open(m_vendor_id, m_product_id, m_serial_number.c_str());
|
||||
if (!m_device)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// See UsbHidPeripheral.h for documentation of this method.
|
||||
UsbHidPeripheral::~UsbHidPeripheral()
|
||||
{
|
||||
if (m_device)
|
||||
{
|
||||
hid_close(m_device);
|
||||
/* Free static HIDAPI objects. */
|
||||
hid_exit();
|
||||
}
|
||||
}
|
||||
|
||||
// See UsbHidPeripheral.h for documentation of this method.
|
||||
status_t UsbHidPeripheral::read(uint8_t *buffer, uint32_t requestedBytes, uint32_t *actualBytes, uint32_t timeout)
|
||||
{
|
||||
assert(buffer);
|
||||
|
||||
// Read the requested number of bytes.
|
||||
int count = hid_read_timeout(m_device, buffer, requestedBytes, timeout);
|
||||
if (actualBytes)
|
||||
{
|
||||
*actualBytes = count;
|
||||
}
|
||||
|
||||
if (Log::getLogger()->getFilterLevel() == Logger::kDebug2)
|
||||
{
|
||||
// Log bytes read in hex
|
||||
Log::debug2("<");
|
||||
for (int i = 0; i < (int)count; i++)
|
||||
{
|
||||
Log::debug2("%02x", buffer[i]);
|
||||
if (i != (count - 1))
|
||||
{
|
||||
Log::debug2(" ");
|
||||
}
|
||||
}
|
||||
Log::debug2(">\n");
|
||||
}
|
||||
|
||||
// Bail if we got an error (-1), or if the number of bytes read was less than
|
||||
// the report header.
|
||||
if (count < (int)sizeof(bl_hid_header_t))
|
||||
{
|
||||
if (count == -1)
|
||||
{
|
||||
return kStatus_Fail;
|
||||
}
|
||||
else
|
||||
{
|
||||
return kStatus_Timeout;
|
||||
}
|
||||
}
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
// See UsbHidPeripheral.h for documentation of this method.
|
||||
status_t UsbHidPeripheral::write(const uint8_t *buffer, uint32_t byteCount, uint32_t timeoutMS)
|
||||
{
|
||||
assert(buffer);
|
||||
|
||||
if (Log::getLogger()->getFilterLevel() == Logger::kDebug2)
|
||||
{
|
||||
// Log bytes written in hex
|
||||
Log::debug2("[");
|
||||
for (uint32_t i = 0; i < byteCount; i++)
|
||||
{
|
||||
Log::debug2("%02x", buffer[i]);
|
||||
if (i != (byteCount - 1))
|
||||
{
|
||||
Log::debug2(" ");
|
||||
}
|
||||
}
|
||||
Log::debug2("]\n");
|
||||
}
|
||||
|
||||
#ifdef LINUX
|
||||
int count = hid_write(m_device, buffer, byteCount);
|
||||
#else
|
||||
int count = hid_write_timeout(m_device, buffer, byteCount, timeoutMS);
|
||||
#endif
|
||||
if (count < 0)
|
||||
{
|
||||
const wchar_t *errorMessage = hid_error(m_device);
|
||||
if (errorMessage)
|
||||
{
|
||||
int len = wcslen(errorMessage);
|
||||
char *msg = new char[len + 1];
|
||||
wcstombs(msg, errorMessage, len + 1);
|
||||
Log::error("%s", msg);
|
||||
delete[] msg;
|
||||
}
|
||||
return kStatus_Fail;
|
||||
}
|
||||
|
||||
return kStatus_Success;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EOF
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
65
src/blfwk/src/Value.cpp
Normal file
65
src/blfwk/src/Value.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "blfwk/Value.h"
|
||||
|
||||
using namespace blfwk;
|
||||
|
||||
//! Returns a varying size depending on the word size attribute.
|
||||
//!
|
||||
size_t SizedIntegerValue::getSize() const
|
||||
{
|
||||
switch (m_size)
|
||||
{
|
||||
case kWordSize:
|
||||
return sizeof(uint32_t);
|
||||
case kHalfWordSize:
|
||||
return sizeof(uint16_t);
|
||||
case kByteSize:
|
||||
return sizeof(uint8_t);
|
||||
}
|
||||
return kWordSize;
|
||||
}
|
||||
|
||||
//! The resulting mask can be used to truncate the integer value to be
|
||||
//! certain it doesn't extend beyond the associated word size.
|
||||
uint32_t SizedIntegerValue::getWordSizeMask() const
|
||||
{
|
||||
switch (m_size)
|
||||
{
|
||||
case kWordSize:
|
||||
return 0xffffffff;
|
||||
case kHalfWordSize:
|
||||
return 0x0000ffff;
|
||||
case kByteSize:
|
||||
return 0x000000ff;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
101
src/blfwk/src/format_string.cpp
Normal file
101
src/blfwk/src/format_string.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2013-14, Freescale Semiconductor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* o Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* o Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* o Neither the name of Freescale Semiconductor, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "blfwk/format_string.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdexcept>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
//! Size of the temporary buffer to hold the formatted output string.
|
||||
#define WIN32_FMT_BUF_LEN (512)
|
||||
|
||||
/*!
|
||||
* \brief Simple template class to free a pointer.
|
||||
*/
|
||||
template <typename T>
|
||||
class free_ptr
|
||||
{
|
||||
public:
|
||||
//! \brief Constructor.
|
||||
free_ptr(T ptr)
|
||||
: m_p(ptr)
|
||||
{
|
||||
}
|
||||
|
||||
//! \brief Destructor.
|
||||
~free_ptr()
|
||||
{
|
||||
if (m_p)
|
||||
{
|
||||
free(m_p);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
T m_p; //!< The value to free.
|
||||
};
|
||||
|
||||
//! The purpose of this function to provide a convenient way of generating formatted
|
||||
//! STL strings inline. This is especially useful when throwing exceptions that take
|
||||
//! a std::string for a message. The length of the formatted output string is limited
|
||||
//! only by memory. Memory temporarily allocated for the output string is disposed of
|
||||
//! before returning.
|
||||
//!
|
||||
//! Example usage:
|
||||
//! \code
|
||||
//! throw std::runtime_error(format_string("error on line %d", line));
|
||||
//! \endcode
|
||||
//!
|
||||
//! \param fmt Format string using printf-style format markers.
|
||||
//! \return An STL string object of the formatted output.
|
||||
std::string format_string(const char *fmt, ...)
|
||||
{
|
||||
char *buf = 0;
|
||||
va_list vargs;
|
||||
va_start(vargs, fmt);
|
||||
int result = -1;
|
||||
#if WIN32
|
||||
buf = (char *)malloc(WIN32_FMT_BUF_LEN);
|
||||
if (buf)
|
||||
{
|
||||
result = _vsnprintf(buf, WIN32_FMT_BUF_LEN, fmt, vargs);
|
||||
}
|
||||
#else // WIN32
|
||||
result = vasprintf(&buf, fmt, vargs);
|
||||
#endif // WIN32
|
||||
va_end(vargs);
|
||||
if (result != -1 && buf)
|
||||
{
|
||||
free_ptr<char *> freebuf(buf);
|
||||
return std::string(buf);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
811
src/blfwk/src/hid-linux.c
Normal file
811
src/blfwk/src/hid-linux.c
Normal file
File diff suppressed because it is too large
Load Diff
1146
src/blfwk/src/hid-mac.c
Normal file
1146
src/blfwk/src/hid-mac.c
Normal file
File diff suppressed because it is too large
Load Diff
977
src/blfwk/src/hid-windows.c
Normal file
977
src/blfwk/src/hid-windows.c
Normal file
File diff suppressed because it is too large
Load Diff
3785
src/blfwk/src/jsoncpp.cpp
Normal file
3785
src/blfwk/src/jsoncpp.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user