It's often useful to get some information about a barebox image before starting or flashing it. This patch introduces barebox Image MetaData (IMD). When enabled a barebox image will contain a list of tags containing the desired information. We have tags for: - the barebox release (2014.07.0-00160-g035de50-dirty) - the build timestamp (#741 Mon Jul 28 15:08:54 CEST 2014) - the board model the image is intended for - the device tree toplevel compatible property Also there is an additional generic key-value store which stores parameters for which no dedicated tag exists. In this patch it is used for the memory size an image supports. Since there is no fixed offset in a barebox image which can be used for storing the information, the metadata is stored somewhere in the image and found by iterating over the image. This works for most image types, but obviously not for SoC images which are encoded or encrypted in some way. There is a 'imd' tool compiled from the same sources for barebox, for the compile host and for the target, so the metadata information is available whereever needed. For device tree boards the model and of_compatible tags are automatically generated. Example output of the imd tool for a Phytec phyFLEX image: build: #889 Wed Jul 30 16:08:54 CEST 2014 release: 2014.07.0-00167-g6b2070d-dirty parameter: memsize=1024 of_compatible: phytec,imx6x-pbab01 phytec,imx6dl-pfla02 fsl,imx6dl model: Phytec phyFLEX-i.MX6 Duallite Carrier-Board Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
118 lines
3.4 KiB
C
118 lines
3.4 KiB
C
#ifndef __INCLUDE_IMAGE_METADTA_H
|
|
#define __INCLUDE_IMAGE_METADTA_H
|
|
|
|
/*
|
|
* barebox Image MetaData (IMD)
|
|
*
|
|
* IMD is a mechanism to store metadata in barebox images. With IMD
|
|
* it's possible to extract the release, the build timestamp and the
|
|
* board type from a barebox image.
|
|
*
|
|
* Since there is no fixed place in the image suitable for all SoC image
|
|
* types the metadata can be stored anywhere in the image and is found
|
|
* by iterating over the image. The metadata starts with a start header
|
|
* and ends with an end header. All tags in between carry the payload.
|
|
*
|
|
* Make sure source files containing IMD data are compiled with lwl-y so
|
|
* that the tags end up in the PBL if one exists and in the regular image
|
|
* without PBL.
|
|
*
|
|
* The following types exist:
|
|
*/
|
|
#define IMD_TYPE_START 0x640c0001
|
|
#define IMD_TYPE_RELEASE 0x640c8002 /* The barebox release aka UTS_RELEASE */
|
|
#define IMD_TYPE_BUILD 0x640c8003 /* build number and timestamp (UTS_VERSION) */
|
|
#define IMD_TYPE_MODEL 0x640c8004 /* The board name this image is for */
|
|
#define IMD_TYPE_OF_COMPATIBLE 0x640c8005 /* the device tree compatible string */
|
|
#define IMD_TYPE_PARAMETER 0x640c8006 /* A generic parameter. Use key=value as data */
|
|
#define IMD_TYPE_END 0x640c7fff
|
|
#define IMD_TYPE_INVALID 0xffffffff
|
|
|
|
/*
|
|
* The IMD header. All data is stored in little endian format in the image.
|
|
* The next header starts at the next 4 byte boundary after the data.
|
|
*/
|
|
struct imd_header {
|
|
uint32_t type; /* One of IMD_TYPE_* above */
|
|
uint32_t datalength; /* Length of the data (exluding the header) */
|
|
};
|
|
|
|
/*
|
|
* A IMD string. Set bit 15 of the IMD_TYPE to indicate the data is printable
|
|
* as string.
|
|
*/
|
|
struct imd_entry_string {
|
|
struct imd_header header;
|
|
char data[];
|
|
};
|
|
|
|
static inline int imd_is_string(uint32_t type)
|
|
{
|
|
return (type & 0x8000) ? 1 : 0;
|
|
}
|
|
|
|
static inline int imd_type_valid(uint32_t type)
|
|
{
|
|
return (type & 0xffff0000) == 0x640c0000;
|
|
}
|
|
|
|
struct imd_header *imd_next(struct imd_header *imd);
|
|
|
|
#define imd_for_each(start, imd) \
|
|
for (imd = imd_next(start); imd_read_type(imd) != IMD_TYPE_END; imd = imd_next(imd))
|
|
|
|
static inline uint32_t imd_read_le32(void *_ptr)
|
|
{
|
|
uint8_t *ptr = _ptr;
|
|
|
|
return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
|
|
}
|
|
|
|
static inline uint32_t imd_read_type(struct imd_header *imd)
|
|
{
|
|
return imd_read_le32(&imd->type);
|
|
}
|
|
|
|
static inline uint32_t imd_read_length(struct imd_header *imd)
|
|
{
|
|
return imd_read_le32(&imd->datalength);
|
|
}
|
|
|
|
struct imd_header *imd_find_type(struct imd_header *imd, uint32_t type);
|
|
|
|
extern int imd_command_verbose;
|
|
int imd_command_setenv(const char *variable_name, const char *value);
|
|
int imd_command(int argc, char *argv[]);
|
|
|
|
#ifdef __BAREBOX__
|
|
|
|
#include <linux/stringify.h>
|
|
|
|
#define __BAREBOX_IMD_SECTION(_section) \
|
|
__attribute__ ((unused,section (__stringify(_section)))) \
|
|
__attribute__((aligned(4)))
|
|
|
|
#define BAREBOX_IMD_TAG_STRING(_name, _type, _string, _keep_if_unused) \
|
|
const struct imd_entry_string __barebox_imd_##_name \
|
|
__BAREBOX_IMD_SECTION(.barebox_imd_ ## _keep_if_unused ## _ ## _name) = { \
|
|
.header.type = cpu_to_le32(_type), \
|
|
.header.datalength = cpu_to_le32(sizeof(_string)), \
|
|
.data = _string, \
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_IMD
|
|
void imd_used(const void *);
|
|
#else
|
|
static inline void imd_used(const void *unused)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
#define IMD_USED(_name) \
|
|
imd_used(&__barebox_imd_##_name)
|
|
|
|
#endif /* __BAREBOX__ */
|
|
|
|
#endif /* __INCLUDE_IMAGE_METADTA_H */
|