diff options
author | Yilun Lin <yllin@google.com> | 2018-05-29 12:39:39 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-07-02 04:34:53 -0700 |
commit | 90e5f21c4e104aa7861875dd4b66f2828a578fbb (patch) | |
tree | e82febd9307f7ce242bb4a57dda04fde80056e57 /util/gen_emmc_transfer_data.c | |
parent | f18fa2977539fd3460d808637503d8fcb6d0b594 (diff) | |
download | chrome-ec-90e5f21c4e104aa7861875dd4b66f2828a578fbb.tar.gz |
common/bootblock: Pack bootblock in EC image.
Packs a bootblock into EC image. The bootblock content will be firstly
tranlated to eMMC emulated data, and then been packed to the RO image.
Getting idear from: CL:1039105(which generates eMMC data as a header file).
BRANCH=none
BUG=b:80159522
TEST=BOOTBLOCK=xyz make BOARD=kukui -j
BOOTBLOCK=xyz make BOARD=kukui -j # check it doesn't repack.
BOOTBLOCK=abc make BOARD=kukui -j # check it repacks the bootblock.
Change-Id: Ia1564d6c54aed7a91fc42210d6247bdecfd82f4e
Signed-off-by: Yilun Lin <yllin@google.com>
Reviewed-on: https://chromium-review.googlesource.com/1075907
Commit-Ready: Yilun Lin <yllin@chromium.org>
Tested-by: Yilun Lin <yllin@chromium.org>
Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
Diffstat (limited to 'util/gen_emmc_transfer_data.c')
-rw-r--r-- | util/gen_emmc_transfer_data.c | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/util/gen_emmc_transfer_data.c b/util/gen_emmc_transfer_data.c new file mode 100644 index 0000000000..98417beb9b --- /dev/null +++ b/util/gen_emmc_transfer_data.c @@ -0,0 +1,158 @@ +/* Copyright 2018 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Generate transferring data from a file. The transferring data emulates the + * eMMC protocol. + */ + +#include <err.h> +#include <errno.h> +#include <getopt.h> +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +#include <compile_time_macros.h> + +/* eMMC transfer block size */ +#define BLOCK_SIZE 512 +#define BLOCK_RAW_DATA "bootblock_raw_data" + +uint16_t crc16_arg(uint8_t data, uint16_t previous_crc) +{ + unsigned int crc = previous_crc << 8; + int i; + + crc ^= (data << 16); + for (i = 8; i; i--) { + if (crc & 0x800000) + crc ^= (0x11021 << 7); + crc <<= 1; + } + + return (uint16_t)(crc >> 8); +} + +void header_format(FILE *fin, FILE *fout) +{ + uint8_t data[BLOCK_SIZE]; + int blk, j; + uint16_t crc16; + size_t cnt = 0; + + fprintf(fout, "/* This file is auto-generated. Do not modify. */\n" + "#ifndef __CROS_EC_BOOTBLOCK_DATA_H\n" + "#define __CROS_EC_BOOTBLOCK_DATA_H\n" + "\n" + "#include <stdint.h>\n" + "\n" + ); + + fprintf(fout, + "static const uint8_t %s[] __attribute__((aligned(4))) =\n" + "{\n" + "\t0xff, 0x97, /* Acknowledge boot mode: 1 S=0 010 E=1 11 */\n" + "\t0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\n", + BLOCK_RAW_DATA); + + for (blk = 0;; blk++) { + crc16 = 0; + if (fin) + cnt = fread(data, 1, BLOCK_SIZE, fin); + + if (cnt == 0) + break; + else if (cnt < BLOCK_SIZE) + memset(&data[cnt], 0xff, BLOCK_SIZE-cnt); + + fprintf(fout, "\t/* Block %d (%ld) */\n", blk, cnt); + fprintf(fout, "\t0xff, 0xfe, /* idle, start bit. */"); + for (j = 0; j < sizeof(data); j++) { + fprintf(fout, "%s0x%02x,", + (j % 8) == 0 ? "\n\t" : " ", data[j]); + crc16 = crc16_arg(data[j], crc16); + } + fprintf(fout, "\n"); + + fprintf(fout, "\t0x%02x, 0x%02x, 0xff," + " /* CRC, end bit, idle */\n", + crc16 >> 8, crc16 & 0xff); + } + + fprintf(fout, "\t/* Last block: idle */\n"); + fprintf(fout, "\t0xff, 0xff, 0xff, 0xff\n"); + fprintf(fout, "};\n"); + fprintf(fout, "#endif /* __CROS_EC_BOOTBLOCK_DATA_H */\n"); +} + +int main(int argc, char **argv) +{ + int nopt; + int ret = 0; + const char *output_name = NULL; + char *input_name = NULL; + FILE *fin = NULL; + FILE *fout = NULL; + + const char short_opts[] = "i:ho:"; + const struct option long_opts[] = { + { "input", 1, NULL, 'i' }, + { "help", 0, NULL, 'h' }, + { "out", 1, NULL, 'o' }, + { NULL } + }; + const char usage[] = "USAGE: %s [-i <input>] -o <output>\n"; + + while ((nopt = getopt_long(argc, argv, short_opts, long_opts, + NULL)) != -1) { + switch (nopt) { + case 'i': /* -i or --input*/ + input_name = optarg; + break; + case 'h': /* -h or --help */ + fprintf(stdout, usage, argv[0]); + return 0; + case 'o': /* -o or --out */ + output_name = optarg; + break; + default: /* Invalid parameter. */ + fprintf(stderr, usage, argv[0]); + return 1; + } + } + + if (output_name == NULL) { + fprintf(stderr, usage, argv[0]); + return 1; + } + + if (input_name == NULL) { + printf("No bootblock provided, outputting default file.\n"); + } else { + fin = fopen(input_name, "r"); + if (!fin) { + printf("Cannot open input file: %s\n", input_name); + ret = 1; + goto out; + } + } + + fout = fopen(output_name, "w"); + + if (!fout) { + printf("Cannot open output file: %s\n", output_name); + ret = 1; + goto out; + } + + header_format(fin, fout); + + fclose(fout); + +out: + if (fin) + fclose(fin); + + return ret; +} |