mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-27 19:53:42 +00:00
futility: Add remaining vboot binary utilities
This change adds these formerly external utilities into the futility binary: dev_sign_file dump_kernel_config gbb_utility vbutil_firmware vbutil_kernel These target binaries will remain independent of futility, since they are not directly related to verified boot: cgpt crossystem tpm_init_temp_fix tpmc Also, dumpRSAPublicKey is removed from the target, since it is only used on the build host to create new keypairs. This change also add several additional tests. BUG=chromium:224734 BRANCH=ToT CQ-DEPEND=CL:210391,CL:210568,CL:210587 TEST=manual make runtests make clean Also build and test: - normal image - test image - recovery image - firmware shellball Note that this CL depends on simultaneous changes to the chromeos-initramfs ebuild. Change-Id: If791b5e9b5aac218ceafa9f45fc1785f16b91a64 Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/210403
This commit is contained in:
committed by
chrome-internal-fetch
parent
b52d7b7acb
commit
6f3961507e
114
Makefile
114
Makefile
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
|
# Copyright 2013 The Chromium OS Authors. All rights reserved.
|
||||||
# Use of this source code is governed by a BSD-style license that can be
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
# found in the LICENSE file.
|
# found in the LICENSE file.
|
||||||
|
|
||||||
@@ -43,23 +43,17 @@ export BUILD
|
|||||||
# Stuff for 'make install'
|
# Stuff for 'make install'
|
||||||
INSTALL = install
|
INSTALL = install
|
||||||
DESTDIR = /usr/local/bin
|
DESTDIR = /usr/local/bin
|
||||||
OLDDIR = old_bins
|
|
||||||
|
|
||||||
# Where exactly do the pieces go?
|
# Where exactly do the pieces go?
|
||||||
# FT_DIR = futility target directory - where it will be on the target
|
# UB_DIR = utility binary directory
|
||||||
# F_DIR = futility install directory - where it gets put right now
|
# VB_DIR = vboot binary directory for dev-mode-only scripts
|
||||||
# UB_DIR = userspace binary directory for futility's exec() targets
|
|
||||||
# VB_DIR = target vboot directory - for dev-mode-only helpers, keys, etc.
|
|
||||||
ifeq (${MINIMAL},)
|
ifeq (${MINIMAL},)
|
||||||
# Host install just puts everything in one place
|
# Host install just puts everything where it's told
|
||||||
FT_DIR=${DESTDIR}
|
UB_DIR=${DESTDIR}
|
||||||
F_DIR=${DESTDIR}
|
VB_DIR=${DESTDIR}
|
||||||
UB_DIR=${DESTDIR}/${OLDDIR}
|
|
||||||
else
|
else
|
||||||
# Target install puts things into DESTDIR subdirectories
|
# Target install puts things into subdirectories under DESTDIR
|
||||||
FT_DIR=/usr/bin
|
UB_DIR=${DESTDIR}/usr/bin
|
||||||
F_DIR=${DESTDIR}${FT_DIR}
|
|
||||||
UB_DIR=${F_DIR}/${OLDDIR}
|
|
||||||
VB_DIR=${DESTDIR}/usr/share/vboot/bin
|
VB_DIR=${DESTDIR}/usr/share/vboot/bin
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@@ -143,10 +137,6 @@ CC ?= gcc
|
|||||||
CFLAGS += -DCHROMEOS_ENVIRONMENT -Wall -Werror ${DEBUG_FLAGS}
|
CFLAGS += -DCHROMEOS_ENVIRONMENT -Wall -Werror ${DEBUG_FLAGS}
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq (${OLDDIR},)
|
|
||||||
CFLAGS += -DOLDDIR=${OLDDIR}
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifneq (${DEBUG},)
|
ifneq (${DEBUG},)
|
||||||
CFLAGS += -DVBOOT_DEBUG
|
CFLAGS += -DVBOOT_DEBUG
|
||||||
endif
|
endif
|
||||||
@@ -365,6 +355,7 @@ UTILLIB_SRCS = \
|
|||||||
cgpt/flash_ts.c \
|
cgpt/flash_ts.c \
|
||||||
cgpt/flash_ts_drv.c \
|
cgpt/flash_ts_drv.c \
|
||||||
firmware/lib/cgptlib/mtdlib.c \
|
firmware/lib/cgptlib/mtdlib.c \
|
||||||
|
futility/dump_kernel_config_lib.c \
|
||||||
host/arch/${ARCH}/lib/crossystem_arch.c \
|
host/arch/${ARCH}/lib/crossystem_arch.c \
|
||||||
host/lib/crossystem.c \
|
host/lib/crossystem.c \
|
||||||
host/lib/file_keys.c \
|
host/lib/file_keys.c \
|
||||||
@@ -375,8 +366,7 @@ UTILLIB_SRCS = \
|
|||||||
host/lib/host_misc.c \
|
host/lib/host_misc.c \
|
||||||
host/lib/util_misc.c \
|
host/lib/util_misc.c \
|
||||||
host/lib/host_signature.c \
|
host/lib/host_signature.c \
|
||||||
host/lib/signature_digest.c \
|
host/lib/signature_digest.c
|
||||||
utility/dump_kernel_config_lib.c
|
|
||||||
|
|
||||||
UTILLIB_OBJS = ${UTILLIB_SRCS:%.c=${BUILD}/%.o}
|
UTILLIB_OBJS = ${UTILLIB_SRCS:%.c=${BUILD}/%.o}
|
||||||
ALL_OBJS += ${UTILLIB_OBJS}
|
ALL_OBJS += ${UTILLIB_OBJS}
|
||||||
@@ -403,10 +393,10 @@ HOSTLIB_SRCS = \
|
|||||||
firmware/stub/tpm_lite_stub.c \
|
firmware/stub/tpm_lite_stub.c \
|
||||||
firmware/stub/utility_stub.c \
|
firmware/stub/utility_stub.c \
|
||||||
firmware/stub/vboot_api_stub_init.c \
|
firmware/stub/vboot_api_stub_init.c \
|
||||||
|
futility/dump_kernel_config_lib.c \
|
||||||
host/arch/${ARCH}/lib/crossystem_arch.c \
|
host/arch/${ARCH}/lib/crossystem_arch.c \
|
||||||
host/lib/crossystem.c \
|
host/lib/crossystem.c \
|
||||||
host/lib/host_misc.c \
|
host/lib/host_misc.c
|
||||||
utility/dump_kernel_config_lib.c
|
|
||||||
|
|
||||||
HOSTLIB_OBJS = ${HOSTLIB_SRCS:%.c=${BUILD}/%.o}
|
HOSTLIB_OBJS = ${HOSTLIB_SRCS:%.c=${BUILD}/%.o}
|
||||||
ALL_OBJS += ${HOSTLIB_OBJS}
|
ALL_OBJS += ${HOSTLIB_OBJS}
|
||||||
@@ -429,7 +419,7 @@ TINYHOSTLIB_SRCS = \
|
|||||||
firmware/lib/cgptlib/mtdlib.c \
|
firmware/lib/cgptlib/mtdlib.c \
|
||||||
firmware/lib/utility_string.c \
|
firmware/lib/utility_string.c \
|
||||||
firmware/stub/utility_stub.c \
|
firmware/stub/utility_stub.c \
|
||||||
utility/dump_kernel_config_lib.c
|
futility/dump_kernel_config_lib.c
|
||||||
|
|
||||||
TINYHOSTLIB_OBJS = ${TINYHOSTLIB_SRCS:%.c=${BUILD}/%.o}
|
TINYHOSTLIB_OBJS = ${TINYHOSTLIB_SRCS:%.c=${BUILD}/%.o}
|
||||||
|
|
||||||
@@ -477,22 +467,18 @@ endif
|
|||||||
|
|
||||||
# These utilities should be linked statically.
|
# These utilities should be linked statically.
|
||||||
UTIL_NAMES_STATIC = \
|
UTIL_NAMES_STATIC = \
|
||||||
utility/crossystem \
|
utility/crossystem
|
||||||
utility/gbb_utility
|
|
||||||
|
|
||||||
UTIL_NAMES = ${UTIL_NAMES_STATIC} \
|
UTIL_NAMES = ${UTIL_NAMES_STATIC} \
|
||||||
utility/dev_sign_file \
|
|
||||||
utility/dump_kernel_config \
|
|
||||||
utility/dumpRSAPublicKey \
|
|
||||||
utility/tpm_init_temp_fix \
|
utility/tpm_init_temp_fix \
|
||||||
utility/tpmc \
|
utility/tpmc
|
||||||
utility/vbutil_firmware \
|
|
||||||
utility/vbutil_kernel
|
|
||||||
|
|
||||||
|
# TODO: Do we still need eficompress and efidecompress for anything?
|
||||||
ifeq (${MINIMAL},)
|
ifeq (${MINIMAL},)
|
||||||
UTIL_NAMES += \
|
UTIL_NAMES += \
|
||||||
utility/bmpblk_font \
|
utility/bmpblk_font \
|
||||||
utility/bmpblk_utility \
|
utility/bmpblk_utility \
|
||||||
|
utility/dumpRSAPublicKey \
|
||||||
utility/eficompress \
|
utility/eficompress \
|
||||||
utility/efidecompress \
|
utility/efidecompress \
|
||||||
utility/load_kernel_test \
|
utility/load_kernel_test \
|
||||||
@@ -533,50 +519,32 @@ FUTIL_BIN = ${BUILD}/futility/futility
|
|||||||
# But we still need both static (tiny) and dynamic (with openssl) versions.
|
# But we still need both static (tiny) and dynamic (with openssl) versions.
|
||||||
FUTIL_STATIC_BIN = ${FUTIL_BIN}_s
|
FUTIL_STATIC_BIN = ${FUTIL_BIN}_s
|
||||||
|
|
||||||
# These are the executables to be replaced with symlinks.
|
# These are the executables that are now built in to futility. We'll create
|
||||||
FUTIL_OLD = \
|
# symlinks for these so the old names will still work.
|
||||||
bmpblk_font \
|
# TODO: Do we still need dev_sign_file for anything?
|
||||||
bmpblk_utility \
|
FUTIL_BUILTIN = \
|
||||||
cgpt \
|
|
||||||
chromeos-tpm-recovery \
|
|
||||||
crossystem \
|
|
||||||
dev_debug_vboot \
|
|
||||||
dev_make_keypair \
|
|
||||||
dev_sign_file \
|
dev_sign_file \
|
||||||
dumpRSAPublicKey \
|
|
||||||
dump_fmap \
|
dump_fmap \
|
||||||
dump_kernel_config \
|
dump_kernel_config \
|
||||||
eficompress \
|
|
||||||
efidecompress \
|
|
||||||
enable_dev_usb_boot \
|
|
||||||
gbb_utility \
|
gbb_utility \
|
||||||
load_kernel_test \
|
|
||||||
make_dev_firmware.sh \
|
|
||||||
make_dev_ssd.sh \
|
|
||||||
pad_digest_utility \
|
|
||||||
resign_firmwarefd.sh \
|
|
||||||
set_gbb_flags.sh \
|
|
||||||
signature_digest_utility \
|
|
||||||
tpm-nvsize \
|
|
||||||
tpm_init_temp_fix \
|
|
||||||
tpmc \
|
|
||||||
vbutil_firmware \
|
vbutil_firmware \
|
||||||
vbutil_kernel \
|
vbutil_kernel \
|
||||||
vbutil_key \
|
vbutil_key \
|
||||||
vbutil_keyblock \
|
vbutil_keyblock
|
||||||
vbutil_what_keys \
|
|
||||||
verify_data
|
|
||||||
|
|
||||||
FUTIL_STATIC_SRCS = \
|
FUTIL_STATIC_SRCS = \
|
||||||
futility/futility.c \
|
futility/futility.c \
|
||||||
futility/cmd_dump_fmap.c \
|
futility/cmd_dump_fmap.c \
|
||||||
futility/cmd_foo.c
|
futility/cmd_gbb_utility.c
|
||||||
|
|
||||||
FUTIL_SRCS = \
|
FUTIL_SRCS = \
|
||||||
$(FUTIL_STATIC_SRCS) \
|
$(FUTIL_STATIC_SRCS) \
|
||||||
|
futility/cmd_dev_sign_file.c \
|
||||||
|
futility/cmd_dump_kernel_config.c \
|
||||||
|
futility/cmd_vbutil_firmware.c \
|
||||||
|
futility/cmd_vbutil_kernel.c \
|
||||||
futility/cmd_vbutil_key.c \
|
futility/cmd_vbutil_key.c \
|
||||||
futility/cmd_vbutil_keyblock.c \
|
futility/cmd_vbutil_keyblock.c
|
||||||
futility/cmd_hey.c
|
|
||||||
|
|
||||||
FUTIL_LDS = futility/futility.lds
|
FUTIL_LDS = futility/futility.lds
|
||||||
|
|
||||||
@@ -628,6 +596,7 @@ TEST_NAMES = \
|
|||||||
tests/vboot_firmware_tests \
|
tests/vboot_firmware_tests \
|
||||||
tests/vboot_kernel_tests \
|
tests/vboot_kernel_tests \
|
||||||
tests/vboot_nvstorage_test \
|
tests/vboot_nvstorage_test \
|
||||||
|
tests/futility/binary_editor \
|
||||||
tests/futility/test_not_really
|
tests/futility/test_not_really
|
||||||
|
|
||||||
ifdef REGION_READ
|
ifdef REGION_READ
|
||||||
@@ -906,15 +875,10 @@ utils_install: ${UTIL_BINS} ${UTIL_SCRIPTS}
|
|||||||
.PHONY: signing_install
|
.PHONY: signing_install
|
||||||
signing_install: ${SIGNING_SCRIPTS} ${SIGNING_SCRIPTS_DEV} ${SIGNING_COMMON}
|
signing_install: ${SIGNING_SCRIPTS} ${SIGNING_SCRIPTS_DEV} ${SIGNING_COMMON}
|
||||||
@$(PRINTF) " INSTALL SIGNING\n"
|
@$(PRINTF) " INSTALL SIGNING\n"
|
||||||
${Q}mkdir -p ${UB_DIR}
|
${Q}mkdir -p ${UB_DIR} ${VB_DIR}
|
||||||
${Q}${INSTALL} -t ${UB_DIR} ${SIGNING_SCRIPTS}
|
${Q}${INSTALL} -t ${UB_DIR} ${SIGNING_SCRIPTS}
|
||||||
${Q}${INSTALL} -t ${UB_DIR} ${SIGNING_SCRIPTS_DEV}
|
${Q}${INSTALL} -t ${VB_DIR} ${SIGNING_SCRIPTS_DEV}
|
||||||
${Q}${INSTALL} -t ${UB_DIR} -m 'u=rw,go=r,a-s' ${SIGNING_COMMON}
|
${Q}${INSTALL} -t ${VB_DIR} -m 'u=rw,go=r,a-s' ${SIGNING_COMMON}
|
||||||
ifneq (${VB_DIR},)
|
|
||||||
${Q}mkdir -p ${VB_DIR}
|
|
||||||
${Q}for prog in $(notdir ${SIGNING_SCRIPTS_DEV}); do \
|
|
||||||
ln -sf "${FT_DIR}/futility" "${VB_DIR}/$$prog"; done
|
|
||||||
endif
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# new Firmware Utility
|
# new Firmware Utility
|
||||||
@@ -934,10 +898,10 @@ ${FUTIL_BIN}: ${FUTIL_LDS} ${FUTIL_OBJS} ${UTILLIB}
|
|||||||
.PHONY: futil_install
|
.PHONY: futil_install
|
||||||
futil_install: ${FUTIL_BIN}
|
futil_install: ${FUTIL_BIN}
|
||||||
@$(PRINTF) " INSTALL futility\n"
|
@$(PRINTF) " INSTALL futility\n"
|
||||||
${Q}mkdir -p ${F_DIR}
|
${Q}mkdir -p ${UB_DIR}
|
||||||
${Q}${INSTALL} -t ${F_DIR} ${FUTIL_BIN} ${FUTIL_STATIC_BIN}
|
${Q}${INSTALL} -t ${UB_DIR} ${FUTIL_BIN} ${FUTIL_STATIC_BIN}
|
||||||
${Q}for prog in ${FUTIL_OLD}; do \
|
${Q}for prog in ${FUTIL_BUILTIN}; do \
|
||||||
ln -sf futility "${F_DIR}/$$prog"; done
|
ln -sf futility "${UB_DIR}/$$prog"; done
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# Utility to generate TLCL structure definition header file.
|
# Utility to generate TLCL structure definition header file.
|
||||||
@@ -1004,9 +968,6 @@ ${BUILD}/%.o: %.cc
|
|||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
# Here are the special tweaks to the generic rules.
|
# Here are the special tweaks to the generic rules.
|
||||||
|
|
||||||
# GBB utility needs C++ linker. TODO: It shouldn't.
|
|
||||||
${BUILD}/utility/gbb_utility: LD = ${CXX}
|
|
||||||
|
|
||||||
# Because we play some clever linker script games to add new commands without
|
# Because we play some clever linker script games to add new commands without
|
||||||
# changing any header files, futility must be linked with ld.bfd, not gold.
|
# changing any header files, futility must be linked with ld.bfd, not gold.
|
||||||
${FUTIL_BIN}: LDFLAGS += -fuse-ld=bfd
|
${FUTIL_BIN}: LDFLAGS += -fuse-ld=bfd
|
||||||
@@ -1018,9 +979,6 @@ CRYPTO_LIBS := $(shell ${PKG_CONFIG} --libs libcrypto)
|
|||||||
${BUILD}/utility/dumpRSAPublicKey: LDLIBS += ${CRYPTO_LIBS}
|
${BUILD}/utility/dumpRSAPublicKey: LDLIBS += ${CRYPTO_LIBS}
|
||||||
${BUILD}/utility/pad_digest_utility: LDLIBS += ${CRYPTO_LIBS}
|
${BUILD}/utility/pad_digest_utility: LDLIBS += ${CRYPTO_LIBS}
|
||||||
${BUILD}/utility/signature_digest_utility: LDLIBS += ${CRYPTO_LIBS}
|
${BUILD}/utility/signature_digest_utility: LDLIBS += ${CRYPTO_LIBS}
|
||||||
${BUILD}/utility/dev_sign_file: LDLIBS += ${CRYPTO_LIBS}
|
|
||||||
${BUILD}/utility/vbutil_firmware: LDLIBS += ${CRYPTO_LIBS}
|
|
||||||
${BUILD}/utility/vbutil_kernel: LDLIBS += ${CRYPTO_LIBS}
|
|
||||||
|
|
||||||
${BUILD}/host/linktest/main: LDLIBS += ${CRYPTO_LIBS}
|
${BUILD}/host/linktest/main: LDLIBS += ${CRYPTO_LIBS}
|
||||||
${BUILD}/tests/vb2_common2_tests: LDLIBS += ${CRYPTO_LIBS}
|
${BUILD}/tests/vb2_common2_tests: LDLIBS += ${CRYPTO_LIBS}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
/* Copyright 2011 The Chromium OS Authors. All rights reserved.
|
||||||
* Use of this source code is governed by a BSD-style license that can be
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*
|
*
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "cryptolib.h"
|
#include "cryptolib.h"
|
||||||
|
#include "futility.h"
|
||||||
#include "host_common.h"
|
#include "host_common.h"
|
||||||
#include "kernel_blob.h"
|
#include "kernel_blob.h"
|
||||||
#include "vboot_common.h"
|
#include "vboot_common.h"
|
||||||
@@ -273,7 +274,7 @@ static int Verify(const char* filename, const char* vblock_file,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int do_dev_sign_file(int argc, char* argv[]) {
|
||||||
char* filename = NULL;
|
char* filename = NULL;
|
||||||
char* keyblock_file = NULL;
|
char* keyblock_file = NULL;
|
||||||
char* signprivate_file = NULL;
|
char* signprivate_file = NULL;
|
||||||
@@ -353,3 +354,6 @@ int main(int argc, char* argv[]) {
|
|||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECLARE_FUTIL_COMMAND(dev_sign_file, do_dev_sign_file,
|
||||||
|
"Sign or verify dev-mode files (DEPRECATED)");
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
|
/* Copyright 2012 The Chromium OS Authors. All rights reserved.
|
||||||
* Use of this source code is governed by a BSD-style license that can be
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*
|
*
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "futility.h"
|
||||||
#include "vboot_host.h"
|
#include "vboot_host.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -33,7 +34,7 @@ static int PrintHelp(void) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int do_dump_kernel_config(int argc, char* argv[]) {
|
||||||
char *infile = NULL;
|
char *infile = NULL;
|
||||||
char *config = NULL;
|
char *config = NULL;
|
||||||
uint64_t kernel_body_load_address = USE_PREAMBLE_LOAD_ADDR;
|
uint64_t kernel_body_load_address = USE_PREAMBLE_LOAD_ADDR;
|
||||||
@@ -87,3 +88,6 @@ int main(int argc, char* argv[]) {
|
|||||||
free(config);
|
free(config);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECLARE_FUTIL_COMMAND(dump_kernel_config, do_dump_kernel_config,
|
||||||
|
"Prints the kernel command line");
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2013 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "futility.h"
|
|
||||||
|
|
||||||
static int do_something(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
printf("this is %s\n", __func__);
|
|
||||||
for (i = 0; i < argc; i++)
|
|
||||||
printf("argv[%d] = %s\n", i, argv[i]);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DECLARE_FUTIL_COMMAND(foo, do_something, "invoke a foo");
|
|
||||||
DECLARE_FUTIL_COMMAND(bar, do_something, "go to bar");
|
|
||||||
611
futility/cmd_gbb_utility.c
Normal file
611
futility/cmd_gbb_utility.c
Normal file
@@ -0,0 +1,611 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014 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.
|
||||||
|
*/
|
||||||
|
#include <errno.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "futility.h"
|
||||||
|
#include "gbb_header.h"
|
||||||
|
|
||||||
|
static void help_and_quit(const char *prog) {
|
||||||
|
fprintf(stderr, "\n"
|
||||||
|
"Usage: %s [-g|-s|-c] [OPTIONS] bios_file [output_file]\n"
|
||||||
|
"\n"
|
||||||
|
"GET MODE:\n"
|
||||||
|
"-g, --get (default)\tGet (read) from bios_file, "
|
||||||
|
"with following options:\n"
|
||||||
|
" --hwid \tReport hardware id (default).\n"
|
||||||
|
" --flags \tReport header flags.\n"
|
||||||
|
" -k, --rootkey=FILE \tFile name to export Root Key.\n"
|
||||||
|
" -b, --bmpfv=FILE \tFile name to export Bitmap FV.\n"
|
||||||
|
" -r --recoverykey=FILE\tFile name to export Recovery Key.\n"
|
||||||
|
"\n"
|
||||||
|
"SET MODE:\n"
|
||||||
|
"-s, --set \tSet (write) to bios_file, "
|
||||||
|
"with following options:\n"
|
||||||
|
" -o, --output=FILE \tNew file name for ouptput.\n"
|
||||||
|
" --hwid=HWID \tThe new hardware id to be changed.\n"
|
||||||
|
" --flags=FLAGS \tThe new (numeric) flags value.\n"
|
||||||
|
" -k, --rootkey=FILE \tFile name of new Root Key.\n"
|
||||||
|
" -b, --bmpfv=FILE \tFile name of new Bitmap FV.\n"
|
||||||
|
" -r --recoverykey=FILE\tFile name of new Recovery Key.\n"
|
||||||
|
"\n"
|
||||||
|
"CREATE MODE:\n"
|
||||||
|
"-c, --create=hwid_size,rootkey_size,bmpfv_size,recoverykey_size\n"
|
||||||
|
" \tCreate a GBB blob by given size list.\n"
|
||||||
|
"SAMPLE:\n"
|
||||||
|
" %s -g bios.bin\n"
|
||||||
|
" %s --set --hwid='New Model' -k key.bin bios.bin newbios.bin\n"
|
||||||
|
" %s -c 0x100,0x1000,0x03DE80,0x1000 gbb.blob\n\n",
|
||||||
|
prog, prog, prog, prog);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Command line options */
|
||||||
|
static struct option long_opts[] = {
|
||||||
|
/* name hasarg *flag val */
|
||||||
|
{"get", 0, NULL, 'g' },
|
||||||
|
{"set", 0, NULL, 's' },
|
||||||
|
{"create", 1, NULL, 'c' },
|
||||||
|
{"output", 1, NULL, 'o' },
|
||||||
|
{"rootkey", 1, NULL, 'k' },
|
||||||
|
{"bmpfv", 1, NULL, 'b' },
|
||||||
|
{"recoverykey", 1, NULL, 'R' },
|
||||||
|
{"hwid", 2, NULL, 'i' },
|
||||||
|
{"flags", 2, NULL, 'L' },
|
||||||
|
{ NULL, 0, NULL, 0 },
|
||||||
|
};
|
||||||
|
static char *short_opts = ":gsc:o:k:b:R:r:h:i:L:f:";
|
||||||
|
|
||||||
|
static int errorcnt;
|
||||||
|
|
||||||
|
static int ValidGBB(GoogleBinaryBlockHeader *gbb, size_t maxlen)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
if (gbb->major_version != GBB_MAJOR_VER)
|
||||||
|
goto bad;
|
||||||
|
if (gbb->header_size != GBB_HEADER_SIZE || gbb->header_size > maxlen)
|
||||||
|
goto bad;
|
||||||
|
if (gbb->hwid_offset < GBB_HEADER_SIZE)
|
||||||
|
goto bad;
|
||||||
|
if (gbb->hwid_offset + gbb->hwid_size > maxlen)
|
||||||
|
goto bad;
|
||||||
|
if (gbb->hwid_size) {
|
||||||
|
/* Make sure the HWID is null-terminated (assumes ASCII, not unicode). */
|
||||||
|
s = (char *)((char *)gbb + gbb->hwid_offset);
|
||||||
|
for (i = 0; i < gbb->hwid_size; i++)
|
||||||
|
if (*s++ == '\0')
|
||||||
|
break;
|
||||||
|
if (i >= gbb->hwid_size)
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
if (gbb->rootkey_offset < GBB_HEADER_SIZE)
|
||||||
|
goto bad;
|
||||||
|
if (gbb->rootkey_offset + gbb->rootkey_size > maxlen)
|
||||||
|
goto bad;
|
||||||
|
if (gbb->bmpfv_offset < GBB_HEADER_SIZE)
|
||||||
|
goto bad;
|
||||||
|
if (gbb->bmpfv_offset + gbb->bmpfv_size > maxlen)
|
||||||
|
goto bad;
|
||||||
|
if (gbb->recovery_key_offset < GBB_HEADER_SIZE)
|
||||||
|
goto bad;
|
||||||
|
if (gbb->recovery_key_offset + gbb->recovery_key_size > maxlen)
|
||||||
|
goto bad;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
errorcnt++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GBB_SEARCH_STRIDE 4
|
||||||
|
GoogleBinaryBlockHeader *FindGbbHeader(uint8_t *ptr, size_t size)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
GoogleBinaryBlockHeader *tmp, *gbb_header = NULL;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (i = 0;
|
||||||
|
i <= size - GBB_SEARCH_STRIDE;
|
||||||
|
i += GBB_SEARCH_STRIDE) {
|
||||||
|
if (0 != memcmp(ptr + i, GBB_SIGNATURE, GBB_SIGNATURE_SIZE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Found something. See if it's any good. */
|
||||||
|
tmp = (GoogleBinaryBlockHeader *)(ptr + i);
|
||||||
|
if (ValidGBB(tmp, size - i))
|
||||||
|
if (!count++)
|
||||||
|
gbb_header = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (count) {
|
||||||
|
case 0:
|
||||||
|
errorcnt++;
|
||||||
|
return NULL;
|
||||||
|
case 1:
|
||||||
|
return gbb_header;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "ERROR: multiple GBB headers found\n");
|
||||||
|
errorcnt++;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t *create_gbb(const char *desc, off_t *sizeptr)
|
||||||
|
{
|
||||||
|
char *str, *sizes, *param, *e = NULL;
|
||||||
|
size_t size = GBB_HEADER_SIZE;
|
||||||
|
int i = 0;
|
||||||
|
/* Danger Will Robinson! four entries ==> four paramater blocks */
|
||||||
|
uint32_t val[] = {0, 0, 0, 0};
|
||||||
|
uint8_t *buf;
|
||||||
|
GoogleBinaryBlockHeader *gbb;
|
||||||
|
|
||||||
|
sizes = strdup(desc);
|
||||||
|
if (!sizes) {
|
||||||
|
errorcnt++;
|
||||||
|
fprintf(stderr, "ERROR: strdup() failed: %s\n", strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (str = sizes; (param = strtok(str, ", ")) != NULL; str = NULL) {
|
||||||
|
val[i] = (uint32_t)strtoul(param, &e, 0);
|
||||||
|
if (e && *e) {
|
||||||
|
errorcnt++;
|
||||||
|
fprintf(stderr, "ERROR: invalid creation parameter: \"%s\"\n", param);
|
||||||
|
free(sizes);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
size += val[i++];
|
||||||
|
if (i > ARRAY_SIZE(val))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = (uint8_t *)calloc(1, size);
|
||||||
|
if (!buf) {
|
||||||
|
errorcnt++;
|
||||||
|
fprintf(stderr, "ERROR: can't malloc %zu bytes: %s\n",
|
||||||
|
size, strerror(errno));
|
||||||
|
free(sizes);
|
||||||
|
return NULL;
|
||||||
|
} else if (sizeptr) {
|
||||||
|
*sizeptr = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
gbb = (GoogleBinaryBlockHeader *)buf;
|
||||||
|
memcpy(gbb->signature, GBB_SIGNATURE, GBB_SIGNATURE_SIZE);
|
||||||
|
gbb->major_version = GBB_MAJOR_VER;
|
||||||
|
gbb->minor_version = GBB_MINOR_VER;
|
||||||
|
gbb->header_size = GBB_HEADER_SIZE;
|
||||||
|
gbb->flags = 0;
|
||||||
|
|
||||||
|
i = GBB_HEADER_SIZE;
|
||||||
|
gbb->hwid_offset = i;
|
||||||
|
gbb->hwid_size = val[0];
|
||||||
|
i += val[0];
|
||||||
|
|
||||||
|
gbb->rootkey_offset = i;
|
||||||
|
gbb->rootkey_size = val[1];
|
||||||
|
i += val[1];
|
||||||
|
|
||||||
|
gbb->bmpfv_offset = i;
|
||||||
|
gbb->bmpfv_size = val[2];
|
||||||
|
i += val[2];
|
||||||
|
|
||||||
|
gbb->recovery_key_offset = i;
|
||||||
|
gbb->recovery_key_size = val[3];
|
||||||
|
i += val[1];
|
||||||
|
|
||||||
|
free(sizes);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *read_entire_file(const char *filename, off_t *sizeptr)
|
||||||
|
{
|
||||||
|
FILE *fp = NULL;
|
||||||
|
uint8_t *buf = NULL;
|
||||||
|
struct stat sb;
|
||||||
|
|
||||||
|
fp = fopen(filename, "rb");
|
||||||
|
if (!fp) {
|
||||||
|
fprintf(stderr, "ERROR: Unable to open %s for reading: %s\n",
|
||||||
|
filename, strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != fstat(fileno(fp), &sb)) {
|
||||||
|
fprintf(stderr, "ERROR: can't fstat %s: %s\n",
|
||||||
|
filename, strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (sizeptr)
|
||||||
|
*sizeptr = sb.st_size;
|
||||||
|
|
||||||
|
buf = (uint8_t *)malloc(sb.st_size);
|
||||||
|
if (!buf) {
|
||||||
|
fprintf(stderr, "ERROR: can't malloc %" PRIi64 " bytes: %s\n",
|
||||||
|
sb.st_size, strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1 != fread(buf, sb.st_size, 1, fp)) {
|
||||||
|
fprintf(stderr, "ERROR: Unable to read from %s: %s\n",
|
||||||
|
filename, strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fp && 0 != fclose(fp)) {
|
||||||
|
fprintf(stderr, "ERROR: Unable to close %s: %s\n",
|
||||||
|
filename, strerror(errno));
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
errorcnt++;
|
||||||
|
|
||||||
|
if (buf)
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
if (fp && 0 != fclose(fp))
|
||||||
|
fprintf(stderr, "ERROR: Unable to close %s: %s\n",
|
||||||
|
filename, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_to_file(const char *msg, const char *filename,
|
||||||
|
uint8_t *start, size_t size)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
fp = fopen(filename, "wb");
|
||||||
|
if (!fp) {
|
||||||
|
fprintf(stderr, "ERROR: Unable to open %s for writing: %s\n",
|
||||||
|
filename, strerror(errno));
|
||||||
|
errorcnt++;
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't write zero bytes */
|
||||||
|
if (size && 1 != fwrite(start, size, 1, fp)) {
|
||||||
|
fprintf(stderr, "ERROR: Unable to write to %s: %s\n",
|
||||||
|
filename, strerror(errno));
|
||||||
|
errorcnt++;
|
||||||
|
r = errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != fclose(fp)) {
|
||||||
|
fprintf(stderr, "ERROR: Unable to close %s: %s\n",
|
||||||
|
filename, strerror(errno));
|
||||||
|
errorcnt++;
|
||||||
|
if (!r)
|
||||||
|
r = errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!r && msg)
|
||||||
|
printf("%s %s\n", msg, filename);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int read_from_file(const char *msg, const char *filename,
|
||||||
|
uint8_t *start, uint32_t size)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
struct stat sb;
|
||||||
|
size_t count;
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
fp = fopen(filename, "rb");
|
||||||
|
if (!fp) {
|
||||||
|
fprintf(stderr, "ERROR: Unable to open %s for reading: %s\n",
|
||||||
|
filename, strerror(errno));
|
||||||
|
errorcnt++;
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != fstat(fileno(fp), &sb)) {
|
||||||
|
fprintf(stderr, "ERROR: can't fstat %s: %s\n",
|
||||||
|
filename, strerror(errno));
|
||||||
|
errorcnt++;
|
||||||
|
r = errno;
|
||||||
|
goto done_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sb.st_size > size) {
|
||||||
|
fprintf(stderr, "ERROR: file %s exceeds capacity (%" PRIu32 ")\n",
|
||||||
|
filename, size);
|
||||||
|
errorcnt++;
|
||||||
|
r = errno;
|
||||||
|
goto done_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* It's okay if we read less than size. That's just the max. */
|
||||||
|
count = fread(start, 1, size, fp);
|
||||||
|
if (ferror(fp)) {
|
||||||
|
fprintf(stderr, "ERROR: Read %zu/%" PRIi64 " bytes from %s: %s\n",
|
||||||
|
count, sb.st_size, filename, strerror(errno));
|
||||||
|
errorcnt++;
|
||||||
|
r = errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
done_close:
|
||||||
|
if (0 != fclose(fp)) {
|
||||||
|
fprintf(stderr, "ERROR: Unable to close %s: %s\n",
|
||||||
|
filename, strerror(errno));
|
||||||
|
errorcnt++;
|
||||||
|
if (!r)
|
||||||
|
r = errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!r && msg)
|
||||||
|
printf(" - import %s from %s: success\n", msg, filename);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int do_gbb_utility(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
enum do_what_now {DO_GET, DO_SET, DO_CREATE} mode = DO_GET;
|
||||||
|
char *infile = NULL;
|
||||||
|
char *outfile = NULL;
|
||||||
|
char *opt_create = NULL;
|
||||||
|
char *opt_rootkey = NULL;
|
||||||
|
char *opt_bmpfv = NULL;
|
||||||
|
char *opt_recoverykey = NULL;
|
||||||
|
char *opt_hwid = NULL;
|
||||||
|
char *opt_flags = NULL;
|
||||||
|
int sel_hwid = 0;
|
||||||
|
int sel_flags = 0;
|
||||||
|
uint8_t *inbuf = NULL;
|
||||||
|
off_t filesize;
|
||||||
|
uint8_t *outbuf = NULL;
|
||||||
|
GoogleBinaryBlockHeader *gbb;
|
||||||
|
uint8_t *gbb_base;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
opterr = 0; /* quiet, you */
|
||||||
|
while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) {
|
||||||
|
switch (i) {
|
||||||
|
case 'g':
|
||||||
|
mode = DO_GET;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
mode = DO_SET;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
mode = DO_CREATE;
|
||||||
|
opt_create = optarg;
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
outfile = optarg;
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
opt_rootkey = optarg;
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
opt_bmpfv = optarg;
|
||||||
|
break;
|
||||||
|
case 'R': case 'r':
|
||||||
|
opt_recoverykey = optarg;
|
||||||
|
break;
|
||||||
|
case 'i': case 'h':
|
||||||
|
/* --hwid is optional: might be null, which could be okay */
|
||||||
|
opt_hwid = optarg;
|
||||||
|
sel_hwid = 1;
|
||||||
|
break;
|
||||||
|
case 'L': case 'f':
|
||||||
|
/* --flags is optional: might be null, which could be okay */
|
||||||
|
opt_flags = optarg;
|
||||||
|
sel_flags = 1;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
errorcnt++;
|
||||||
|
if (optopt)
|
||||||
|
fprintf(stderr, "ERROR: unrecognized option: -%c\n", optopt);
|
||||||
|
else if (argv[optind - 1] )
|
||||||
|
fprintf(stderr, "ERROR: unrecognized option (possibly \"%s\")\n",
|
||||||
|
argv[optind - 1]);
|
||||||
|
else
|
||||||
|
fprintf(stderr, "ERROR: unrecognized option\n");
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
errorcnt++;
|
||||||
|
if (argv[optind - 1])
|
||||||
|
fprintf(stderr, "ERROR: missing argument to -%c (%s)\n",
|
||||||
|
optopt, argv[optind - 1]);
|
||||||
|
else
|
||||||
|
fprintf(stderr, "ERROR: missing argument to -%c\n", optopt);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errorcnt++;
|
||||||
|
fprintf(stderr, "ERROR: unexpected error while parsing options\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Problems? */
|
||||||
|
if (errorcnt)
|
||||||
|
help_and_quit(argv[0]);
|
||||||
|
|
||||||
|
/* Now try to do something */
|
||||||
|
switch (mode) {
|
||||||
|
case DO_GET:
|
||||||
|
if (argc - optind < 1) {
|
||||||
|
fprintf(stderr, "\nERROR: missing input filename\n");
|
||||||
|
help_and_quit(argv[0]);
|
||||||
|
} else {
|
||||||
|
infile = argv[optind++];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* With no args, show the HWID */
|
||||||
|
if (!opt_rootkey && !opt_bmpfv && !opt_recoverykey && !sel_flags)
|
||||||
|
sel_hwid = 1;
|
||||||
|
|
||||||
|
inbuf = read_entire_file(infile, &filesize);
|
||||||
|
if (!inbuf)
|
||||||
|
break;
|
||||||
|
|
||||||
|
gbb = FindGbbHeader(inbuf, filesize);
|
||||||
|
if (!gbb) {
|
||||||
|
fprintf(stderr, "ERROR: No GBB found in %s\n", infile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gbb_base = (uint8_t *)gbb;
|
||||||
|
|
||||||
|
/* Get the stuff */
|
||||||
|
if (sel_hwid)
|
||||||
|
printf("hardware_id: %s\n",
|
||||||
|
gbb->hwid_size ? (char *)(gbb_base + gbb->hwid_offset) : "");
|
||||||
|
if (sel_flags)
|
||||||
|
printf("flags: 0x%08x\n", gbb->flags);
|
||||||
|
if (opt_rootkey)
|
||||||
|
write_to_file(" - exported root_key to file:", opt_rootkey,
|
||||||
|
gbb_base + gbb->rootkey_offset,
|
||||||
|
gbb->rootkey_size);
|
||||||
|
if (opt_bmpfv)
|
||||||
|
write_to_file(" - exported bmp_fv to file:", opt_bmpfv,
|
||||||
|
gbb_base + gbb->bmpfv_offset,
|
||||||
|
gbb->bmpfv_size);
|
||||||
|
if (opt_recoverykey)
|
||||||
|
write_to_file(" - exported recovery_key to file:", opt_recoverykey,
|
||||||
|
gbb_base + gbb->recovery_key_offset,
|
||||||
|
gbb->recovery_key_size);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DO_SET:
|
||||||
|
if (argc - optind < 1) {
|
||||||
|
fprintf(stderr, "\nERROR: missing input filename\n");
|
||||||
|
help_and_quit(argv[0]);
|
||||||
|
}
|
||||||
|
infile = argv[optind++];
|
||||||
|
if (!outfile)
|
||||||
|
outfile = (argc - optind < 1) ? infile : argv[optind++];
|
||||||
|
|
||||||
|
if (sel_hwid && !opt_hwid) {
|
||||||
|
fprintf(stderr, "\nERROR: missing new HWID value\n");
|
||||||
|
help_and_quit(argv[0]);
|
||||||
|
}
|
||||||
|
if (sel_flags && (!opt_flags || !*opt_flags)) {
|
||||||
|
fprintf(stderr, "\nERROR: missing new flags value\n");
|
||||||
|
help_and_quit(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* With no args, we'll either copy it unchanged or do nothing */
|
||||||
|
inbuf = read_entire_file(infile, &filesize);
|
||||||
|
if (!inbuf)
|
||||||
|
break;
|
||||||
|
|
||||||
|
gbb = FindGbbHeader(inbuf, filesize);
|
||||||
|
if (!gbb) {
|
||||||
|
fprintf(stderr, "ERROR: No GBB found in %s\n", infile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gbb_base = (uint8_t *)gbb;
|
||||||
|
|
||||||
|
outbuf = (uint8_t *)malloc(filesize);
|
||||||
|
if (!outbuf) {
|
||||||
|
errorcnt++;
|
||||||
|
fprintf(stderr, "ERROR: can't malloc %" PRIi64 " bytes: %s\n",
|
||||||
|
filesize, strerror(errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Switch pointers to outbuf */
|
||||||
|
memcpy(outbuf, inbuf, filesize);
|
||||||
|
gbb = FindGbbHeader(outbuf, filesize);
|
||||||
|
if (!gbb) {
|
||||||
|
fprintf(stderr, "INTERNAL ERROR: No GBB found in outbuf\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
gbb_base = (uint8_t *)gbb;
|
||||||
|
|
||||||
|
if (opt_hwid) {
|
||||||
|
if (strlen(opt_hwid) + 1 > gbb->hwid_size) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"ERROR: null-terminated HWID exceeds capacity (%d)\n",
|
||||||
|
gbb->hwid_size);
|
||||||
|
errorcnt++;
|
||||||
|
} else {
|
||||||
|
strcpy((char *)(gbb_base + gbb->hwid_offset), opt_hwid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt_flags) {
|
||||||
|
char *e = NULL;
|
||||||
|
uint32_t val;
|
||||||
|
val = (uint32_t)strtoul(opt_flags, &e, 0);
|
||||||
|
if (e && *e) {
|
||||||
|
fprintf(stderr, "ERROR: invalid flags value: %s\n", opt_flags);
|
||||||
|
errorcnt++;
|
||||||
|
} else {
|
||||||
|
gbb->flags = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt_rootkey)
|
||||||
|
read_from_file("root_key", opt_rootkey,
|
||||||
|
gbb_base + gbb->rootkey_offset,
|
||||||
|
gbb->rootkey_size);
|
||||||
|
if (opt_bmpfv)
|
||||||
|
read_from_file("bmp_fv", opt_bmpfv,
|
||||||
|
gbb_base + gbb->bmpfv_offset,
|
||||||
|
gbb->bmpfv_size);
|
||||||
|
if (opt_recoverykey)
|
||||||
|
read_from_file("recovery_key", opt_recoverykey,
|
||||||
|
gbb_base + gbb->recovery_key_offset,
|
||||||
|
gbb->recovery_key_size);
|
||||||
|
|
||||||
|
/* Write it out if there are no problems. */
|
||||||
|
if (!errorcnt)
|
||||||
|
write_to_file("successfully saved new image to:",
|
||||||
|
outfile, outbuf, filesize);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DO_CREATE:
|
||||||
|
if (!outfile) {
|
||||||
|
if (argc - optind < 1) {
|
||||||
|
fprintf(stderr, "\nERROR: missing output filename\n");
|
||||||
|
help_and_quit(argv[0]);
|
||||||
|
}
|
||||||
|
outfile = argv[optind++];
|
||||||
|
}
|
||||||
|
/* Parse the creation args */
|
||||||
|
outbuf = create_gbb(opt_create, &filesize);
|
||||||
|
if (!outbuf) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\nERROR: unable to parse creation spec (%s)\n", opt_create);
|
||||||
|
help_and_quit(argv[0]);
|
||||||
|
}
|
||||||
|
if (!errorcnt)
|
||||||
|
write_to_file("successfully created new GBB to:",
|
||||||
|
outfile, outbuf, filesize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (inbuf)
|
||||||
|
free(inbuf);
|
||||||
|
if (outbuf)
|
||||||
|
free(outbuf);
|
||||||
|
return !!errorcnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_FUTIL_COMMAND(gbb_utility, do_gbb_utility,
|
||||||
|
"Utility to manage Google Binary Block (GBB)");
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2013 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "futility.h"
|
|
||||||
|
|
||||||
static int do_something(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
printf("this is %s\n", __func__);
|
|
||||||
for (i = 0; i < argc; i++)
|
|
||||||
printf("argv[%d] = %s\n", i, argv[i]);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DECLARE_FUTIL_COMMAND(hey, do_something, "shout");
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
/* Copyright 2011 The Chromium OS Authors. All rights reserved.
|
||||||
* Use of this source code is governed by a BSD-style license that can be
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*
|
*
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "cryptolib.h"
|
#include "cryptolib.h"
|
||||||
|
#include "futility.h"
|
||||||
#include "host_common.h"
|
#include "host_common.h"
|
||||||
#include "kernel_blob.h"
|
#include "kernel_blob.h"
|
||||||
#include "util_misc.h"
|
#include "util_misc.h"
|
||||||
@@ -290,7 +291,7 @@ static int Verify(const char* infile, const char* signpubkey,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int do_vbutil_firmware(int argc, char* argv[]) {
|
||||||
|
|
||||||
char* filename = NULL;
|
char* filename = NULL;
|
||||||
char* key_block_file = NULL;
|
char* key_block_file = NULL;
|
||||||
@@ -371,3 +372,6 @@ int main(int argc, char* argv[]) {
|
|||||||
return PrintHelp();
|
return PrintHelp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECLARE_FUTIL_COMMAND(vbutil_firmware, do_vbutil_firmware,
|
||||||
|
"Verified boot firmware utility");
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
|
/* Copyright 2012 The Chromium OS Authors. All rights reserved.
|
||||||
* Use of this source code is governed by a BSD-style license that can be
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*
|
*
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "cryptolib.h"
|
#include "cryptolib.h"
|
||||||
|
#include "futility.h"
|
||||||
#include "host_common.h"
|
#include "host_common.h"
|
||||||
#include "kernel_blob.h"
|
#include "kernel_blob.h"
|
||||||
#include "util_misc.h"
|
#include "util_misc.h"
|
||||||
@@ -211,21 +212,21 @@ static unsigned int find_cmdline_start(char *input, unsigned int max_len) {
|
|||||||
/* Here are globals containing all the bits & pieces I'm working on. */
|
/* Here are globals containing all the bits & pieces I'm working on. */
|
||||||
|
|
||||||
/* The individual parts that go into the kernel blob */
|
/* The individual parts that go into the kernel blob */
|
||||||
uint8_t *g_kernel_data;
|
static uint8_t *g_kernel_data;
|
||||||
uint64_t g_kernel_size;
|
static uint64_t g_kernel_size;
|
||||||
uint8_t *g_param_data;
|
static uint8_t *g_param_data;
|
||||||
uint64_t g_param_size;
|
static uint64_t g_param_size;
|
||||||
uint8_t *g_config_data;
|
static uint8_t *g_config_data;
|
||||||
uint64_t g_config_size;
|
static uint64_t g_config_size;
|
||||||
uint8_t *g_bootloader_data;
|
static uint8_t *g_bootloader_data;
|
||||||
uint64_t g_bootloader_size;
|
static uint64_t g_bootloader_size;
|
||||||
uint64_t g_bootloader_address;
|
static uint64_t g_bootloader_address;
|
||||||
|
|
||||||
|
|
||||||
/* The individual parts of the verification blob (including the data that
|
/* The individual parts of the verification blob (including the data that
|
||||||
* immediately follows the headers) */
|
* immediately follows the headers) */
|
||||||
VbKeyBlockHeader* g_keyblock;
|
static VbKeyBlockHeader* g_keyblock;
|
||||||
VbKernelPreambleHeader* g_preamble;
|
static VbKernelPreambleHeader* g_preamble;
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
@@ -695,7 +696,7 @@ static int Verify(uint8_t* kernel_blob,
|
|||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int do_vbutil_kernel(int argc, char* argv[]) {
|
||||||
char* filename = NULL;
|
char* filename = NULL;
|
||||||
char* oldfile = NULL;
|
char* oldfile = NULL;
|
||||||
char* keyblock_file = NULL;
|
char* keyblock_file = NULL;
|
||||||
@@ -966,3 +967,6 @@ int main(int argc, char* argv[]) {
|
|||||||
fprintf(stderr, "You must specify a mode: --pack, --repack or --verify\n");
|
fprintf(stderr, "You must specify a mode: --pack, --repack or --verify\n");
|
||||||
return PrintHelp(progname);
|
return PrintHelp(progname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECLARE_FUTIL_COMMAND(vbutil_kernel, do_vbutil_kernel,
|
||||||
|
"Verified boot kernel utility");
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
|
/* Copyright 2012 The Chromium OS Authors. All rights reserved.
|
||||||
* Use of this source code is governed by a BSD-style license that can be
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*
|
*
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
|
* Copyright 2013 The Chromium OS Authors. All rights reserved.
|
||||||
* Use of this source code is governed by a BSD-style license that can be
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
@@ -18,13 +18,6 @@
|
|||||||
|
|
||||||
#define MYNAME "futility"
|
#define MYNAME "futility"
|
||||||
#define MYNAME_S MYNAME "_s"
|
#define MYNAME_S MYNAME "_s"
|
||||||
#ifdef OLDDIR
|
|
||||||
#define XSTR(A) STR(A)
|
|
||||||
#define STR(A) #A
|
|
||||||
#define SUBDIR XSTR(OLDDIR)
|
|
||||||
#else
|
|
||||||
#define SUBDIR "old_bins"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* File to use for logging, if present */
|
/* File to use for logging, if present */
|
||||||
#define LOGFILE "/tmp/futility.log"
|
#define LOGFILE "/tmp/futility.log"
|
||||||
@@ -39,21 +32,15 @@ static const char * const usage= "\n\
|
|||||||
Usage: " MYNAME " PROGRAM|COMMAND [args...]\n\
|
Usage: " MYNAME " PROGRAM|COMMAND [args...]\n\
|
||||||
\n\
|
\n\
|
||||||
This is the unified firmware utility, which will eventually replace\n\
|
This is the unified firmware utility, which will eventually replace\n\
|
||||||
all the distinct userspace tools formerly produced by the\n\
|
most of the distinct verified boot tools formerly produced by the\n\
|
||||||
vboot_reference package.\n\
|
vboot_reference package.\n\
|
||||||
\n\
|
\n\
|
||||||
When symlinked under the name of one of those previous tools, it can\n\
|
When symlinked under the name of one of those previous tools, should\n\
|
||||||
do one of two things: either it will fully implement the original\n\
|
fully implement the original behavior. It can also be invoked directly\n\
|
||||||
behavior, or (until that functionality is complete) it will just exec\n\
|
as " MYNAME ", followed by the original name as the first argument.\n\
|
||||||
the original binary.\n\
|
|
||||||
\n\
|
\n\
|
||||||
In either case it can append some usage information to " LOGFILE "\n\
|
In either case it will append some usage information to " LOGFILE "\n\
|
||||||
to help improve coverage and correctness.\n\
|
(iff that file exists), to help improve coverage and correctness.\n\
|
||||||
\n\
|
|
||||||
If you invoke it directly instead of via a symlink, it requires one\n\
|
|
||||||
argument, which is the name of the old binary to exec. That binary\n\
|
|
||||||
must be located in a directory named \"" SUBDIR "\" underneath\n\
|
|
||||||
the " MYNAME " executable.\n\
|
|
||||||
\n";
|
\n";
|
||||||
|
|
||||||
static int do_help(int argc, char *argv[])
|
static int do_help(int argc, char *argv[])
|
||||||
@@ -63,7 +50,7 @@ static int do_help(int argc, char *argv[])
|
|||||||
|
|
||||||
fputs(usage, stdout);
|
fputs(usage, stdout);
|
||||||
|
|
||||||
printf("The following commands are built-in:\n");
|
printf("The following commands are built-in:\n\n");
|
||||||
|
|
||||||
for (cmd = futil_cmds; *cmd; cmd++)
|
for (cmd = futil_cmds; *cmd; cmd++)
|
||||||
printf(" %-20s %s\n", (*cmd)->name, (*cmd)->shorthelp);
|
printf(" %-20s %s\n", (*cmd)->name, (*cmd)->shorthelp);
|
||||||
@@ -77,16 +64,19 @@ static int do_help(int argc, char *argv[])
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
DECLARE_FUTIL_COMMAND(help, do_help, "show a bit of help");
|
DECLARE_FUTIL_COMMAND(help, do_help,
|
||||||
|
"Show a bit of help (you're looking at it)");
|
||||||
|
|
||||||
/* Deprecated functions can't be invoked through symlinks. */
|
/*
|
||||||
|
* These are built-in functions that we'd like to abandon completely someday.
|
||||||
|
* TODO: If no one complains, get rid of them.
|
||||||
|
*/
|
||||||
static char *dep_cmds[] = {
|
static char *dep_cmds[] = {
|
||||||
"eficompress",
|
"dev_sign_file",
|
||||||
"efidecompress",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const dep_usage= "\n\
|
static const char * const dep_usage= "\n\
|
||||||
The program \"%s\" is deprecated.\n\
|
The program \"%s\" is deprecated and may go away soon.\n\
|
||||||
\n\
|
\n\
|
||||||
If you feel this is in error, please open a bug at\n\
|
If you feel this is in error, please open a bug at\n\
|
||||||
\n\
|
\n\
|
||||||
@@ -223,25 +213,21 @@ static void log_args(int argc, char *argv[])
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/* Here we go */
|
/* Here we go */
|
||||||
|
|
||||||
#ifdef COVERAGE
|
|
||||||
void __gcov_flush(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int main(int argc, char *argv[], char *envp[])
|
int main(int argc, char *argv[], char *envp[])
|
||||||
{
|
{
|
||||||
char *progname;
|
char *fullname, *progname;
|
||||||
char truename[PATH_MAX];
|
char truename[PATH_MAX];
|
||||||
char oldname[PATH_MAX];
|
|
||||||
char buf[80];
|
char buf[80];
|
||||||
pid_t myproc;
|
pid_t myproc;
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
char *s;
|
|
||||||
struct futil_cmd_t **cmd;
|
struct futil_cmd_t **cmd;
|
||||||
int i;
|
int i;
|
||||||
|
int via_symlink = 0;
|
||||||
|
|
||||||
log_args(argc, argv);
|
log_args(argc, argv);
|
||||||
|
|
||||||
/* How were we invoked? */
|
/* How were we invoked? */
|
||||||
|
fullname = strdup(argv[0]);
|
||||||
progname = strrchr(argv[0], '/');
|
progname = strrchr(argv[0], '/');
|
||||||
if (progname)
|
if (progname)
|
||||||
progname++;
|
progname++;
|
||||||
@@ -259,18 +245,18 @@ int main(int argc, char *argv[], char *envp[])
|
|||||||
argc--;
|
argc--;
|
||||||
argv++;
|
argv++;
|
||||||
|
|
||||||
/* So now what name do we want to invoke? */
|
/* So now what function do we want to invoke? */
|
||||||
progname = strrchr(argv[0], '/');
|
progname = strrchr(argv[0], '/');
|
||||||
if (progname)
|
if (progname)
|
||||||
progname++;
|
progname++;
|
||||||
else
|
else
|
||||||
progname = argv[0];
|
progname = argv[0];
|
||||||
} else { /* Invoked by symlink */
|
} else { /* Invoked by symlink */
|
||||||
|
via_symlink = 1;
|
||||||
/* Block any deprecated functions. */
|
/* Block any deprecated functions. */
|
||||||
for (i = 0; i < ARRAY_SIZE(dep_cmds); i++)
|
for (i = 0; i < ARRAY_SIZE(dep_cmds); i++)
|
||||||
if (0 == strcmp(dep_cmds[i], progname))
|
if (0 == strcmp(dep_cmds[i], progname))
|
||||||
deprecated(progname);
|
deprecated(progname);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See if it's asking for something we know how to do ourselves */
|
/* See if it's asking for something we know how to do ourselves */
|
||||||
@@ -278,9 +264,14 @@ int main(int argc, char *argv[], char *envp[])
|
|||||||
if (0 == strcmp((*cmd)->name, progname))
|
if (0 == strcmp((*cmd)->name, progname))
|
||||||
return (*cmd)->handler(argc, argv);
|
return (*cmd)->handler(argc, argv);
|
||||||
|
|
||||||
/* Nope, it must be wrapped */
|
/* Nope */
|
||||||
|
if (!via_symlink) {
|
||||||
|
do_help(0, 0);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Complain about bogus symlink */
|
||||||
|
|
||||||
/* The old binaries live under the true executable. Find out where that is. */
|
|
||||||
myproc = getpid();
|
myproc = getpid();
|
||||||
snprintf(buf, sizeof(buf), "/proc/%d/exe", myproc);
|
snprintf(buf, sizeof(buf), "/proc/%d/exe", myproc);
|
||||||
r = readlink(buf, truename, PATH_MAX - 1);
|
r = readlink(buf, truename, PATH_MAX - 1);
|
||||||
@@ -288,37 +279,18 @@ int main(int argc, char *argv[], char *envp[])
|
|||||||
fprintf(stderr, "%s is lost: %s => %s: %s\n", MYNAME, argv[0],
|
fprintf(stderr, "%s is lost: %s => %s: %s\n", MYNAME, argv[0],
|
||||||
buf, strerror(errno));
|
buf, strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
} else if (r == PATH_MAX - 1) {
|
|
||||||
/* Yes, it might _just_ fit, but we'll count that as wrong anyway. We can't
|
|
||||||
* determine the right size using the example in the readlink manpage,
|
|
||||||
* because the /proc symlink returns an st_size of 0. */
|
|
||||||
fprintf(stderr, "%s is too long: %s => %s\n", MYNAME, argv[0], buf);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
truename[r] = '\0';
|
truename[r] = '\0';
|
||||||
s = strrchr(truename, '/'); /* Find the true directory */
|
|
||||||
if (s) {
|
|
||||||
*s = '\0';
|
|
||||||
} else { /* I don't think this can happen */
|
|
||||||
fprintf(stderr, "%s says %s doesn't make sense\n", MYNAME, truename);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
/* If the old binary path doesn't fit, just give up. */
|
|
||||||
r = snprintf(oldname, PATH_MAX, "%s/%s/%s", truename, SUBDIR, progname);
|
|
||||||
if (r >= PATH_MAX) {
|
|
||||||
fprintf(stderr, "%s/%s/%s is too long\n", truename, SUBDIR, progname);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fflush(0);
|
fprintf(stderr, "\n\
|
||||||
#ifdef COVERAGE
|
The program\n\n %s\n\nis a symlink to\n\n %s\n\
|
||||||
/* Write gcov data prior to exec. */
|
\n\
|
||||||
__gcov_flush();
|
However, " MYNAME " doesn't know how to implement that function.\n\
|
||||||
#endif
|
\n\
|
||||||
execve(oldname, argv, envp);
|
This is probably an error in your installation. If the problem persists\n\
|
||||||
|
after a fresh checkout/build/install, please open a bug at\n\
|
||||||
fprintf(stderr, "%s failed to exec %s: %s\n", MYNAME,
|
\n\
|
||||||
oldname, strerror(errno));
|
http://dev.chromium.org/for-testers/bug-reporting-guidelines\n\
|
||||||
|
\n", fullname, truename);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
|
// Copyright 2010 The Chromium OS Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
//
|
//
|
||||||
39
tests/futility/binary_editor.c
Normal file
39
tests/futility/binary_editor.c
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014 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.
|
||||||
|
*
|
||||||
|
* This is a very simple binary editor, used to create corrupted structs for
|
||||||
|
* testing. It copies stdin to stdout, replacing bytes beginning at the given
|
||||||
|
* offset with the specified 8-bit values.
|
||||||
|
*
|
||||||
|
* There is NO conversion checking of the arguments.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
uint32_t offset, curpos, curarg;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
if (argc < 3) {
|
||||||
|
fprintf(stderr, "Need two or more args: OFFSET VAL [VAL...]\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = (uint32_t)strtoul(argv[1], 0, 0);
|
||||||
|
curarg = 2;
|
||||||
|
for ( curpos = 0; (c = fgetc(stdin)) != EOF; curpos++) {
|
||||||
|
|
||||||
|
if (curpos == offset && curarg < argc) {
|
||||||
|
c = (uint8_t)strtoul(argv[curarg++], 0, 0);
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
|
||||||
|
fputc(c, stdout);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/bin/bash -eu
|
#!/bin/bash -eu
|
||||||
# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
|
# Copyright 2013 The Chromium OS Authors. All rights reserved.
|
||||||
# Use of this source code is governed by a BSD-style license that can be
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
# found in the LICENSE file.
|
# found in the LICENSE file.
|
||||||
|
|
||||||
@@ -13,7 +13,6 @@ BINDIR="$1"
|
|||||||
shift
|
shift
|
||||||
|
|
||||||
FUTILITY="$BINDIR/futility"
|
FUTILITY="$BINDIR/futility"
|
||||||
OLDDIR="$BINDIR/old_bins"
|
|
||||||
|
|
||||||
|
|
||||||
# The Makefile should export the $BUILD directory, but if it's not just warn
|
# The Makefile should export the $BUILD directory, but if it's not just warn
|
||||||
@@ -28,7 +27,6 @@ OUTDIR="${BUILD}/tests/futility_test_results"
|
|||||||
|
|
||||||
# Let each test know where to find things...
|
# Let each test know where to find things...
|
||||||
export FUTILITY
|
export FUTILITY
|
||||||
export OLDDIR
|
|
||||||
export SCRIPTDIR
|
export SCRIPTDIR
|
||||||
export OUTDIR
|
export OUTDIR
|
||||||
|
|
||||||
@@ -36,6 +34,7 @@ export OUTDIR
|
|||||||
TESTS="
|
TESTS="
|
||||||
${SCRIPTDIR}/test_main.sh
|
${SCRIPTDIR}/test_main.sh
|
||||||
${SCRIPTDIR}/test_dump_fmap.sh
|
${SCRIPTDIR}/test_dump_fmap.sh
|
||||||
|
${SCRIPTDIR}/test_gbb_utility.sh
|
||||||
"
|
"
|
||||||
|
|
||||||
|
|
||||||
@@ -43,62 +42,6 @@ ${SCRIPTDIR}/test_dump_fmap.sh
|
|||||||
pass=0
|
pass=0
|
||||||
progs=0
|
progs=0
|
||||||
|
|
||||||
##############################################################################
|
|
||||||
# But first, we'll just test the wrapped functions. This will go away when
|
|
||||||
# everything is built in (chromium:196079).
|
|
||||||
|
|
||||||
# Here are the old programs to be wrapped
|
|
||||||
# TODO(crbug.com/224734): dev_debug_vboot isn't tested right now.
|
|
||||||
PROGS=${*:-cgpt crossystem dev_sign_file dumpRSAPublicKey
|
|
||||||
dump_kernel_config enable_dev_usb_boot gbb_utility
|
|
||||||
tpm_init_temp_fix tpmc vbutil_firmware vbutil_kernel
|
|
||||||
vbutil_what_keys}
|
|
||||||
|
|
||||||
# For now just compare results of invoking each program with no args.
|
|
||||||
# TODO: Create true rigorous tests for every program.
|
|
||||||
echo "-- old_bins --"
|
|
||||||
for i in $PROGS; do
|
|
||||||
: $(( progs++ ))
|
|
||||||
|
|
||||||
# Try the real thing first
|
|
||||||
echo -n "$i ... "
|
|
||||||
rc=$("${OLDDIR}/$i" \
|
|
||||||
1>"${OUTDIR}/$i.stdout.orig" 2>"${OUTDIR}/$i.stderr.orig" \
|
|
||||||
|| echo "$?")
|
|
||||||
echo "${rc:-0}" > "${OUTDIR}/$i.return.orig"
|
|
||||||
|
|
||||||
# Then try the symlink
|
|
||||||
rc=$("$BINDIR/$i" 1>"${OUTDIR}/$i.stdout.link" \
|
|
||||||
2>"${OUTDIR}/$i.stderr.link" || echo "$?")
|
|
||||||
echo "${rc:-0}" > "${OUTDIR}/$i.return.link"
|
|
||||||
|
|
||||||
# And finally try the explicit wrapper
|
|
||||||
rc=$("$FUTILITY" "$i" 1>"${OUTDIR}/$i.stdout.futil" \
|
|
||||||
2>"${OUTDIR}/$i.stderr.futil" || echo "$?")
|
|
||||||
echo "${rc:-0}" > "${OUTDIR}/$i.return.futil"
|
|
||||||
|
|
||||||
# Different?
|
|
||||||
if cmp -s "${OUTDIR}/$i.return.orig" "${OUTDIR}/$i.return.link" &&
|
|
||||||
cmp -s "${OUTDIR}/$i.stdout.orig" "${OUTDIR}/$i.stdout.link" &&
|
|
||||||
cmp -s "${OUTDIR}/$i.stderr.orig" "${OUTDIR}/$i.stderr.link" &&
|
|
||||||
cmp -s "${OUTDIR}/$i.return.orig" "${OUTDIR}/$i.return.futil" &&
|
|
||||||
cmp -s "${OUTDIR}/$i.stdout.orig" "${OUTDIR}/$i.stdout.futil" &&
|
|
||||||
cmp -s "${OUTDIR}/$i.stderr.orig" "${OUTDIR}/$i.stderr.futil" ; then
|
|
||||||
green "passed"
|
|
||||||
: $(( pass++ ))
|
|
||||||
rm -f ${OUTDIR}/$i.{stdout,stderr,return}.{orig,link,futil}
|
|
||||||
else
|
|
||||||
red "failed"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# How many wrapped executables are left to incorporate? Did we check them all?
|
|
||||||
xprogs=$(find ${OLDDIR} -type f -perm /111 | wc -l)
|
|
||||||
if [ $xprogs -gt 0 ]; then
|
|
||||||
yellow "${progs}/${xprogs} wrapped executables tested"
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# Invoke the scripts that test the builtin functions.
|
# Invoke the scripts that test the builtin functions.
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
#!/bin/bash -eux
|
#!/bin/bash -eux
|
||||||
# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
|
# Copyright 2013 The Chromium OS Authors. All rights reserved.
|
||||||
# Use of this source code is governed by a BSD-style license that can be
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
# found in the LICENSE file.
|
# found in the LICENSE file.
|
||||||
|
|
||||||
me=${0##*/}
|
me=${0##*/}
|
||||||
|
TMP="$me.tmp"
|
||||||
|
|
||||||
# Work in scratch directory
|
# Work in scratch directory
|
||||||
cd "$OUTDIR"
|
cd "$OUTDIR"
|
||||||
TMP="$me.tmp"
|
|
||||||
|
|
||||||
# Good FMAP
|
# Good FMAP
|
||||||
"$FUTILITY" dump_fmap -f "${SCRIPTDIR}/data_fmap.bin" > "$TMP"
|
"$FUTILITY" dump_fmap -f "${SCRIPTDIR}/data_fmap.bin" > "$TMP"
|
||||||
@@ -19,17 +19,18 @@ cmp "${SCRIPTDIR}/data_fmap_expect_p.txt" "$TMP"
|
|||||||
"$FUTILITY" dump_fmap -h "${SCRIPTDIR}/data_fmap.bin" > "$TMP"
|
"$FUTILITY" dump_fmap -h "${SCRIPTDIR}/data_fmap.bin" > "$TMP"
|
||||||
cmp "${SCRIPTDIR}/data_fmap_expect_h.txt" "$TMP"
|
cmp "${SCRIPTDIR}/data_fmap_expect_h.txt" "$TMP"
|
||||||
|
|
||||||
|
|
||||||
# This should fail because the input file is truncated and doesn't really
|
# This should fail because the input file is truncated and doesn't really
|
||||||
# contain the stuff that the FMAP claims it does.
|
# contain the stuff that the FMAP claims it does.
|
||||||
! "$FUTILITY" dump_fmap -x "${SCRIPTDIR}/data_fmap.bin" FMAP
|
if "$FUTILITY" dump_fmap -x "${SCRIPTDIR}/data_fmap.bin" FMAP; then false; fi
|
||||||
|
|
||||||
# However, this should work.
|
# However, this should work.
|
||||||
"$FUTILITY" dump_fmap -x "${SCRIPTDIR}/data_fmap.bin" SI_DESC > "$TMP"
|
"$FUTILITY" dump_fmap -x "${SCRIPTDIR}/data_fmap.bin" SI_DESC > "$TMP"
|
||||||
cmp "${SCRIPTDIR}/data_fmap_expect_x.txt" "$TMP"
|
cmp "${SCRIPTDIR}/data_fmap_expect_x.txt" "$TMP"
|
||||||
|
|
||||||
|
|
||||||
# This FMAP has problems, and will fail.
|
# This FMAP has problems, and should fail.
|
||||||
! "$FUTILITY" dump_fmap -h "${SCRIPTDIR}/data_fmap2.bin" > "$TMP"
|
if "$FUTILITY" dump_fmap -h "${SCRIPTDIR}/data_fmap2.bin" > "$TMP"; then false; fi
|
||||||
cmp "${SCRIPTDIR}/data_fmap2_expect_h.txt" "$TMP"
|
cmp "${SCRIPTDIR}/data_fmap2_expect_h.txt" "$TMP"
|
||||||
|
|
||||||
"$FUTILITY" dump_fmap -hh "${SCRIPTDIR}/data_fmap2.bin" > "$TMP"
|
"$FUTILITY" dump_fmap -hh "${SCRIPTDIR}/data_fmap2.bin" > "$TMP"
|
||||||
@@ -40,5 +41,5 @@ cmp "${SCRIPTDIR}/data_fmap2_expect_hhH.txt" "$TMP"
|
|||||||
|
|
||||||
|
|
||||||
# cleanup
|
# cleanup
|
||||||
rm -f "$TMP" FMAP SI_DESC
|
rm -f ${TMP}* FMAP SI_DESC
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
206
tests/futility/test_gbb_utility.sh
Executable file
206
tests/futility/test_gbb_utility.sh
Executable file
@@ -0,0 +1,206 @@
|
|||||||
|
#!/bin/bash -eux
|
||||||
|
# Copyright 2014 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.
|
||||||
|
|
||||||
|
me=${0##*/}
|
||||||
|
TMP="$me.tmp"
|
||||||
|
|
||||||
|
# Work in scratch directory
|
||||||
|
cd "$OUTDIR"
|
||||||
|
|
||||||
|
# Helper utility to modify binary blobs
|
||||||
|
REPLACE="${BUILD_RUN}/tests/futility/binary_editor"
|
||||||
|
|
||||||
|
# First, let's test the basic functionality
|
||||||
|
|
||||||
|
# For simplicity, we'll use the same size for all properties.
|
||||||
|
${FUTILITY} gbb_utility -c 16,0x10,16,0x10 ${TMP}.blob
|
||||||
|
|
||||||
|
# Flags
|
||||||
|
${FUTILITY} gbb_utility -s --flags=0xdeadbeef ${TMP}.blob
|
||||||
|
${FUTILITY} gbb_utility -g --flags ${TMP}.blob | grep -i 0xdeadbeef
|
||||||
|
|
||||||
|
# HWID length should include the terminating null - this is too long
|
||||||
|
if ${FUTILITY} gbb_utility -s -i "0123456789ABCDEF" ${TMP}.blob; then false; fi
|
||||||
|
# This works
|
||||||
|
${FUTILITY} gbb_utility -s -i "0123456789ABCDE" ${TMP}.blob
|
||||||
|
# Read it back?
|
||||||
|
${FUTILITY} gbb_utility -g ${TMP}.blob | grep "0123456789ABCDE"
|
||||||
|
|
||||||
|
# Same kind of tests for the other fields, but they need binary files.
|
||||||
|
|
||||||
|
# too long
|
||||||
|
dd if=/dev/urandom bs=17 count=1 of=${TMP}.data1.toolong
|
||||||
|
dd if=/dev/urandom bs=17 count=1 of=${TMP}.data2.toolong
|
||||||
|
dd if=/dev/urandom bs=17 count=1 of=${TMP}.data3.toolong
|
||||||
|
if ${FUTILITY} gbb_utility -s --rootkey ${TMP}.data1.toolong ${TMP}.blob; then false; fi
|
||||||
|
if ${FUTILITY} gbb_utility -s --recoverykey ${TMP}.data2.toolong ${TMP}.blob; then false; fi
|
||||||
|
if ${FUTILITY} gbb_utility -s --bmpfv ${TMP}.data3.toolong ${TMP}.blob; then false; fi
|
||||||
|
|
||||||
|
# shorter than max should be okay, though
|
||||||
|
dd if=/dev/urandom bs=10 count=1 of=${TMP}.data1.short
|
||||||
|
dd if=/dev/urandom bs=10 count=1 of=${TMP}.data2.short
|
||||||
|
dd if=/dev/urandom bs=10 count=1 of=${TMP}.data3.short
|
||||||
|
${FUTILITY} gbb_utility -s \
|
||||||
|
--rootkey ${TMP}.data1.short \
|
||||||
|
--recoverykey ${TMP}.data2.short \
|
||||||
|
--bmpfv ${TMP}.data3.short ${TMP}.blob
|
||||||
|
# read 'em back
|
||||||
|
${FUTILITY} gbb_utility -g \
|
||||||
|
--rootkey ${TMP}.read1 \
|
||||||
|
--recoverykey ${TMP}.read2 \
|
||||||
|
--bmpfv ${TMP}.read3 ${TMP}.blob
|
||||||
|
# Verify (but remember, it's short)
|
||||||
|
cmp -n 10 ${TMP}.data1.short ${TMP}.read1
|
||||||
|
cmp -n 10 ${TMP}.data2.short ${TMP}.read2
|
||||||
|
cmp -n 10 ${TMP}.data3.short ${TMP}.read3
|
||||||
|
|
||||||
|
# Okay
|
||||||
|
dd if=/dev/urandom bs=16 count=1 of=${TMP}.data1
|
||||||
|
dd if=/dev/urandom bs=16 count=1 of=${TMP}.data2
|
||||||
|
dd if=/dev/urandom bs=16 count=1 of=${TMP}.data3
|
||||||
|
${FUTILITY} gbb_utility -s --rootkey ${TMP}.data1 ${TMP}.blob
|
||||||
|
${FUTILITY} gbb_utility -s --recoverykey ${TMP}.data2 ${TMP}.blob
|
||||||
|
${FUTILITY} gbb_utility -s --bmpfv ${TMP}.data3 ${TMP}.blob
|
||||||
|
|
||||||
|
# Read 'em back.
|
||||||
|
${FUTILITY} gbb_utility -g --rootkey ${TMP}.read1 ${TMP}.blob
|
||||||
|
${FUTILITY} gbb_utility -g --recoverykey ${TMP}.read2 ${TMP}.blob
|
||||||
|
${FUTILITY} gbb_utility -g --bmpfv ${TMP}.read3 ${TMP}.blob
|
||||||
|
# Verify
|
||||||
|
cmp ${TMP}.data1 ${TMP}.read1
|
||||||
|
cmp ${TMP}.data2 ${TMP}.read2
|
||||||
|
cmp ${TMP}.data3 ${TMP}.read3
|
||||||
|
|
||||||
|
|
||||||
|
# Okay, creating GBB blobs seems to work. Now let's make sure that corrupted
|
||||||
|
# blobs are rejected.
|
||||||
|
|
||||||
|
# Danger Will Robinson! We assume that ${TMP}.blob has this binary struct:
|
||||||
|
#
|
||||||
|
# Field Offset Value
|
||||||
|
#
|
||||||
|
# signature: 0x0000 $GBB
|
||||||
|
# major_version: 0x0004 0x0001
|
||||||
|
# minor_version: 0x0006 0x0001
|
||||||
|
# header_size: 0x0008 0x00000080
|
||||||
|
# flags: 0x000c 0xdeadbeef
|
||||||
|
# hwid_offset: 0x0010 0x00000080
|
||||||
|
# hwid_size: 0x0014 0x00000010
|
||||||
|
# rootkey_offset: 0x0018 0x00000090
|
||||||
|
# rootkey_size: 0x001c 0x00000010
|
||||||
|
# bmpfv_offset: 0x0020 0x000000a0
|
||||||
|
# bmpfv_size: 0x0024 0x00000010
|
||||||
|
# recovery_key_offset: 0x0028 0x000000b0
|
||||||
|
# recovery_key_size: 0x002c 0x00000010
|
||||||
|
# pad: 0x0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
# 0x0040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
# 0x0050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
# 0x0060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
# 0x0070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
# (HWID) 0x0080 30 31 32 33 34 35 36 37 38 39 41 42 43 44 45 00
|
||||||
|
# (rootkey) 0x0090 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
|
||||||
|
# (bmpfv) 0x00a0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
|
||||||
|
# (recovery_key) 0x00b0 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
|
||||||
|
# 0x00c0 <EOF>
|
||||||
|
#
|
||||||
|
|
||||||
|
# bad major_version
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x4 2 > ${TMP}.blob.bad
|
||||||
|
if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
|
||||||
|
|
||||||
|
# header size too large
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x8 0x81 > ${TMP}.blob.bad
|
||||||
|
if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
|
||||||
|
|
||||||
|
# header size too small
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x8 0x7f > ${TMP}.blob.bad
|
||||||
|
if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
|
||||||
|
|
||||||
|
# HWID not null-terminated is invalid
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x8f 0x41 > ${TMP}.blob.bad
|
||||||
|
if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
|
||||||
|
|
||||||
|
# HWID of length zero is okay
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x14 0x00 > ${TMP}.blob.ok
|
||||||
|
${FUTILITY} gbb_utility ${TMP}.blob.ok
|
||||||
|
# And HWID of length 1 consisting only of '\0' is okay, too.
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x14 0x01 | ${REPLACE} 0x80 0x00 > ${TMP}.blob.ok
|
||||||
|
${FUTILITY} gbb_utility ${TMP}.blob.ok
|
||||||
|
|
||||||
|
# zero-length HWID not null-terminated is invalid
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x8f 0x41 > ${TMP}.blob.bad
|
||||||
|
if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
|
||||||
|
|
||||||
|
# hwid_offset < GBB_HEADER_SIZE is invalid
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x10 0x7f > ${TMP}.blob.bad
|
||||||
|
if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x10 0x00 > ${TMP}.blob.bad
|
||||||
|
if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
|
||||||
|
|
||||||
|
# rootkey_offset < GBB_HEADER_SIZE is invalid
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x18 0x7f > ${TMP}.blob.bad
|
||||||
|
if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x18 0x00 > ${TMP}.blob.bad
|
||||||
|
if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
|
||||||
|
|
||||||
|
# bmpfv_offset < GBB_HEADER_SIZE is invalid
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x20 0x7f > ${TMP}.blob.bad
|
||||||
|
if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x20 0x00 > ${TMP}.blob.bad
|
||||||
|
if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
|
||||||
|
|
||||||
|
# recovery_key_offset < GBB_HEADER_SIZE is invalid
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x28 0x7f > ${TMP}.blob.bad
|
||||||
|
if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x28 0x00 > ${TMP}.blob.bad
|
||||||
|
if ${FUTILITY} gbb_utility ${TMP}.blob.bad; then false; fi
|
||||||
|
|
||||||
|
# hwid: offset + size == end of file is okay; beyond is invalid
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x14 0x40 > ${TMP}.blob.bad
|
||||||
|
${FUTILITY} gbb_utility -g ${TMP}.blob.bad
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x14 0x41 > ${TMP}.blob.bad
|
||||||
|
if ${FUTILITY} gbb_utility -g ${TMP}.blob.bad; then false; fi
|
||||||
|
|
||||||
|
# rootkey: offset + size == end of file is okay; beyond is invalid
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x1c 0x30 > ${TMP}.blob.bad
|
||||||
|
${FUTILITY} gbb_utility -g ${TMP}.blob.bad
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x1c 0x31 > ${TMP}.blob.bad
|
||||||
|
if ${FUTILITY} gbb_utility -g ${TMP}.blob.bad; then false; fi
|
||||||
|
|
||||||
|
# bmpfv: offset + size == end of file is okay; beyond is invalid
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x24 0x20 > ${TMP}.blob.bad
|
||||||
|
${FUTILITY} gbb_utility -g ${TMP}.blob.bad
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x24 0x21 > ${TMP}.blob.bad
|
||||||
|
if ${FUTILITY} gbb_utility -g ${TMP}.blob.bad; then false; fi
|
||||||
|
|
||||||
|
# recovery_key: offset + size == end of file is okay; beyond is invalid
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x2c 0x10 > ${TMP}.blob.bad
|
||||||
|
${FUTILITY} gbb_utility -g ${TMP}.blob.bad
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x2c 0x11 > ${TMP}.blob.bad
|
||||||
|
if ${FUTILITY} gbb_utility -g ${TMP}.blob.bad; then false; fi
|
||||||
|
|
||||||
|
# hwid_size == 0 doesn't complain, but can't be set
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x14 0x00 > ${TMP}.blob.bad
|
||||||
|
${FUTILITY} gbb_utility -g ${TMP}.blob.bad
|
||||||
|
if ${FUTILITY} gbb_utility -s -i "A" ${TMP}.blob.bad; then false; fi
|
||||||
|
|
||||||
|
# rootkey_size == 0 gives warning, gets nothing, can't be set
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x1c 0x00 > ${TMP}.blob.bad
|
||||||
|
${FUTILITY} gbb_utility -g --rootkey ${TMP}.read1 ${TMP}.blob.bad
|
||||||
|
if ${FUTILITY} gbb_utility -s --rootkey ${TMP}.data1 ${TMP}.blob.bad; then false; fi
|
||||||
|
|
||||||
|
# bmpfv_size == 0 gives warning, gets nothing, can't be set
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x24 0x00 > ${TMP}.blob.bad
|
||||||
|
${FUTILITY} gbb_utility -g --bmpfv ${TMP}.read3 ${TMP}.blob.bad
|
||||||
|
if ${FUTILITY} gbb_utility -s --bmpfv ${TMP}.data3 ${TMP}.blob.bad; then false; fi
|
||||||
|
|
||||||
|
# recovery_key_size == 0 gives warning, gets nothing, can't be set
|
||||||
|
cat ${TMP}.blob | ${REPLACE} 0x2c 0x00 > ${TMP}.blob.bad
|
||||||
|
${FUTILITY} gbb_utility -g --recoverykey ${TMP}.read2 ${TMP}.blob.bad
|
||||||
|
if ${FUTILITY} gbb_utility -s --recoverykey ${TMP}.data2 ${TMP}.blob.bad; then false; fi
|
||||||
|
|
||||||
|
# cleanup
|
||||||
|
rm -f ${TMP}*
|
||||||
|
exit 0
|
||||||
@@ -1,26 +1,32 @@
|
|||||||
#!/bin/bash -eux
|
#!/bin/bash -eux
|
||||||
# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
|
# Copyright 2014 The Chromium OS Authors. All rights reserved.
|
||||||
# Use of this source code is governed by a BSD-style license that can be
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
# found in the LICENSE file.
|
# found in the LICENSE file.
|
||||||
|
|
||||||
me=${0##*/}
|
me=${0##*/}
|
||||||
|
TMP="$me.tmp"
|
||||||
|
|
||||||
# Work in scratch directory
|
# Work in scratch directory
|
||||||
cd "$OUTDIR"
|
cd "$OUTDIR"
|
||||||
TMP="$me.tmp"
|
|
||||||
|
|
||||||
# Built-in do-nothing commands.
|
|
||||||
# TODO(crbug.com/224734): Remove these when we have enough built-in commands
|
|
||||||
"$FUTILITY" foo hi
|
|
||||||
"$FUTILITY" bar there
|
|
||||||
"$FUTILITY" hey boys
|
|
||||||
|
|
||||||
# No args returns nonzero exit code
|
# No args returns nonzero exit code
|
||||||
"$FUTILITY" && false
|
"$FUTILITY" && false
|
||||||
|
|
||||||
"$FUTILITY" help > "$TMP"
|
# Make sure all built-in commands are listed and have help
|
||||||
grep Usage "$TMP"
|
expected=\
|
||||||
# TODO(crbug.com/224734): Make sure all built-in commands have help, too.
|
'dev_sign_file
|
||||||
|
dump_fmap
|
||||||
|
dump_kernel_config
|
||||||
|
gbb_utility
|
||||||
|
help
|
||||||
|
vbutil_firmware
|
||||||
|
vbutil_kernel
|
||||||
|
vbutil_key
|
||||||
|
vbutil_keyblock'
|
||||||
|
got=$("$FUTILITY" help |
|
||||||
|
egrep '^[[:space:]]+[^[:space:]]+[[:space:]]+[^[:space:]]+' |
|
||||||
|
awk '{print $1}')
|
||||||
|
[ "$expected" = "$got" ]
|
||||||
|
|
||||||
# It's weird but okay if the command is a full path.
|
# It's weird but okay if the command is a full path.
|
||||||
"$FUTILITY" /fake/path/to/help > "$TMP"
|
"$FUTILITY" /fake/path/to/help > "$TMP"
|
||||||
@@ -35,6 +41,16 @@ touch "$LOG"
|
|||||||
grep "$FUTILITY" "$LOG"
|
grep "$FUTILITY" "$LOG"
|
||||||
rm "$LOG"
|
rm "$LOG"
|
||||||
|
|
||||||
|
# Make sure deprecated functions fail via symlink
|
||||||
|
ln -sf "$FUTILITY" dev_sign_file
|
||||||
|
if ./dev_sign_file 2>${TMP}.outmsg ; then false; fi
|
||||||
|
grep deprecated ${TMP}.outmsg
|
||||||
|
# They may still fail when invoked through futility (this one does),
|
||||||
|
# but with a different error message.
|
||||||
|
"$FUTILITY" dev_sign_file 1>${TMP}.outmsg2 2>&1 || true
|
||||||
|
if grep deprecated ${TMP}.outmsg2; then false; fi
|
||||||
|
|
||||||
|
|
||||||
# cleanup
|
# cleanup
|
||||||
rm -f "$TMP"
|
rm -f ${TMP}*
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
// Copyright 2011 The Chromium OS Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
//
|
//
|
||||||
@@ -609,7 +609,7 @@ static bool parse_creation_param(const string &input_string,
|
|||||||
if (*parsed && *parsed != ',')
|
if (*parsed && *parsed != ',')
|
||||||
return false;
|
return false;
|
||||||
output_vector->push_back(param);
|
output_vector->push_back(param);
|
||||||
input = parsed + 1;
|
input = *parsed ? parsed + 1 : parsed;
|
||||||
} while (*input);
|
} while (*input);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user