/* * 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 #include #else /* !__KERNEL__ */ #include #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; /** * List of supported DSP modes. * This enum is converted by u-boot in spc300_atag values, see * asm/arch/spc300-atag.h. * Beware that values can differ between the two files. */ typedef enum { SPIDCOM_IMG_DESC_DSP_MODE_NONE, SPIDCOM_IMG_DESC_DSP_MODE_1X, SPIDCOM_IMG_DESC_DSP_MODE_2X, SPIDCOM_IMG_DESC_DSP_MODE_NB } spidcom_image_desc_dsp_mode_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; /** DSP PLL mode */ uint32_t dsp_mode; } spidcom_image_desc_header_t; /** * Reserved size at the end of all descriptors (in bytes). */ #define SPIDCOM_IMG_DESC_COMMON_RESERVER_SIZE 828 /** * 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 */