From: Jan Luebbe <jlu@xxxxxxxxxxxxxx> Signed-off-by: Jan Luebbe <jlu@xxxxxxxxxxxxxx> Signed-off-by: Ulrich Ölmann <u.oelmann@xxxxxxxxxxxxxx> --- images/Makefile | 3 +- include/filetype.h | 2 + scripts/.gitignore | 1 + scripts/Makefile | 1 + scripts/bareboxcrc.c | 219 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 scripts/bareboxcrc.c diff --git a/images/Makefile b/images/Makefile index da9cc8d396ee..812074e624b0 100644 --- a/images/Makefile +++ b/images/Makefile @@ -71,7 +71,8 @@ quiet_cmd_pblx ?= PBLX $@ cmd_pblx ?= cat $(obj)/$(patsubst %.pblx,%.pblb,$(2)) > $@; \ $(call size_append, $(obj)/barebox.z) >> $@; \ cat $(obj)/barebox.z >> $@; \ - $(objtree)/scripts/fix_size -f $@ + $(objtree)/scripts/fix_size -f $@; \ + $(objtree)/scripts/bareboxcrc $@ $(obj)/%.pblx: $(obj)/%.pblb $(obj)/barebox.z FORCE $(call if_changed,pblx,$(@F)) diff --git a/include/filetype.h b/include/filetype.h index e87ca174a89d..ec0e01f64f9f 100644 --- a/include/filetype.h +++ b/include/filetype.h @@ -51,6 +51,8 @@ enum filetype is_fat_or_mbr(const unsigned char *sector, unsigned long *bootsec) int is_fat_boot_sector(const void *_buf); bool filetype_is_barebox_image(enum filetype ft); +#define BAREBOX_CRC_MAGIC_VALUE "crc" + #define ARM_HEAD_SIZE 0x30 #define ARM_HEAD_MAGICWORD_OFFSET 0x20 #define ARM_HEAD_SIZE_OFFSET 0x2C diff --git a/scripts/.gitignore b/scripts/.gitignore index 533bffd97d36..d11ac7f97f32 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -2,6 +2,7 @@ bin2c mkimage fix_size bareboxenv +bareboxcrc bareboxcrc32 kernel-install bareboximd diff --git a/scripts/Makefile b/scripts/Makefile index a5c16b2f3133..1683d38c222d 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -8,6 +8,7 @@ hostprogs-y += bin2c hostprogs-y += mkimage hostprogs-y += fix_size hostprogs-y += bareboxenv +hostprogs-y += bareboxcrc hostprogs-y += bareboxcrc32 hostprogs-y += kernel-install hostprogs-$(CONFIG_IMD) += bareboximd diff --git a/scripts/bareboxcrc.c b/scripts/bareboxcrc.c new file mode 100644 index 000000000000..37cb9b0a6ce8 --- /dev/null +++ b/scripts/bareboxcrc.c @@ -0,0 +1,219 @@ +/* + * bareboxcrc.c + * + * Copyright (C) 2016 Jan Luebbe <j.luebbe@xxxxxxxxxxxxxx> + * + * 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, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#define _DEFAULT_SOURCE + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdint.h> +#include <limits.h> +#include <errno.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> +#include <getopt.h> +#include <endian.h> + +#include "compiler.h" + +#include "../include/filetype.h" +#include "../crypto/crc32.c" + +#define EX_SUCCESS 0 +#define EX_NO_CHECKSUM 1 +#define EX_CHECKSUM_FAULTY 2 +#define EX_NO_BAREBOX_HEADER 3 +#define EX_IMAGE_TOO_SMALL 4 +#define EX_IMAGE_TOO_BIG 5 +#define EX_LOCATION_OCCUPIED 6 +#define EX_OUT_OF_MEMORY 7 +#define EX_IO_ERROR 8 +#define EX_WRONG_USAGE 9 + +void usage(char *prgname) +{ + fprintf(stderr, "Usage : %s [OPTION] FILE\n" + "\n" + "options:\n" + " -c verify checksum\n" + " -f force\n", + prgname); +} + +int get_barebox_head_size(const char *head) +{ + if (!strcmp(head + ARM_HEAD_MAGICWORD_OFFSET, "barebox")) + return ARM_HEAD_SIZE; + else if (!strcmp(head + MIPS_HEAD_MAGICWORD_OFFSET, "barebox")) + return MIPS_HEAD_SIZE; + + return 0; +} + +int checksum(FILE *image, bool check, bool force, off_t size) +{ + void *buf = malloc(size); + int ret = EX_SUCCESS; + size_t head_size; + uint32_t crc = 0; + uint32_t *p; + + if (!buf) { + fprintf(stderr, "malloc: out of memory\n"); + return EX_OUT_OF_MEMORY; + } + + if (fseeko(image, 0, SEEK_SET) == -1) { + perror("fseeko"); + ret = EX_IO_ERROR; + goto out; + } + + if (fread(buf, 1, size, image) < size) { + perror("fread"); + ret = EX_IO_ERROR; + goto out; + } + + head_size = get_barebox_head_size(buf); + if (!head_size) { + fprintf(stderr, "image does not contain a barebox header\n"); + ret = EX_NO_BAREBOX_HEADER; + goto out; + } + + if (size < head_size + 2 * sizeof(uint32_t)) { + fprintf(stderr, "image is too small\n"); + ret = EX_IMAGE_TOO_SMALL; + goto out; + } + + p = buf + head_size; + + if (check) { + if (strcmp((const char*) p, BAREBOX_CRC_MAGIC_VALUE)) { + fprintf(stderr, "image does not contain a checksum\n"); + ret = EX_NO_CHECKSUM; + goto out; + } + } else { + if (!force && (*p != 0x55555555 || *(p+1) != 0x55555555)) { + fprintf(stderr, "location for magic value and CRC seems already " + "to be occupied by something else\n"); + ret = EX_LOCATION_OCCUPIED; + goto out; + } + + if (fseeko(image, head_size, SEEK_SET) == -1) { + perror("fseeko"); + ret = EX_IO_ERROR; + goto out; + } + + if (fwrite(BAREBOX_CRC_MAGIC_VALUE, sizeof(uint32_t), 1, image) != 1) { + perror("fwrite"); + ret = EX_IO_ERROR; + goto out; + } + + sprintf((char*) p, "%s", BAREBOX_CRC_MAGIC_VALUE); + } + + crc = crc32(crc, buf, head_size + sizeof(uint32_t)); + crc = crc32(crc, buf + head_size + 2 * sizeof(uint32_t), + size - (head_size + 2 * sizeof(uint32_t))); + crc = htobe32(crc); + + if (check) { + if (crc != *(p + 1)) { + fprintf(stderr, "embedded checksum is faulty\n"); + ret = EX_CHECKSUM_FAULTY; + } + } else { + if (fwrite(&crc, sizeof(uint32_t), 1, image) != 1) { + perror("fwrite"); + ret = EX_IO_ERROR; + } + } + +out: + free(buf); + return ret; +} + +int main(int argc, char *argv[]) +{ + FILE *image; + bool check = false; + bool force = false; + int opt; + int ret; + off_t size; + + while((opt = getopt(argc, argv, "cf")) != -1) { + switch (opt) { + case 'c': + check = true; + break; + case 'f': + force = true; + break; + } + } + + if (optind >= argc) { + usage(argv[0]); + exit(EX_WRONG_USAGE); + } + + image = fopen(argv[optind], check ? "r" : "r+"); + if (image == NULL) { + perror("fopen"); + exit(EX_IO_ERROR); + } + + if (fseeko(image, 0, SEEK_END) == -1) { + perror("fseeko"); + exit(EX_IO_ERROR); + } + size = ftello(image); + if (size == -1) { + perror("ftello"); + exit(EX_IO_ERROR); + } + if (size > 0xa00000) { + fprintf(stderr, "error: image should be smaller than 10 MiB\n"); + exit(EX_IMAGE_TOO_BIG); + } + + ret = checksum(image, check, force, size); + if (ret) + exit(ret); + + if (fclose(image) != 0) { + perror("fclose"); + exit(EX_IO_ERROR); + } + + exit(EX_SUCCESS); +} -- 2.8.1 _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox