Skip to content

Commit

Permalink
Merge pull request #108 from mripard/uboot-crc
Browse files Browse the repository at this point in the history
Uboot crc
  • Loading branch information
wens committed Nov 30, 2017
2 parents cd9e609 + ef802e4 commit 5c19710
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 25 deletions.
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ sunxi-fexc: fexc.h script.h script.c \
LIBUSB = libusb-1.0
LIBUSB_CFLAGS ?= `pkg-config --cflags $(LIBUSB)`
LIBUSB_LIBS ?= `pkg-config --libs $(LIBUSB)`

ZLIB = zlib
ZLIB_CFLAGS ?= `pkg-config --cflags $(ZLIB)`
ZLIB_LIBS ?= `pkg-config --libs $(ZLIB)`

ifeq ($(OS),Windows_NT)
# Windows lacks mman.h / mmap()
DEFAULT_CFLAGS += -DNO_MMAP
Expand All @@ -132,7 +137,8 @@ SOC_INFO := soc_info.c soc_info.h
FEL_LIB := fel_lib.c fel_lib.h

sunxi-fel: fel.c thunks/fel-to-spl-thunk.h $(PROGRESS) $(SOC_INFO) $(FEL_LIB)
$(CC) $(HOST_CFLAGS) $(LIBUSB_CFLAGS) $(LDFLAGS) -o $@ $(filter %.c,$^) $(LIBS) $(LIBUSB_LIBS)
$(CC) $(HOST_CFLAGS) $(LIBUSB_CFLAGS) $(ZLIB_CFLAGS) $(LDFLAGS) -o $@ \
$(filter %.c,$^) $(LIBS) $(LIBUSB_LIBS) $(ZLIB_LIBS)

sunxi-nand-part: nand-part-main.c nand-part.c nand-part-a10.h nand-part-a20.h
$(CC) $(HOST_CFLAGS) -c -o nand-part-main.o nand-part-main.c
Expand Down
74 changes: 50 additions & 24 deletions fel.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <zlib.h>
#include <sys/stat.h>

static bool verbose = false; /* If set, makes the 'fel' tool more talkative */
Expand All @@ -48,8 +49,28 @@ static uint32_t uboot_size = 0; /* size of U-Boot binary */
/* Additional error codes, newly introduced for get_image_type() */
#define IH_TYPE_ARCH_MISMATCH -1

#define HEADER_NAME_OFFSET 32 /* offset of name field */
#define HEADER_SIZE (HEADER_NAME_OFFSET + IH_NMLEN)
/*
* Legacy format image U-Boot header,
* all data in network byte order (aka natural aka bigendian).
* Taken from ${U-BOOT}/include/image.h
*/
typedef struct image_header {
uint32_t ih_magic; /* Image Header Magic Number */
uint32_t ih_hcrc; /* Image Header CRC Checksum */
uint32_t ih_time; /* Image Creation Timestamp */
uint32_t ih_size; /* Image Data Size */
uint32_t ih_load; /* Data Load Address */
uint32_t ih_ep; /* Entry Point Address */
uint32_t ih_dcrc; /* Image Data CRC Checksum */
uint8_t ih_os; /* Operating System */
uint8_t ih_arch; /* CPU architecture */
uint8_t ih_type; /* Image Type */
uint8_t ih_comp; /* Compression Type */
uint8_t ih_name[IH_NMLEN]; /* Image Name */
} image_header_t;

#define HEADER_NAME_OFFSET offsetof(image_header_t, ih_name)
#define HEADER_SIZE sizeof(image_header_t)

/*
* Utility function to determine the image type from a mkimage-compatible
Expand All @@ -63,18 +84,19 @@ static uint32_t uboot_size = 0; /* size of U-Boot binary */
*/
int get_image_type(const uint8_t *buf, size_t len)
{
uint32_t *buf32 = (uint32_t *)buf;
image_header_t *hdr = (image_header_t *)buf;

if (len <= HEADER_SIZE) /* insufficient length/size */
return IH_TYPE_INVALID;
if (be32toh(buf32[0]) != IH_MAGIC) /* signature mismatch */

if (be32toh(hdr->ih_magic) != IH_MAGIC) /* signature mismatch */
return IH_TYPE_INVALID;
/* For sunxi, we always expect ARM architecture here */
if (buf[29] != IH_ARCH_ARM)
if (hdr->ih_arch != IH_ARCH_ARM)
return IH_TYPE_ARCH_MISMATCH;

/* assume a valid header, and return ih_type */
return buf[30];
return hdr->ih_type;
}

void aw_fel_print_version(feldev_handle *dev)
Expand Down Expand Up @@ -740,7 +762,16 @@ void aw_fel_write_uboot_image(feldev_handle *dev, uint8_t *buf, size_t len)
if (len <= HEADER_SIZE)
return; /* Insufficient size (no actual data), just bail out */

uint32_t *buf32 = (uint32_t *)buf;
image_header_t hdr = *(image_header_t *)buf;

uint32_t hcrc = be32toh(hdr.ih_hcrc);

/* The CRC is calculated on the whole header but the CRC itself */
hdr.ih_hcrc = 0;
uint32_t computed_hcrc = crc32(0, (const uint8_t *) &hdr, HEADER_SIZE);
if (hcrc != computed_hcrc)
pr_fatal("U-Boot header CRC mismatch: expected %x, got %x\n",
hcrc, computed_hcrc);

/* Check for a valid mkimage header */
int image_type = get_image_type(buf, len);
Expand All @@ -762,23 +793,18 @@ void aw_fel_write_uboot_image(feldev_handle *dev, uint8_t *buf, size_t len)
pr_fatal("U-Boot image type mismatch: "
"expected IH_TYPE_FIRMWARE, got %02X\n", image_type);

uint32_t data_size = be32toh(buf32[3]); /* Image Data Size */
uint32_t load_addr = be32toh(buf32[4]); /* Data Load Address */
if (data_size != len - HEADER_SIZE)
pr_fatal("U-Boot image data size mismatch: "
"expected %zu, got %u\n", len - HEADER_SIZE, data_size);

/* TODO: Verify image data integrity using the checksum field ih_dcrc,
* available from be32toh(buf32[6])
*
* However, this requires CRC routines that mimic their U-Boot
* counterparts, namely image_check_dcrc() in ${U-BOOT}/common/image.c
* and crc_wd() in ${U-BOOT}/lib/crc32.c
*
* It should be investigated if existing CRC routines in sunxi-tools
* could be factored out and reused for this purpose - e.g. calc_crc32()
* from nand-part-main.c
*/
uint32_t data_size = be32toh(hdr.ih_size); /* Image Data Size */
uint32_t load_addr = be32toh(hdr.ih_load); /* Data Load Address */
if (data_size > len - HEADER_SIZE)
pr_fatal("U-Boot image data trucated: "
"expected %zu bytes, got %u\n",
len - HEADER_SIZE, data_size);

uint32_t dcrc = be32toh(hdr.ih_dcrc);
uint32_t computed_dcrc = crc32(0, buf + HEADER_SIZE, data_size);
if (dcrc != computed_dcrc)
pr_fatal("U-Boot data CRC mismatch: expected %x, got %x\n",
dcrc, computed_dcrc);

/* If we get here, we're "good to go" (i.e. actually write the data) */
pr_info("Writing image \"%.*s\", %u bytes @ 0x%08X.\n",
Expand Down

0 comments on commit 5c19710

Please sign in to comment.