summaryrefslogtreecommitdiff
path: root/util/gen_emmc_transfer_data.c
diff options
context:
space:
mode:
authorYilun Lin <yllin@google.com>2018-05-29 12:39:39 +0800
committerchrome-bot <chrome-bot@chromium.org>2018-07-02 04:34:53 -0700
commit90e5f21c4e104aa7861875dd4b66f2828a578fbb (patch)
treee82febd9307f7ce242bb4a57dda04fde80056e57 /util/gen_emmc_transfer_data.c
parentf18fa2977539fd3460d808637503d8fcb6d0b594 (diff)
downloadchrome-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.c158
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;
+}