Initial commit from NXP 2.6.7 sources
NXP is constantly breaking links, but it was found at: https://www.nxp.com/design/software/development-software/mcuxpresso-software-and-tools-/mcu-bootloader-for-nxp-microcontrollers:MCUBOOT
This commit is contained in:
commit
6648373d8e
55
SW-Content-Register.txt
Normal file
55
SW-Content-Register.txt
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
Release Name: blhost
|
||||||
|
Release Version: 2.6.7
|
||||||
|
Package License: LA_OPT_NXP_Software_License.htm - Production Use, Section 2.3 applies
|
||||||
|
|
||||||
|
Host tools Source Description: Source code for blhost
|
||||||
|
Author: Freescale
|
||||||
|
License: Open Source - BSD-3-Clause
|
||||||
|
Format: source code
|
||||||
|
Location: src
|
||||||
|
|
||||||
|
Host tools - Serial support Description: Windows Serial peripheral support
|
||||||
|
Author: Bus Pirate Project
|
||||||
|
License: Open Source - CC0-1.0 (Creative Commons Zero)
|
||||||
|
URL: http://code.google.com/p/the-bus-pirate/
|
||||||
|
Format: source code
|
||||||
|
Location:
|
||||||
|
src/blfwk/serial.h,
|
||||||
|
src/blfwk/src/serial.c
|
||||||
|
|
||||||
|
Host tools - USB HID Description: Windows USB HID support
|
||||||
|
support Author: HIDAPI
|
||||||
|
License: Open Source - BSD-3-Clause
|
||||||
|
URL: http://github.com/signal11/hidapi
|
||||||
|
Format: source code
|
||||||
|
Location:
|
||||||
|
src/blfwk/hidapi.h,
|
||||||
|
src/blfwk/src/hid-*.c
|
||||||
|
|
||||||
|
Host tools - JSON support Description: Windows JSON support
|
||||||
|
Author: JSONCPP
|
||||||
|
License: Open Source - MIT
|
||||||
|
Format: source code
|
||||||
|
Location:
|
||||||
|
src/blfwk/json.h,
|
||||||
|
src/jsoncpp.cpp
|
||||||
|
|
||||||
|
Host tools - options Description: Command line parsing utility
|
||||||
|
support Author: bradapp@enteract.com
|
||||||
|
License: Open Source - MIT
|
||||||
|
URL: http://www.bradapp.com
|
||||||
|
Format: source code
|
||||||
|
Location:
|
||||||
|
src/blfwk/options.h,
|
||||||
|
src/options.cpp
|
||||||
|
|
||||||
|
Host tools - blfwk.lib Description: C++ interface to the Vincent Rijmen's
|
||||||
|
Rijndael block cipher
|
||||||
|
Author: Szymon Stefanek (stefanek@tin.it)
|
||||||
|
License: Public Domain
|
||||||
|
URL:
|
||||||
|
http://www.pragmaware.net/software/rijndael/index.php
|
||||||
|
Format: source code
|
||||||
|
Location:
|
||||||
|
src/blfwk/rijndael.h,
|
||||||
|
src/blfwk/src/rijndael.cpp
|
BIN
bin/linux/amd64/blhost
Executable file
BIN
bin/linux/amd64/blhost
Executable file
Binary file not shown.
BIN
bin/mac/blhost
Normal file
BIN
bin/mac/blhost
Normal file
Binary file not shown.
BIN
bin/win/blhost.exe
Normal file
BIN
bin/win/blhost.exe
Normal file
Binary file not shown.
BIN
blhost Release Notes.pdf
Normal file
BIN
blhost Release Notes.pdf
Normal file
Binary file not shown.
BIN
docs/blhost User's Guide.pdf
Normal file
BIN
docs/blhost User's Guide.pdf
Normal file
Binary file not shown.
126
mk/common.mk
Normal file
126
mk/common.mk
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# Copyright (c) 2012 Freescale Semiconductor, Inc.
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# Utility
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Kludge to create a variable equal to a single space.
|
||||||
|
empty :=
|
||||||
|
space := $(empty) $(empty)
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# OS
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Get the OS name. Known values are "Linux", "CYGWIN_NT-5.1", and "Darwin".
|
||||||
|
os_name := $(shell uname -s)
|
||||||
|
|
||||||
|
# Set to 1 if running on cygwin.
|
||||||
|
is_cygwin := $(and $(findstring CYGWIN,$(os_name)),1)
|
||||||
|
|
||||||
|
# Set to 1 if running on cygwin.
|
||||||
|
is_mingw := $(and $(findstring MINGW,$(os_name)),1)
|
||||||
|
|
||||||
|
# Set to 1 if running on redhat.
|
||||||
|
is_redhat := $(shell if [ -f /etc/redhat-release ]; then echo 1 ; fi)
|
||||||
|
|
||||||
|
# Disable parallel builds for cygwin since they hang.
|
||||||
|
ifeq "$(is_cygwin)" "1"
|
||||||
|
.NOTPARALLEL:
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq "$(is_mingw)" "1"
|
||||||
|
.NOTPARALLEL:
|
||||||
|
endif
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# Logging options
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Enable color output by default.
|
||||||
|
BUILD_SDK_COLOR ?= 1
|
||||||
|
|
||||||
|
# MAKE
|
||||||
|
MAKE := make
|
||||||
|
ifeq "$(is_cygwin)" "1"
|
||||||
|
MAKE := mingw32-make
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq "$(is_mingw)" "1"
|
||||||
|
MAKE := mingw32-make
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Normally, commands in recipes are prefixed with '@' so the command itself
|
||||||
|
# is not echoed by make. But if VERBOSE is defined (set to anything non-empty),
|
||||||
|
# then the '@' is removed from recipes. The 'at' variable is used to control
|
||||||
|
# this. Similarly, 'silent_make' is used to pass the -s option to child make
|
||||||
|
# invocations when not in VERBOSE mode.
|
||||||
|
ifeq "$(VERBOSE)" "1"
|
||||||
|
at :=
|
||||||
|
silent_make :=
|
||||||
|
else
|
||||||
|
at := @
|
||||||
|
silent_make := -s
|
||||||
|
endif
|
||||||
|
|
||||||
|
# These colors must be printed with the printf command. echo won't handle the
|
||||||
|
# escape sequences.
|
||||||
|
color_default = \033[00m
|
||||||
|
color_bold = \033[01m
|
||||||
|
color_red = \033[31m
|
||||||
|
color_green = \033[32m
|
||||||
|
color_yellow = \033[33m
|
||||||
|
color_blue = \033[34m
|
||||||
|
color_magenta = \033[35m
|
||||||
|
color_cyan = \033[36m
|
||||||
|
color_orange = \033[38;5;172m
|
||||||
|
color_light_blue = \033[38;5;039m
|
||||||
|
color_gray = \033[38;5;008m
|
||||||
|
color_purple = \033[38;5;097m
|
||||||
|
|
||||||
|
ifeq "$(BUILD_SDK_COLOR)" "1"
|
||||||
|
color_build := $(color_light_blue)
|
||||||
|
color_c := $(color_green)
|
||||||
|
color_cxx := $(color_green)
|
||||||
|
color_cpp := $(color_orange)
|
||||||
|
color_asm := $(color_magenta)
|
||||||
|
color_ar := $(color_yellow)
|
||||||
|
color_link := $(color_purple)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Used in printmessage if the color args are not present.
|
||||||
|
color_ :=
|
||||||
|
|
||||||
|
# Use in recipes to print color messages if printing to a terminal. If
|
||||||
|
# BUILD_SDK_COLOR is not set to 1, this reverts to a simple uncolorized printf.
|
||||||
|
# A newline is added to the end of the printed message.
|
||||||
|
#
|
||||||
|
# Arguments:
|
||||||
|
# 1 - name of the color variable (see above), minus the "color_" prefix
|
||||||
|
# 2 - first colorized part of the message
|
||||||
|
# 3 - first uncolorized part of the message
|
||||||
|
# 4 - color name for second colorized message
|
||||||
|
# 5 - second colorized message
|
||||||
|
# 6 - second uncolorized part of the message
|
||||||
|
# 7 - uncolorized prefix on the whole line; this is last because it is expected to be used rarely
|
||||||
|
#
|
||||||
|
# All arguments are optional.
|
||||||
|
#
|
||||||
|
# Use like:
|
||||||
|
# $(call printmessage,cyan,Building, remainder of the message...)
|
||||||
|
ifeq "$(BUILD_SDK_COLOR)" "1"
|
||||||
|
define printmessage
|
||||||
|
if [ -t 1 ]; then printf "$(7)$(color_$(1))$(2)$(color_default)$(3)$(color_$(4))$(5)$(color_default)$(6)\n" ; \
|
||||||
|
else printf "$(7)$(2)$(3)$(5)$(6)\n" ; fi
|
||||||
|
endef
|
||||||
|
else
|
||||||
|
define printmessage
|
||||||
|
printf "$(7)$(2)$(3)$(5)$(6)\n" ; fi
|
||||||
|
endef
|
||||||
|
endif
|
||||||
|
|
149
src/blfwk/AESCounter.h
Normal file
149
src/blfwk/AESCounter.h
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* File: AESCounter.h
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
134
src/blfwk/AESKey.h
Normal file
134
src/blfwk/AESKey.h
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* File: AESKey.h
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
36
src/blfwk/BlfwkErrors.h
Normal file
36
src/blfwk/BlfwkErrors.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* File: BlfwkErrors.h
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
70
src/blfwk/Blob.h
Normal file
70
src/blfwk/Blob.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
117
src/blfwk/Bootloader.h
Normal file
117
src/blfwk/Bootloader.h
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _Bootloader_h_
|
||||||
|
#define _Bootloader_h_
|
||||||
|
|
||||||
|
#include "Command.h"
|
||||||
|
#include "Packetizer.h"
|
||||||
|
#include "Peripheral.h"
|
||||||
|
#include "Logging.h"
|
||||||
|
|
||||||
|
#include <string.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 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 The property tag
|
||||||
|
//!
|
||||||
|
//! \param memoryIdorIndex memoryId is required by GetProperty 25(External attribute)
|
||||||
|
//! Index is required by GetProperty 14/15(RAM start addr/RAM size)
|
||||||
|
//!
|
||||||
|
//! \return vector of the response values.
|
||||||
|
uint32_vector_t getProperty(property_t tag, uint32_t memoryIdorIndex = kMemoryInternal);
|
||||||
|
|
||||||
|
//! \brief Checks if 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 Execute the get-property(current-version) command.
|
||||||
|
standard_version_t getVersion();
|
||||||
|
|
||||||
|
//! \brief Execute the get-property(flash-security-state) command.
|
||||||
|
uint32_t getSecurityState();
|
||||||
|
|
||||||
|
//! \brief Execute the get-property(max-supported-packet-size) command.
|
||||||
|
uint32_t getDataPacketSize();
|
||||||
|
|
||||||
|
//! \brief Send a ping if applicable.
|
||||||
|
void ping(int retries, unsigned int delay, int comSpeed, int* actualComSpeed);
|
||||||
|
|
||||||
|
//! @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
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
304
src/blfwk/BusPal.h
Normal file
304
src/blfwk/BusPal.h
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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_SAI,
|
||||||
|
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 Define the SAI bus type
|
||||||
|
enum sai_protocol_t
|
||||||
|
{
|
||||||
|
kSaiProtocol_BusLeftJustified = 0, /*!< Uses left justified format.*/
|
||||||
|
kSaiProtocol_BusRightJustified = 1, /*!< Uses right justified format. */
|
||||||
|
kSaiProtocol_BusI2S = 2, /*!< Uses I2S format. */
|
||||||
|
kSaiProtocol_BusPCMA = 3, /*!< Uses I2S PCM A format.*/
|
||||||
|
kSaiProtocol_BusPCMB = 4 /*!< Uses I2S PCM B format. */
|
||||||
|
};
|
||||||
|
|
||||||
|
//! @brief Mono or stereo audio format
|
||||||
|
enum sai_mono_stereo_t
|
||||||
|
{
|
||||||
|
kSaiMonoStereo_Stereo = 0, /*!< Stereo sound. */
|
||||||
|
kSaiMonoStereo_MonoRight = 1, /*!< Only Right channel have sound. */
|
||||||
|
kSaiMonoStereo_MonoLeft = 2 /*!< Only left channel have sound. */
|
||||||
|
};
|
||||||
|
|
||||||
|
//! @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;
|
||||||
|
uint32_t saiSpeedHz;
|
||||||
|
sai_protocol_t saiProtocol;
|
||||||
|
sai_mono_stereo_t saiStereo;
|
||||||
|
uint8_t reserved0[2];
|
||||||
|
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;
|
||||||
|
saiSpeedHz = 8000;
|
||||||
|
saiProtocol = BusPal::kSaiProtocol_BusI2S;
|
||||||
|
saiStereo = BusPal::kSaiMonoStereo_Stereo;
|
||||||
|
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 Sai mode.
|
||||||
|
virtual bool enterSaiMode();
|
||||||
|
|
||||||
|
//! @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 Set SAI speed.
|
||||||
|
virtual bool setSaiSpeed(unsigned int speed);
|
||||||
|
|
||||||
|
//! @brief Sets the SAI configuration
|
||||||
|
virtual bool setSaiConfig(sai_protocol_t protocol, sai_mono_stereo_t stereo);
|
||||||
|
|
||||||
|
//! @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 write via Sai
|
||||||
|
virtual bool writeSai(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 read via Sai
|
||||||
|
virtual int readSai(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,
|
||||||
|
kBusPalModeSai
|
||||||
|
};
|
||||||
|
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;
|
||||||
|
unsigned int m_saiWriteByteCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace blfwk
|
||||||
|
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
#endif // _BusPal_h_
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// EOF
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
67
src/blfwk/BusPalPeripheral.h
Normal file
67
src/blfwk/BusPalPeripheral.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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);
|
||||||
|
|
||||||
|
virtual _host_peripheral_types get_type(void) { return kHostPeripheralType_BUSPAL_UART; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
BusPal *m_busPal; //!< Represents Bus Pal hardware.
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace blfwk
|
||||||
|
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
#endif // _BusPalPeripheral_h_
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// EOF
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
2135
src/blfwk/Command.h
Normal file
2135
src/blfwk/Command.h
Normal file
File diff suppressed because it is too large
Load Diff
40
src/blfwk/Crc.h
Normal file
40
src/blfwk/Crc.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2015 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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_
|
303
src/blfwk/DataSource.h
Normal file
303
src/blfwk/DataSource.h
Normal file
@ -0,0 +1,303 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
55
src/blfwk/DataSourceImager.h
Normal file
55
src/blfwk/DataSourceImager.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* File: DataSourceImager.h
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
132
src/blfwk/DataTarget.h
Normal file
132
src/blfwk/DataTarget.h
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
349
src/blfwk/ELF.h
Normal file
349
src/blfwk/ELF.h
Normal file
@ -0,0 +1,349 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
228
src/blfwk/ELFSourceFile.h
Normal file
228
src/blfwk/ELFSourceFile.h
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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)
|
||||||
|
, m_secinfoOption(kSecinfoDefault)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \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_
|
149
src/blfwk/EndianUtilities.h
Normal file
149
src/blfwk/EndianUtilities.h
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
68
src/blfwk/ExcludesListMatcher.h
Normal file
68
src/blfwk/ExcludesListMatcher.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* File: ExcludesListMatcher.h
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
70
src/blfwk/GHSSecInfo.h
Normal file
70
src/blfwk/GHSSecInfo.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
61
src/blfwk/GlobMatcher.h
Normal file
61
src/blfwk/GlobMatcher.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* File: GlobMatcher.h
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
23
src/blfwk/HexValues.h
Normal file
23
src/blfwk/HexValues.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* File: HexValues.h
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
100
src/blfwk/I2cPeripheral.h
Normal file
100
src/blfwk/I2cPeripheral.h
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 - 2022 NXP
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _i2c_peripheral_h_
|
||||||
|
#define _i2c_peripheral_h_
|
||||||
|
|
||||||
|
#include "Peripheral.h"
|
||||||
|
#include "blfwk/i2c.h"
|
||||||
|
#include "packet/command_packet.h"
|
||||||
|
|
||||||
|
//! @addtogroup i2c_peripheral
|
||||||
|
//! @{
|
||||||
|
|
||||||
|
namespace blfwk
|
||||||
|
{
|
||||||
|
/*!
|
||||||
|
* @brief Peripheral that talks to the target device over I2C port hardware.
|
||||||
|
*/
|
||||||
|
class I2cPeripheral : public Peripheral
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! @breif Constants.
|
||||||
|
enum _i2c_peripheral_constants
|
||||||
|
{
|
||||||
|
// The read() implementation for the I2cPeripheral does not use this the timeout parameter.
|
||||||
|
kI2cPeripheral_UnusedTimeout = 0,
|
||||||
|
// Serial timeout is set to this default during init().
|
||||||
|
kI2cPeripheral_DefaultReadTimeoutMs = 10,
|
||||||
|
kI2cPeripheral_DefaultSpeedKHz = 100,
|
||||||
|
kI2cPeripheral_DefaultAddress = 0x10
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
//! @brief Parameterized constructor that opens the serial port.
|
||||||
|
//!
|
||||||
|
//! Opens and configures the port. Throws exception if port configuration fails.
|
||||||
|
//!
|
||||||
|
//! @param port OS file path for I2C port. For example "/dev/i2c-0.0" on Linux.
|
||||||
|
//! @param speed Port speed, e.g. 9600.
|
||||||
|
//! @param address I2C slave's address
|
||||||
|
I2cPeripheral(const char *port,
|
||||||
|
long speed = kI2cPeripheral_DefaultSpeedKHz,
|
||||||
|
uint8_t address = kI2cPeripheral_DefaultAddress);
|
||||||
|
|
||||||
|
//! @brief Destructor.
|
||||||
|
virtual ~I2cPeripheral();
|
||||||
|
|
||||||
|
//! @brief Flush.
|
||||||
|
//!
|
||||||
|
//! should be called on an open I2C port in order to flush any remaining data in the I2C 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);
|
||||||
|
|
||||||
|
//! @brief Return peripheral Type
|
||||||
|
virtual _host_peripheral_types get_type(void) { return kHostPeripheralType_I2C; }
|
||||||
|
|
||||||
|
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 I2C port. For example "/dev/i2c-0.0" on Linux.
|
||||||
|
//! @param speed Port speed, e.g. 9600.
|
||||||
|
//! @param address I2C slave's address
|
||||||
|
bool init(const char *port, long speed, uint8_t address);
|
||||||
|
|
||||||
|
int m_fileDescriptor; //!< Port file descriptor.
|
||||||
|
uint8_t m_buffer[kDefaultMaxPacketSize]; //!< Buffer for bytes used to build read packet.
|
||||||
|
uint32_t m_current_ReadTimeout; //!< The last value sent to serial_set_read_timeout().
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace blfwk
|
||||||
|
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
#endif // _i2c_peripheral_h_
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// EOF
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
78
src/blfwk/IntelHexSourceFile.h
Normal file
78
src/blfwk/IntelHexSourceFile.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2015 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
261
src/blfwk/Logging.h
Normal file
261
src/blfwk/Logging.h
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
232
src/blfwk/LpcUsbSio.h
Normal file
232
src/blfwk/LpcUsbSio.h
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 - 2022 NXP
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _LpcUsbSio_h_
|
||||||
|
#define _LpcUsbSio_h_
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "host_types.h"
|
||||||
|
#include "middleware/libusbsio/inc/lpcusbsio.h"
|
||||||
|
|
||||||
|
//! @addtogroup lpc_usb_sio
|
||||||
|
//! @{
|
||||||
|
|
||||||
|
namespace blfwk
|
||||||
|
{
|
||||||
|
/*!
|
||||||
|
* @brief Interface with the LPC USB Serial I/O
|
||||||
|
*/
|
||||||
|
class LpcUsbSio
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! @brief Constants
|
||||||
|
|
||||||
|
enum _lpc_usb_sio_port_contants
|
||||||
|
{
|
||||||
|
kDefault_Vid = LPCUSBSIO_VID, //!< NXP VID
|
||||||
|
kDefault_Pid = LPCUSBSIO_PID, //!< PID for LPC USB Serial I/O
|
||||||
|
};
|
||||||
|
|
||||||
|
enum _lpc_usb_sio_timeout_contants
|
||||||
|
{
|
||||||
|
kDefault_TimeoutMs = LPCUSBSIO_READ_TMO, //!< 500ms, timeout miliseconds for reading
|
||||||
|
};
|
||||||
|
|
||||||
|
enum lpc_usb_sio_function_t
|
||||||
|
{
|
||||||
|
kFunction_None,
|
||||||
|
kFunction_SPI,
|
||||||
|
kFunction_I2C,
|
||||||
|
kFunction_GPIO,
|
||||||
|
};
|
||||||
|
//! @brief SPI clock polarity configuration.
|
||||||
|
enum spi_clock_polarity_t
|
||||||
|
{
|
||||||
|
kSpiPolarity_ActiveHigh = 0, //!< Active-high SPI clock (idles low).
|
||||||
|
kSpiPolarity_ActiveLow = 1 //!< Active-low SPI clock (idles high).
|
||||||
|
};
|
||||||
|
|
||||||
|
//! @brief SPI clock phase configuration.
|
||||||
|
enum spi_clock_phase_t
|
||||||
|
{
|
||||||
|
kSpiPhase_FirstEdge = 0, //!< First edge on SPSCK occurs at the middle of the first cycle of a data transfer.
|
||||||
|
kSpiPhase_SecondEdge = 1 //!< First edge on SPSCK occurs at the start of the first cycle of a data transfer.
|
||||||
|
};
|
||||||
|
|
||||||
|
//! @brief I2C slave address
|
||||||
|
enum i2c_slave_address_t
|
||||||
|
{
|
||||||
|
kI2cAddress_Default = 0x10, //!< Default I2C slave address.
|
||||||
|
};
|
||||||
|
|
||||||
|
//! @brief LPC USB Serial I/O USB port configuration.
|
||||||
|
struct LpcUsbSioPortConfigData
|
||||||
|
{
|
||||||
|
uint16_t usbVid;
|
||||||
|
uint16_t usbPid;
|
||||||
|
std::string usbString;
|
||||||
|
std::string usbPath;
|
||||||
|
int32_t portIndex;
|
||||||
|
|
||||||
|
LpcUsbSioPortConfigData()
|
||||||
|
{
|
||||||
|
usbVid = LpcUsbSio::kDefault_Vid;
|
||||||
|
usbPid = LpcUsbSio::kDefault_Pid;
|
||||||
|
portIndex = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//! @brief LPC USB Serial I/O SPI configuration.
|
||||||
|
struct LpcUsbSioSpiConfigData
|
||||||
|
{
|
||||||
|
uint32_t spiSpeedHz;
|
||||||
|
spi_clock_polarity_t spiPolarity;
|
||||||
|
spi_clock_phase_t spiPhase;
|
||||||
|
uint8_t spiSselPort;
|
||||||
|
uint8_t spiSselPin;
|
||||||
|
int32_t spiPortIndex;
|
||||||
|
|
||||||
|
LpcUsbSioSpiConfigData()
|
||||||
|
{
|
||||||
|
spiSpeedHz = 100000;
|
||||||
|
spiPolarity = LpcUsbSio::kSpiPolarity_ActiveLow;
|
||||||
|
spiPhase = LpcUsbSio::kSpiPhase_SecondEdge;
|
||||||
|
spiSselPort = 0;
|
||||||
|
spiSselPin = 0;
|
||||||
|
spiPortIndex = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//! @brief LPC USB Serial I/O I2C configuration.
|
||||||
|
struct LpcUsbSioI2cConfigData
|
||||||
|
{
|
||||||
|
uint8_t i2cAddress;
|
||||||
|
I2C_CLOCKRATE_T i2cSpeedHz;
|
||||||
|
int32_t i2cPortIndex;
|
||||||
|
|
||||||
|
LpcUsbSioI2cConfigData()
|
||||||
|
{
|
||||||
|
i2cAddress = LpcUsbSio::kI2cAddress_Default;
|
||||||
|
i2cSpeedHz = I2C_CLOCK_STANDARD_MODE;
|
||||||
|
i2cPortIndex = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//! @brief LPC USB Serial I/O GPIO configuration.
|
||||||
|
struct LpcUsbSioGpioConfigData
|
||||||
|
{
|
||||||
|
uint8_t gpioPort;
|
||||||
|
uint8_t gpioPin;
|
||||||
|
uint8_t gpioValue;
|
||||||
|
uint8_t gpioMode;
|
||||||
|
int32_t gpioPortIndex;
|
||||||
|
|
||||||
|
LpcUsbSioGpioConfigData()
|
||||||
|
{
|
||||||
|
gpioPort = 0;
|
||||||
|
gpioPin = 0;
|
||||||
|
gpioValue = 0;
|
||||||
|
gpioMode = 0;
|
||||||
|
gpioPortIndex = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//! @brief LPC USB Serial I/O configuration data.
|
||||||
|
struct LpcUsbSioConfigData
|
||||||
|
{
|
||||||
|
lpc_usb_sio_function_t function;
|
||||||
|
LpcUsbSioPortConfigData portConfig;
|
||||||
|
LpcUsbSioSpiConfigData spiConfig;
|
||||||
|
LpcUsbSioI2cConfigData i2cConfig;
|
||||||
|
|
||||||
|
LpcUsbSioConfigData() { function = LpcUsbSio::kFunction_None; }
|
||||||
|
};
|
||||||
|
|
||||||
|
//! @brief Constructor.
|
||||||
|
LpcUsbSio(const LpcUsbSio::LpcUsbSioPortConfigData &config);
|
||||||
|
|
||||||
|
//! @brief Destructor.
|
||||||
|
virtual ~LpcUsbSio();
|
||||||
|
|
||||||
|
//! @brief Parse the params in options into the config structure.
|
||||||
|
static bool parse(const string_vector_t ¶ms, LpcUsbSio::LpcUsbSioConfigData &config);
|
||||||
|
|
||||||
|
//! @brief Convert LPC USB Serial I/O error code to detail string.
|
||||||
|
static const std::string getError(LPCUSBSIO_ERR_T errorCode);
|
||||||
|
|
||||||
|
//! @brief Write data.
|
||||||
|
virtual uint32_t write(const uint8_t *data, uint32_t byteCount) = 0;
|
||||||
|
|
||||||
|
//! @brief Read data.
|
||||||
|
virtual uint32_t read(uint8_t *data, uint32_t byteCount) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint16_t m_usbVid; //!< The VID of LPC USB Serial I/O.
|
||||||
|
uint16_t m_usbPid; //!< The PID of LPC USB Serial I/O.
|
||||||
|
std::string m_usbString; //!< The USB Serial String of LPC USB Serial I/O port.
|
||||||
|
std::string m_usbPath; //!< The USB instance path of LPC USB Serial I/O port.
|
||||||
|
int32_t m_portCount; //!< The number of LPC USB Serial I/O connected.
|
||||||
|
int32_t m_portIndex; //!< The port of LPC USB Serial I/O which is active. Index starts from 0.
|
||||||
|
LPC_HANDLE m_portHandler; //!< The LPC USB Serial I/O hardware operation handler.
|
||||||
|
};
|
||||||
|
|
||||||
|
class LpcUsbSioSpi : public LpcUsbSio
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! @brief Constructor.
|
||||||
|
LpcUsbSioSpi(const LpcUsbSio::LpcUsbSioPortConfigData &portConfig,
|
||||||
|
const LpcUsbSio::LpcUsbSioSpiConfigData &spiConfig);
|
||||||
|
|
||||||
|
//! @brief Destructor.
|
||||||
|
virtual ~LpcUsbSioSpi();
|
||||||
|
|
||||||
|
//! @brief Write data.
|
||||||
|
virtual uint32_t write(const uint8_t *data, uint32_t byteCount);
|
||||||
|
|
||||||
|
//! @brief Read data.
|
||||||
|
virtual uint32_t read(uint8_t *data, uint32_t byteCount);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int32_t m_spiPortCount; //!< The number of SPI port on current LPC USB Serial I/O.
|
||||||
|
int32_t m_spiPortIndex; //!< The port of SPI which is active. Index starts from 0.
|
||||||
|
uint8_t m_spiSselPort; //!< The port numer of the SPI->SSELn pin on LPC USB Serial I/O.
|
||||||
|
uint8_t m_spiSselPin; //!< The pin number of the SPI->SSELn pin on LPC USB Serial I/O.
|
||||||
|
LPC_HANDLE m_spiPortHandler; //!< The SPI operation handler.
|
||||||
|
};
|
||||||
|
|
||||||
|
class LpcUsbSioI2c : public LpcUsbSio
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! @brief Constructor.
|
||||||
|
LpcUsbSioI2c(const LpcUsbSio::LpcUsbSioPortConfigData &portConfig,
|
||||||
|
const LpcUsbSio::LpcUsbSioI2cConfigData &i2cConfig);
|
||||||
|
|
||||||
|
//! @brief Destructor.
|
||||||
|
virtual ~LpcUsbSioI2c();
|
||||||
|
|
||||||
|
//! @brief Write data.
|
||||||
|
virtual uint32_t write(const uint8_t *data, uint32_t byteCount);
|
||||||
|
|
||||||
|
//! @brief Read data.
|
||||||
|
virtual uint32_t read(uint8_t *data, uint32_t byteCount);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int32_t m_i2cPortCount; //!< The number of I2C port on current LPC USB Serial I/O.
|
||||||
|
int32_t m_i2cPortIndex; //!< The port of I2C which is active. Index starts from 0.
|
||||||
|
LPC_HANDLE m_i2cPortHandler; //!< The I2C operation handler.
|
||||||
|
uint8_t m_i2cAddress; //!< The I2C slave address to communicate.
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace blfwk
|
||||||
|
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
#endif // _LpcUsbSio_h_
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// EOF
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
63
src/blfwk/LpcUsbSioPeripheral.h
Normal file
63
src/blfwk/LpcUsbSioPeripheral.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 - 2022 NXP
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef _LpcUsbSioPeripheral_h_
|
||||||
|
#define _LpcUsbSioPeripheral_h_
|
||||||
|
|
||||||
|
#include "Peripheral.h"
|
||||||
|
|
||||||
|
//! @addtogroup lpc_usb_sio_peripheral
|
||||||
|
//! @{
|
||||||
|
|
||||||
|
namespace blfwk
|
||||||
|
{
|
||||||
|
/*!
|
||||||
|
* @brief Peripheral that talks to the target device over LPCUSB Serial I/O hardware.
|
||||||
|
*/
|
||||||
|
class LpcUsbSioPeripheral : public Peripheral
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! @brief Parameterized constructor that opens the LPC USB Serial I/O port.
|
||||||
|
//!
|
||||||
|
//! Opens and configures the port. Throws exception if operation fails.
|
||||||
|
//!
|
||||||
|
//! @param config The configuration data of LPCUSB Serial I/O device.
|
||||||
|
LpcUsbSioPeripheral(const LpcUsbSio::LpcUsbSioConfigData &config);
|
||||||
|
|
||||||
|
//! @brief Destructor.
|
||||||
|
virtual ~LpcUsbSioPeripheral();
|
||||||
|
|
||||||
|
//! @brief Read bytes.
|
||||||
|
//!
|
||||||
|
//! @param buffer Pointer to buffer
|
||||||
|
//! @param requestedBytes Number of bytes to read
|
||||||
|
//! @param actualBytes Number of bytes got
|
||||||
|
//! @param timeoutMs The timeout microseconds for the read operation
|
||||||
|
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);
|
||||||
|
|
||||||
|
//! @brief Get the peripheral type.
|
||||||
|
virtual _host_peripheral_types get_type(void) { return kHostPeripheralType_LPCUSBSIO; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
LpcUsbSio *m_lpcUsbSio; //!< Represents LPC USB Serial I/O hardware.
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace blfwk
|
||||||
|
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
#endif // _LpcUsbSioPeripheral_h_
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// EOF
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
51
src/blfwk/OptionContext.h
Normal file
51
src/blfwk/OptionContext.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
109
src/blfwk/Packetizer.h
Normal file
109
src/blfwk/Packetizer.h
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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)
|
||||||
|
, m_readCount(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
//! @brieif Optional control of number of bytes requested from peripheral by readPacket().
|
||||||
|
virtual void setReadCount(uint32_t byteCount) { m_readCount = byteCount; }
|
||||||
|
//! @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.
|
||||||
|
uint32_t m_packetTimeoutMs;
|
||||||
|
bool m_isAbortEnabled; //!< True if allowing abort packet. Not used by all packetizers.
|
||||||
|
uint32_t m_readCount; //!< Optional control of number of bytes requested by readPacket().
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace blfwk
|
||||||
|
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
#endif // _Packetizer_h_
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// EOF
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
88
src/blfwk/Peripheral.h
Normal file
88
src/blfwk/Peripheral.h
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* Copyright 2020 - 2022 NXP
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _Peripheral_h_
|
||||||
|
#define _Peripheral_h_
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "BusPal.h"
|
||||||
|
#include "LpcUsbSio.h"
|
||||||
|
#include "bootloader_common.h"
|
||||||
|
|
||||||
|
//! @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_LPCUSBSIO,
|
||||||
|
kHostPeripheralType_USB_HID,
|
||||||
|
kHostPeripheralType_SIM,
|
||||||
|
kHostPeripheralType_I2C,
|
||||||
|
kHostPeripheralType_SPI,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PeripheralConfigData
|
||||||
|
{
|
||||||
|
_host_peripheral_types peripheralType;
|
||||||
|
bool ping;
|
||||||
|
std::string comPortName;
|
||||||
|
long comPortSpeed;
|
||||||
|
uint32_t packetTimeoutMs;
|
||||||
|
unsigned short usbHidVid;
|
||||||
|
unsigned short usbHidPid;
|
||||||
|
std::string usbHidSerialNumber;
|
||||||
|
std::string usbPath;
|
||||||
|
#if defined(LINUX) && defined(__ARM__)
|
||||||
|
unsigned char i2cAddress;
|
||||||
|
unsigned char spiPolarity;
|
||||||
|
unsigned char spiPhase;
|
||||||
|
unsigned char spiSequence;
|
||||||
|
#endif // #if defined(LINUX) && defined(__ARM__)
|
||||||
|
BusPal::BusPalConfigData busPalConfig;
|
||||||
|
LpcUsbSio::LpcUsbSioConfigData lpcUsbSioConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
//! @brief Return peripheral Type
|
||||||
|
virtual _host_peripheral_types get_type(void) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace blfwk
|
||||||
|
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
#endif // _Peripheral_h_
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// EOF
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
86
src/blfwk/Progress.h
Normal file
86
src/blfwk/Progress.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _Progress_h_
|
||||||
|
#define _Progress_h_
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "blfwk/host_types.h"
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Contains the callback function for progress and abort phase.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class Progress
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! @brief Default constructor.
|
||||||
|
Progress()
|
||||||
|
: m_segmentIndex(1)
|
||||||
|
, m_segmentCount(1)
|
||||||
|
, m_progressCallback(NULL)
|
||||||
|
, m_abortPhase(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @brief Constructor with initial callback.
|
||||||
|
Progress(void(*callback)(int, int, int), bool *abortPhase)
|
||||||
|
: m_segmentIndex(1)
|
||||||
|
, m_segmentCount(1)
|
||||||
|
, m_progressCallback(callback)
|
||||||
|
, m_abortPhase(abortPhase)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @brief Default destructor.
|
||||||
|
~Progress() {}
|
||||||
|
//! @brief execute the progress callback function.
|
||||||
|
//!
|
||||||
|
//! @param percentage the percentage of current executed progress.
|
||||||
|
void progressCallback(int percentage)
|
||||||
|
{
|
||||||
|
if (m_progressCallback != NULL)
|
||||||
|
{
|
||||||
|
m_progressCallback(percentage, m_segmentIndex, m_segmentCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @brief Check whether the data phase is canceled.
|
||||||
|
bool abortPhase(void)
|
||||||
|
{
|
||||||
|
if ((m_abortPhase) && (*m_abortPhase == true))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @biref initialized the progress callback function and the variable of controlling data phase.
|
||||||
|
//!
|
||||||
|
//! @param callback The progress callback function.
|
||||||
|
//!
|
||||||
|
//! @param abortPhase The pointer pointing to a variable controlling whether abort current data phase.
|
||||||
|
void registerCallback(void(*callback)(int, int, int), bool *abortPhase)
|
||||||
|
{
|
||||||
|
m_progressCallback = callback;
|
||||||
|
m_abortPhase = abortPhase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
int m_segmentIndex; //!< Index of data segment in progressing.
|
||||||
|
int m_segmentCount; //!< The number of data segments.
|
||||||
|
|
||||||
|
private:
|
||||||
|
void(*m_progressCallback)(int percentage, int segmentIndex, int segmentCount); //!< The progress callback function.
|
||||||
|
bool *m_abortPhase; //!< The pointer pointing to a variable controlling whether abort current data phase.
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _Progress_h_
|
58
src/blfwk/Random.h
Normal file
58
src/blfwk/Random.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* File: Random.h
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
62
src/blfwk/RijndaelCTR.h
Normal file
62
src/blfwk/RijndaelCTR.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* File: RijndaelCTR.h
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
135
src/blfwk/SBSourceFile.h
Normal file
135
src/blfwk/SBSourceFile.h
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
387
src/blfwk/SDPCommand.h
Normal file
387
src/blfwk/SDPCommand.h
Normal file
@ -0,0 +1,387 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015 Freescale Semiconductor, Inc.
|
||||||
|
* Copyright 2016-2018 NXP
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SDPCommand_h_
|
||||||
|
#define _SDPCommand_h_
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "host_types.h"
|
||||||
|
#include "Progress.h"
|
||||||
|
#include "Packetizer.h"
|
||||||
|
|
||||||
|
//! @addtogroup sdp_commands
|
||||||
|
//! @{
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace blfwk
|
||||||
|
{
|
||||||
|
//! @brief SDP Command structure.
|
||||||
|
struct sdp_cmd_t
|
||||||
|
{
|
||||||
|
uint16_t cmdType;
|
||||||
|
const char *const name;
|
||||||
|
|
||||||
|
sdp_cmd_t(uint16_t cmdType, const char *name)
|
||||||
|
: cmdType(cmdType)
|
||||||
|
, name(name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//! @name SDP command types and names.
|
||||||
|
//@{
|
||||||
|
const sdp_cmd_t kSDPCommand_ReadRegister(0x0101, "read-register");
|
||||||
|
const sdp_cmd_t kSDPCommand_WriteRegister(0x0202, "write-register");
|
||||||
|
const sdp_cmd_t kSDPCommand_WriteFile(0x0404, "write-file");
|
||||||
|
const sdp_cmd_t kSDPCommand_ErrorStatus(0x0505, "error-status");
|
||||||
|
const sdp_cmd_t kSDPCommand_DcdWrite(0x0a0a, "dcd-write");
|
||||||
|
const sdp_cmd_t kSDPCommand_SkipDcdHeader(0x0c0c, "skip-dcd-header");
|
||||||
|
const sdp_cmd_t kSDPCommand_JumpAddress(0x0b0b, "jump-address");
|
||||||
|
const sdp_cmd_t kSDPCommand_SetBaudrate(0x0d0d, "set-baudrate");
|
||||||
|
const sdp_cmd_t kSDPCommand_Ping(0x5aa6, "ping");
|
||||||
|
//@}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Represents an SDP command.
|
||||||
|
*
|
||||||
|
* Do not instantiate this class. Instead, use the create() method to
|
||||||
|
* create the appropriate subclass based on command name in argv[0].
|
||||||
|
*/
|
||||||
|
class SDPCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! @brief Constants
|
||||||
|
enum _constants
|
||||||
|
{
|
||||||
|
kCmdSizeBytes = 16, //!< Number of bytes in SDP command.
|
||||||
|
kHabModeSizeBytes = 4, //!< Number of bytes in HAB mode response.
|
||||||
|
kResponseSizeBytes = 64, //!< Number of bytes in status response.
|
||||||
|
kSendDataSizeBytes = 1024, //!< Number of bytes in data packet.
|
||||||
|
kMaxDcdSizeBytes = 1024, //!< Max number bytes in DCD table.
|
||||||
|
kHabEnabled = 0x12343412, //!< HAB mode enabled.
|
||||||
|
kHabDisabled = 0x56787856, //!< HAB mode disabled.
|
||||||
|
kWriteComplete = 0x128a8a12, //!< Write Complete status response.
|
||||||
|
kWriteFileComplete = 0x88888888, //!< Write File Complete status response.
|
||||||
|
kHabStatusFailure = 0x33333333, //!< HAB failed response.
|
||||||
|
kHabStatusWarning = 0x69696969, //!< HAB wrarning response.
|
||||||
|
kHabStatusSuccess = 0xf0f0f0f0, //!< HAB success resopnse.
|
||||||
|
kReEnum_Ack = 0x89232389, //!< Return Error Number Ack
|
||||||
|
kStatus_NoResponse = 10004, //!< Matches Bootloader kStatusNoResponse.
|
||||||
|
kOk_Ack = 0x900DD009, //!< Response to skip-dcd-header command.
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
//! @brief Create an appropriate command subclass.
|
||||||
|
//!
|
||||||
|
//! Pass the command name in argv[0] and optional
|
||||||
|
//! arguments in the rest of the string vector.
|
||||||
|
//! Caller is responsible for deleting the returned object.
|
||||||
|
//!
|
||||||
|
//! @param argv Argument vector
|
||||||
|
//! @retval Command object
|
||||||
|
static SDPCommand *create(const string_vector_t *argv);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//! @brief Constructor that takes a command name and list of arguments.
|
||||||
|
//!
|
||||||
|
//! @param argv Argument vector
|
||||||
|
SDPCommand(const string_vector_t *argv)
|
||||||
|
: m_argv(*argv)
|
||||||
|
, m_progress()
|
||||||
|
, m_responseValues()
|
||||||
|
, m_cmdBuf()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
//! @brief Destructor.
|
||||||
|
virtual ~SDPCommand() {}
|
||||||
|
//! @brief Initialize.
|
||||||
|
//!
|
||||||
|
//! Subclasses should implement init() to check for valid arguments.
|
||||||
|
virtual bool init() { return true; }
|
||||||
|
//! @name String arguments accessors.
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! @brief Get the specified argument.
|
||||||
|
virtual std::string getArg(int arg) const { return m_argv.at(arg); }
|
||||||
|
//! @brief Get the command name (i.e. argv[0]).
|
||||||
|
virtual std::string getName() const { return getArg(0); }
|
||||||
|
//! @brief Get the number of arguments, including the command name.
|
||||||
|
virtual size_t getArgCount() const { return m_argv.size(); }
|
||||||
|
//@}
|
||||||
|
|
||||||
|
//! @brief Send command to packetizer and on to peripheral.
|
||||||
|
virtual void sendTo(Packetizer &packetizer) {}
|
||||||
|
//! @brief Get response values vector.
|
||||||
|
virtual const uint32_vector_t *getResponseValues() const
|
||||||
|
{
|
||||||
|
return const_cast<uint32_vector_t *>(&m_responseValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @brief Get response as JSON string.
|
||||||
|
virtual std::string getResponse() const;
|
||||||
|
|
||||||
|
//! @brief Log the response description.
|
||||||
|
virtual void logResponses() const;
|
||||||
|
|
||||||
|
//! @brief Register an object for displaying transfer progress.
|
||||||
|
virtual void registerProgress(Progress *progress) { m_progress = progress; }
|
||||||
|
protected:
|
||||||
|
//! @brief Create packed buffer with SDP command.
|
||||||
|
void packCommand(uint16_t cmdType, uint32_t address, uint32_t format, uint32_t dataCount, uint32_t data);
|
||||||
|
|
||||||
|
//! @brief Send command to packetizer.
|
||||||
|
status_t sendCommand(Packetizer &packetizer);
|
||||||
|
|
||||||
|
//! @brief Send command and read HAB mode response.
|
||||||
|
status_t sendCommandGetHabMode(Packetizer &packetizer);
|
||||||
|
|
||||||
|
//! @brief Read response value from device.
|
||||||
|
//!
|
||||||
|
//! Use kPacketTypeData for 64-byte read-register response, kPacketTypeCommand for 4-byte status response and HAB
|
||||||
|
//! mode response.
|
||||||
|
uint8_t *getStatusResponse(Packetizer &packetizer, packet_type_t type = kPacketType_Command);
|
||||||
|
|
||||||
|
//! @brief Read HAB mode response from device.
|
||||||
|
bool isHabModeValid(Packetizer &packetizer);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
string_vector_t m_argv; //!< Vector of argument strings.
|
||||||
|
Progress *m_progress; //!< Variable for progress control.
|
||||||
|
uint32_vector_t m_responseValues; //!< Vector of response values.
|
||||||
|
uint8_t m_cmdBuf[kCmdSizeBytes]; //!< Buffer for command bytes.
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Represents the SDP ReadRegister command.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class SDPReadRegister : public SDPCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! @brief Constructor that takes argument vector.
|
||||||
|
SDPReadRegister(const string_vector_t *argv)
|
||||||
|
: SDPCommand(argv)
|
||||||
|
, m_address(0)
|
||||||
|
, m_format(32)
|
||||||
|
, m_dataCount(4)
|
||||||
|
, m_file()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @brief Initialize.
|
||||||
|
virtual bool init();
|
||||||
|
|
||||||
|
//! @brief Send command to packetizer.
|
||||||
|
virtual void sendTo(Packetizer &packetizer);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint32_t m_address; //!< Target memory address.
|
||||||
|
uint32_t m_format; //!< Register format.
|
||||||
|
uint32_t m_dataCount; //!< Number of bytes to read.
|
||||||
|
std::string m_file; //!< Data file path.
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Represents the SDP WriteRegister command.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class SDPWriteRegister : public SDPCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! @brief Constructor that takes argument vector.
|
||||||
|
SDPWriteRegister(const string_vector_t *argv)
|
||||||
|
: SDPCommand(argv)
|
||||||
|
, m_address(0)
|
||||||
|
, m_format(32)
|
||||||
|
, m_data(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @brief Initialize.
|
||||||
|
virtual bool init();
|
||||||
|
|
||||||
|
//! @brief Send command to packetizer.
|
||||||
|
virtual void sendTo(Packetizer &packetizer);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint32_t m_address; //!< Target memory address.
|
||||||
|
uint32_t m_format; //!< Register format.
|
||||||
|
uint32_t m_data; //!< Data value to write.
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Represents the SDP WriteFile command.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class SDPWriteFile : public SDPCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! @brief Constructor that takes argument vector.
|
||||||
|
SDPWriteFile(const string_vector_t *argv)
|
||||||
|
: SDPCommand(argv)
|
||||||
|
, m_address(0)
|
||||||
|
, m_file()
|
||||||
|
, m_dataCount(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @brief Initialize.
|
||||||
|
virtual bool init();
|
||||||
|
|
||||||
|
//! @brief Send command to packetizer.
|
||||||
|
virtual void sendTo(Packetizer &packetizer);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint32_t m_address; //!< Target memory address.
|
||||||
|
std::string m_file; //!< Data file path.
|
||||||
|
uint32_t m_dataCount; //!< Number of bytes to write.
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Represents the SDP ErrorStatus command.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class SDPErrorStatus : public SDPCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! @brief Constructor that takes argument vector.
|
||||||
|
SDPErrorStatus(const string_vector_t *argv)
|
||||||
|
: SDPCommand(argv)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @brief Initialize.
|
||||||
|
virtual bool init();
|
||||||
|
|
||||||
|
//! @brief Send command to packetizer.
|
||||||
|
virtual void sendTo(Packetizer &packetizer);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Represents the SDP DcdWrite command.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class SDPDcdWrite : public SDPCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! @brief Constructor that takes argument vector.
|
||||||
|
SDPDcdWrite(const string_vector_t *argv)
|
||||||
|
: SDPCommand(argv)
|
||||||
|
, m_address(0)
|
||||||
|
, m_file()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @brief Initialize.
|
||||||
|
virtual bool init();
|
||||||
|
|
||||||
|
//! @brief Send command to packetizer.
|
||||||
|
virtual void sendTo(Packetizer &packetizer);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint32_t m_address; //!< Temporary storage address.
|
||||||
|
std::string m_file; //!< Data file path.
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Represents the SDP SkipDcdHeader command.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class SDPSkipDcdHeader : public SDPCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! @brief Constructor that takes argument vector.
|
||||||
|
SDPSkipDcdHeader(const string_vector_t *argv)
|
||||||
|
: SDPCommand(argv)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @brief Initialize.
|
||||||
|
virtual bool init();
|
||||||
|
|
||||||
|
//! @brief Send command to packetizer.
|
||||||
|
virtual void sendTo(Packetizer &packetizer);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Represents the SDP JumpAddress command.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class SDPJumpAddress : public SDPCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! @brief Constructor that takes argument vector.
|
||||||
|
SDPJumpAddress(const string_vector_t *argv)
|
||||||
|
: SDPCommand(argv)
|
||||||
|
, m_address(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @brief Initialize.
|
||||||
|
virtual bool init();
|
||||||
|
|
||||||
|
//! @brief Send command to packetizer.
|
||||||
|
virtual void sendTo(Packetizer &packetizer);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint32_t m_address; //!< Target memory address.
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief REpresents the SDP SetBaudrate command.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class SDPSetBaudrate : public SDPCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! @brief Constructor that takes argument vector.
|
||||||
|
SDPSetBaudrate(const string_vector_t *argv)
|
||||||
|
: SDPCommand(argv)
|
||||||
|
, m_baudrate(115200)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @brief Initialize.
|
||||||
|
virtual bool init();
|
||||||
|
|
||||||
|
//! @brief Send command to packetizer.
|
||||||
|
virtual void sendTo(Packetizer &packetizer);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint32_t m_baudrate; //!< Baudrate
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Represents the SDP SkipDcdHeader command.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class SDPPing : public SDPCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! @brief Constructor that takes argument vector.
|
||||||
|
SDPPing(const string_vector_t *argv)
|
||||||
|
: SDPCommand(argv)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @brief Initialize.
|
||||||
|
virtual bool init();
|
||||||
|
|
||||||
|
//! @brief Send command to packetizer.
|
||||||
|
virtual void sendTo(Packetizer &packetizer);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace blfwk
|
||||||
|
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
#endif // _SDPCommand_h_
|
108
src/blfwk/SDPUartPacketizer.h
Normal file
108
src/blfwk/SDPUartPacketizer.h
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _sdp_uart_packetizer_h_
|
||||||
|
#define _sdp_uart_packetizer_h_
|
||||||
|
|
||||||
|
#include "Packetizer.h"
|
||||||
|
#include "UartPeripheral.h"
|
||||||
|
#include "serial.h"
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
//! @addtogroup sdp_uart_packetizer
|
||||||
|
//! @{
|
||||||
|
|
||||||
|
namespace blfwk
|
||||||
|
{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Provides source and sink for SDP packets that go over UART.
|
||||||
|
*/
|
||||||
|
class SDPUartPacketizer : public Packetizer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! @brief Constants.
|
||||||
|
enum _constants
|
||||||
|
{
|
||||||
|
kMaxReadSizeBytes = 64, //!< Max bytes returned by single read.
|
||||||
|
kNumBytesCommandResponse = 4, //!< Number of bytes in a kPacketTypeCommand read.
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
//! @brief Default Constructor.
|
||||||
|
SDPUartPacketizer(UartPeripheral *peripheral, uint32_t readPacketTimeoutMs)
|
||||||
|
: Packetizer(peripheral, readPacketTimeoutMs)
|
||||||
|
, m_readBuf()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @brief Destructor.
|
||||||
|
virtual ~SDPUartPacketizer() {}
|
||||||
|
|
||||||
|
//! @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)
|
||||||
|
{
|
||||||
|
uint32_t count = ((packetType == kPacketType_Command) || (m_readCount == 0)) ? kNumBytesCommandResponse : m_readCount;
|
||||||
|
if (count > sizeof(m_readBuf))
|
||||||
|
{
|
||||||
|
count = sizeof(m_readBuf);
|
||||||
|
}
|
||||||
|
status_t status = getPeripheral()->read(m_readBuf, count, packetLength, m_packetTimeoutMs);
|
||||||
|
*packet = m_readBuf;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @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)
|
||||||
|
{
|
||||||
|
return getPeripheral()->write(packet, byteCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @brief Finalize.
|
||||||
|
virtual void finalize() {};
|
||||||
|
|
||||||
|
//! @brief Peripheral accessor.
|
||||||
|
virtual UartPeripheral *getPeripheral() { return (UartPeripheral *)m_peripheral; }
|
||||||
|
|
||||||
|
//! @brief Abort data phase.
|
||||||
|
virtual void abortPacket() {};
|
||||||
|
|
||||||
|
//! @brief Send framing packet ack.
|
||||||
|
virtual void sync() {};
|
||||||
|
|
||||||
|
//! @brief Enable simulator command processor pump.
|
||||||
|
virtual void enableSimulatorPump() {};
|
||||||
|
|
||||||
|
//! @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) {};
|
||||||
|
|
||||||
|
//! @brief Return the max packet size.
|
||||||
|
virtual uint32_t getMaxPacketSize() { return 0; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint8_t m_readBuf[kMaxReadSizeBytes]; //!< Buffer for read data.
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace blfwk
|
||||||
|
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
#endif // _sdp_uart_packetizer_h_
|
106
src/blfwk/SDPUsbHidPacketizer.h
Normal file
106
src/blfwk/SDPUsbHidPacketizer.h
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _sdp_usb_hid_packetizer_h_
|
||||||
|
#define _sdp_usb_hid_packetizer_h_
|
||||||
|
|
||||||
|
#include "Packetizer.h"
|
||||||
|
#include "UsbHidPeripheral.h"
|
||||||
|
#include "hidapi.h"
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
//! @addtogroup sdp_usb_hid_packetizer
|
||||||
|
//! @{
|
||||||
|
|
||||||
|
namespace blfwk
|
||||||
|
{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief Provides source and sink for SDP packets that go over USB HID class.
|
||||||
|
*/
|
||||||
|
class SDPUsbHidPacketizer : public Packetizer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! @brief Constants
|
||||||
|
enum _usbhid_constants
|
||||||
|
{
|
||||||
|
kMaxReportSizeBytes = 1024 + 1, //!< Number of bytes in largest report, including report type byte.
|
||||||
|
kIdReport1 = 1, //!< Code for report ID 1.
|
||||||
|
kReport1SizeBytes = 16 + 1, //!< Number of bytes in report 1, including report type byte.
|
||||||
|
kIdReport2 = 2, //!< Code for report ID 2.
|
||||||
|
kReport2SizeBytes = 1024 + 1, //!< Number of bytes in report 2, including report type byte.
|
||||||
|
kIdReport3 = 3, //!< Code for report ID 3.
|
||||||
|
#if defined(WIN32)
|
||||||
|
kReport3SizeBytes = 64 + 1, //!< Number of bytes in report 3, including report type byte.
|
||||||
|
#elif defined(LINUX) || defined(MACOSX)
|
||||||
|
kReport3SizeBytes = 4 + 1, //!< Number of bytes in report 3, including report type byte.
|
||||||
|
#endif
|
||||||
|
kIdReport4 = 4, //!< Code for report ID 4.
|
||||||
|
kReport4SizeBytes = 64 + 1, //!< Number of bytes in report 4, including report type byte.
|
||||||
|
kPollPacketMaxRetryCnt = 50, //!< Number of read retries.
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
//! @brief Default Constructor.
|
||||||
|
SDPUsbHidPacketizer(UsbHidPeripheral *peripheral, uint32_t readPacketTimeoutMs)
|
||||||
|
: Packetizer(peripheral, readPacketTimeoutMs)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//! @brief Destructor.
|
||||||
|
virtual ~SDPUsbHidPacketizer() {}
|
||||||
|
|
||||||
|
//! @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 Finalize.
|
||||||
|
virtual void finalize() {};
|
||||||
|
|
||||||
|
//! @brief Peripheral accessor.
|
||||||
|
virtual UsbHidPeripheral *getPeripheral() { return (UsbHidPeripheral *)m_peripheral; }
|
||||||
|
|
||||||
|
//! @brief Abort data phase.
|
||||||
|
virtual void abortPacket() {};
|
||||||
|
|
||||||
|
//! @brief Send framing packet ack.
|
||||||
|
virtual void sync() {};
|
||||||
|
|
||||||
|
//! @brief Enable simulator command processor pump.
|
||||||
|
virtual void enableSimulatorPump() {};
|
||||||
|
|
||||||
|
//! @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) {};
|
||||||
|
|
||||||
|
//! @brief Return the max packet size.
|
||||||
|
virtual uint32_t getMaxPacketSize() { return 0; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint8_t m_report[kMaxReportSizeBytes]; //!< Buffer for report bytes.
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace blfwk
|
||||||
|
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
#endif // _sdp_usb_hid_packetizer_h_
|
81
src/blfwk/SRecordSourceFile.h
Normal file
81
src/blfwk/SRecordSourceFile.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
57
src/blfwk/SearchPath.h
Normal file
57
src/blfwk/SearchPath.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
147
src/blfwk/SerialPacketizer.h
Normal file
147
src/blfwk/SerialPacketizer.h
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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(Peripheral *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, int *actualComSpeed);
|
||||||
|
|
||||||
|
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
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
86
src/blfwk/SimPacketizer.h
Normal file
86
src/blfwk/SimPacketizer.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
57
src/blfwk/SimPeripheral.h
Normal file
57
src/blfwk/SimPeripheral.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
91
src/blfwk/Simulator.h
Normal file
91
src/blfwk/Simulator.h
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
271
src/blfwk/SimulatorMemory.h
Normal file
271
src/blfwk/SimulatorMemory.h
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
181
src/blfwk/SourceFile.h
Normal file
181
src/blfwk/SourceFile.h
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
109
src/blfwk/SpiPeripheral.h
Normal file
109
src/blfwk/SpiPeripheral.h
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 - 2022 NXP
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _spi_peripheral_h_
|
||||||
|
#define _spi_peripheral_h_
|
||||||
|
|
||||||
|
#include "Peripheral.h"
|
||||||
|
#include "blfwk/spi.h"
|
||||||
|
#include "packet/command_packet.h"
|
||||||
|
|
||||||
|
//! @addtogroup spi_peripheral
|
||||||
|
//! @{
|
||||||
|
|
||||||
|
namespace blfwk
|
||||||
|
{
|
||||||
|
/*!
|
||||||
|
* @brief Peripheral that talks to the target device over SPI port hardware.
|
||||||
|
*/
|
||||||
|
class SpiPeripheral : public Peripheral
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//! @breif Constants.
|
||||||
|
enum _spi_peripheral_constants
|
||||||
|
{
|
||||||
|
// The read() implementation for the SpiPeripheral does not use this the timeout parameter.
|
||||||
|
kSpiPeripheral_UnusedTimeout = 0,
|
||||||
|
// Serial timeout is set to this default during init().
|
||||||
|
kSpiPeripheral_DefaultReadTimeoutMs = 1,
|
||||||
|
kSpiPeripheral_DefaultSpeedKHz = 100,
|
||||||
|
kSpiPeripheral_DefaultClockPolarity = 1,
|
||||||
|
kSpiPeripheral_DefaultClockPhase = 1,
|
||||||
|
kSpiPeripheral_DefaultBitSequence = 1,
|
||||||
|
kSpiPeripheral_DefaultBitsPerWord = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
//! @brief Parameterized constructor that opens the serial port.
|
||||||
|
//!
|
||||||
|
//! Opens and configures the port. Throws exception if port configuration fails.
|
||||||
|
//!
|
||||||
|
//! @param port OS file path for SPI port. For example "/dev/spidev-0.0" on Linux.
|
||||||
|
//! @param speed Port speed in KHz, e.g. 100(means 100KHz).
|
||||||
|
//! @param polarity SPI clock polarity, 1 for active-high, 0 for active-low.
|
||||||
|
//! @param phase SPI clock phase, 1 for second clock edge, 0 for first clock edge.
|
||||||
|
//! @param sequence SPI data transfer bits sequence. 1 for LSB, 0 for MSB.
|
||||||
|
SpiPeripheral(const char *port,
|
||||||
|
long speed = kSpiPeripheral_DefaultSpeedKHz,
|
||||||
|
uint8_t polarity = kSpiPeripheral_DefaultClockPolarity,
|
||||||
|
uint8_t phase = kSpiPeripheral_DefaultClockPhase,
|
||||||
|
uint8_t sequence = kSpiPeripheral_DefaultBitSequence);
|
||||||
|
|
||||||
|
//! @brief Destructor.
|
||||||
|
virtual ~SpiPeripheral();
|
||||||
|
|
||||||
|
//! @brief Flush.
|
||||||
|
//!
|
||||||
|
//! should be called on an open SPI port in order to flush any remaining data in the SPI 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);
|
||||||
|
|
||||||
|
//! @brief Return peripheral Type
|
||||||
|
virtual _host_peripheral_types get_type(void) { return kHostPeripheralType_SPI; }
|
||||||
|
|
||||||
|
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 SPI port. For example "/dev/spidev-0.0" on Linux.
|
||||||
|
//! @param speed Port speed in KHz, e.g. 100(means 100KHz).
|
||||||
|
//! @param polarity SPI clock polarity, 1 for active-high, 0 for active-low.
|
||||||
|
//! @param phase SPI clock phase, 1 for second clock edge, 0 for first clock edge.
|
||||||
|
//! @param direction SPI data transfer bits direction. 1 for LSB, 0 for MSB.
|
||||||
|
bool init(const char *port, long speed, uint8_t polarity, uint8_t phase, uint8_t direction);
|
||||||
|
|
||||||
|
int m_fileDescriptor; //!< Port file descriptor.
|
||||||
|
uint8_t m_buffer[kDefaultMaxPacketSize]; //!< Buffer for bytes used to build read packet.
|
||||||
|
uint32_t m_current_ReadTimeout; //!< The last value sent to serial_set_read_timeout().
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace blfwk
|
||||||
|
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
#endif // _spi_peripheral_h_
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// EOF
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
198
src/blfwk/StELFFile.h
Normal file
198
src/blfwk/StELFFile.h
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#if !defined(_StELFFile_h_)
|
||||||
|
#define _StELFFile_h_
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "blfwk/ELF.h"
|
||||||
|
#include "blfwk/stdafx.h"
|
||||||
|
|
||||||
|
//! Variations of the ARM ELF format.
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
eIllegalVariant = 0, //!< Illegal variant.
|
||||||
|
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_
|
257
src/blfwk/StExecutableImage.h
Normal file
257
src/blfwk/StExecutableImage.h
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
155
src/blfwk/StIntelHexFile.h
Normal file
155
src/blfwk/StIntelHexFile.h
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2015 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
122
src/blfwk/StSRecordFile.h
Normal file
122
src/blfwk/StSRecordFile.h
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
60
src/blfwk/StringMatcher.h
Normal file
60
src/blfwk/StringMatcher.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
95
src/blfwk/UartPeripheral.h
Normal file
95
src/blfwk/UartPeripheral.h
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* Copyright 2015-2020 NXP
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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);
|
||||||
|
|
||||||
|
//! @brief Return peripheral Type
|
||||||
|
virtual _host_peripheral_types get_type(void) { return kHostPeripheralType_UART; }
|
||||||
|
|
||||||
|
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);
|
||||||
|
char *port_name; //!< Port name
|
||||||
|
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-2014 Freescale Semiconductor, Inc.
|
||||||
|
* Copyright 2015-2020 NXP.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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 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, uint32_t memoryId);
|
||||||
|
|
||||||
|
//! \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 Erase the specified FLASH region.
|
||||||
|
//!
|
||||||
|
//! \exception std::runtime_error Thrown if an error occurred.
|
||||||
|
//!
|
||||||
|
//! \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.
|
||||||
|
//!
|
||||||
|
//! \param memoryId The ID of the memory to erase.
|
||||||
|
void eraseRegion(uint32_t start, uint32_t length, uint32_t memoryId);
|
||||||
|
|
||||||
|
//! \brief Execute the FlashEraseAll bootloader command.
|
||||||
|
//!
|
||||||
|
//! \exception std::runtime_error Thrown if an error occurred
|
||||||
|
//!
|
||||||
|
//! \param memoryId The ID of the memory to erase.
|
||||||
|
void eraseAll(uint32_t memoryId);
|
||||||
|
|
||||||
|
//! \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 get total internal flash size of current device.
|
||||||
|
//!
|
||||||
|
//! \exception std::runtime_error Raised if the operation is failed.
|
||||||
|
//!
|
||||||
|
//! \return the size in bytes. Return 0 means no internal Flash available.
|
||||||
|
uint32_t getInternalFlashSize(void);
|
||||||
|
|
||||||
|
//! \brief get total internal RAM size of current device.
|
||||||
|
//!
|
||||||
|
//! \exception std::runtime_error Raised if the operation is failed.
|
||||||
|
//!
|
||||||
|
//! \return the size in bytes. Return 0 means no internal RAM available.
|
||||||
|
uint32_t getInternalRAMSize(void);
|
||||||
|
|
||||||
|
//! \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, bool isLsb);
|
||||||
|
//@}
|
||||||
|
//
|
||||||
|
|
||||||
|
protected:
|
||||||
|
//! \name Bootloader commands
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! \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();
|
||||||
|
|
||||||
|
//! \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 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 fuseProgram(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 fuseProgram(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);
|
||||||
|
|
||||||
|
//! \brief Check if the memory is supported by current device.
|
||||||
|
bool isMemorySupported(uint32_t memoryId);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint32_t m_base_address; //!< Base address of the image.
|
||||||
|
SourceFile *m_sourceFile; //!< SourceFile object.
|
||||||
|
uint32_t m_memoryId; //!< ID of the memory to flush the image to.
|
||||||
|
progress_callback_t m_progressCallback; //!< Callback used to report update progress.
|
||||||
|
Progress m_progress; //!< Progress control.
|
||||||
|
standard_version_t m_version; //!< Version of the bootloader running on current device.
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // namespace blfwk
|
||||||
|
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
#endif // _Updater_h_
|
104
src/blfwk/UsbHidPacketizer.h
Normal file
104
src/blfwk/UsbHidPacketizer.h
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* Copyright 2015-2020 NXP.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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,
|
||||||
|
kPollAbortTimeoutMs = 10,
|
||||||
|
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
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
102
src/blfwk/UsbHidPeripheral.h
Normal file
102
src/blfwk/UsbHidPeripheral.h
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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
|
||||||
|
//kK32H_Pid = 0x0083 //!< PID for K32H (Ultra)
|
||||||
|
kK32H_Pid = 0x0052 //!< test pid (mx50)
|
||||||
|
};
|
||||||
|
|
||||||
|
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, const char *path);
|
||||||
|
|
||||||
|
//! @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 Return peripheral Type
|
||||||
|
virtual _host_peripheral_types get_type(void) { return kHostPeripheralType_USB_HID; }
|
||||||
|
|
||||||
|
//! @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;
|
||||||
|
std::string m_path;
|
||||||
|
hid_device *m_device; //!< Device handle.
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace blfwk
|
||||||
|
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
#endif // _UsbHidPeripheral_h_
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// EOF
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
206
src/blfwk/Value.h
Normal file
206
src/blfwk/Value.h
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
25
src/blfwk/bootloader_config.h
Normal file
25
src/blfwk/bootloader_config.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
58
src/blfwk/doc/blfwk.dox
Normal file
58
src/blfwk/doc/blfwk.dox
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*!
|
||||||
|
|
||||||
|
@defgroup blfwk Host Bootloader Framework
|
||||||
|
@brief Host Bootloader components.
|
||||||
|
|
||||||
|
@defgroup bus_pal Bus Pal Transport
|
||||||
|
@ingroup blfwk
|
||||||
|
@brief Bus Pal transport support.
|
||||||
|
|
||||||
|
@defgroup host_peripherals Peripherals
|
||||||
|
@ingroup blfwk
|
||||||
|
@brief Peripheral support.
|
||||||
|
|
||||||
|
@defgroup bus_pal_peripheral Bus Pal Peripheral
|
||||||
|
@ingroup host_peripherals
|
||||||
|
@brief Bus Pal Peripheral.
|
||||||
|
|
||||||
|
@defgroup uart_peripheral UART Peripheral
|
||||||
|
@ingroup host_peripherals
|
||||||
|
@brief UART Peripheral.
|
||||||
|
|
||||||
|
@defgroup host_usb_hid_peripheral USB-HID Peripheral
|
||||||
|
@ingroup host_peripherals
|
||||||
|
@brief USB-HID Peripheral.
|
||||||
|
|
||||||
|
@defgroup host_commands Commands
|
||||||
|
@ingroup blfwk
|
||||||
|
@brief Command support.
|
||||||
|
|
||||||
|
@defgroup host_packetizers Packetizers
|
||||||
|
@ingroup blfwk
|
||||||
|
@brief Packet creation.
|
||||||
|
|
||||||
|
@defgroup serial_packetizer Serial Packetizer
|
||||||
|
@ingroup host_packetizers
|
||||||
|
@brief Serial Packet creation.
|
||||||
|
|
||||||
|
@defgroup usb_hid_packetizer USB-HID Packetizer
|
||||||
|
@ingroup host_packetizers
|
||||||
|
@brief USB-HID Packet creation.
|
||||||
|
|
||||||
|
@defgroup logging Logging
|
||||||
|
@ingroup blfwk
|
||||||
|
@brief Logging support.
|
||||||
|
|
||||||
|
@defgroup smart_pointer Smart Pointer
|
||||||
|
@ingroup blfwk
|
||||||
|
@brief Smart pointer.
|
||||||
|
|
||||||
|
@defgroup host_error Error
|
||||||
|
@ingroup blfwk
|
||||||
|
@brief Errors.
|
||||||
|
|
||||||
|
@defgroup host_updater Updater
|
||||||
|
@ingroup blfwk
|
||||||
|
@brief Updater application support.
|
||||||
|
|
||||||
|
*/
|
18
src/blfwk/doc/blfwk.md
Normal file
18
src/blfwk/doc/blfwk.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
Host Bootloader Framework {#blfwk}
|
||||||
|
=====
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
-----
|
||||||
|
The Bootloader Framework is a library of C++ classes implementing communication from a host PC to bootloader firmware running on a target device. Due to the nature of the underlying bootloader command and data protocol, the Bootloader Frameworks supports all target devices without requiring any device-specific knowledge.
|
||||||
|
|
||||||
|
Applications
|
||||||
|
-----
|
||||||
|
The Bootloader Framework library is used by the Blhost command line tool and by the KinetisFlashTool GUI firmware download tool. It can be built as a library or included as source in a PC or embedded application. The current release includes tool chains to build the library for Windows OS and Mac OS X.
|
||||||
|
|
||||||
|
Peripherals
|
||||||
|
-----
|
||||||
|
Support for the following PC peripherals is included:
|
||||||
|
|
||||||
|
- UART (COM port)
|
||||||
|
- USB-HID (using custom reports)
|
||||||
|
- Bus Pal example (UART to I2C/SPI using special hardware)
|
18
src/blfwk/format_string.h
Normal file
18
src/blfwk/format_string.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
419
src/blfwk/hidapi.h
Normal file
419
src/blfwk/hidapi.h
Normal file
@ -0,0 +1,419 @@
|
|||||||
|
/*******************************************************
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length);
|
||||||
|
|
||||||
|
/** @brief Write an Output report to a HID device with timeout.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
int HID_API_EXPORT HID_API_CALL hid_write_timeout(hid_device *device,
|
||||||
|
const unsigned char *data,
|
||||||
|
size_t length,
|
||||||
|
int milliseconds);
|
||||||
|
|
||||||
|
/** @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
|
34
src/blfwk/host_types.h
Normal file
34
src/blfwk/host_types.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
86
src/blfwk/i2c.h
Normal file
86
src/blfwk/i2c.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 - 2022 NXP
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __I2C_H__
|
||||||
|
#define __I2C_H__
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <linux/i2c-dev.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
//! @addtogroup i2c
|
||||||
|
//! @{
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* API
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//! @name I2C
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! @brief Configure the opened device port.
|
||||||
|
//!
|
||||||
|
//! @param fd Device port handler.
|
||||||
|
//! @param speed Device clock frequency.
|
||||||
|
//! @param address Slave device address.
|
||||||
|
int i2c_setup(int fd, uint32_t speed, uint8_t address);
|
||||||
|
|
||||||
|
//! @brief Set the transfer timeout.
|
||||||
|
//!
|
||||||
|
//! @param fd Device port handler.
|
||||||
|
//! @param miliseconds Transfer timeout.
|
||||||
|
int i2c_set_timeout(int fd, uint32_t miliseconds);
|
||||||
|
|
||||||
|
//! @brief Write bytes.
|
||||||
|
//!
|
||||||
|
//! @param fd Device port handler.
|
||||||
|
//! @param buf Pointer to buffer.
|
||||||
|
//! @param size Number of bytes to write.
|
||||||
|
int i2c_write(int fd, char *buf, int size);
|
||||||
|
|
||||||
|
//! @brief Read bytes.
|
||||||
|
//!
|
||||||
|
//! @param fd Device port handler.
|
||||||
|
//! @param buf Pointer to buffer.
|
||||||
|
//! @param size Number of bytes to read.
|
||||||
|
int i2c_read(int fd, char *buf, int size);
|
||||||
|
|
||||||
|
//! @brief Open the device port.
|
||||||
|
//!
|
||||||
|
//! @param port Device port string.
|
||||||
|
int i2c_open(char *port);
|
||||||
|
|
||||||
|
//! @brief Close the device port.
|
||||||
|
//!
|
||||||
|
//! @param fd Device port handler.
|
||||||
|
int i2c_close(int fd);
|
||||||
|
|
||||||
|
//@}
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
#endif //__I2C_H__
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// EOF
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
27
src/blfwk/int_size.h
Normal file
27
src/blfwk/int_size.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
MinEraseAlignment = 1024,
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // 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
|
215
src/blfwk/smart_ptr.h
Normal file
215
src/blfwk/smart_ptr.h
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
#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_
|
86
src/blfwk/spi.h
Normal file
86
src/blfwk/spi.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 - 2022 NXP
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef __SPI_H__
|
||||||
|
#define __SPI_H__
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <linux/spi/spidev.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
//! @addtogroup spi
|
||||||
|
//! @{
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* API
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//! @name SPI
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! @brief Configure the opened device port.
|
||||||
|
//!
|
||||||
|
//! @param fd Device port handler.
|
||||||
|
//! @param speed Device clock frequency.
|
||||||
|
//! @param mode Polarity and phase mode.
|
||||||
|
//! @param bits_per_word Transfer size.
|
||||||
|
int spi_setup(int fd, uint32_t speed, uint32_t mode, uint32_t bits_per_word);
|
||||||
|
|
||||||
|
//! @brief Set the transfer timeout.
|
||||||
|
//!
|
||||||
|
//! @param fd Device port handler.
|
||||||
|
//! @param miliseconds Transfer timeout.
|
||||||
|
int spi_set_timeout(int fd, uint32_t miliseconds);
|
||||||
|
|
||||||
|
//! @brief Write bytes.
|
||||||
|
//!
|
||||||
|
//! @param fd Device port handler.
|
||||||
|
//! @param buf Pointer to buffer.
|
||||||
|
//! @param size Number of bytes to write.
|
||||||
|
int spi_write(int fd, char *buf, int size);
|
||||||
|
|
||||||
|
//! @brief Read bytes.
|
||||||
|
//!
|
||||||
|
//! @param fd Device port handler.
|
||||||
|
//! @param buf Pointer to buffer.
|
||||||
|
//! @param size Number of bytes to read.
|
||||||
|
int spi_read(int fd, char *buf, int size);
|
||||||
|
|
||||||
|
//! @brief Open the device port.
|
||||||
|
//!
|
||||||
|
//! @param port Device port string.
|
||||||
|
int spi_open(char *port);
|
||||||
|
|
||||||
|
//! @brief Close the device port.
|
||||||
|
//!
|
||||||
|
//! @param fd Device port handler.
|
||||||
|
int spi_close(int fd);
|
||||||
|
|
||||||
|
//@}
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
#endif //__SPI_H__
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// EOF
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
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;
|
||||||
|
}
|
359
src/blfwk/src/Bootloader.cpp
Normal file
359
src/blfwk/src/Bootloader.cpp
Normal file
@ -0,0 +1,359 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* Copyright 2015-2020 NXP
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "blfwk/Bootloader.h"
|
||||||
|
#include "blfwk/BusPalPeripheral.h"
|
||||||
|
#include "blfwk/LpcUsbSioPeripheral.h"
|
||||||
|
#include "blfwk/SerialPacketizer.h"
|
||||||
|
#include "blfwk/UartPeripheral.h"
|
||||||
|
#if defined(LINUX) && defined(__ARM__)
|
||||||
|
#include "blfwk/I2cPeripheral.h"
|
||||||
|
#include "blfwk/SpiPeripheral.h"
|
||||||
|
#endif
|
||||||
|
#include "blfwk/UsbHidPacketizer.h"
|
||||||
|
#include "blfwk/UsbHidPeripheral.h"
|
||||||
|
#include "blfwk/format_string.h"
|
||||||
|
#include "blfwk/json.h"
|
||||||
|
#include "blfwk/utils.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, NULL);
|
||||||
|
}
|
||||||
|
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 = NULL;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
peripheral = new UsbHidPeripheral(config.usbHidVid, config.usbHidPid, config.usbHidSerialNumber.c_str(),
|
||||||
|
config.usbPath.c_str());
|
||||||
|
m_hostPacketizer = new UsbHidPacketizer(peripheral, config.packetTimeoutMs);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
delete peripheral;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#if defined(LINUX) && defined(__ARM__)
|
||||||
|
case Peripheral::kHostPeripheralType_I2C:
|
||||||
|
{
|
||||||
|
I2cPeripheral *peripheral =
|
||||||
|
new I2cPeripheral(config.comPortName.c_str(), config.i2cAddress, config.comPortSpeed);
|
||||||
|
m_hostPacketizer = new SerialPacketizer(peripheral, config.packetTimeoutMs);
|
||||||
|
|
||||||
|
if (config.ping)
|
||||||
|
{
|
||||||
|
// Send initial ping.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ping(0, 0, config.comPortSpeed, NULL);
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(format_string("Error: Initial ping failure: %s", e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Peripheral::kHostPeripheralType_SPI:
|
||||||
|
{
|
||||||
|
SpiPeripheral *peripheral = new SpiPeripheral(config.comPortName.c_str(), config.comPortSpeed,
|
||||||
|
config.spiPolarity, config.spiPhase, config.spiSequence);
|
||||||
|
m_hostPacketizer = new SerialPacketizer(peripheral, config.packetTimeoutMs);
|
||||||
|
|
||||||
|
if (config.ping)
|
||||||
|
{
|
||||||
|
// Send initial ping.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ping(0, 0, config.comPortSpeed, NULL);
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(format_string("Error: Initial ping failure: %s", e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif // #if defined(LINUX) && defined(__ARM__)
|
||||||
|
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, NULL);
|
||||||
|
}
|
||||||
|
catch (const std::exception &e)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(format_string("Error: Initial ping failure: %s", e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#if defined(LPCUSBSIO)
|
||||||
|
case Peripheral::kHostPeripheralType_LPCUSBSIO:
|
||||||
|
{
|
||||||
|
LpcUsbSioPeripheral *peripheral = new LpcUsbSioPeripheral(config.lpcUsbSioConfig);
|
||||||
|
m_hostPacketizer = new SerialPacketizer(peripheral, config.packetTimeoutMs);
|
||||||
|
|
||||||
|
if (config.ping)
|
||||||
|
{
|
||||||
|
// Send initial ping.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ping(0, 0, 0, NULL);
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
#endif // #if defined(LPCUSBSIO)
|
||||||
|
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.
|
||||||
|
if (m_hostPacketizer)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_vector_t Bootloader::getProperty(property_t tag, uint32_t memoryIdorIndex)
|
||||||
|
{
|
||||||
|
// Inject the get-property(tag) command.
|
||||||
|
GetProperty cmd(tag, memoryIdorIndex);
|
||||||
|
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.
|
||||||
|
bool Bootloader::isCommandSupported(const cmd_t &command)
|
||||||
|
{
|
||||||
|
uint32_t fw_response = getProperty(kProperty_AvailableCommands, 0).at(1);
|
||||||
|
|
||||||
|
// See if the command is supported.
|
||||||
|
return ((fw_response & command.mask) == command.mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
// See host_bootloader.h for documentation of this method.
|
||||||
|
standard_version_t Bootloader::getVersion()
|
||||||
|
{
|
||||||
|
return standard_version_t(getProperty(kProperty_CurrentVersion, 0).at(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// See host_bootloader.h for documentation of this method.
|
||||||
|
uint32_t Bootloader::getSecurityState()
|
||||||
|
{
|
||||||
|
// Inject the get-property 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 getProperty(kProperty_FlashSecurityState, 0).at(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// See host_bootloader.h for documentation of this method.
|
||||||
|
uint32_t Bootloader::getDataPacketSize()
|
||||||
|
{
|
||||||
|
return getProperty(kProperty_MaxPacketSize, 0).at(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// See host_bootloader.h for documentation of this method.
|
||||||
|
void Bootloader::ping(int retries, unsigned int delay, int comSpeed, int *actualComSpeed)
|
||||||
|
{
|
||||||
|
this->flush();
|
||||||
|
|
||||||
|
SerialPacketizer *pPacketizer = dynamic_cast<SerialPacketizer *>(m_hostPacketizer);
|
||||||
|
if (pPacketizer)
|
||||||
|
{
|
||||||
|
status_t status = pPacketizer->ping(retries, delay, NULL, comSpeed, actualComSpeed);
|
||||||
|
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<Json::UInt>(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
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
1353
src/blfwk/src/BusPal.cpp
Normal file
1353
src/blfwk/src/BusPal.cpp
Normal file
File diff suppressed because it is too large
Load Diff
239
src/blfwk/src/BusPalPeripheral.cpp
Normal file
239
src/blfwk/src/BusPalPeripheral.cpp
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* Copyright 2015-2020 NXP.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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()
|
||||||
|
{
|
||||||
|
if (m_busPal)
|
||||||
|
{
|
||||||
|
free(m_busPal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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_SAI:
|
||||||
|
if (!m_busPal->enterSaiMode())
|
||||||
|
{
|
||||||
|
throw std::runtime_error(format_string("Error: BusPalUartPeripheral() cannot enter SAI Mode."));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_busPal->setSaiSpeed(config.saiSpeedHz))
|
||||||
|
{
|
||||||
|
throw std::runtime_error(
|
||||||
|
format_string("Error: BusPalUartPeripheral() cannot set SAI speed(%d Hz).", config.saiSpeedHz));
|
||||||
|
}
|
||||||
|
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
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
4495
src/blfwk/src/Command.cpp
Normal file
4495
src/blfwk/src/Command.cpp
Normal file
File diff suppressed because it is too large
Load Diff
44
src/blfwk/src/Crc.cpp
Normal file
44
src/blfwk/src/Crc.cpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2015 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "blfwk/Crc.h"
|
||||||
|
#include "property/property.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;
|
||||||
|
}
|
258
src/blfwk/src/DataSource.cpp
Normal file
258
src/blfwk/src/DataSource.cpp
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
}
|
60
src/blfwk/src/DataTarget.cpp
Normal file
60
src/blfwk/src/DataTarget.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
627
src/blfwk/src/ELFSourceFile.cpp
Normal file
627
src/blfwk/src/ELFSourceFile.cpp
Normal file
@ -0,0 +1,627 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* Copyright 2015-2020 NXP
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "blfwk/ELFSourceFile.h"
|
||||||
|
#include "blfwk/GHSSecInfo.h"
|
||||||
|
#include "blfwk/Logging.h"
|
||||||
|
#ifdef LINUX
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//! The name of the toolset option.
|
||||||
|
#define kToolsetOptionName "toolset"
|
||||||
|
#define kGHSToolsetName "GHS"
|
||||||
|
#define kGCCToolsetName "GCC"
|
||||||
|
#define kGNUToolsetName "GNU"
|
||||||
|
#define kADSToolsetName "ADS"
|
||||||
|
|
||||||
|
//! Name of the option to control .secinfo action.
|
||||||
|
#define kSecinfoClearOptionName "secinfoClear"
|
||||||
|
#define kSecinfoDefaultName "DEFAULT"
|
||||||
|
#define kSecinfoIgnoreName "IGNORE"
|
||||||
|
#define kSecinfoROMName "ROM"
|
||||||
|
#define kSecinfoCName "C"
|
||||||
|
|
||||||
|
using namespace blfwk;
|
||||||
|
|
||||||
|
ELFSourceFile::ELFSourceFile(const std::string &path)
|
||||||
|
: SourceFile(path, kELFSourceFile)
|
||||||
|
, m_toolset(kUnknownToolset)
|
||||||
|
, m_secinfoOption(kSecinfoDefault)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ELFSourceFile::~ELFSourceFile() {}
|
||||||
|
|
||||||
|
bool ELFSourceFile::isELFFile(std::istream &stream)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
StELFFile elf(stream);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ELFSourceFile::open()
|
||||||
|
{
|
||||||
|
// Read toolset option
|
||||||
|
m_toolset = readToolsetOption();
|
||||||
|
|
||||||
|
// Read option and select default value
|
||||||
|
m_secinfoOption = readSecinfoClearOption();
|
||||||
|
if (m_secinfoOption == kSecinfoDefault)
|
||||||
|
{
|
||||||
|
m_secinfoOption = kSecinfoCStartupClear;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the stream
|
||||||
|
SourceFile::open();
|
||||||
|
|
||||||
|
m_file = new StELFFile(*m_stream);
|
||||||
|
// m_file->dumpSections();
|
||||||
|
|
||||||
|
// Set toolset in elf file object
|
||||||
|
switch (m_toolset)
|
||||||
|
{
|
||||||
|
// default toolset is GHS
|
||||||
|
case kGHSToolset:
|
||||||
|
case kUnknownToolset:
|
||||||
|
m_file->setELFVariant(eGHSVariant);
|
||||||
|
break;
|
||||||
|
case kGCCToolset:
|
||||||
|
m_file->setELFVariant(eGCCVariant);
|
||||||
|
break;
|
||||||
|
case kADSToolset:
|
||||||
|
m_file->setELFVariant(eARMVariant);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ELFSourceFile::close()
|
||||||
|
{
|
||||||
|
SourceFile::close();
|
||||||
|
|
||||||
|
m_file.safe_delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
elf_toolset_t ELFSourceFile::readToolsetOption()
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const OptionContext *options = getOptions();
|
||||||
|
if (!options || !options->hasOption(kToolsetOptionName))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Value *value = options->getOption(kToolsetOptionName);
|
||||||
|
const StringValue *stringValue = dynamic_cast<const StringValue *>(value);
|
||||||
|
if (!stringValue)
|
||||||
|
{
|
||||||
|
// Not a string value, warn the user.
|
||||||
|
Log::log(Logger::kWarning, "invalid type for 'toolset' option\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string toolsetName = *stringValue;
|
||||||
|
|
||||||
|
// convert option value to uppercase
|
||||||
|
std::transform<std::string::const_iterator, std::string::iterator, int (*)(int)>(
|
||||||
|
toolsetName.begin(), toolsetName.end(), toolsetName.begin(), toupper);
|
||||||
|
|
||||||
|
if (toolsetName == kGHSToolsetName)
|
||||||
|
{
|
||||||
|
return kGHSToolset;
|
||||||
|
}
|
||||||
|
else if (toolsetName == kGCCToolsetName || toolsetName == kGNUToolsetName)
|
||||||
|
{
|
||||||
|
return kGCCToolset;
|
||||||
|
}
|
||||||
|
else if (toolsetName == kADSToolsetName)
|
||||||
|
{
|
||||||
|
return kADSToolset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unrecognized option value, log a warning.
|
||||||
|
Log::log(Logger::kWarning, "unrecognized value for 'toolset' option\n");
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
return kUnknownToolset;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! It is up to the caller to convert from kSecinfoDefault to the actual default
|
||||||
|
//! value.
|
||||||
|
secinfo_clear_t ELFSourceFile::readSecinfoClearOption()
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
const OptionContext *options = getOptions();
|
||||||
|
if (!options || !options->hasOption(kSecinfoClearOptionName))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Value *value = options->getOption(kSecinfoClearOptionName);
|
||||||
|
const StringValue *stringValue = dynamic_cast<const StringValue *>(value);
|
||||||
|
if (!stringValue)
|
||||||
|
{
|
||||||
|
// Not a string value, warn the user.
|
||||||
|
Log::log(Logger::kWarning, "invalid type for 'secinfoClear' option\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string secinfoOption = *stringValue;
|
||||||
|
|
||||||
|
// convert option value to uppercase
|
||||||
|
std::transform<std::string::const_iterator, std::string::iterator, int (*)(int)>(
|
||||||
|
secinfoOption.begin(), secinfoOption.end(), secinfoOption.begin(), toupper);
|
||||||
|
|
||||||
|
if (secinfoOption == kSecinfoDefaultName)
|
||||||
|
{
|
||||||
|
return kSecinfoDefault;
|
||||||
|
}
|
||||||
|
else if (secinfoOption == kSecinfoIgnoreName)
|
||||||
|
{
|
||||||
|
return kSecinfoIgnore;
|
||||||
|
}
|
||||||
|
else if (secinfoOption == kSecinfoROMName)
|
||||||
|
{
|
||||||
|
return kSecinfoROMClear;
|
||||||
|
}
|
||||||
|
else if (secinfoOption == kSecinfoCName)
|
||||||
|
{
|
||||||
|
return kSecinfoCStartupClear;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unrecognized option value, log a warning.
|
||||||
|
Log::log(Logger::kWarning, "unrecognized value for 'secinfoClear' option\n");
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
return kSecinfoDefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! To create a data source for all sections of the ELF file, a WildcardMatcher
|
||||||
|
//! is instantiated and passed to createDataSource(StringMatcher&).
|
||||||
|
DataSource *ELFSourceFile::createDataSource()
|
||||||
|
{
|
||||||
|
WildcardMatcher matcher;
|
||||||
|
return createDataSource(matcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
DataSource *ELFSourceFile::createDataSource(const std::vector<uint32_t> &baseAddresses, bool match)
|
||||||
|
{
|
||||||
|
assert(m_file);
|
||||||
|
ELFDataSource *source = new ELFDataSource(m_file);
|
||||||
|
source->setSecinfoOption(m_secinfoOption);
|
||||||
|
|
||||||
|
if (match)
|
||||||
|
{
|
||||||
|
Log::log(Logger::kDebug2, "filtering sections of file that match base addresses: 0x%08X\n", baseAddresses[0]);
|
||||||
|
for (unsigned i = 1; i < baseAddresses.size(); i++)
|
||||||
|
{
|
||||||
|
Log::log(Logger::kDebug2, " 0x%08X\n",
|
||||||
|
baseAddresses[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log::log(Logger::kDebug2, "filtering sections of file that exclude base addresses: 0x%08X\n", baseAddresses[0]);
|
||||||
|
for (unsigned i = 1; i < baseAddresses.size(); i++)
|
||||||
|
{
|
||||||
|
Log::log(Logger::kDebug2, " 0x%08X\n",
|
||||||
|
baseAddresses[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// We start at section 1 to skip the null section that is always first.
|
||||||
|
unsigned index = 1;
|
||||||
|
for (; index < m_file->getSectionCount(); ++index)
|
||||||
|
{
|
||||||
|
const Elf32_Shdr &header = m_file->getSectionAtIndex(index);
|
||||||
|
std::string name = m_file->getSectionNameAtIndex(header.sh_name);
|
||||||
|
|
||||||
|
// Ignore most section types
|
||||||
|
if (!(header.sh_type == SHT_PROGBITS || header.sh_type == SHT_NOBITS))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore sections that don't have the allocate flag set.
|
||||||
|
if ((header.sh_flags & SHF_ALLOC) == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains =
|
||||||
|
std::find(baseAddresses.begin(), baseAddresses.end(), header.sh_addr) != baseAddresses.end();
|
||||||
|
|
||||||
|
// If we are not matching the supplied address then we will add any section that does not have the
|
||||||
|
// baseAddress If we are matching we will only include the section that matches the baseAddress
|
||||||
|
if ((!match && !contains) || (match && contains))
|
||||||
|
{
|
||||||
|
Log::log(Logger::kDebug2, "creating segment for section %s with base address = 0x%08X\n", name.c_str(),
|
||||||
|
header.sh_addr);
|
||||||
|
source->addSection(index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log::log(Logger::kDebug2, "section %s with base address of 0x%08X is excluded\n", name.c_str(),
|
||||||
|
header.sh_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
delete source;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::log(Logger::kDebug2, "\n");
|
||||||
|
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
DataSource *ELFSourceFile::createDataSource(StringMatcher &matcher)
|
||||||
|
{
|
||||||
|
assert(m_file);
|
||||||
|
ELFDataSource *source = new ELFDataSource(m_file);
|
||||||
|
source->setSecinfoOption(m_secinfoOption);
|
||||||
|
|
||||||
|
Log::log(Logger::kDebug2, "filtering sections of file: %s\n", getPath().c_str());
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// We start at section 1 to skip the null section that is always first.
|
||||||
|
unsigned index = 1;
|
||||||
|
for (; index < m_file->getSectionCount(); ++index)
|
||||||
|
{
|
||||||
|
const Elf32_Shdr &header = m_file->getSectionAtIndex(index);
|
||||||
|
std::string name = m_file->getSectionNameAtIndex(header.sh_name);
|
||||||
|
|
||||||
|
// Ignore most section types
|
||||||
|
if (!(header.sh_type == SHT_PROGBITS || header.sh_type == SHT_NOBITS))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore sections that don't have the allocate flag set.
|
||||||
|
if ((header.sh_flags & SHF_ALLOC) == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matcher.match(name))
|
||||||
|
{
|
||||||
|
Log::log(Logger::kDebug2, "creating segment for section %s\n", name.c_str());
|
||||||
|
source->addSection(index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log::log(Logger::kDebug2, "section %s did not match\n", name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
delete source;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! It is assumed that all ELF files have an entry point.
|
||||||
|
//!
|
||||||
|
bool ELFSourceFile::hasEntryPoint()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! The StELFFile::getTypeOfSymbolAtIndex() method uses different methods of determining
|
||||||
|
//! ARM/Thumb mode depending on the toolset.
|
||||||
|
uint32_t ELFSourceFile::getEntryPointAddress()
|
||||||
|
{
|
||||||
|
uint32_t entryPoint = 0;
|
||||||
|
|
||||||
|
// get entry point address
|
||||||
|
const Elf32_Ehdr &header = m_file->getFileHeader();
|
||||||
|
|
||||||
|
// find symbol corresponding to entry point and determine if
|
||||||
|
// it is arm or thumb mode
|
||||||
|
unsigned symbolIndex = m_file->getIndexOfSymbolAtAddress(header.e_entry);
|
||||||
|
if (symbolIndex != 0)
|
||||||
|
{
|
||||||
|
ARMSymbolType_t symbolType = m_file->getTypeOfSymbolAtIndex(symbolIndex);
|
||||||
|
bool entryPointIsThumb = (symbolType == eThumbSymbol);
|
||||||
|
const Elf32_Sym &symbol = m_file->getSymbolAtIndex(symbolIndex);
|
||||||
|
std::string symbolName = m_file->getSymbolName(symbol);
|
||||||
|
|
||||||
|
Log::log(Logger::kDebug2, "Entry point is %s@0x%08x (%s)\n", symbolName.c_str(), symbol.st_value,
|
||||||
|
entryPointIsThumb ? "Thumb" : "ARM");
|
||||||
|
|
||||||
|
// set entry point, setting the low bit if it is thumb mode
|
||||||
|
entryPoint = header.e_entry + (entryPointIsThumb ? 1 : 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entryPoint = header.e_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
return entryPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \return A DataTarget that describes the named section.
|
||||||
|
//! \retval NULL There was no section with the requested name.
|
||||||
|
DataTarget *ELFSourceFile::createDataTargetForSection(const std::string §ion)
|
||||||
|
{
|
||||||
|
assert(m_file);
|
||||||
|
unsigned index = m_file->getIndexOfSectionWithName(section);
|
||||||
|
if (index == SHN_UNDEF)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Elf32_Shdr §ionHeader = m_file->getSectionAtIndex(index);
|
||||||
|
uint32_t beginAddress = sectionHeader.sh_addr;
|
||||||
|
uint32_t endAddress = beginAddress + sectionHeader.sh_size;
|
||||||
|
ConstantDataTarget *target = new ConstantDataTarget(beginAddress, endAddress);
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \return A DataTarget instance pointing at the requested symbol.
|
||||||
|
//! \retval NULL No symbol matching the requested name was found.
|
||||||
|
DataTarget *ELFSourceFile::createDataTargetForSymbol(const std::string &symbol)
|
||||||
|
{
|
||||||
|
assert(m_file);
|
||||||
|
unsigned symbolCount = m_file->getSymbolCount();
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < symbolCount; ++i)
|
||||||
|
{
|
||||||
|
const Elf32_Sym &symbolHeader = m_file->getSymbolAtIndex(i);
|
||||||
|
std::string symbolName = m_file->getSymbolName(symbolHeader);
|
||||||
|
if (symbolName == symbol)
|
||||||
|
{
|
||||||
|
ARMSymbolType_t symbolType = m_file->getTypeOfSymbolAtIndex(i);
|
||||||
|
bool symbolIsThumb = (symbolType == eThumbSymbol);
|
||||||
|
|
||||||
|
uint32_t beginAddress = symbolHeader.st_value + (symbolIsThumb ? 1 : 0);
|
||||||
|
uint32_t endAddress = beginAddress + symbolHeader.st_size;
|
||||||
|
ConstantDataTarget *target = new ConstantDataTarget(beginAddress, endAddress);
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// didn't find a matching symbol
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ELFSourceFile::hasSymbol(const std::string &name)
|
||||||
|
{
|
||||||
|
Elf32_Sym symbol;
|
||||||
|
return lookupSymbol(name, symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ELFSourceFile::getSymbolValue(const std::string &name)
|
||||||
|
{
|
||||||
|
unsigned symbolCount = m_file->getSymbolCount();
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < symbolCount; ++i)
|
||||||
|
{
|
||||||
|
const Elf32_Sym &symbolHeader = m_file->getSymbolAtIndex(i);
|
||||||
|
std::string symbolName = m_file->getSymbolName(symbolHeader);
|
||||||
|
if (symbolName == name)
|
||||||
|
{
|
||||||
|
// If the symbol is a function, then we check to see if it is Thumb code and set bit 0 if so.
|
||||||
|
if (ELF32_ST_TYPE(symbolHeader.st_info) == STT_FUNC)
|
||||||
|
{
|
||||||
|
ARMSymbolType_t symbolType = m_file->getTypeOfSymbolAtIndex(i);
|
||||||
|
bool symbolIsThumb = (symbolType == eThumbSymbol);
|
||||||
|
return symbolHeader.st_value + (symbolIsThumb ? 1 : 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return symbolHeader.st_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Couldn't find the symbol, so return 0.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned ELFSourceFile::getSymbolSize(const std::string &name)
|
||||||
|
{
|
||||||
|
Elf32_Sym symbol;
|
||||||
|
if (!lookupSymbol(name, symbol))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return symbol.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \param name The name of the symbol on which info is wanted.
|
||||||
|
//! \param[out] info Upon succssful return this is filled in with the symbol's information.
|
||||||
|
//!
|
||||||
|
//! \retval true The symbol was found and \a info is valid.
|
||||||
|
//! \retval false No symbol with \a name was found in the file.
|
||||||
|
bool ELFSourceFile::lookupSymbol(const std::string &name, Elf32_Sym &info)
|
||||||
|
{
|
||||||
|
assert(m_file);
|
||||||
|
unsigned symbolCount = m_file->getSymbolCount();
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < symbolCount; ++i)
|
||||||
|
{
|
||||||
|
const Elf32_Sym &symbol = m_file->getSymbolAtIndex(i);
|
||||||
|
std::string thisSymbolName = m_file->getSymbolName(symbol);
|
||||||
|
|
||||||
|
// Is this the symbol we're looking for?
|
||||||
|
if (thisSymbolName == name)
|
||||||
|
{
|
||||||
|
info = symbol;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Didn't file the symbol.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ELFSourceFile::ELFDataSource::~ELFDataSource()
|
||||||
|
{
|
||||||
|
segment_vector_t::iterator it = m_segments.begin();
|
||||||
|
for (; it != m_segments.end(); ++it)
|
||||||
|
{
|
||||||
|
delete *it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Not all sections will actually result in a new segment being created. Only
|
||||||
|
//! those sections whose type is #SHT_PROGBITS or #SHT_NOBITS will create
|
||||||
|
//! a new segment. Also, only sections whose size is non-zero will actually
|
||||||
|
//! create a segment.
|
||||||
|
//!
|
||||||
|
//! In addition to this, ELF files that have been marked as being created by
|
||||||
|
//! the Green Hills Software toolset have an extra step. #SHT_NOBITS sections
|
||||||
|
//! are looked up in the .secinfo section to determine if they really
|
||||||
|
//! should be filled. If not in the .secinfo table, no segment will be
|
||||||
|
//! created for the section.
|
||||||
|
void ELFSourceFile::ELFDataSource::addSection(unsigned sectionIndex)
|
||||||
|
{
|
||||||
|
// get section info
|
||||||
|
const Elf32_Shdr §ion = m_elf->getSectionAtIndex(sectionIndex);
|
||||||
|
if (section.sh_size == 0)
|
||||||
|
{
|
||||||
|
// empty section, so ignore it
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the right segment subclass based on the section type
|
||||||
|
DataSource::Segment *segment = NULL;
|
||||||
|
if (section.sh_type == SHT_PROGBITS)
|
||||||
|
{
|
||||||
|
segment = new ProgBitsSegment(*this, m_elf, sectionIndex);
|
||||||
|
}
|
||||||
|
else if (section.sh_type == SHT_NOBITS)
|
||||||
|
{
|
||||||
|
// Always add NOBITS sections by default.
|
||||||
|
bool addNobits = true;
|
||||||
|
|
||||||
|
// For GHS ELF files, we use the secinfoClear option to figure out what to do.
|
||||||
|
// If set to ignore, treat like a normal ELF file and always add. If set to
|
||||||
|
// ROM, then only clear if the section is listed in .secinfo. Otherwise if set
|
||||||
|
// to C startup, then let the C startup do all clearing.
|
||||||
|
if (m_elf->ELFVariant() == eGHSVariant)
|
||||||
|
{
|
||||||
|
GHSSecInfo secinfo(m_elf);
|
||||||
|
|
||||||
|
// If there isn't a .secinfo section present then use the normal ELF rules
|
||||||
|
// and always add NOBITS sections.
|
||||||
|
if (secinfo.hasSecinfo() && m_secinfoOption != kSecinfoIgnore)
|
||||||
|
{
|
||||||
|
switch (m_secinfoOption)
|
||||||
|
{
|
||||||
|
case kSecinfoROMClear:
|
||||||
|
addNobits = secinfo.isSectionFilled(section);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kSecinfoCStartupClear:
|
||||||
|
addNobits = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Do nothing.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addNobits)
|
||||||
|
{
|
||||||
|
segment = new NoBitsSegment(*this, m_elf, sectionIndex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string name = m_elf->getSectionNameAtIndex(section.sh_name);
|
||||||
|
Log::log(Logger::kDebug2, "..section %s is not filled\n", name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add segment if one was created
|
||||||
|
if (segment)
|
||||||
|
{
|
||||||
|
m_segments.push_back(segment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ELFSourceFile::ELFDataSource::ProgBitsSegment::ProgBitsSegment(ELFDataSource &source, StELFFile *elf, unsigned index)
|
||||||
|
: DataSource::Segment(source)
|
||||||
|
, m_elf(elf)
|
||||||
|
, m_sectionIndex(index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned ELFSourceFile::ELFDataSource::ProgBitsSegment::getData(unsigned offset, unsigned maxBytes, uint8_t *buffer)
|
||||||
|
{
|
||||||
|
const Elf32_Shdr §ion = m_elf->getSectionAtIndex(m_sectionIndex);
|
||||||
|
uint8_t *data = m_elf->getSectionDataAtIndex(m_sectionIndex);
|
||||||
|
|
||||||
|
assert(offset < section.sh_size);
|
||||||
|
|
||||||
|
unsigned copyBytes = std::min<unsigned>(section.sh_size - offset, maxBytes);
|
||||||
|
if (copyBytes)
|
||||||
|
{
|
||||||
|
memcpy(buffer, &data[offset], copyBytes);
|
||||||
|
}
|
||||||
|
delete[] data;
|
||||||
|
return copyBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned ELFSourceFile::ELFDataSource::ProgBitsSegment::getLength()
|
||||||
|
{
|
||||||
|
const Elf32_Shdr §ion = m_elf->getSectionAtIndex(m_sectionIndex);
|
||||||
|
return section.sh_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ELFSourceFile::ELFDataSource::ProgBitsSegment::getBaseAddress()
|
||||||
|
{
|
||||||
|
const Elf32_Shdr §ion = m_elf->getSectionAtIndex(m_sectionIndex);
|
||||||
|
return section.sh_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ELFSourceFile::ELFDataSource::NoBitsSegment::NoBitsSegment(ELFDataSource &source, StELFFile *elf, unsigned index)
|
||||||
|
: DataSource::PatternSegment(source)
|
||||||
|
, m_elf(elf)
|
||||||
|
, m_sectionIndex(index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned ELFSourceFile::ELFDataSource::NoBitsSegment::getLength()
|
||||||
|
{
|
||||||
|
const Elf32_Shdr §ion = m_elf->getSectionAtIndex(m_sectionIndex);
|
||||||
|
return section.sh_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ELFSourceFile::ELFDataSource::NoBitsSegment::getBaseAddress()
|
||||||
|
{
|
||||||
|
const Elf32_Shdr §ion = m_elf->getSectionAtIndex(m_sectionIndex);
|
||||||
|
return section.sh_addr;
|
||||||
|
}
|
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]);
|
||||||
|
}
|
130
src/blfwk/src/I2cPeripheral.cpp
Normal file
130
src/blfwk/src/I2cPeripheral.cpp
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 - 2022 NXP
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "blfwk/I2cPeripheral.h"
|
||||||
|
#include "blfwk/Logging.h"
|
||||||
|
#include "blfwk/format_string.h"
|
||||||
|
#include "blfwk/i2c.h"
|
||||||
|
|
||||||
|
using namespace blfwk;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Code
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// See I2cPeripheral.h for documentation of this method.
|
||||||
|
I2cPeripheral::I2cPeripheral(const char *port, long speed, uint8_t address)
|
||||||
|
: m_fileDescriptor(-1)
|
||||||
|
{
|
||||||
|
if (!init(port, address, speed))
|
||||||
|
{
|
||||||
|
throw std::runtime_error(format_string("Error: Cannot open I2C port(%s), speed(%d Hz).\n", port, speed));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See I2cPeripheral.h for documentation of this method.
|
||||||
|
bool I2cPeripheral::init(const char *port, long speed, uint8_t address)
|
||||||
|
{
|
||||||
|
assert(port);
|
||||||
|
|
||||||
|
// Open the port.
|
||||||
|
m_fileDescriptor = i2c_open(const_cast<char *>(port));
|
||||||
|
if (m_fileDescriptor == -1)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_setup(m_fileDescriptor, speed, address);
|
||||||
|
|
||||||
|
// Flush garbage from receive buffer before setting read timeout.
|
||||||
|
flushRX();
|
||||||
|
|
||||||
|
// Set host serial timeout to 10 milliseconds. Higherlevel timeouts are implemented in
|
||||||
|
// SerialPacketizer.cpp
|
||||||
|
i2c_set_timeout(m_fileDescriptor, kI2cPeripheral_DefaultReadTimeoutMs);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See I2cPeripheral.h for documentation of this method.
|
||||||
|
I2cPeripheral::~I2cPeripheral()
|
||||||
|
{
|
||||||
|
if (m_fileDescriptor != -1)
|
||||||
|
{
|
||||||
|
i2c_close(m_fileDescriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See I2cPeripheral.h for documentation of this method.
|
||||||
|
status_t I2cPeripheral::read(uint8_t *buffer, uint32_t requestedBytes, uint32_t *actualBytes, uint32_t unused_timeoutMs)
|
||||||
|
{
|
||||||
|
assert(buffer);
|
||||||
|
|
||||||
|
// Read the requested number of bytes.
|
||||||
|
int count = i2c_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 I2cPeripheral.h for documentation of this method.
|
||||||
|
void I2cPeripheral::flushRX() {}
|
||||||
|
|
||||||
|
// See I2cPeripheral.h for documentation of this method.
|
||||||
|
status_t I2cPeripheral::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 (i2c_write(m_fileDescriptor, reinterpret_cast<char *>(const_cast<uint8_t *>(buffer)), byteCount) == byteCount)
|
||||||
|
return kStatus_Success;
|
||||||
|
else
|
||||||
|
return kStatus_Fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// EOF
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
225
src/blfwk/src/IntelHexSourceFile.cpp
Normal file
225
src/blfwk/src/IntelHexSourceFile.cpp
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2015 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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_file(NULL)
|
||||||
|
, m_image(0)
|
||||||
|
, m_hasEntryRecord(false)
|
||||||
|
{
|
||||||
|
memset(&m_entryRecord, 0, sizeof(m_entryRecord));
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
228
src/blfwk/src/Logging.cpp
Normal file
228
src/blfwk/src/Logging.cpp
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* Copyright 2015-2020 NXP.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "blfwk/Logging.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()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_logFile.close();
|
||||||
|
}
|
||||||
|
catch (std::ios_base::failure &e)
|
||||||
|
{
|
||||||
|
printf("Error: Failed to close the log file(%s)", e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileLogger::_log(const char *msg)
|
||||||
|
{
|
||||||
|
m_logFile << msg;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_logFile.flush();
|
||||||
|
}
|
||||||
|
catch (std::ios_base::failure &e)
|
||||||
|
{
|
||||||
|
printf("Error: Failed to write the log file(%s)", e.what());
|
||||||
|
}
|
||||||
|
}
|
477
src/blfwk/src/LpcUsbSio.cpp
Normal file
477
src/blfwk/src/LpcUsbSio.cpp
Normal file
@ -0,0 +1,477 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 - 2022 NXP
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "blfwk/Logging.h"
|
||||||
|
#include "blfwk/LpcUsbSio.h"
|
||||||
|
#include "blfwk/format_string.h"
|
||||||
|
|
||||||
|
using namespace blfwk;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Definitions
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//! This macro converts a value from KHz to Hz.
|
||||||
|
#define CONVERT_KHZ_TO_HZ(KHz) (KHz * 1000)
|
||||||
|
|
||||||
|
//! This struct maps an error code to a description of that code.
|
||||||
|
struct LpcUsbSioErrorMessage
|
||||||
|
{
|
||||||
|
LPCUSBSIO_ERR_T code; //!< Error code value.
|
||||||
|
const std::string message; //!< Description of the status.
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Variables
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//! This variable containing error codes and corresponding descriptions of the codes.
|
||||||
|
LpcUsbSioErrorMessage s_errorMessage[] = {
|
||||||
|
{ LPCUSBSIO_OK, "Success" },
|
||||||
|
{ LPCUSBSIO_ERR_HID_LIB, "HID library error" },
|
||||||
|
{ LPCUSBSIO_ERR_BAD_HANDLE, "Handle passed to the function is invalid" },
|
||||||
|
{ LPCUSBSIO_ERR_SYNCHRONIZATION, "Thread Synchronization error" },
|
||||||
|
{ LPCUSBSIO_ERR_MEM_ALLOC, "Memory Allocation error" },
|
||||||
|
{ LPCUSBSIO_ERR_MUTEX_CREATE, "Mutex Creation error" },
|
||||||
|
{ LPCUSBSIO_ERR_FATAL, "Fatal error occurred" },
|
||||||
|
{ LPCUSBSIO_ERR_I2C_NAK, "Transfer aborted due to NACK" },
|
||||||
|
{ LPCUSBSIO_ERR_I2C_BUS, "Transfer aborted due to bus error" },
|
||||||
|
{ LPCUSBSIO_ERR_I2C_SLAVE_NAK, "NAK received after SLA+W or SLA+R" },
|
||||||
|
{ LPCUSBSIO_ERR_I2C_ARBLOST, "I2C bus arbitration lost to other master" },
|
||||||
|
{ LPCUSBSIO_ERR_TIMEOUT, "Transaction timed out" },
|
||||||
|
{ LPCUSBSIO_ERR_INVALID_CMD, "Invalid HID_SIO Request or Request not supported in this version" },
|
||||||
|
{ LPCUSBSIO_ERR_INVALID_PARAM, "Invalid parameters are provided for the given Request" },
|
||||||
|
{ LPCUSBSIO_ERR_PARTIAL_DATA, "Partial transfer completed" },
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Code
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// See LpcUsbSio.h for documentation of this method.
|
||||||
|
LpcUsbSio::LpcUsbSio(const LpcUsbSio::LpcUsbSioPortConfigData &config)
|
||||||
|
: m_usbVid(config.usbVid)
|
||||||
|
, m_usbPid(config.usbPid)
|
||||||
|
, m_usbString(config.usbString)
|
||||||
|
, m_usbPath(config.usbPath)
|
||||||
|
, m_portIndex(config.portIndex)
|
||||||
|
{
|
||||||
|
m_portCount = LPCUSBSIO_GetNumPorts(m_usbVid, m_usbPid);
|
||||||
|
if (m_portCount < 1)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(format_string("Error: No LPC USB Serial I/O is detected.\n"));
|
||||||
|
}
|
||||||
|
else if (m_portCount < (m_portIndex + 1))
|
||||||
|
{
|
||||||
|
throw std::runtime_error(
|
||||||
|
format_string("Error: Invalid index %d, only %d port(s) available.\n", m_portIndex, m_portCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_portHandler = LPCUSBSIO_Open(m_portIndex);
|
||||||
|
if (m_portHandler == NULL)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(
|
||||||
|
format_string("Error: Failed to open the LPC USB Serial I/O port index %x.\n", m_portIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See LpcUsbSio.h for documentation of this method.
|
||||||
|
LpcUsbSio::~LpcUsbSio()
|
||||||
|
{
|
||||||
|
if (m_portHandler)
|
||||||
|
{
|
||||||
|
LPCUSBSIO_Close(m_portHandler);
|
||||||
|
m_portHandler = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See LpcUsbSio.h for documentation of this method.
|
||||||
|
bool LpcUsbSio::parse(const string_vector_t ¶ms, LpcUsbSio::LpcUsbSioConfigData &config)
|
||||||
|
{
|
||||||
|
if (!params[0].compare(0, 3, "spi"))
|
||||||
|
{
|
||||||
|
config.function = LpcUsbSio::kFunction_SPI;
|
||||||
|
|
||||||
|
// Currently only support one SPI port. Can be extended in the furture.
|
||||||
|
config.spiConfig.spiPortIndex = 0;
|
||||||
|
|
||||||
|
if (params.size() > 1)
|
||||||
|
{
|
||||||
|
int32_t port = atoi(params[1].c_str());
|
||||||
|
if ((port < 0) || (port > 7))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
config.spiConfig.spiSselPort = (uint8_t)port;
|
||||||
|
}
|
||||||
|
if (params.size() > 2)
|
||||||
|
{
|
||||||
|
int32_t pin = atoi(params[2].c_str());
|
||||||
|
if ((pin < 0) || (pin > 0x1F))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
config.spiConfig.spiSselPin = (uint8_t)pin;
|
||||||
|
}
|
||||||
|
if (params.size() > 3)
|
||||||
|
{
|
||||||
|
int32_t spiSpeed = CONVERT_KHZ_TO_HZ(atoi(params[3].c_str()));
|
||||||
|
if (spiSpeed <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
config.spiConfig.spiSpeedHz = spiSpeed;
|
||||||
|
}
|
||||||
|
if (params.size() > 4)
|
||||||
|
{
|
||||||
|
config.spiConfig.spiPolarity = (LpcUsbSio::spi_clock_polarity_t)atoi(params[4].c_str());
|
||||||
|
}
|
||||||
|
if (params.size() > 5)
|
||||||
|
{
|
||||||
|
config.spiConfig.spiPhase = (LpcUsbSio::spi_clock_phase_t)atoi(params[5].c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!params[0].compare(0, 3, "i2c"))
|
||||||
|
{
|
||||||
|
config.function = LpcUsbSio::kFunction_I2C;
|
||||||
|
|
||||||
|
// Currently only support one I2C port. Can be extended in the furture.
|
||||||
|
config.i2cConfig.i2cPortIndex = 0;
|
||||||
|
|
||||||
|
if (params.size() > 1)
|
||||||
|
{
|
||||||
|
uint32_t i2cAddress = strtoul(params[1].c_str(), NULL, 16);
|
||||||
|
|
||||||
|
if (i2cAddress > 0x7F)
|
||||||
|
{
|
||||||
|
i2cAddress &= 0x7F;
|
||||||
|
Log::warning("Warning: Only 7-bit i2c address is supported, so the effective value is 0x%x\n",
|
||||||
|
i2cAddress);
|
||||||
|
}
|
||||||
|
config.i2cConfig.i2cAddress = (uint8_t)i2cAddress;
|
||||||
|
}
|
||||||
|
if (params.size() > 2)
|
||||||
|
{
|
||||||
|
int32_t i2cSpeed = CONVERT_KHZ_TO_HZ(atoi(params[2].c_str()));
|
||||||
|
if (i2cSpeed <= 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i2cSpeed < I2C_CLOCK_FAST_MODE)
|
||||||
|
{
|
||||||
|
config.i2cConfig.i2cSpeedHz = I2C_CLOCK_STANDARD_MODE;
|
||||||
|
}
|
||||||
|
else if (i2cSpeed < I2C_CLOCK_FAST_MODE_PLUS)
|
||||||
|
{
|
||||||
|
config.i2cConfig.i2cSpeedHz = I2C_CLOCK_FAST_MODE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
config.i2cConfig.i2cSpeedHz = I2C_CLOCK_FAST_MODE_PLUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((i2cSpeed != I2C_CLOCK_STANDARD_MODE) && (i2cSpeed != I2C_CLOCK_FAST_MODE) &&
|
||||||
|
(i2cSpeed != I2C_CLOCK_FAST_MODE_PLUS))
|
||||||
|
{
|
||||||
|
Log::warning(
|
||||||
|
"Warning: Only 100Kbps, 400Kbps and 1Mbps are supported, so the effective speed is %dbps\n",
|
||||||
|
config.i2cConfig.i2cSpeedHz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!params[0].compare(0, 4, "gpio"))
|
||||||
|
{
|
||||||
|
// Not supported yet.
|
||||||
|
// config.function = LpcUsbSio::kFunction_GPIO;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Error: Invalid BusPal function.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See LpcUsbSio.h for documentation of this method.
|
||||||
|
const std::string LpcUsbSio::getError(LPCUSBSIO_ERR_T errorCode)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < (sizeof(s_errorMessage) / sizeof(s_errorMessage[0])); ++i)
|
||||||
|
{
|
||||||
|
if (errorCode == s_errorMessage[i].code)
|
||||||
|
{
|
||||||
|
return s_errorMessage[i].message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return format_string("Unknown error code (%d)", errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// See LpcUsbSio.h for documentation of this method.
|
||||||
|
LpcUsbSioSpi::LpcUsbSioSpi(const LpcUsbSio::LpcUsbSioPortConfigData &portConfig,
|
||||||
|
const LpcUsbSio::LpcUsbSioSpiConfigData &spiConfig)
|
||||||
|
: LpcUsbSio(portConfig)
|
||||||
|
, m_spiPortIndex(spiConfig.spiPortIndex)
|
||||||
|
, m_spiSselPort(spiConfig.spiSselPort)
|
||||||
|
, m_spiSselPin(spiConfig.spiSselPin)
|
||||||
|
{
|
||||||
|
m_spiPortCount = (int32_t)LPCUSBSIO_GetNumSPIPorts(m_portHandler);
|
||||||
|
if (m_spiPortCount < 0)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(
|
||||||
|
format_string("Error: Failed to get SPI port count, due to %s.\n", LPCUSBSIO_Error(m_portHandler)));
|
||||||
|
}
|
||||||
|
else if (m_spiPortCount == 0)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(format_string("Error: No SPI port is detected on current LPC USB Serial I/O.\n"));
|
||||||
|
}
|
||||||
|
else if (m_spiPortCount < (m_spiPortIndex + 1))
|
||||||
|
{
|
||||||
|
throw std::runtime_error(
|
||||||
|
format_string("Error: Invalid index %d, only %d port(s) available.\n", m_spiPortIndex, m_spiPortCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
HID_SPI_PORTCONFIG_T spiParam;
|
||||||
|
spiParam.busSpeed = spiConfig.spiSpeedHz;
|
||||||
|
spiParam.Options = HID_SPI_CONFIG_OPTION_DATA_SIZE_8 | HID_SPI_CONFIG_OPTION_POL_0 | HID_SPI_CONFIG_OPTION_PHA_0 |
|
||||||
|
HID_SPI_CONFIG_OPTION_PRE_DELAY(0) | HID_SPI_CONFIG_OPTION_POST_DELAY(0);
|
||||||
|
if (spiConfig.spiPolarity == LpcUsbSio::kSpiPolarity_ActiveLow)
|
||||||
|
{
|
||||||
|
spiParam.Options |= HID_SPI_CONFIG_OPTION_POL_1;
|
||||||
|
}
|
||||||
|
if (spiConfig.spiPhase == LpcUsbSio::kSpiPhase_SecondEdge)
|
||||||
|
{
|
||||||
|
spiParam.Options |= HID_SPI_CONFIG_OPTION_PHA_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_spiPortHandler = SPI_Open(m_portHandler, &spiParam, m_spiPortIndex);
|
||||||
|
if (m_spiPortHandler == NULL)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(
|
||||||
|
format_string("Error: Failed to open SPI port, due to %s.\n", LPCUSBSIO_Error(m_portHandler)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See LpcUsbSio.h for documentation of this method.
|
||||||
|
LpcUsbSioSpi::~LpcUsbSioSpi()
|
||||||
|
{
|
||||||
|
if (m_spiPortHandler)
|
||||||
|
{
|
||||||
|
SPI_Close(m_spiPortHandler);
|
||||||
|
m_spiPortHandler = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See LpcUsbSio.h for documentation of this method.
|
||||||
|
uint32_t LpcUsbSioSpi::write(const uint8_t *data, uint32_t byteCount)
|
||||||
|
{
|
||||||
|
uint32_t total = 0;
|
||||||
|
uint8_t *rxBuffer = (uint8_t *)malloc(byteCount);
|
||||||
|
|
||||||
|
while (byteCount)
|
||||||
|
{
|
||||||
|
uint16_t byteToTransfer = 0;
|
||||||
|
if (byteCount > UINT16_MAX)
|
||||||
|
{
|
||||||
|
byteToTransfer = UINT16_MAX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
byteToTransfer = (uint16_t)byteCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPI_XFER_T xfer;
|
||||||
|
xfer.options = 0;
|
||||||
|
xfer.length = byteToTransfer;
|
||||||
|
xfer.txBuff = data + total;
|
||||||
|
xfer.rxBuff = rxBuffer + total;
|
||||||
|
xfer.device = LPCUSBSIO_GEN_SPI_DEVICE_NUM(m_spiSselPort, m_spiSselPin);
|
||||||
|
|
||||||
|
int result = SPI_Transfer(m_spiPortHandler, &xfer);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
Log::error("Error: Failed to write data via SPI port, due to %x.\n",
|
||||||
|
LpcUsbSio::getError((LPCUSBSIO_ERR_T)result).c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
byteCount -= result;
|
||||||
|
total += result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(rxBuffer);
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See LpcUsbSio.h for documentation of this method.
|
||||||
|
uint32_t LpcUsbSioSpi::read(uint8_t *data, uint32_t byteCount)
|
||||||
|
{
|
||||||
|
uint32_t total = 0;
|
||||||
|
uint8_t *txBuffer = (uint8_t *)malloc(byteCount);
|
||||||
|
memset(txBuffer, 0x0, byteCount);
|
||||||
|
|
||||||
|
while (byteCount)
|
||||||
|
{
|
||||||
|
uint16_t byteToTransfer = 0;
|
||||||
|
if (byteCount > UINT16_MAX)
|
||||||
|
{
|
||||||
|
byteToTransfer = UINT16_MAX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
byteToTransfer = (uint16_t)byteCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPI_XFER_T xfer;
|
||||||
|
xfer.options = 0;
|
||||||
|
xfer.length = byteToTransfer;
|
||||||
|
xfer.txBuff = txBuffer + total;
|
||||||
|
xfer.rxBuff = data + total;
|
||||||
|
xfer.device = LPCUSBSIO_GEN_SPI_DEVICE_NUM(m_spiSselPort, m_spiSselPin);
|
||||||
|
|
||||||
|
int result = SPI_Transfer(m_spiPortHandler, &xfer);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
Log::error("Error: Failed to read data via SPI port, due to %s.\n",
|
||||||
|
LpcUsbSio::getError((LPCUSBSIO_ERR_T)result).c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
byteCount -= result;
|
||||||
|
total += result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(txBuffer);
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See LpcUsbSio.h for documentation of this method.
|
||||||
|
LpcUsbSioI2c::LpcUsbSioI2c(const LpcUsbSio::LpcUsbSioPortConfigData &portConfig,
|
||||||
|
const LpcUsbSio::LpcUsbSioI2cConfigData &i2cConfig)
|
||||||
|
: LpcUsbSio(portConfig)
|
||||||
|
, m_i2cPortIndex(i2cConfig.i2cPortIndex)
|
||||||
|
, m_i2cAddress(i2cConfig.i2cAddress)
|
||||||
|
{
|
||||||
|
m_i2cPortCount = (int32_t)LPCUSBSIO_GetNumSPIPorts(m_portHandler);
|
||||||
|
if (m_i2cPortCount == 0)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(format_string("Error: No I2C port is detected on current LPC USB Serial I/O.\n"));
|
||||||
|
}
|
||||||
|
else if (m_i2cPortCount < 0)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(
|
||||||
|
format_string("Error: Failed to get I2C port count, due to %s.\n", LPCUSBSIO_Error(m_portHandler)));
|
||||||
|
}
|
||||||
|
else if (m_i2cPortCount < (m_i2cPortIndex + 1))
|
||||||
|
{
|
||||||
|
throw std::runtime_error(
|
||||||
|
format_string("Error: Invalid index %d, only %d port(s) available.\n", m_i2cPortIndex, m_i2cPortCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
I2C_PORTCONFIG_T i2cParam;
|
||||||
|
i2cParam.ClockRate = i2cConfig.i2cSpeedHz;
|
||||||
|
i2cParam.Options = 0;
|
||||||
|
m_i2cPortHandler = I2C_Open(m_portHandler, &i2cParam, m_i2cPortIndex);
|
||||||
|
if (m_i2cPortHandler == NULL)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(
|
||||||
|
format_string("Error: Failed to open I2C port, due to %s.\n", LPCUSBSIO_Error(m_portHandler)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See LpcUsbSio.h for documentation of this method.
|
||||||
|
LpcUsbSioI2c::~LpcUsbSioI2c()
|
||||||
|
{
|
||||||
|
if (m_i2cPortHandler)
|
||||||
|
{
|
||||||
|
I2C_Close(m_i2cPortHandler);
|
||||||
|
m_i2cPortHandler = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See LpcUsbSio.h for documentation of this method.
|
||||||
|
uint32_t LpcUsbSioI2c::write(const uint8_t *data, uint32_t byteCount)
|
||||||
|
{
|
||||||
|
uint32_t total = 0;
|
||||||
|
|
||||||
|
while (byteCount)
|
||||||
|
{
|
||||||
|
uint16_t byteToTransfer = 0;
|
||||||
|
if (byteCount > UINT16_MAX)
|
||||||
|
{
|
||||||
|
byteToTransfer = UINT16_MAX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
byteToTransfer = (uint16_t)byteCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = I2C_DeviceWrite(m_i2cPortHandler, m_i2cAddress, (uint8_t *)data + total, byteToTransfer,
|
||||||
|
I2C_TRANSFER_OPTIONS_START_BIT | I2C_TRANSFER_OPTIONS_STOP_BIT |
|
||||||
|
I2C_TRANSFER_OPTIONS_BREAK_ON_NACK | I2C_TRANSFER_OPTIONS_NACK_LAST_BYTE);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
Log::error("Error: Failed to write data via I2C port, due to %s.\n",
|
||||||
|
LpcUsbSio::getError((LPCUSBSIO_ERR_T)result).c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
byteCount -= result;
|
||||||
|
total += result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See LpcUsbSio.h for documentation of this method.
|
||||||
|
uint32_t LpcUsbSioI2c::read(uint8_t *data, uint32_t byteCount)
|
||||||
|
{
|
||||||
|
uint32_t total = 0;
|
||||||
|
|
||||||
|
while (byteCount)
|
||||||
|
{
|
||||||
|
uint16_t byteToTransfer = 0;
|
||||||
|
if (byteCount > UINT16_MAX)
|
||||||
|
{
|
||||||
|
byteToTransfer = UINT16_MAX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
byteToTransfer = (uint16_t)byteCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = I2C_DeviceRead(m_i2cPortHandler, m_i2cAddress, (uint8_t *)data + total, byteToTransfer,
|
||||||
|
I2C_TRANSFER_OPTIONS_START_BIT | I2C_TRANSFER_OPTIONS_STOP_BIT |
|
||||||
|
I2C_TRANSFER_OPTIONS_BREAK_ON_NACK | I2C_TRANSFER_OPTIONS_NACK_LAST_BYTE);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
Log::error("Error: Failed to read data via I2C port, due to %s.\n",
|
||||||
|
LpcUsbSio::getError((LPCUSBSIO_ERR_T)result).c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
byteCount -= result;
|
||||||
|
total += result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// EOF
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
137
src/blfwk/src/LpcUsbSioPeripheral.cpp
Normal file
137
src/blfwk/src/LpcUsbSioPeripheral.cpp
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 - 2022 NXP
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "blfwk/Logging.h"
|
||||||
|
#include "blfwk/LpcUsbSioPeripheral.h"
|
||||||
|
#include "blfwk/format_string.h"
|
||||||
|
|
||||||
|
using namespace blfwk;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Code
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// See LpcUsbSioPeripheral.h for documentation of this method.
|
||||||
|
LpcUsbSioPeripheral::LpcUsbSioPeripheral(const LpcUsbSio::LpcUsbSioConfigData &config)
|
||||||
|
: Peripheral()
|
||||||
|
{
|
||||||
|
if (config.function == LpcUsbSio::kFunction_SPI)
|
||||||
|
{
|
||||||
|
m_lpcUsbSio = new LpcUsbSioSpi(config.portConfig, config.spiConfig);
|
||||||
|
}
|
||||||
|
else if (config.function == LpcUsbSio::kFunction_I2C)
|
||||||
|
{
|
||||||
|
m_lpcUsbSio = new LpcUsbSioI2c(config.portConfig, config.i2cConfig);
|
||||||
|
}
|
||||||
|
else if (config.function == LpcUsbSio::kFunction_GPIO)
|
||||||
|
{
|
||||||
|
// Currently, GPIO function is not supported.
|
||||||
|
throw std::runtime_error(format_string("Error: GPIO function is not supported yet.\n"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw std::runtime_error(format_string("Error: Invalid function of LPC USB Serial I/O.\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See LpcUsbSioPeripheral.h for documentation of this method.
|
||||||
|
LpcUsbSioPeripheral::~LpcUsbSioPeripheral()
|
||||||
|
{
|
||||||
|
if (m_lpcUsbSio)
|
||||||
|
{
|
||||||
|
delete m_lpcUsbSio;
|
||||||
|
m_lpcUsbSio = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See LpcUsbSioPeripheral.h for documentation of this method.
|
||||||
|
status_t LpcUsbSioPeripheral::read(uint8_t *buffer, uint32_t requestedBytes, uint32_t *actualBytes, uint32_t timeoutMs)
|
||||||
|
{
|
||||||
|
assert(buffer);
|
||||||
|
|
||||||
|
uint32_t count = 0;
|
||||||
|
if (requestedBytes)
|
||||||
|
{
|
||||||
|
// Read the requested number of bytes.
|
||||||
|
count = m_lpcUsbSio->read(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 == 0)
|
||||||
|
{
|
||||||
|
// Nothing got is a timeout error.
|
||||||
|
return kStatus_Timeout;
|
||||||
|
}
|
||||||
|
else if (count != requestedBytes)
|
||||||
|
{
|
||||||
|
// Fewer than requested is a failure.
|
||||||
|
return kStatus_Fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return kStatus_Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See LpcUsbSioPeripheral.h for documentation of this method.
|
||||||
|
status_t LpcUsbSioPeripheral::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 (byteCount == 0)
|
||||||
|
{
|
||||||
|
return kStatus_Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t count = m_lpcUsbSio->write(buffer, byteCount);
|
||||||
|
|
||||||
|
if (count < byteCount)
|
||||||
|
{
|
||||||
|
// Fewer than requested is a failure.
|
||||||
|
return kStatus_Fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return kStatus_Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// EOF
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
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);
|
||||||
|
}
|
||||||
|
}
|
80
src/blfwk/src/SBSourceFile.cpp
Normal file
80
src/blfwk/src/SBSourceFile.cpp
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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.");
|
||||||
|
}
|
1002
src/blfwk/src/SDPCommand.cpp
Normal file
1002
src/blfwk/src/SDPCommand.cpp
Normal file
File diff suppressed because it is too large
Load Diff
99
src/blfwk/src/SDPUsbHidPacketizer.cpp
Normal file
99
src/blfwk/src/SDPUsbHidPacketizer.cpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015 Freescale Semiconductor, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "blfwk/SDPUsbHidPacketizer.h"
|
||||||
|
#include "blfwk/Logging.h"
|
||||||
|
|
||||||
|
using namespace blfwk;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Code
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
status_t SDPUsbHidPacketizer::writePacket(const uint8_t *packet, uint32_t byteCount, packet_type_t packetType)
|
||||||
|
{
|
||||||
|
assert(m_peripheral);
|
||||||
|
assert(packetType == kPacketType_Command || packetType == kPacketType_Data);
|
||||||
|
assert(byteCount);
|
||||||
|
assert(packet);
|
||||||
|
|
||||||
|
uint32_t numBytes = 0;
|
||||||
|
|
||||||
|
// Construct report contents.
|
||||||
|
memset(&m_report, 0, sizeof(m_report));
|
||||||
|
if (packetType == kPacketType_Command)
|
||||||
|
{
|
||||||
|
m_report[0] = kIdReport1; // Report 1 is used to send a command to the device.
|
||||||
|
numBytes = kReport1SizeBytes;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_report[0] = kIdReport2; // Report 2 is used to send data to the device.
|
||||||
|
numBytes = kReport2SizeBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&m_report[1], packet, byteCount);
|
||||||
|
|
||||||
|
return getPeripheral()->write((uint8_t *)&m_report, numBytes, m_packetTimeoutMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t SDPUsbHidPacketizer::readPacket(uint8_t **packet, uint32_t *packetLength, packet_type_t packetType)
|
||||||
|
{
|
||||||
|
assert(m_peripheral);
|
||||||
|
assert(packet);
|
||||||
|
assert(packetLength);
|
||||||
|
*packet = NULL;
|
||||||
|
*packetLength = 0;
|
||||||
|
// packetType is not used.
|
||||||
|
|
||||||
|
// Read report.
|
||||||
|
uint32_t actualBytes = 0;
|
||||||
|
uint32_t retryCnt = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
status_t retVal =
|
||||||
|
m_peripheral->read((uint8_t *)&m_report, sizeof(m_report), &actualBytes, m_packetTimeoutMs);
|
||||||
|
if (retVal != kStatus_Success)
|
||||||
|
{
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actualBytes)
|
||||||
|
{
|
||||||
|
// Check the report ID.
|
||||||
|
uint8_t reportId = m_report[0];
|
||||||
|
if (reportId == kIdReport3)
|
||||||
|
{
|
||||||
|
if (actualBytes != kReport3SizeBytes)
|
||||||
|
{
|
||||||
|
Log::error("usbhid: received unexpected number of bytes=%x\n", actualBytes);
|
||||||
|
return kStatus_Fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (reportId == kIdReport4)
|
||||||
|
{
|
||||||
|
if (actualBytes != kReport4SizeBytes)
|
||||||
|
{
|
||||||
|
Log::error("usbhid: received unexpected number of bytes=%x\n", actualBytes);
|
||||||
|
return kStatus_Fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log::error("usbhid: received unexpected report=%x\n", reportId);
|
||||||
|
return kStatus_Fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (!actualBytes && (++retryCnt < kPollPacketMaxRetryCnt));
|
||||||
|
|
||||||
|
// Return results.
|
||||||
|
*packet = &m_report[1];
|
||||||
|
*packetLength = actualBytes - 1;
|
||||||
|
|
||||||
|
return kStatus_Success;
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user