summaryrefslogtreecommitdiffstats
path: root/include/image-metadata.h
blob: e00c209aedc9dc0def63d0a4c0ef4243dc5e3261 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/* SPDX-License-Identifier: GPL-2.0-only */
#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_BUILDSYSTEM	0x640c8007 /* The buildsystem version barebox was built with */
#define IMD_TYPE_CRC32		0x640c1007 /* the checksum of the barebox images */
#define IMD_TYPE_END		0x640c7fff
#define IMD_TYPE_INVALID	0xffffffff

#define IMD_CRC32_FLAG_TAG_VALID	(1 << 0)

/*
 * 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;
}

/*
 * A IMD int.
 */
struct imd_entry_crc32 {
	struct imd_header header;
	uint32_t data;
	uint32_t flags;
};

static inline int imd_is_crc32(uint32_t type)
{
	return type == IMD_TYPE_CRC32;
}

static inline int imd_crc32_is_valid(uint32_t flags)
{
	return (flags & IMD_CRC32_FLAG_TAG_VALID) ? 1 : 0;
}

static inline int imd_type_valid(uint32_t type) {
	return (type & 0xffff0000) == 0x640c0000;
}

const struct imd_header *imd_next(const 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(const void *_ptr)
{
	const uint8_t *ptr = _ptr;

	return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
}

static inline uint32_t imd_read_type(const struct imd_header *imd)
{
	return imd_read_le32(&imd->type);
}

static inline uint32_t imd_read_length(const struct imd_header *imd)
{
	return imd_read_le32(&imd->datalength);
}

static inline uint32_t imd_read_flags(const struct imd_entry_crc32 *imd)
{
	return imd_read_le32(&imd->flags);
}

const struct imd_header *imd_find_type(const struct imd_header *imd,
				       uint32_t type);

const struct imd_header *imd_get(const void *buf, int size);
const char *imd_string_data(const struct imd_header *imd, int index);
const uint32_t *imd_uint32_data(const struct imd_header *imd);
uint32_t *imd_uint32_flags(const struct imd_header *imd);
const char *imd_type_to_name(uint32_t type);
char *imd_concat_strings(const struct imd_header *imd);
const char *imd_get_param(const struct imd_header *imd, const char *name);

extern int imd_command_verbose;
int imd_command_setenv(const char *variable_name, const char *value);
int imd_command(int argc, char *argv[]);
int imd_verify_crc32(void *buf, size_t size);

#ifdef __BAREBOX__

#include <linux/stringify.h>
#include <linux/compiler_types.h>

#define __BAREBOX_IMD_SECTION(_section) \
	__ll_elem(_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,							\
	}

#define BAREBOX_IMD_CRC(_name, _crc, _keep_if_unused)					\
	const struct imd_entry_crc32 __barebox_imd_##__name				\
	__BAREBOX_IMD_SECTION(.barebox_imd_ ## _keep_if_unused ## _ ## _name) = {	\
		.header.type = cpu_to_le32(IMD_TYPE_CRC32),				\
		.header.datalength = cpu_to_le32(sizeof(uint32_t) * 2),			\
		.data = _crc,								\
	}

#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)

__attribute__((deprecated("IMD entries are now always referenced if DT itself is")))
static inline void IMD_USED_OF(void)
{}

#define IMD_USED_OF(_name) IMD_USED_OF()

#endif /* __BAREBOX__ */

#endif /* __INCLUDE_IMAGE_METADTA_H */