summaryrefslogtreecommitdiff
path: root/common/include/spid_img_desc.h
blob: c83dec6c218bcb6cd54953f516a3325ed1cb2572 (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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
/*
 *  include/spid_img_desc.h
 *
 *  Copyright (C) 2012 MStar Semiconductor.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 */
#ifndef __SPID_IMG_DESC_H
#define __SPID_IMG_DESC_H

#ifndef __KERNEL__
#include <stdint.h>
#include <string.h>
#else /* !__KERNEL__ */
#include <linux/string.h>
#endif /* __KERNEL__ */

#define SPIDCOM_IMG_DESC_IMG_NAME_0 "image 0"
#define SPIDCOM_IMG_DESC_IMG_NAME_1 "image 1"

#define SPIDCOM_IMG_DESC_MTD_NAME_0 "/dev/mtd3"
#define SPIDCOM_IMG_DESC_MTD_NAME_1 "/dev/mtd4"

#define SPIDCOM_IMG_DESC_SPC200E 0x00
#define SPIDCOM_IMG_DESC_SPC200C 0x01
#define SPIDCOM_IMG_DESC_SPC200_UNKNOWN 0x02

#define SPIDCOM_IMG_DESC_SPC300 0x00
#define SPIDCOM_IMG_DESC_SPC300_UNKNOWN 0x01

#define SPIDCOM_IMG_DESC_MAGIC "SPIDIMG\0"
#define SPIDCOM_IMG_DESC_SIZE  1024

#define SPIDCOM_IMG_DESC_INVALID_INDEX 0x8fffffff
#define SPIDCOM_IMG_DESC_ORIGIN_INDEX 0xffffffff

#define SPIDCOM_IMG_DESC_NORMAL_TYPE    0x0

#define SPIDCOM_IMG_DESC_PLC_RAM 0x400000 /* 4M */

#define SPIDCOM_IMG_DESC_IS_VALID(desc) (   !memcmp((desc)->magic, SPIDCOM_IMG_DESC_MAGIC, 8) && \
                                            (desc)->is_valid && \
                                            ( (desc)->index != SPIDCOM_IMG_DESC_INVALID_INDEX )     )

/**
 * List of image type supported.
 */
typedef enum {
    SPIDCOM_IMG_DESC_IMAGE_TYPE_200,
    SPIDCOM_IMG_DESC_IMAGE_TYPE_300,
    SPIDCOM_IMG_DESC_IMAGE_TYPE_NB,
    SPIDCOM_IMG_DESC_IMAGE_TYPE_UNKNOWN,
} spidcom_image_desc_image_type_t;

/**
 * Version of the common header for image descriptor.
 */
#define SPIDCOM_IMG_DESC_COMMON_HEADER_VERSION 1

/**
 * Common header for image descriptor.
 * New fields can be added to this header without changing the version
 * (SPIDCOM_IMG_DESC_COMMON_HEADER_VERSION / header_version) as long as the
 * changes are compatible between old and previous version.
 * If you change a field meaning or type, you probably need to change the
 * version value (and add code to handle different behaviors based on
 * header_version value).
 */
typedef struct {
    /** Must be SPIDCOM_IMG_DESC_MAGIC, otherwise the header is invalid. */
    char magic[8];
    /** Version of this header. */
    uint32_t header_version;
    /** Type of the image, see spid_img_desc_image_type_t. */
    uint32_t image_type;
    /** Speed of System Clock in MHz */
    uint32_t sysclk_speed;
} spidcom_image_desc_header_t;

/**
 * Reserved size at the end of all descriptors (in bytes).
 */
#define SPIDCOM_IMG_DESC_COMMON_RESERVER_SIZE 832

/**
 * Image descriptor for SPC300 (and MSE500-300).
 * All values are in little-endian.
 */
typedef struct {
    char     magic[8];              /* Magic number = "SPIDIMG\0"
                                     * = { 0x53, 0x50, 0x49, 0x44,
                                     *     0x49, 0x4d, 0x47, 0x00 } */
    uint32_t index;                 /* The biggest one is the image to boot */
    uint32_t is_valid:1;            /* Is image valid (bootable ?) */
    uint32_t is_1st_boot:1;         /* Is first image boot ? */
    uint32_t is_not_success:1;      /* Is first boot successful ? */
    uint32_t is_not_update:1;       /* Is update process finished correctly? */
    uint32_t size;                  /* Firmware size (descriptor included) */
    uint32_t type;                  /* Image type :  0 is normal image */
    uint8_t  md5_sum[16];           /* MD5 checksum of the whole firmware */
    char     version[16];           /* Image version string */
    char     description[64];       /* Image description string */
    uint32_t arch;                  /* spc300 or unknown */
    uint32_t plc_ram;               /* RAM size needed for the PLC processor */
    char     board_type[32];        /* Board type string */
    char     empty[12];             /* Empty field to make the common header
                                       start at the same offset on both
                                       spidcom image descriptor. */
    spidcom_image_desc_header_t header; /* Common header. */
    char     reserved[SPIDCOM_IMG_DESC_COMMON_RESERVER_SIZE];
    char     image[0];              /* Used in bootloader  to mark beging of the payload */
} spidcom_image_desc_300_t;

/**
 * Image descriptor for SPC200 (and MSE500-200).
 * All values are in little-endian.
 */
typedef struct {
    char     magic[8];         /* Magic number = "SPIDIMG\0"
                                * = { 0x53, 0x50, 0x49, 0x44,
                                *     0x49, 0x4d, 0x47, 0x00 } */
    uint32_t index;            /* The biggest one is the image to boot */
    uint32_t is_valid:1;       /* Is image valid (bootable ?) */
    uint32_t is_1st_boot:1;    /* Is first image boot ? */
    uint32_t is_not_success:1; /* Is first boot successful ? */
    uint32_t size;             /* Firmware size (descriptor included) */
    uint32_t type;             /* Image type :  0 is normal image */
    uint8_t  md5_sum[16];      /* MD5 checksum of the whole firmware */
    char     version[64];      /* Image version string */
    char     description[64];  /* Image description string */
    uint32_t arch;	     /* spc200e, spc200c or unknown */
    spidcom_image_desc_header_t header; /* Common header. */
    char     reserved[SPIDCOM_IMG_DESC_COMMON_RESERVER_SIZE];
    char     image[0];         /* Used in bootloader */
} spidcom_image_desc_200_t;

/**
 * Common image descriptor between 200 and 300.
 */
typedef struct
{
    char     magic[8];         /* Magic number = "SPIDIMG\0"
                                * = { 0x53, 0x50, 0x49, 0x44,
                                *     0x49, 0x4d, 0x47, 0x00 } */
    uint32_t index;            /* The biggest one is the image to boot */
    uint32_t is_valid:1;       /* Is image valid (bootable ?) */
    uint32_t is_1st_boot:1;    /* Is first image boot ? */
    uint32_t is_not_success:1; /* Is first boot successful ? */
    uint32_t size;             /* Firmware size (descriptor included) */
    uint32_t type;             /* Image type :  0 is normal image */
    uint8_t  md5_sum[16];      /* MD5 checksum of the whole firmware */
    char empty[132];
    spidcom_image_desc_header_t header;
    char     reserved[SPIDCOM_IMG_DESC_COMMON_RESERVER_SIZE];
    char     image[0];
} spidcom_image_desc_common_200_300_t;

/**
 * Generic structure to access a spdicom image descriptor.
 * There is two kind of image descriptor, a 200 and a 300. A new header exists
 * to distinguish between the two.
 */
typedef struct {
    /**
     * Image descriptor type.
     */
    spidcom_image_desc_image_type_t type;
    /**
     * Union to access image descriptor.
     * If it is not possible to know the image type, it will default to 200:
     * all applications, expect 200 ones, have been changed to add support to
     * know the image type.
     */
    union {
        spidcom_image_desc_200_t img_200;
        spidcom_image_desc_300_t img_300;
        spidcom_image_desc_common_200_300_t img_common;
    };
    /**
     * Common header if present (NULL otherwise).
     */
    spidcom_image_desc_header_t *header;
} spidcom_image_desc_generic_t;

