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>
This commit is contained in:
parent
f18fa29775
commit
90e5f21c4e
4
Makefile
4
Makefile
|
@ -36,6 +36,10 @@ config=$(out)/.config
|
|||
# If no key file is provided, use the default dev key
|
||||
PEM ?= $(BDIR)/dev_key.pem
|
||||
|
||||
# If CONFIG_BOOTBLOCK is set, includes AP-FW bootblock in the EC image.
|
||||
# If no bootblock is provided, just pack an empty file.
|
||||
BOOTBLOCK ?=
|
||||
|
||||
# If CONFIG_TOUCHPAD_HASH_FW is set, include hashes of a touchpad firmware in
|
||||
# the EC image (if no touchpad firmware is provided, just output blank hashes).
|
||||
TOUCHPAD_FW ?=
|
||||
|
|
|
@ -103,6 +103,9 @@ cmd_link_taskinfo = $(BUILDCC) $(BUILD_CFLAGS) --shared -fPIC $^ \
|
|||
cmd_tp_hash = $(out)/util/gen_touchpad_hash \
|
||||
$(if $(TOUCHPAD_FW),-f $(TOUCHPAD_FW)) -o $@
|
||||
|
||||
cmd_emmc_bootblock = $(out)/util/gen_emmc_transfer_data \
|
||||
$(if $(BOOTBLOCK),-i $(BOOTBLOCK)) -o $@
|
||||
|
||||
# commands for RSA signature: rwsig does not need to sign the whole image
|
||||
# (it signs the RW part separately). usbpd1 type needs to sign the final image.
|
||||
ifeq ($(CONFIG_RWSIG_TYPE_RWSIG),)
|
||||
|
|
|
@ -157,6 +157,30 @@ $(out)/RW/common/rsa.o: CFLAGS+=-O3
|
|||
$(out)/RO/common/rsa.o: CFLAGS+=-O3
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_BOOTBLOCK),)
|
||||
build-util-bin += gen_emmc_transfer_data
|
||||
|
||||
# Bootblock is only packed in RO image.
|
||||
$(out)/util/gen_emmc_transfer_data: BUILD_LDFLAGS += -DSECTION_IS_RO
|
||||
$(out)/bootblock_data.h: $(out)/util/gen_emmc_transfer_data $(out)/.bootblock
|
||||
$(call quiet,emmc_bootblock,BTBLK )
|
||||
|
||||
# We only want to repack the bootblock if: $(BOOTBLOCK) variable value has
|
||||
# changed, or the file pointed at by $(BOOTBLOCK) has changed. We do this
|
||||
# by recording the latest $(BOOTBLOCK) file information in .bootblock
|
||||
# TODO: Need a better makefile tricks to do this.
|
||||
|
||||
bootblock_ls := $(shell ls -l "$(BOOTBLOCK)" 2>&1)
|
||||
old_bootblock_ls := $(shell cat $(out)/.bootblock 2>/dev/null)
|
||||
|
||||
$(out)/.bootblock: $(BOOTBLOCK)
|
||||
@echo "$(bootblock_ls)" > $@
|
||||
|
||||
ifneq ($(bootblock_ls),$(old_bootblock_ls))
|
||||
.PHONY: $(out)/.bootblock
|
||||
endif
|
||||
endif # CONFIG_BOOTBLOCK
|
||||
|
||||
ifneq ($(CONFIG_TOUCHPAD_HASH_FW),)
|
||||
$(out)/RO/common/update_fw.o: $(out)/touchpad_fw_hash.h
|
||||
$(out)/RW/common/update_fw.o: $(out)/touchpad_fw_hash.h
|
||||
|
|
|
@ -419,6 +419,12 @@
|
|||
/* Size of boot header in storage. */
|
||||
#undef CONFIG_BOOT_HEADER_STORAGE_SIZE
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Bootblock config */
|
||||
|
||||
/* Pack AP-FW bootblock in EC image. */
|
||||
#undef CONFIG_BOOTBLOCK
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* EC has GPIOs to allow board to reset RTC */
|
||||
|
|
|
@ -58,6 +58,13 @@ $(out)/util/%/usb_pd_policy.o: %/usb_pd_policy.c
|
|||
$(call quiet,c_to_vif,BUILDCC)
|
||||
endif # CONFIG_USB_POWER_DELIVERY
|
||||
|
||||
ifneq ($(CONFIG_BOOTBLOCK),)
|
||||
build-util-bin += gen_emmc_transfer_data
|
||||
|
||||
# Bootblock is only packed in RO image.
|
||||
$(out)/util/gen_emmc_transfer_data: BUILD_LDFLAGS += -DSECTION_IS_RO
|
||||
endif # CONFIG_BOOTBLOCK
|
||||
|
||||
ifneq ($(CONFIG_TOUCHPAD_HASH_FW),)
|
||||
build-util-bin += gen_touchpad_hash
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue