123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- #include "pbl_crc32.h"
- #include "imagetool.h"
- #include "mkimage.h"
- #include <image.h>
- #define HEADER_OFFSET 0x40
- #define VALIDATION_WORD 0x31305341
- #define PADDED_SIZE 0x10000
- #define MAX_INPUT_SIZE (PADDED_SIZE - sizeof(uint32_t))
- static uint8_t buffer[PADDED_SIZE];
- static struct socfpga_header {
- uint32_t validation;
- uint8_t version;
- uint8_t flags;
- uint16_t length_u32;
- uint16_t zero;
- uint16_t checksum;
- } header;
- static uint16_t hdr_checksum(struct socfpga_header *header)
- {
- int len = sizeof(*header) - sizeof(header->checksum);
- uint8_t *buf = (uint8_t *)header;
- uint16_t ret = 0;
- while (--len)
- ret += *buf++;
- return ret;
- }
- static void build_header(uint8_t *buf, uint8_t version, uint8_t flags,
- uint16_t length_bytes)
- {
- header.validation = cpu_to_le32(VALIDATION_WORD);
- header.version = version;
- header.flags = flags;
- header.length_u32 = cpu_to_le16(length_bytes/4);
- header.zero = 0;
- header.checksum = cpu_to_le16(hdr_checksum(&header));
- memcpy(buf, &header, sizeof(header));
- }
- static int verify_header(const uint8_t *buf)
- {
- memcpy(&header, buf, sizeof(header));
- if (le32_to_cpu(header.validation) != VALIDATION_WORD)
- return -1;
- if (le16_to_cpu(header.checksum) != hdr_checksum(&header))
- return -1;
- return le16_to_cpu(header.length_u32) * 4;
- }
- static int sign_buffer(uint8_t *buf,
- uint8_t version, uint8_t flags,
- int len, int pad_64k)
- {
- uint32_t calc_crc;
-
- len = (len + 3) & (~3);
-
- build_header(buf + HEADER_OFFSET, version, flags, len + 4);
-
- calc_crc = ~pbl_crc32(0, (char *)buf, len);
- *((uint32_t *)(buf + len)) = cpu_to_le32(calc_crc);
- if (!pad_64k)
- return len + 4;
- return PADDED_SIZE;
- }
- static int verify_buffer(const uint8_t *buf)
- {
- int len;
- uint32_t calc_crc;
- uint32_t buf_crc;
- len = verify_header(buf + HEADER_OFFSET);
- if (len < 0) {
- debug("Invalid header\n");
- return -1;
- }
- if (len < HEADER_OFFSET || len > PADDED_SIZE) {
- debug("Invalid header length (%i)\n", len);
- return -1;
- }
-
- len -= 4;
- calc_crc = ~pbl_crc32(0, (const char *)buf, len);
- buf_crc = le32_to_cpu(*((uint32_t *)(buf + len)));
- if (buf_crc != calc_crc) {
- fprintf(stderr, "CRC32 does not match (%08x != %08x)\n",
- buf_crc, calc_crc);
- return -1;
- }
- return 0;
- }
- static int socfpgaimage_verify_header(unsigned char *ptr, int image_size,
- struct image_tool_params *params)
- {
- if (image_size != PADDED_SIZE)
- return -1;
- return verify_buffer(ptr);
- }
- static void socfpgaimage_print_header(const void *ptr)
- {
- if (verify_buffer(ptr) == 0)
- printf("Looks like a sane SOCFPGA preloader\n");
- else
- printf("Not a sane SOCFPGA preloader\n");
- }
- static int socfpgaimage_check_params(struct image_tool_params *params)
- {
-
- return (params->dflag && (params->fflag || params->lflag)) ||
- (params->fflag && (params->dflag || params->lflag)) ||
- (params->lflag && (params->dflag || params->fflag));
- }
- static int socfpgaimage_check_image_types(uint8_t type)
- {
- if (type == IH_TYPE_SOCFPGAIMAGE)
- return EXIT_SUCCESS;
- return EXIT_FAILURE;
- }
- static int data_size;
- #define FAKE_HEADER_SIZE (PADDED_SIZE - data_size)
- static int socfpgaimage_vrec_header(struct image_tool_params *params,
- struct image_type_params *tparams)
- {
- struct stat sbuf;
- if (params->datafile &&
- stat(params->datafile, &sbuf) == 0 &&
- sbuf.st_size <= MAX_INPUT_SIZE) {
- data_size = sbuf.st_size;
- tparams->header_size = FAKE_HEADER_SIZE;
- }
- return 0;
- }
- static void socfpgaimage_set_header(void *ptr, struct stat *sbuf, int ifd,
- struct image_tool_params *params)
- {
- uint8_t *buf = (uint8_t *)ptr;
-
- memmove(buf, buf + FAKE_HEADER_SIZE, data_size);
- memset(buf + data_size, 0, FAKE_HEADER_SIZE);
- sign_buffer(buf, 0, 0, data_size, 0);
- }
- U_BOOT_IMAGE_TYPE(
- socfpgaimage,
- "Altera SOCFPGA preloader support",
- 0,
- (void *)buffer,
- socfpgaimage_check_params,
- socfpgaimage_verify_header,
- socfpgaimage_print_header,
- socfpgaimage_set_header,
- NULL,
- socfpgaimage_check_image_types,
- NULL,
- socfpgaimage_vrec_header
- );
|