/* For more information on ARCH_IS_POLUX, see polux/include/image_desc.h. */
#ifdef ARCH_IS_POLUX
typedef spidcom_image_desc_200_t spidcom_image_desc_t;
#else
typedef spidcom_image_desc_300_t spidcom_image_desc_t;
#endif

/**
 * If structures spidcom_image_desc_{2,3}00_t and
 * spidcom_image_desc_common_200_300_t have a sizeof different from
 * SPIDCOM_IMG_DESC_SIZE, this define has a negative value, otherwise it will
 * be 1.
 */
#define error_size (1 - 2 \
                    * ((sizeof (spidcom_image_desc_200_t) \
                        != SPIDCOM_IMG_DESC_SIZE) \
                       || \
                       (sizeof (spidcom_image_desc_300_t) \
                        != SPIDCOM_IMG_DESC_SIZE) \
                       || \
                       (sizeof (spidcom_image_desc_common_200_300_t) \
                        != SPIDCOM_IMG_DESC_SIZE)))
/**
 * This typedef is used to produce an error if error_size is negative.
 * If you have an error while building (i.e.: array size is negative), this
 * mean at least one of the structure spidcom_image_desc_* has a size
 * different from SPIDCOM_IMG_DESC_SIZE bytes. You need to fix it!
 */
typedef char all_spidcom_images_desc_must_have_fixed_size[error_size];

#undef error_size

/**
 * Load image descriptor of generic structure.
 * \param  img_desc  the generic image descriptor to load
 * \return  0 if success, -1 if error, 1 if common header has not been found
 * or is buggy
 */
static inline int
spidcom_image_desc_load (spidcom_image_desc_generic_t *img_desc)
{
    if (!img_desc)
        return -1;

    /* Load common header into generic structure. */
    img_desc->header = &img_desc->img_common.header;

    /* Let's try to read the header part. */
    if (memcmp (img_desc->header->magic, SPIDCOM_IMG_DESC_MAGIC,
                sizeof (img_desc->header->magic))
        && (img_desc->header->header_version
            == SPIDCOM_IMG_DESC_COMMON_HEADER_VERSION)
        && (img_desc->header->image_type
            < SPIDCOM_IMG_DESC_IMAGE_TYPE_NB))
    {
        img_desc->type
            = (spidcom_image_desc_image_type_t) img_desc->header->image_type;
        return 0;
    }
    else
    {
        /* We fake it is a SPC300 image. If is a 200, we are screwed... */
        img_desc->type = SPIDCOM_IMG_DESC_IMAGE_TYPE_300;
        return 1;
    }
}

/**
 * Fill the version depending on the header type.
 * \param  img_desc  the generic image descriptor
 * \param  version  a allocated string (must be the biggest length of version
 * from all spidcom image descriptor
 * \return  version size used (16 or 64)
 *
 * @note the version string may or may not be null terminated, it is just
 * copied directly from the version field of the image descriptor.
 */
static inline int
spidcom_image_desc_read_version (spidcom_image_desc_generic_t *img_desc,
                                 char *version)
{
    int version_size;
    char *version_addr;
    switch (img_desc->type)
    {
    case SPIDCOM_IMG_DESC_IMAGE_TYPE_300:
        version_addr = img_desc->img_300.version;
        version_size = sizeof (img_desc->img_300.version);
        break;
    case SPIDCOM_IMG_DESC_IMAGE_TYPE_200:
        version_addr = img_desc->img_200.version;
        version_size = sizeof (img_desc->img_200.version);
        break;
    default:
        strcpy (version, "UnknowID");
        version_size = strlen (version);
        return version_size;
    }
    strncpy (version, version_addr, version_size);
    return version_size;
}

#endif /* __SPID_IMG_DESC_H */