summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2013-03-04 13:21:16 -0800
committerBill Richardson <wfrichar@chromium.org>2013-03-04 14:22:48 -0800
commita4c40a0f7bb0a7e099052c1699fdad92fe4d9efb (patch)
treef7c1ad247c852ab8f8ab6fa7e406275299f3d65e
parent7f73c9c38468faf03464ac0d22d5bf1f999b2ffe (diff)
parent81a0b3de707b4e00958faf36f41b8f3d7bac6808 (diff)
downloadvboot-a4c40a0f7bb0a7e099052c1699fdad92fe4d9efb.tar.gz
Merge remote-tracking branch 'm/master' into futility
BUG=none BRANCH=none TEST=none Change-Id: I817f78c5844a3e8e3ef7fdca339b716b09b2e3d2 Signed-off-by: Bill Richardson <wfrichar@chromium.org>
-rw-r--r--Makefile269
-rw-r--r--cgpt/CgptManager.cc429
-rw-r--r--cgpt/CgptManager.h172
-rw-r--r--firmware/lib/include/vboot_display.h4
-rw-r--r--firmware/lib/include/vboot_kernel.h1
-rw-r--r--firmware/lib/rollback_index.c17
-rw-r--r--firmware/lib/tpm_bootmode.c3
-rw-r--r--firmware/lib/vboot_api_kernel.c1
-rw-r--r--firmware/lib/vboot_common.c34
-rw-r--r--firmware/lib/vboot_common_init.c43
-rw-r--r--firmware/lib/vboot_display.c6
-rw-r--r--firmware/linktest/main_vbinit.c13
-rw-r--r--firmware/linktest/main_vbsf.c14
-rw-r--r--firmware/stub/utility_stub.c19
-rw-r--r--firmware/stub/vboot_api_stub.c76
-rw-r--r--firmware/stub/vboot_api_stub_init.c73
-rw-r--r--firmware/stub/vboot_api_stub_sf.c40
-rw-r--r--tests/CgptManagerTests.cc403
-rw-r--r--utility/mount-encrypted.c1349
-rw-r--r--utility/mount-encrypted.h144
-rw-r--r--utility/mount-helpers.c803
-rw-r--r--utility/mount-helpers.h42
22 files changed, 313 insertions, 3642 deletions
diff --git a/Makefile b/Makefile
index af1234a9..676a3aad 100644
--- a/Makefile
+++ b/Makefile
@@ -192,30 +192,9 @@ endif
export BUILD_RUN
-# Some things only compile inside the Chromium OS chroot.
-# TODO: Those things should be in their own repo, not part of vboot_reference
-# TODO: Is there a better way to detect this?
-ifneq (${CROS_WORKON_SRCROOT},)
-IN_CHROOT := yes
-endif
-
-# TODO: Move to separate repo.
-ifneq (${IN_CHROOT},)
-PC_BASE_VER ?= 125070
-PC_DEPS := libchrome-${PC_BASE_VER}
-PC_CFLAGS := $(shell ${PKG_CONFIG} --cflags ${PC_DEPS})
-PC_LDLIBS := $(shell ${PKG_CONFIG} --libs ${PC_DEPS})
-endif
-
-
##############################################################################
# Now we need to describe everything we might want or need to build
-# TODO: This should go in its own repo.
-AU_CGPTLIB = ${BUILD}/cgpt/libcgpt-cc.a
-# This is just ... Gah. There's no good place for it.
-DUMPKERNELCONFIGLIB = ${BUILD}/libdump_kernel_config.a
-
# Everything wants these headers.
INCLUDES += \
-Ifirmware/include \
@@ -235,12 +214,16 @@ endif
# Firmware library. TODO: Do we still need to export this?
FWLIB = ${BUILD}/vboot_fw.a
-# find lib -iname '*.c' | sort
-FWLIB_SRCS = \
- firmware/lib/cgptlib/cgptlib.c \
- firmware/lib/cgptlib/cgptlib_internal.c \
- firmware/lib/cgptlib/crc32.c \
+# Firmware library sources needed by VbInit() call
+VBINIT_SRCS = \
firmware/lib/crc8.c \
+ firmware/lib/utility.c \
+ firmware/lib/vboot_api_init.c \
+ firmware/lib/vboot_common_init.c \
+ firmware/lib/vboot_nvstorage.c \
+
+# Additional firmware library sources needed by VbSelectFirmware() call
+VBSF_SRCS = \
firmware/lib/cryptolib/padding.c \
firmware/lib/cryptolib/rsa.c \
firmware/lib/cryptolib/rsa_utility.c \
@@ -249,48 +232,75 @@ FWLIB_SRCS = \
firmware/lib/cryptolib/sha512.c \
firmware/lib/cryptolib/sha_utility.c \
firmware/lib/stateful_util.c \
- firmware/lib/utility.c \
- firmware/lib/utility_string.c \
- firmware/lib/vboot_api_init.c \
firmware/lib/vboot_api_firmware.c \
+ firmware/lib/vboot_common.c \
+ firmware/lib/vboot_firmware.c
+
+# Additional firmware library sources needed by VbSelectAndLoadKernel() call
+VBSLK_SRCS = \
+ firmware/lib/cgptlib/cgptlib.c \
+ firmware/lib/cgptlib/cgptlib_internal.c \
+ firmware/lib/cgptlib/crc32.c \
+ firmware/lib/utility_string.c \
firmware/lib/vboot_api_kernel.c \
firmware/lib/vboot_audio.c \
- firmware/lib/vboot_common.c \
firmware/lib/vboot_display.c \
- firmware/lib/vboot_firmware.c \
- firmware/lib/vboot_kernel.c \
- firmware/lib/vboot_nvstorage.c
+ firmware/lib/vboot_kernel.c
# Support real TPM unless BIOS sets MOCK_TPM
ifeq (${MOCK_TPM},)
-FWLIB_SRCS += \
+VBINIT_SRCS += \
firmware/lib/rollback_index.c \
- firmware/lib/tpm_bootmode.c \
firmware/lib/tpm_lite/tlcl.c
+
+VBSF_SRCS += \
+ firmware/lib/tpm_bootmode.c
else
-FWLIB_SRCS += \
+VBINIT_SRCS += \
firmware/lib/mocked_rollback_index.c \
- firmware/lib/mocked_tpm_bootmode.c \
firmware/lib/tpm_lite/mocked_tlcl.c
+
+VBSF_SRCS += \
+ firmware/lib/mocked_tpm_bootmode.c
endif
ifeq (${FIRMWARE_ARCH},)
# Include BIOS stubs in the firmware library when compiling for host
-FWLIB_SRCS += \
+# TODO: split out other stub funcs too
+VBINIT_SRCS += \
firmware/stub/tpm_lite_stub.c \
firmware/stub/utility_stub.c \
+ firmware/stub/vboot_api_stub_init.c
+
+VBSF_SRCS += \
+ firmware/stub/vboot_api_stub_sf.c
+
+VBSLK_SRCS += \
firmware/stub/vboot_api_stub.c \
firmware/stub/vboot_api_stub_disk.c
endif
+VBSF_SRCS += ${VBINIT_SRCS}
+FWLIB_SRCS += ${VBSF_SRCS} ${VBSLK_SRCS}
+
+VBINIT_OBJS = ${VBINIT_SRCS:%.c=${BUILD}/%.o}
+VBSF_OBJS = ${VBSF_SRCS:%.c=${BUILD}/%.o}
+
FWLIB_OBJS = ${FWLIB_SRCS:%.c=${BUILD}/%.o}
ALL_OBJS += ${FWLIB_OBJS}
# Library to build the utilities. "HOST" mostly means "userspace".
-HOSTLIB = ${BUILD}/vboot_host.a
+HOSTLIB = ${BUILD}/libvboot_host.a
HOSTLIB_SRCS = \
+ cgpt/cgpt_create.c \
+ cgpt/cgpt_add.c \
+ cgpt/cgpt_boot.c \
+ cgpt/cgpt_show.c \
+ cgpt/cgpt_repair.c \
+ cgpt/cgpt_prioritize.c \
+ cgpt/cgpt_common.c \
host/arch/${ARCH}/lib/crossystem_arch.c \
host/lib/crossystem.c \
host/lib/file_keys.c \
@@ -300,18 +310,37 @@ HOSTLIB_SRCS = \
host/lib/host_keyblock.c \
host/lib/host_misc.c \
host/lib/host_signature.c \
- host/lib/signature_digest.c
+ host/lib/signature_digest.c \
+ utility/dump_kernel_config_lib.c
HOSTLIB_OBJS = ${HOSTLIB_SRCS:%.c=${BUILD}/%.o}
ALL_OBJS += ${HOSTLIB_OBJS}
-
# Link with hostlib by default
LIBS = $(HOSTLIB)
# Might need this too.
CRYPTO_LIBS := $(shell ${PKG_CONFIG} --libs libcrypto)
+# Sigh. For historical reasons, the autoupdate installer must sometimes be a
+# 32-bit executable, even when everything else is 64-bit. But it only needs a
+# few functions, so let's just build those.
+TINYHOSTLIB = ${BUILD}/libtinyvboot_host.a
+
+TINYHOSTLIB_SRCS = \
+ cgpt/cgpt_create.c \
+ cgpt/cgpt_add.c \
+ cgpt/cgpt_boot.c \
+ cgpt/cgpt_show.c \
+ cgpt/cgpt_repair.c \
+ cgpt/cgpt_prioritize.c \
+ cgpt/cgpt_common.c \
+ utility/dump_kernel_config_lib.c \
+ firmware/lib/cgptlib/crc32.c \
+ firmware/lib/cgptlib/cgptlib_internal.c \
+ firmware/stub/utility_stub.c
+
+TINYHOSTLIB_OBJS = ${TINYHOSTLIB_SRCS:%.c=${BUILD}/%.o}
# ----------------------------------------------------------------------------
# Now for the userspace binaries
@@ -384,10 +413,6 @@ endif
UTIL_BINS_STATIC := $(addprefix ${BUILD}/utility/,${UTIL_NAMES_STATIC})
UTIL_BINS = $(addprefix ${BUILD}/utility/,${UTIL_NAMES})
-ifneq (${IN_CHROOT},)
-UTIL_SBINS = $(addprefix ${BUILD}/utility/,mount-encrypted)
-endif
-
ALL_DEPS += $(addsuffix .d,${UTIL_BINS})
@@ -411,7 +436,7 @@ SIGNING_COMMON = scripts/image_signing/common_minimal.sh
FUTIL_BIN = ${BUILD}/futility/futility
# These are the others it will replace.
-FUTIL_OLD = $(notdir ${CGPT} ${UTIL_BINS} ${UTIL_SCRIPTS} ${UTIL_SBINS} \
+FUTIL_OLD = $(notdir ${CGPT} ${UTIL_BINS} ${UTIL_SCRIPTS} \
${SIGNING_SCRIPTS} ${SIGNING_SCRIPTS_DEV})
FUTIL_SRCS = \
@@ -469,11 +494,6 @@ TEST_NAMES = \
vboot_kernel_tests \
vboot_nvstorage_test
-# Grrr
-ifneq (${IN_CHROOT},)
-TEST_NAMES += CgptManagerTests
-endif
-
# TODO: port these tests to new API, if not already eqivalent
# functionality in other tests. These don't even compile at present.
#
@@ -516,29 +536,6 @@ ALL_DEPS += $(addsuffix .d,${TEST_BINS})
# Directory containing test keys
TEST_KEYS = ${SRC_RUN}/tests/testkeys
-# ----------------------------------------------------------------------------
-# TODO: why not make this include *all* the cgpt files, and simply have
-# cgpt link against it?
-# TODO: CgptManager.cc should move to the installer project. Shouldn't be
-# in libcgpt-cc.a.
-AU_CGPTLIB_SRCS = \
- cgpt/CgptManager.cc \
- cgpt/cgpt_create.c \
- cgpt/cgpt_add.c \
- cgpt/cgpt_boot.c \
- cgpt/cgpt_show.c \
- cgpt/cgpt_repair.c \
- cgpt/cgpt_prioritize.c \
- cgpt/cgpt_common.c \
- firmware/lib/cgptlib/crc32.c \
- firmware/lib/cgptlib/cgptlib_internal.c \
- firmware/stub/utility_stub.c
-
-AU_CGPTLIB_OBJS = $(filter %.o, \
- ${AU_CGPTLIB_SRCS:%.c=${BUILD}/%.o} \
- ${AU_CGPTLIB_SRCS:%.cc=${BUILD}/%.o})
-ALL_OBJS += ${AU_CGPTLIB_OBJS}
-
##############################################################################
# Finally, some targets. High-level ones first.
@@ -559,10 +556,6 @@ all: fwlib $(if ${FIRMWARE_ARCH},,host_stuff) $(if ${COV},coverage)
.PHONY: host_stuff
host_stuff: hostlib cgpt utils futil tests
-# AU targets
-.PHONY: au_stuff
-au_stuff: libcgpt_cc libdump_kernel_config cgptmanager_tests
-
.PHONY: clean
clean:
${Q}/bin/rm -rf ${BUILD}
@@ -622,8 +615,20 @@ ifeq (${FIRMWARE_ARCH},)
${FWLIB_OBJS}: CFLAGS += -DDISABLE_ROLLBACK_TPM
endif
+# Link tests
+${BUILD}/firmware/linktest/main_vbinit: LIBS =
+${BUILD}/firmware/linktest/main_vbinit: OBJS = ${VBINIT_OBJS}
+${BUILD}/firmware/linktest/main_vbsf: LIBS =
+${BUILD}/firmware/linktest/main_vbsf: OBJS = ${VBSF_OBJS}
+
+.phony: fwlinktest
+fwlinktest: ${FWLIB} \
+ ${BUILD}/firmware/linktest/main_vbinit \
+ ${BUILD}/firmware/linktest/main_vbsf \
+ ${BUILD}/firmware/linktest/main
+
.PHONY: fwlib
-fwlib: ${FWLIB} $(if ${FIRMWARE_ARCH},,${BUILD}/firmware/linktest/main)
+fwlib: ${FWLIB} $(if ${FIRMWARE_ARCH},,fwlinktest)
${FWLIB}: ${FWLIB_OBJS}
@printf " RM $(subst ${BUILD}/,,$@)\n"
@@ -648,6 +653,18 @@ ${HOSTLIB}: ${HOSTLIB_OBJS} ${FWLIB_OBJS}
@printf " AR $(subst ${BUILD}/,,$@)\n"
${Q}ar qc $@ $^
+
+# Ugh. This is a very cut-down version of HOSTLIB just for the installer.
+.PHONY: tinyhostlib
+tinyhostlib: ${TINYHOSTLIB}
+ ${Q}cp -f ${TINYHOSTLIB} ${HOSTLIB}
+
+${TINYHOSTLIB}: ${TINYHOSTLIB_OBJS}
+ @printf " RM $(subst ${BUILD}/,,$@)\n"
+ ${Q}rm -f $@
+ @printf " AR $(subst ${BUILD}/,,$@)\n"
+ ${Q}ar qc $@ $^
+
# ----------------------------------------------------------------------------
# CGPT library and utility
@@ -677,24 +694,15 @@ ${BUILD}/utility/%: INCLUDES += -Ihost/include -Iutility/include
${UTIL_BINS_STATIC}: LDFLAGS += -static
.PHONY: utils
-utils: ${UTIL_BINS} ${UTIL_SCRIPTS} ${UTIL_SBINS}
+utils: ${UTIL_BINS} ${UTIL_SCRIPTS}
${Q}cp -f ${UTIL_SCRIPTS} ${BUILD}/utility
${Q}chmod a+rx $(patsubst %,${BUILD}/%,${UTIL_SCRIPTS})
.PHONY: utils_install
-utils_install: ${UTIL_BINS} ${UTIL_SCRIPTS} ${UTIL_SBINS}
+utils_install: ${UTIL_BINS} ${UTIL_SCRIPTS}
@printf " INSTALL UTILS\n"
${Q}mkdir -p ${UB_DIR}
${Q}${INSTALL} -t ${UB_DIR} ${UTIL_BINS} ${UTIL_SCRIPTS}
-ifneq (${UTIL_SBINS},)
- ${Q}${INSTALL} -t ${UB_DIR} ${UTIL_SBINS}
-ifneq (${SB_DIR},)
- ${Q}mkdir -p ${SB_DIR}
- ${Q}for prog in $(notdir ${UTIL_SBINS}); do \
- ln -sf "${FT_DIR}/futility" "${SB_DIR}/$$prog"; done
-endif
-endif
-
# And some signing stuff for the target
.PHONY: signing_install
@@ -729,44 +737,6 @@ futil_install: ${FUTIL_BIN}
ln -sf futility "${F_DIR}/$$prog"; done
# ----------------------------------------------------------------------------
-# Mount-encrypted utility for cryptohome
-
-# TODO: mount-encrypted should move to cryptohome and just link against
-# vboot-host.a for tlcl and crossystem.
-
-# The embedded libcrypto conflicts with the shipped openssl,
-# so mount-* builds without the common CFLAGS (and those includes).
-
-${BUILD}/utility/mount-helpers.o: \
- utility/mount-helpers.c \
- utility/mount-helpers.h \
- utility/mount-encrypted.h
- @printf " CCm-e $(subst ${BUILD}/,,$@)\n"
- ${Q}${CC} -Wall -Werror -O2 -D_FORTIFY_SOURCE=2 -fstack-protector \
- ${COV_FLAGS} \
- $(shell ${PKG_CONFIG} --cflags glib-2.0 openssl) \
- -c $< -o $@
-
-${BUILD}/utility/mount-encrypted: \
- utility/mount-encrypted.c \
- utility/mount-encrypted.h \
- ${BUILD}/utility/mount-helpers.o ${LIBS}
- @printf " CCm-exe $(subst ${BUILD}/,,$@)\n"
- ${Q}${CC} -Wall -Werror -O2 -D_FORTIFY_SOURCE=2 -fstack-protector \
- $(shell ${PKG_CONFIG} --cflags glib-2.0 openssl) \
- -Ifirmware/include \
- -Ihost/include \
- ${COV_FLAGS} \
- ${LDFLAGS} \
- $< -o $@ \
- ${BUILD}/utility/mount-helpers.o ${LIBS} \
- $(shell ${PKG_CONFIG} --libs glib-2.0 openssl) \
- -lm
-ifneq (${COV},)
- ${Q}mv -f mount-encrypted.gcno ${BUILD}/utility
-endif
-
-# ----------------------------------------------------------------------------
# Utility to generate TLCL structure definition header file.
${BUILD}/utility/tlcl_generator: CFLAGS += -fpack-struct
@@ -783,32 +753,6 @@ update_tlcl_structures: ${BUILD}/utility/tlcl_generator
cp ${STRUCTURES_TMP} ${STRUCTURES_SRC} )
# ----------------------------------------------------------------------------
-# Library to dump kernel config
-# Used by platform/installer, as well as standalone utility.
-
-.PHONY: libdump_kernel_config
-libdump_kernel_config: ${DUMPKERNELCONFIGLIB}
-
-${DUMPKERNELCONFIGLIB}: ${BUILD}/utility/dump_kernel_config_lib.o
- @printf " RM $(subst ${BUILD}/,,$@)\n"
- ${Q}rm -f $@
- @printf " AR $(subst ${BUILD}/,,$@)\n"
- ${Q}ar qc $@ $^
-
-# ----------------------------------------------------------------------------
-# And this thing.
-
-.PHONY: libcgpt_cc
-libcgpt_cc: ${AU_CGPTLIB}
-
-${AU_CGPTLIB}: INCLUDES += -Ifirmware/lib/cgptlib/include
-${AU_CGPTLIB}: ${AU_CGPTLIB_OBJS}
- @printf " RM $(subst ${BUILD}/,,$@)\n"
- ${Q}rm -f $@
- @printf " AR $(subst ${BUILD}/,,$@)\n"
- ${Q}ar qc $@ $^
-
-# ----------------------------------------------------------------------------
# Tests
.PHONY: tests
@@ -858,10 +802,6 @@ ${BUILD}/%.o: %.cc
# Linktest ensures firmware lib doesn't rely on outside libraries
${BUILD}/firmware/linktest/main: LIBS = ${FWLIB}
-# Specific dependency here.
-${BUILD}/utility/dump_kernel_config: LIBS += ${DUMPKERNELCONFIGLIB}
-${BUILD}/utility/dump_kernel_config: ${DUMPKERNELCONFIGLIB}
-
# GBB utility needs C++ linker. TODO: It shouldn't.
${BUILD}/utility/gbb_utility: LD = ${CXX}
@@ -918,15 +858,6 @@ ${BUILD}/tests/vboot_audio_tests: OBJS += \
${BUILD}/tests/vboot_audio_tests: \
${BUILD}/firmware/lib/vboot_audio_for_test.o
-.PHONY: cgptmanager_tests
-cgptmanager_tests: ${BUILD}/tests/CgptManagerTests
-
-${BUILD}/tests/CgptManagerTests: CFLAGS += ${PC_CFLAGS}
-${BUILD}/tests/CgptManagerTests: LD = ${CXX}
-${BUILD}/tests/CgptManagerTests: LDLIBS += -lgtest -lgflags ${PC_LDLIBS}
-${BUILD}/tests/CgptManagerTests: LIBS = ${AU_CGPTLIB}
-${BUILD}/tests/CgptManagerTests: ${AU_CGPTLIB}
-
${BUILD}/tests/rollback_index_test: INCLUDES += -I/usr/include
${BUILD}/tests/rollback_index_test: LIBS += -ltlcl
@@ -988,10 +919,6 @@ runbmptests: test_setup
.PHONY: runcgpttests
runcgpttests: test_setup
${RUNTEST} ${BUILD_RUN}/tests/cgptlib_test
-# HEY - elsewhere
-ifneq (${IN_CHROOT},)
- ${RUNTEST} ${BUILD_RUN}/tests/CgptManagerTests --v=1
-endif
.PHONY: runtestscripts
runtestscripts: test_setup genfuzztestcases
diff --git a/cgpt/CgptManager.cc b/cgpt/CgptManager.cc
deleted file mode 100644
index a1a018a3..00000000
--- a/cgpt/CgptManager.cc
+++ /dev/null
@@ -1,429 +0,0 @@
-// Copyright (c) 2012 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 <string.h>
-
-#include "CgptManager.h"
-
-extern "C" {
-#include "cgpt_params.h"
-}
-
-using std::string;
-
-// We don't use these variables for the libcgpt version.
-const char* progname = "";
-const char* command = "";
-void (*uuid_generator)(uint8_t* buffer) = NULL;
-
-
-// This file implements the C++ wrapper methods over the C cgpt methods.
-
-CgptManager::CgptManager():
- is_initialized_(false) {
-}
-
-CgptManager::~CgptManager() {
-}
-
-CgptErrorCode CgptManager::Initialize(const string& device_name) {
- device_name_ = device_name;
- is_initialized_ = true;
- return kCgptSuccess;
-}
-
-CgptErrorCode CgptManager::ClearAll() {
- if (!is_initialized_)
- return kCgptNotInitialized;
-
- CgptCreateParams params;
- memset(&params, 0, sizeof(params));
-
- params.drive_name = const_cast<char *>(device_name_.c_str());
- params.zap = 0;
-
- int retval = cgpt_create(&params);
- if (retval != CGPT_OK)
- return kCgptUnknownError;
-
- return kCgptSuccess;
-}
-
-CgptErrorCode CgptManager::AddPartition(const string& label,
- const Guid& partition_type_guid,
- const Guid& unique_id,
- uint64_t beginning_offset,
- uint64_t num_sectors) {
- if (!is_initialized_)
- return kCgptNotInitialized;
-
- CgptAddParams params;
- memset(&params, 0, sizeof(params));
-
- params.drive_name = const_cast<char *>(device_name_.c_str());
- params.label = const_cast<char *>(label.c_str());
-
- params.type_guid = partition_type_guid;
- params.set_type = 1;
-
- params.begin = beginning_offset;
- params.set_begin = 1;
-
- params.size = num_sectors;
- params.set_size = 1;
-
- if (!IsZero(&unique_id)) {
- params.unique_guid = unique_id;
- params.set_unique = 1;
- }
-
- int retval = cgpt_add(&params);
- if (retval != CGPT_OK)
- return kCgptUnknownError;
-
- return kCgptSuccess;
-}
-
-CgptErrorCode CgptManager::GetNumNonEmptyPartitions(uint8_t* num_partitions) const {
- if (!is_initialized_)
- return kCgptNotInitialized;
-
- if (!num_partitions)
- return kCgptInvalidArgument;
-
- CgptShowParams params;
- memset(&params, 0, sizeof(params));
-
- params.drive_name = const_cast<char *>(device_name_.c_str());
- int retval = cgpt_get_num_non_empty_partitions(&params);
-
- if (retval != CGPT_OK)
- return kCgptUnknownError;
-
- *num_partitions = params.num_partitions;
- return kCgptSuccess;
-}
-
-CgptErrorCode CgptManager::SetPmbr(uint32_t boot_partition_number,
- const string& boot_file_name,
- bool should_create_legacy_partition) {
- if (!is_initialized_)
- return kCgptNotInitialized;
-
- CgptBootParams params;
- memset(&params, 0, sizeof(params));
-
- params.drive_name = const_cast<char *>(device_name_.c_str());
- if (!boot_file_name.empty())
- params.bootfile = const_cast<char *>(boot_file_name.c_str());
-
- params.partition = boot_partition_number;
- params.create_pmbr = should_create_legacy_partition;
-
- int retval = cgpt_boot(&params);
- if (retval != CGPT_OK)
- return kCgptUnknownError;
-
- return kCgptSuccess;
-}
-
-CgptErrorCode CgptManager::GetPmbrBootPartitionNumber(
- uint32_t* boot_partition) const {
- if (!is_initialized_)
- return kCgptNotInitialized;
-
- if (!boot_partition)
- return kCgptInvalidArgument;
-
- CgptBootParams params;
- memset(&params, 0, sizeof(params));
-
- params.drive_name = const_cast<char *>(device_name_.c_str());
-
- int retval = cgpt_get_boot_partition_number(&params);
- if (retval != CGPT_OK)
- return kCgptUnknownError;
-
- *boot_partition = params.partition;
- return kCgptSuccess;
-}
-
-CgptErrorCode CgptManager::SetSuccessful(
- uint32_t partition_number,
- bool is_successful) {
- if (!is_initialized_)
- return kCgptNotInitialized;
-
- CgptAddParams params;
- memset(&params, 0, sizeof(params));
-
- params.drive_name = const_cast<char *>(device_name_.c_str());
- params.partition = partition_number;
-
- params.successful = is_successful;
- params.set_successful = true;
-
- int retval = cgpt_set_attributes(&params);
- if (retval != CGPT_OK)
- return kCgptUnknownError;
-
- return kCgptSuccess;
-}
-
-CgptErrorCode CgptManager::GetSuccessful(uint32_t partition_number,
- bool* is_successful) const {
- if (!is_initialized_)
- return kCgptNotInitialized;
-
- if (!is_successful)
- return kCgptInvalidArgument;
-
- CgptAddParams params;
- memset(&params, 0, sizeof(params));
-
- params.drive_name = const_cast<char *>(device_name_.c_str());
- params.partition = partition_number;
-
- int retval = cgpt_get_partition_details(&params);
- if (retval != CGPT_OK)
- return kCgptUnknownError;
-
- *is_successful = params.successful;
- return kCgptSuccess;
-}
-
-CgptErrorCode CgptManager::SetNumTriesLeft(uint32_t partition_number,
- int numTries) {
- if (!is_initialized_)
- return kCgptNotInitialized;
-
- CgptAddParams params;
- memset(&params, 0, sizeof(params));
-
- params.drive_name = const_cast<char *>(device_name_.c_str());
- params.partition = partition_number;
-
- params.tries = numTries;
- params.set_tries = true;
-
- int retval = cgpt_set_attributes(&params);
- if (retval != CGPT_OK)
- return kCgptUnknownError;
-
- return kCgptSuccess;
-}
-
-CgptErrorCode CgptManager::GetNumTriesLeft(uint32_t partition_number,
- int* numTries) const {
- if (!is_initialized_)
- return kCgptNotInitialized;
-
- if (!numTries)
- return kCgptInvalidArgument;
-
- CgptAddParams params;
- memset(&params, 0, sizeof(params));
-
- params.drive_name = const_cast<char *>(device_name_.c_str());
- params.partition = partition_number;
-
- int retval = cgpt_get_partition_details(&params);
- if (retval != CGPT_OK)
- return kCgptUnknownError;
-
- *numTries = params.tries;
- return kCgptSuccess;
-}
-
-CgptErrorCode CgptManager::SetPriority(uint32_t partition_number,
- uint8_t priority) {
- if (!is_initialized_)
- return kCgptNotInitialized;
-
- CgptAddParams params;
- memset(&params, 0, sizeof(params));
-
- params.drive_name = const_cast<char *>(device_name_.c_str());
- params.partition = partition_number;
-
- params.priority = priority;
- params.set_priority = true;
-
- int retval = cgpt_set_attributes(&params);
- if (retval != CGPT_OK)
- return kCgptUnknownError;
-
- return kCgptSuccess;
-}
-
-CgptErrorCode CgptManager::GetPriority(uint32_t partition_number,
- uint8_t* priority) const {
- if (!is_initialized_)
- return kCgptNotInitialized;
-
- if (!priority)
- return kCgptInvalidArgument;
-
- CgptAddParams params;
- memset(&params, 0, sizeof(params));
-
- params.drive_name = const_cast<char *>(device_name_.c_str());
- params.partition = partition_number;
-
- int retval = cgpt_get_partition_details(&params);
- if (retval != CGPT_OK)
- return kCgptUnknownError;
-
- *priority = params.priority;
- return kCgptSuccess;
-}
-
-CgptErrorCode CgptManager::GetBeginningOffset(uint32_t partition_number,
- uint64_t* offset) const {
- if (!is_initialized_)
- return kCgptNotInitialized;
-
- if (!offset)
- return kCgptInvalidArgument;
-
- CgptAddParams params;
- memset(&params, 0, sizeof(params));
-
- params.drive_name = const_cast<char *>(device_name_.c_str());
- params.partition = partition_number;
-
- int retval = cgpt_get_partition_details(&params);
- if (retval != CGPT_OK)
- return kCgptUnknownError;
-
- *offset = params.begin;
- return kCgptSuccess;
-}
-
-CgptErrorCode CgptManager::GetNumSectors(uint32_t partition_number,
- uint64_t* num_sectors) const {
- if (!is_initialized_)
- return kCgptNotInitialized;
-
- if (!num_sectors)
- return kCgptInvalidArgument;
-
- CgptAddParams params;
- memset(&params, 0, sizeof(params));
-
- params.drive_name = const_cast<char *>(device_name_.c_str());
- params.partition = partition_number;
-
- int retval = cgpt_get_partition_details(&params);
- if (retval != CGPT_OK)
- return kCgptUnknownError;
-
- *num_sectors = params.size;
- return kCgptSuccess;
-}
-
-CgptErrorCode CgptManager::GetPartitionTypeId(uint32_t partition_number,
- Guid* type_id) const {
- if (!is_initialized_)
- return kCgptNotInitialized;
-
- if (!type_id)
- return kCgptInvalidArgument;
-
- CgptAddParams params;
- memset(&params, 0, sizeof(params));
-
- params.drive_name = const_cast<char *>(device_name_.c_str());
- params.partition = partition_number;
-
- int retval = cgpt_get_partition_details(&params);
- if (retval != CGPT_OK)
- return kCgptUnknownError;
-
- *type_id = params.type_guid;
- return kCgptSuccess;
-}
-
-CgptErrorCode CgptManager::GetPartitionUniqueId(uint32_t partition_number,
- Guid* unique_id) const {
- if (!is_initialized_)
- return kCgptNotInitialized;
-
- if (!unique_id)
- return kCgptInvalidArgument;
-
- CgptAddParams params;
- memset(&params, 0, sizeof(params));
-
- params.drive_name = const_cast<char *>(device_name_.c_str());
- params.partition = partition_number;
-
- int retval = cgpt_get_partition_details(&params);
- if (retval != CGPT_OK)
- return kCgptUnknownError;
-
- *unique_id = params.unique_guid;
- return kCgptSuccess;
-}
-
-CgptErrorCode CgptManager::GetPartitionNumberByUniqueId(
- const Guid& unique_id,
- uint32_t* partition_number) const {
- if (!is_initialized_)
- return kCgptNotInitialized;
-
- if (!partition_number)
- return kCgptInvalidArgument;
-
- CgptAddParams params;
- memset(&params, 0, sizeof(params));
-
- params.drive_name = const_cast<char *>(device_name_.c_str());
- params.unique_guid = unique_id;
- params.set_unique = 1;
-
- int retval = cgpt_get_partition_details(&params);
- if (retval != CGPT_OK)
- return kCgptUnknownError;
-
- *partition_number = params.partition;
- return kCgptSuccess;
-}
-
-CgptErrorCode CgptManager::SetHighestPriority(uint32_t partition_number,
- uint8_t highest_priority) {
- if (!is_initialized_)
- return kCgptNotInitialized;
-
- CgptPrioritizeParams params;
- memset(&params, 0, sizeof(params));
-
- params.drive_name = const_cast<char *>(device_name_.c_str());
- params.set_partition = partition_number;
- params.max_priority = highest_priority;
-
- int retval = cgpt_prioritize(&params);
- if (retval != CGPT_OK)
- return kCgptUnknownError;
-
- return kCgptSuccess;
-}
-
-CgptErrorCode CgptManager::SetHighestPriority(uint32_t partition_number) {
- // The internal implementation in cgpt_prioritize automatically computes the
- // right priority number if we supply 0 for the highest_priority argument.
- return SetHighestPriority(partition_number, 0);
-}
-
-CgptErrorCode CgptManager::Validate() {
- if (!is_initialized_)
- return kCgptNotInitialized;
-
- uint8_t num_partitions;
-
- // GetNumNonEmptyPartitions does the check for GptSanityCheck.
- // so call it (ignore the num_partitions result) and just return
- // its success/failure result.
- return GetNumNonEmptyPartitions(&num_partitions);
-}
diff --git a/cgpt/CgptManager.h b/cgpt/CgptManager.h
deleted file mode 100644
index 2dbca6f2..00000000
--- a/cgpt/CgptManager.h
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright (c) 2012 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.
-
-#ifndef VBOOT_REFERENCE_CGPT_CGPTMANAGER_H_
-#define VBOOT_REFERENCE_CGPT_CGPTMANAGER_H_
-
-#include <string>
-#include "gpt.h"
-
-// This file defines a simple C++ wrapper class interface for the cgpt methods.
-
-// These are the possible error codes that can be returned by the CgptManager.
-typedef enum CgptErrorCode
-{
- kCgptSuccess = 0,
- kCgptNotInitialized = 1,
- kCgptUnknownError = 2,
- kCgptInvalidArgument = 3,
-} CgptErrorCode;
-
-
-// CgptManager exposes methods to manipulate the Guid Partition Table as needed
-// for ChromeOS scenarios.
-class CgptManager {
- public:
- // Default constructor. The Initialize method must be called before
- // any other method can be called on this class.
- CgptManager();
-
- // Destructor. Automatically closes any opened device.
- ~CgptManager();
-
- // Opens the given device_name (e.g. "/dev/sdc") and initializes
- // with the Guid Partition Table of that device. This is the first method
- // that should be called on this class. Otherwise those methods will
- // return kCgptNotInitialized.
- // Returns kCgptSuccess or an appropriate error code.
- // This device is automatically closed when this object is destructed.
- CgptErrorCode Initialize(const std::string& device_name);
-
- // Clears all the existing contents of the GPT and PMBR on the current
- // device.
- CgptErrorCode ClearAll();
-
- // Adds a new partition at the end of the existing partitions
- // with the new label, type, unique Id, offset and size.
- // Returns kCgptSuccess or an appropriate error code.
- CgptErrorCode AddPartition(const std::string& label,
- const Guid& partition_type_guid,
- const Guid& unique_id,
- uint64_t beginning_offset,
- uint64_t num_sectors);
-
- // Populates num_partitions parameter with the number of partitions
- // that are currently on this device and not empty.
- // Returns kCgptSuccess or an appropriate error code.
- CgptErrorCode GetNumNonEmptyPartitions(uint8_t* num_partitions) const;
-
- // Sets the Protective Master Boot Record on this device with the given
- // boot_partition number after populating the MBR with the contents of the
- // given boot_file_name. It also creates a legacy partition if
- // should_create_legacy_partition is true.
- // Note: Strictly speaking, the PMBR is not part of the GPT, but it is
- // included here for ease of use.
- CgptErrorCode SetPmbr(uint32_t boot_partition_number,
- const std::string& boot_file_name,
- bool should_create_legacy_partition);
-
- // Populates boot_partition with the partition number that's set to
- // boot in the PMBR.
- // Returns kCgptSuccess or an appropriate error code.
- CgptErrorCode GetPmbrBootPartitionNumber(uint32_t* boot_partition) const;
-
- // Sets the "successful" attribute of the given kernelPartition to 0 or 1
- // based on the value of is_successful being true (1) or false(0)
- // Returns kCgptSuccess or an appropriate error code.
- CgptErrorCode SetSuccessful(uint32_t partition_number, bool is_successful);
-
- // Populates is_successful to true if the successful attribute in the
- // given kernelPartition is non-zero, or to false if it's zero.
- // Returns kCgptSuccess or an appropriate error code.
- CgptErrorCode GetSuccessful(uint32_t partition_number,
- bool* is_successful) const;
-
- // Sets the "NumTriesLeft" attribute of the given kernelPartition to
- // the given num_tries_left value.
- // Returns kCgptSuccess or an appropriate error code.
- CgptErrorCode SetNumTriesLeft(uint32_t partition_number,
- int num_tries_left);
-
- // Populates the num_tries_left parameter with the value of the
- // NumTriesLeft attribute of the given kernelPartition.
- // Returns kCgptSuccess or an appropriate error code.
- CgptErrorCode GetNumTriesLeft(uint32_t partition_number,
- int* num_tries_left) const;
-
- // Sets the "Priority" attribute of the given kernelPartition to
- // the given priority value.
- // Returns kCgptSuccess or an appropriate error code.
- CgptErrorCode SetPriority(uint32_t partition_number,
- uint8_t priority);
-
- // Populates the priority parameter with the value of the Priority
- // attribute of the given kernelPartition.
- // Returns kCgptSuccess or an appropriate error code.
- CgptErrorCode GetPriority(uint32_t partition_number,
- uint8_t* priority) const;
-
- // Populates the offset parameter with the beginning offset of the
- // given partition.
- // Returns kCgptSuccess or an appropriate error code.
- CgptErrorCode GetBeginningOffset(uint32_t partition_number,
- uint64_t* offset) const;
-
- // Populates the number of sectors in the given partition.
- // Returns kCgptSuccess or an appropriate error code.
- CgptErrorCode GetNumSectors(uint32_t partition_number,
- uint64_t* num_sectors) const;
-
- // Populates the type_id parameter with the partition type id
- // (these are the standard ids for kernel, rootfs, etc.)
- // of the partition corresponding to the given partition_number.
- // Returns kCgptSuccess or an appropriate error code.
- CgptErrorCode GetPartitionTypeId(uint32_t partition_number,
- Guid* type_id) const;
-
- // Populates the unique_id parameter with the Guid that uniquely identifies
- // the given partition_number.
- // Returns kCgptSuccess or an appropriate error code.
- CgptErrorCode GetPartitionUniqueId(uint32_t partition_number,
- Guid* unique_id) const;
-
- // Populates the partition_number parameter with the partition number of
- // the partition which is uniquely identified by the given unique_id.
- // Returns kCgptSuccess or an appropriate error code.
- CgptErrorCode GetPartitionNumberByUniqueId(
- const Guid& unique_id,
- uint32_t* partition_number) const;
-
- // Sets the "Priority" attribute of given kernelPartition to the value
- // specified in higestPriority parameter. In addition, also reduces the
- // priorities of all the other kernel partitions, if necessary, to ensure
- // no other partition has a higher priority. It does preserve the relative
- // ordering among the remaining partitions and doesn't touch the partitions
- // whose priorities are zero.
- // Returns kCgptSuccess or an appropriate error code.
- CgptErrorCode SetHighestPriority(uint32_t partition_number,
- uint8_t highest_priority);
-
- // Same as SetHighestPriority above but works without having to explicitly
- // give a value for highest_priority. The internal implementation figures
- // out the best highest number that needs to be given depending on the
- // existing priorities.
- // Returns kCgptSuccess or an appropriate error code.
- CgptErrorCode SetHighestPriority(uint32_t partition_number);
-
- // Runs the sanity checks on the CGPT and MBR and
- // Returns kCgptSuccess if everything is valid or an appropriate error code
- // if there's anything invalid or if there's any error encountered during
- // the validation.
- CgptErrorCode Validate();
-
- private:
- std::string device_name_;
- bool is_initialized_;
-
- CgptManager(const CgptManager &);
- void operator=(const CgptManager &);
-};
-
-#endif // VBOOT_REFERENCE_CGPT_CGPTMANAGER_H_
diff --git a/firmware/lib/include/vboot_display.h b/firmware/lib/include/vboot_display.h
index 52730b9e..17ce48b8 100644
--- a/firmware/lib/include/vboot_display.h
+++ b/firmware/lib/include/vboot_display.h
@@ -34,7 +34,7 @@ ImageInfo *VbFindFontGlyph(VbFont_t *font, uint32_t ascii,
/**
* Try to display the specified text at a particular position.
*/
-void VbRenderTextAtPos(char *text, int right_to_left,
+void VbRenderTextAtPos(const char *text, int right_to_left,
uint32_t x, uint32_t y, VbFont_t *font);
/**
@@ -45,7 +45,7 @@ const char *RecoveryReasonString(uint8_t code);
/**
* Return a fixed string representing the HWID.
*/
-char *VbHWID(VbCommonParams *cparams);
+const char *VbHWID(VbCommonParams *cparams);
/**
* Get the number of localizations in the GBB bitmap data.
diff --git a/firmware/lib/include/vboot_kernel.h b/firmware/lib/include/vboot_kernel.h
index e3a44190..1243cb84 100644
--- a/firmware/lib/include/vboot_kernel.h
+++ b/firmware/lib/include/vboot_kernel.h
@@ -12,7 +12,6 @@
#include "cgptlib.h"
#include "load_firmware_fw.h"
#include "vboot_api.h"
-#include "vboot_kernel.h"
/**
* Allocate and read GPT data from the drive. The sector_bytes and
diff --git a/firmware/lib/rollback_index.c b/firmware/lib/rollback_index.c
index a7b65510..0c6e02ac 100644
--- a/firmware/lib/rollback_index.c
+++ b/firmware/lib/rollback_index.c
@@ -17,6 +17,15 @@
#define offsetof(A,B) __builtin_offsetof(A,B)
#endif
+/*
+ * Provide protoypes for functions not in the header file. These prototypes
+ * fix -Wmissing-prototypes warnings.
+ */
+uint32_t ReadSpaceFirmware(RollbackSpaceFirmware *rsf);
+uint32_t WriteSpaceFirmware(RollbackSpaceFirmware *rsf);
+uint32_t ReadSpaceKernel(RollbackSpaceKernel *rsk);
+uint32_t WriteSpaceKernel(RollbackSpaceKernel *rsk);
+
#ifdef FOR_TEST
/*
* Compiling for unit test, so we need the real implementations of
@@ -33,11 +42,11 @@ static int g_rollback_recovery_mode = 0;
__pragma(warning (disable: 4127))
#define RETURN_ON_FAILURE(tpm_command) do { \
- uint32_t result; \
- if ((result = (tpm_command)) != TPM_SUCCESS) { \
+ uint32_t result_; \
+ if ((result_ = (tpm_command)) != TPM_SUCCESS) { \
VBDEBUG(("Rollback: %08x returned by " #tpm_command \
- "\n", (int)result)); \
- return result; \
+ "\n", (int)result_)); \
+ return result_; \
} \
} while (0)
diff --git a/firmware/lib/tpm_bootmode.c b/firmware/lib/tpm_bootmode.c
index ec8fac7e..218db207 100644
--- a/firmware/lib/tpm_bootmode.c
+++ b/firmware/lib/tpm_bootmode.c
@@ -96,7 +96,8 @@ const uint8_t kBootInvalidSHA1Digest[] = {
* Given the boot state, return the correct SHA1 digest index for TPMExtend
* in kBootStateSHA1Digests[].
*/
-int GetBootStateIndex(int dev_mode, int rec_mode, uint64_t keyblock_flags)
+static int GetBootStateIndex(int dev_mode, int rec_mode,
+ uint64_t keyblock_flags)
{
int index = 0;
diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c
index a55d8064..483d47ed 100644
--- a/firmware/lib/vboot_api_kernel.c
+++ b/firmware/lib/vboot_api_kernel.c
@@ -13,6 +13,7 @@
#include "vboot_audio.h"
#include "vboot_common.h"
#include "vboot_display.h"
+#include "vboot_kernel.h"
#include "vboot_nvstorage.h"
/* Global variables */
diff --git a/firmware/lib/vboot_common.c b/firmware/lib/vboot_common.c
index 50a4cff8..3e3375f1 100644
--- a/firmware/lib/vboot_common.c
+++ b/firmware/lib/vboot_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+/* 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.
*
@@ -430,38 +430,6 @@ int VerifyKernelPreamble(const VbKernelPreambleHeader *preamble,
return VBOOT_SUCCESS;
}
-int VbSharedDataInit(VbSharedDataHeader *header, uint64_t size)
-{
- VBDEBUG(("VbSharedDataInit, %d bytes, header %d bytes\n", (int)size,
- sizeof(VbSharedDataHeader)));
-
- if (size < sizeof(VbSharedDataHeader)) {
- VBDEBUG(("Not enough data for header.\n"));
- return VBOOT_SHARED_DATA_INVALID;
- }
- if (size < VB_SHARED_DATA_MIN_SIZE) {
- VBDEBUG(("Shared data buffer too small.\n"));
- return VBOOT_SHARED_DATA_INVALID;
- }
-
- if (!header)
- return VBOOT_SHARED_DATA_INVALID;
-
- /* Zero the header */
- Memset(header, 0, sizeof(VbSharedDataHeader));
-
- /* Initialize fields */
- header->magic = VB_SHARED_DATA_MAGIC;
- header->struct_version = VB_SHARED_DATA_VERSION;
- header->struct_size = sizeof(VbSharedDataHeader);
- header->data_size = size;
- header->data_used = sizeof(VbSharedDataHeader);
- header->firmware_index = 0xFF;
-
- /* Success */
- return VBOOT_SUCCESS;
-}
-
uint64_t VbSharedDataReserve(VbSharedDataHeader *header, uint64_t size)
{
uint64_t offs = header->data_used;
diff --git a/firmware/lib/vboot_common_init.c b/firmware/lib/vboot_common_init.c
new file mode 100644
index 00000000..9d6670ea
--- /dev/null
+++ b/firmware/lib/vboot_common_init.c
@@ -0,0 +1,43 @@
+/* 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.
+ *
+ * Common functions between firmware and kernel verified boot.
+ * (Firmware portion)
+ */
+
+#include "vboot_api.h"
+#include "vboot_common.h"
+#include "utility.h"
+
+int VbSharedDataInit(VbSharedDataHeader *header, uint64_t size)
+{
+ VBDEBUG(("VbSharedDataInit, %d bytes, header %d bytes\n", (int)size,
+ sizeof(VbSharedDataHeader)));
+
+ if (size < sizeof(VbSharedDataHeader)) {
+ VBDEBUG(("Not enough data for header.\n"));
+ return VBOOT_SHARED_DATA_INVALID;
+ }
+ if (size < VB_SHARED_DATA_MIN_SIZE) {
+ VBDEBUG(("Shared data buffer too small.\n"));
+ return VBOOT_SHARED_DATA_INVALID;
+ }
+
+ if (!header)
+ return VBOOT_SHARED_DATA_INVALID;
+
+ /* Zero the header */
+ Memset(header, 0, sizeof(VbSharedDataHeader));
+
+ /* Initialize fields */
+ header->magic = VB_SHARED_DATA_MAGIC;
+ header->struct_version = VB_SHARED_DATA_VERSION;
+ header->struct_size = sizeof(VbSharedDataHeader);
+ header->data_size = size;
+ header->data_used = sizeof(VbSharedDataHeader);
+ header->firmware_index = 0xFF;
+
+ /* Success */
+ return VBOOT_SUCCESS;
+}
diff --git a/firmware/lib/vboot_display.c b/firmware/lib/vboot_display.c
index 7c916d01..9abc51d9 100644
--- a/firmware/lib/vboot_display.c
+++ b/firmware/lib/vboot_display.c
@@ -46,7 +46,7 @@ VbError_t VbGetLocalizationCount(VbCommonParams *cparams, uint32_t *count)
return VBERROR_SUCCESS;
}
-char *VbHWID(VbCommonParams *cparams)
+const char *VbHWID(VbCommonParams *cparams)
{
GoogleBinaryBlockHeader *gbb =
(GoogleBinaryBlockHeader *)cparams->gbb_data;
@@ -120,7 +120,7 @@ ImageInfo *VbFindFontGlyph(VbFont_t *font, uint32_t ascii,
return &(entry->info);
}
-void VbRenderTextAtPos(char *text, int right_to_left,
+void VbRenderTextAtPos(const char *text, int right_to_left,
uint32_t x, uint32_t y, VbFont_t *font)
{
int i;
@@ -182,7 +182,7 @@ VbError_t VbDisplayScreenFromGBB(VbCommonParams *cparams, uint32_t screen,
uint32_t offset;
uint32_t i;
VbFont_t *font;
- char *text_to_show;
+ const char *text_to_show;
int rtol = 0;
char outbuf[OUTBUF_LEN] = "";
uint32_t used = 0;
diff --git a/firmware/linktest/main_vbinit.c b/firmware/linktest/main_vbinit.c
new file mode 100644
index 00000000..a3d50196
--- /dev/null
+++ b/firmware/linktest/main_vbinit.c
@@ -0,0 +1,13 @@
+/* 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 "vboot_api.h"
+
+int main(void)
+{
+ /* vboot_api.h - entry points INTO vboot_reference */
+ VbInit(0, 0);
+ return 0;
+}
diff --git a/firmware/linktest/main_vbsf.c b/firmware/linktest/main_vbsf.c
new file mode 100644
index 00000000..1a3825a8
--- /dev/null
+++ b/firmware/linktest/main_vbsf.c
@@ -0,0 +1,14 @@
+/* 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 "vboot_api.h"
+
+int main(void)
+{
+ /* vboot_api.h - entry points INTO vboot_reference */
+ VbSelectFirmware(0, 0);
+ VbUpdateFirmwareBodyHash(0, 0, 0);
+ return 0;
+}
diff --git a/firmware/stub/utility_stub.c b/firmware/stub/utility_stub.c
index e3ec19be..549ee851 100644
--- a/firmware/stub/utility_stub.c
+++ b/firmware/stub/utility_stub.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+/* 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.
*
@@ -15,18 +15,19 @@
#include <string.h>
#include <sys/time.h>
-
-int Memcmp(const void* src1, const void* src2, size_t n) {
- return memcmp(src1, src2, n);
+int Memcmp(const void *src1, const void *src2, size_t n)
+{
+ return memcmp(src1, src2, n);
}
-
-void* Memcpy(void* dest, const void* src, uint64_t n) {
- return memcpy(dest, src, (size_t)n);
+void *Memcpy(void *dest, const void *src, uint64_t n)
+{
+ return memcpy(dest, src, (size_t)n);
}
-void* Memset(void* d, const uint8_t c, uint64_t n) {
- return memset(d, c, n);
+void *Memset(void *d, const uint8_t c, uint64_t n)
+{
+ return memset(d, c, n);
}
diff --git a/firmware/stub/vboot_api_stub.c b/firmware/stub/vboot_api_stub.c
index c71c38ac..1829764f 100644
--- a/firmware/stub/vboot_api_stub.c
+++ b/firmware/stub/vboot_api_stub.c
@@ -18,66 +18,6 @@
/* disable MSVC warnings on unused arguments */
__pragma(warning (disable: 4100))
-
-/* U-Boot's printf uses '%L' for uint64_t. gcc uses '%l'. */
-#define MAX_FMT 255
-static char fmtbuf[MAX_FMT+1];
-
-static const char *fixfmt(const char *format)
-{
- int i;
- for(i=0; i<MAX_FMT && format[i]; i++) {
- fmtbuf[i] = format[i];
- if(format[i] == '%' && format[i+1] == 'L') {
- fmtbuf[i+1] = 'l';
- i++;
- }
- }
- fmtbuf[i] = '\0';
- return fmtbuf;
-}
-
-void VbExError(const char *format, ...)
-{
- va_list ap;
- va_start(ap, format);
- fprintf(stderr, "ERROR: ");
- vfprintf(stderr, fixfmt(format), ap);
- va_end(ap);
- exit(1);
-}
-
-void VbExDebug(const char *format, ...)
-{
- va_list ap;
- va_start(ap, format);
- fprintf(stderr, "DEBUG: ");
- vfprintf(stderr, fixfmt(format), ap);
- va_end(ap);
-}
-
-void *VbExMalloc(size_t size)
-{
- void *p = malloc(size);
- if (!p) {
- /* Fatal Error. We must abort. */
- abort();
- }
- return p;
-}
-
-void VbExFree(void *ptr)
-{
- free(ptr);
-}
-
-uint64_t VbExGetTimer(void)
-{
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return (uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec;
-}
-
void VbExSleepMs(uint32_t msec)
{
}
@@ -87,22 +27,6 @@ VbError_t VbExBeep(uint32_t msec, uint32_t frequency)
return VBERROR_SUCCESS;
}
-VbError_t VbExNvStorageRead(uint8_t *buf)
-{
- return VBERROR_SUCCESS;
-}
-
-VbError_t VbExNvStorageWrite(const uint8_t *buf)
-{
- return VBERROR_SUCCESS;
-}
-
-VbError_t VbExHashFirmwareBody(VbCommonParams *cparams,
- uint32_t firmware_index)
-{
- return VBERROR_SUCCESS;
-}
-
VbError_t VbExDisplayInit(uint32_t *width, uint32_t *height)
{
return VBERROR_SUCCESS;
diff --git a/firmware/stub/vboot_api_stub_init.c b/firmware/stub/vboot_api_stub_init.c
new file mode 100644
index 00000000..76a29175
--- /dev/null
+++ b/firmware/stub/vboot_api_stub_init.c
@@ -0,0 +1,73 @@
+/* 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.
+ *
+ * Stub implementations of firmware-provided API functions.
+ */
+
+#define _STUB_IMPLEMENTATION_
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include "vboot_api.h"
+
+/* disable MSVC warnings on unused arguments */
+__pragma(warning (disable: 4100))
+
+/* U-Boot's printf uses '%L' for uint64_t. gcc uses '%l'. */
+#define MAX_FMT 255
+static char fmtbuf[MAX_FMT+1];
+
+static const char *fixfmt(const char *format)
+{
+ int i;
+ for(i=0; i<MAX_FMT && format[i]; i++) {
+ fmtbuf[i] = format[i];
+ if(format[i] == '%' && format[i+1] == 'L') {
+ fmtbuf[i+1] = 'l';
+ i++;
+ }
+ }
+ fmtbuf[i] = '\0';
+ return fmtbuf;
+}
+
+void VbExError(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ fprintf(stderr, "ERROR: ");
+ vfprintf(stderr, fixfmt(format), ap);
+ va_end(ap);
+ exit(1);
+}
+
+void VbExDebug(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ fprintf(stderr, "DEBUG: ");
+ vfprintf(stderr, fixfmt(format), ap);
+ va_end(ap);
+}
+
+uint64_t VbExGetTimer(void)
+{
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return (uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec;
+}
+
+VbError_t VbExNvStorageRead(uint8_t *buf)
+{
+ return VBERROR_SUCCESS;
+}
+
+VbError_t VbExNvStorageWrite(const uint8_t *buf)
+{
+ return VBERROR_SUCCESS;
+}
diff --git a/firmware/stub/vboot_api_stub_sf.c b/firmware/stub/vboot_api_stub_sf.c
new file mode 100644
index 00000000..41a16467
--- /dev/null
+++ b/firmware/stub/vboot_api_stub_sf.c
@@ -0,0 +1,40 @@
+/* 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.
+ *
+ * Stub implementations of firmware-provided API functions.
+ */
+
+#define _STUB_IMPLEMENTATION_
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include "vboot_api.h"
+
+/* disable MSVC warnings on unused arguments */
+__pragma(warning (disable: 4100))
+
+void *VbExMalloc(size_t size)
+{
+ void *p = malloc(size);
+ if (!p) {
+ /* Fatal Error. We must abort. */
+ abort();
+ }
+ return p;
+}
+
+void VbExFree(void *ptr)
+{
+ free(ptr);
+}
+
+VbError_t VbExHashFirmwareBody(VbCommonParams *cparams,
+ uint32_t firmware_index)
+{
+ return VBERROR_SUCCESS;
+}
diff --git a/tests/CgptManagerTests.cc b/tests/CgptManagerTests.cc
deleted file mode 100644
index 35da0d09..00000000
--- a/tests/CgptManagerTests.cc
+++ /dev/null
@@ -1,403 +0,0 @@
-// Copyright (c) 2012 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.
-
-// Unit tests for CgptManager class.
-#include <string>
-
-#include "../cgpt/CgptManager.h"
-
-// We use some specific GUID constants for some of the tests,
-// so pulling in cgpt.h. Make sure this is included after
-// CgptManager.h so that we can test the actual usage of
-// CgptManager.h as the post-install package would use.
-// Example: this would catch an incorrect usage of a GUID
-// that's defined only in cgpt.h and being accidentally
-// used in CgptManager.h (which should not have any cgpt.h
-// dependencies).
-extern "C" {
-#include "../cgpt/cgpt.h"
-}
-
-#include <base/logging.h>
-#include <gflags/gflags.h>
-#include <gtest/gtest.h>
-#include <uuid/uuid.h>
-
-using std::string;
-
-static const Guid p2guid = {{{0, 1, 2, 3, 4, {2, 2, 2, 2, 2, 2}}}};
-static const Guid p3guid = {{{0, 6, 5, 4, 2, {3, 3, 3, 3, 3, 3}}}};
-
-#define EXPECT_SUCCESS(c) EXPECT_EQ(kCgptSuccess, c)
-
-// The --v flag controls the log verbosity level.
-DEFINE_int32(v, 0, 0);
-
-// This class unit tests the CgptManager class.
-class CgptManagerUnitTest : public ::testing::Test {
-public:
- CgptManagerUnitTest() {
- // Even though the post-installer doesn't use any methods that require
- // uuid_generate, for the unit test we use those methods, so we need to
- // set the uuid_generator.
- uuid_generator = uuid_generate;
- }
-
- void SetUp() {
- const string device_name = "/tmp/DummyFileForCgptManagerTests.bin";
-
- CreateDummyDevice(device_name);
-
- LOG(INFO) << "Initializing cgpt with " << device_name;
- EXPECT_SUCCESS(cgpt_manager.Initialize(device_name));
- EXPECT_SUCCESS(cgpt_manager.ClearAll());
-
- CheckPartitionCount(0);
- }
-
- virtual ~CgptManagerUnitTest() { }
-
-protected:
- CgptManager cgpt_manager;
-
- void CreateDummyDevice(const string& dummy_device) {
- FILE* fp = fopen(dummy_device.c_str(), "w");
-
- ASSERT_TRUE(fp != NULL);
-
- const int kNumSectors = 1000;
- const int kSectorSize = 512;
- const char kFillChar = '7'; // Some character, value doesn't matter.
-
- for(int i = 0; i < kNumSectors * kSectorSize; i++) {
- EXPECT_EQ(kFillChar, fputc(kFillChar, fp));
- }
-
- fclose(fp);
- }
-
- void CheckEquality(string field,
- uint64_t expected,
- uint64_t actual) {
-
-
- VLOG(1) << field << ":"
- << "Expected = " << expected
- << ";Actual = " << actual;
-
- EXPECT_EQ(expected, actual);
- }
-
-
- void CheckGuidEquality(string field,
- const Guid& expected_id,
- const Guid& actual_id) {
- char expected_id_str[GUID_STRLEN];
- GuidToStr(&expected_id, expected_id_str, sizeof(expected_id_str));
-
- char actual_id_str[GUID_STRLEN];
- GuidToStr(&actual_id, actual_id_str, sizeof(actual_id_str));
-
- VLOG(1) << field << ":"
- << "Expected = " << expected_id_str
- << ";Actual = " << actual_id_str;
-
- EXPECT_TRUE(GuidEqual(&expected_id, &actual_id));
- }
-
- // Checks if the current number of partitions in the device matches
- // the value of expected_num_partitions.
- void CheckPartitionCount(uint8 expected_num_partitions) {
- uint8_t actual_num_partitions;
- EXPECT_SUCCESS(cgpt_manager.GetNumNonEmptyPartitions(
- &actual_num_partitions));
-
- CheckEquality("NumPartitions",
- expected_num_partitions,
- actual_num_partitions);
- }
-
- void SetAndCheckSuccessfulBit(uint32_t partition_number,
- bool expected_is_successful) {
- EXPECT_SUCCESS(cgpt_manager.SetSuccessful(partition_number,
- expected_is_successful));
-
- bool actual_is_successful;
- EXPECT_SUCCESS(cgpt_manager.GetSuccessful(partition_number,
- &actual_is_successful));
- EXPECT_EQ(expected_is_successful, actual_is_successful);
- }
-
-
- void SetAndCheckNumTriesLeft(uint32_t partition_number,
- int expected_num_tries) {
- EXPECT_SUCCESS(cgpt_manager.SetNumTriesLeft(partition_number,
- expected_num_tries));
-
- int actual_num_tries;
- EXPECT_SUCCESS(cgpt_manager.GetNumTriesLeft(partition_number,
- &actual_num_tries));
- CheckEquality("NumTries", expected_num_tries, actual_num_tries);
- }
-
- void SetAndCheckPriority(uint32_t partition_number,
- uint8_t expected_priority) {
- EXPECT_SUCCESS(cgpt_manager.SetPriority(partition_number,
- expected_priority));
-
- uint8_t actual_priority;
- EXPECT_SUCCESS(cgpt_manager.GetPriority(partition_number,
- &actual_priority));
- CheckEquality("Priority", expected_priority, actual_priority);
- }
-
- void CheckPriority(uint32_t partition_number,
- uint8_t expected_priority) {
- uint8_t actual_priority;
- EXPECT_SUCCESS(cgpt_manager.GetPriority(partition_number,
- &actual_priority));
- CheckEquality("Priority", expected_priority, actual_priority);
- }
-
-
- void CheckBeginningOffset(uint32_t partition_number,
- uint64_t expected_offset) {
- uint64_t actual_offset;
- EXPECT_SUCCESS(cgpt_manager.GetBeginningOffset(partition_number,
- &actual_offset));
- CheckEquality("Beginning Offset", expected_offset, actual_offset);
- }
-
-
- void CheckNumSectors(uint32_t partition_number,
- uint64_t expected_num_sectors) {
- uint64_t actual_num_sectors;
- EXPECT_SUCCESS(cgpt_manager.GetNumSectors(partition_number,
- &actual_num_sectors));
- CheckEquality("Num Sectors", expected_num_sectors, actual_num_sectors);
- }
-
-
- void CheckPartitionTypeId(int partition_number,
- const Guid& expected_partition_type_id) {
- // Get the partition type id and check if it matches the expected value.
- Guid actual_partition_type_id;
- EXPECT_SUCCESS(cgpt_manager.GetPartitionTypeId(partition_number,
- &actual_partition_type_id));
-
- CheckGuidEquality("PartitionTypeId",
- expected_partition_type_id,
- actual_partition_type_id);
- }
-
- void CheckPartitionUniqueId(int partition_number,
- const Guid& expected_partition_unique_id) {
- // Get the partition unique id and check if it matches the expected value.
- Guid actual_partition_unique_id;
- EXPECT_SUCCESS(cgpt_manager.GetPartitionUniqueId(
- partition_number,
- &actual_partition_unique_id));
-
- CheckGuidEquality("PartitionUniqueId",
- expected_partition_unique_id,
- actual_partition_unique_id);
- }
-
- void CheckPartitionNumberByUniqueId(const Guid& unique_id,
- uint32_t expected_partition_number) {
- // Get the partition number for the unique id and check
- // if it matches the expected value.
- uint32_t actual_partition_number;
- EXPECT_SUCCESS(cgpt_manager.GetPartitionNumberByUniqueId(
- unique_id,
- &actual_partition_number));
-
- CheckEquality("PartitionNumberForUniqueId",
- expected_partition_number,
- actual_partition_number);
- }
-
-
- void CreateBootFile(const string& boot_file_name) {
- FILE* fp = fopen(boot_file_name.c_str(), "w");
-
- ASSERT_TRUE(fp != NULL);
-
- const int kNumSectors = 1;
- const int kSectorSize = 512;
- const char kFillChar = '8'; // Some character, value doesn't matter.
-
- for(int i = 0; i < kNumSectors * kSectorSize; i++) {
- EXPECT_EQ(kFillChar, fputc(kFillChar, fp));
- }
-
- fclose(fp);
- }
-
-private:
- DISALLOW_COPY_AND_ASSIGN(CgptManagerUnitTest);
-};
-
-TEST_F(CgptManagerUnitTest, AutoPrioritizationTest) {
- EXPECT_SUCCESS(cgpt_manager.AddPartition("k1",
- guid_chromeos_kernel,
- guid_unused,
- 100,
- 10));
- CheckPartitionCount(1);
-
- EXPECT_SUCCESS(cgpt_manager.AddPartition("k2",
- guid_chromeos_kernel,
- p2guid,
- 200,
- 20));
- CheckPartitionCount(2);
-
- EXPECT_SUCCESS(cgpt_manager.AddPartition("k3",
- guid_chromeos_kernel,
- p3guid,
- 300,
- 30));
- CheckPartitionCount(3);
-
- uint8_t expectedk1Priority = 1;
- uint8_t expectedk2Priority = 2;
- uint8_t expectedk3Priority = 0;
-
- // Calling SetAndCheckPriority will do a set and get of the above priorities.
- SetAndCheckPriority(1, expectedk1Priority);
- SetAndCheckPriority(2, expectedk2Priority);
- SetAndCheckPriority(3, expectedk3Priority);
-
- EXPECT_SUCCESS(cgpt_manager.SetHighestPriority(1));
-
- expectedk1Priority = 2;
- expectedk2Priority = 1;
-
- CheckPriority(1, expectedk1Priority);
- CheckPriority(2, expectedk2Priority);
- CheckPriority(3, expectedk3Priority);
-}
-
-
-TEST_F(CgptManagerUnitTest, AddPartitionTest) {
- int p2_offset = 200;
- int p2_size = 20;
- int p3_offset = 300;
- int p3_size = 30;
-
- VLOG(1) << "Adding various types of partitions ... ";
- EXPECT_SUCCESS(cgpt_manager.AddPartition("data stuff",
- guid_linux_data,
- guid_unused,
- 100,
- 10));
- CheckPartitionCount(1);
-
- EXPECT_SUCCESS(cgpt_manager.AddPartition("kernel stuff",
- guid_chromeos_kernel,
- p2guid,
- p2_offset,
- p2_size));
- CheckPartitionCount(2);
-
- EXPECT_SUCCESS(cgpt_manager.AddPartition("rootfs stuff",
- guid_chromeos_rootfs,
- p3guid,
- p3_offset,
- p3_size));
- CheckPartitionCount(3);
-
- uint32_t pmbr_boot_partition_number = 4;
- EXPECT_SUCCESS(cgpt_manager.AddPartition("ESP stuff",
- guid_efi,
- guid_unused,
- 400,
- 40));
- CheckPartitionCount(4);
-
- EXPECT_SUCCESS(cgpt_manager.AddPartition("fture stuff",
- guid_chromeos_reserved,
- guid_unused,
- 500,
- 50));
- CheckPartitionCount(5);
-
- Guid guid_random = {{{0x2364a860, 0xbf63, 0x42fb, 0xa8, 0x3d,
- {0x9a, 0xd3, 0xe0, 0x57, 0xfc, 0xf5}}}};
-
- EXPECT_SUCCESS(cgpt_manager.AddPartition("random stuff",
- guid_random,
- guid_unused,
- 600,
- 60));
-
- CheckPartitionCount(6);
-
- string boot_file_name = "/tmp/BootFileForCgptManagerTests.bin";
- LOG(INFO) << "Adding EFI partition to PMBR with bootfile: "
- << boot_file_name;
-
- CreateBootFile(boot_file_name);
- EXPECT_SUCCESS(cgpt_manager.SetPmbr(pmbr_boot_partition_number,
- boot_file_name,
- true));
-
- VLOG(1) << "Checking if contents of GPT match values set in AddPartition.";
-
- uint32_t actual_boot_partition_number;
- EXPECT_SUCCESS(cgpt_manager.GetPmbrBootPartitionNumber(
- &actual_boot_partition_number));
- EXPECT_EQ(pmbr_boot_partition_number, actual_boot_partition_number);
-
- // Set the successful attribute for some partition to various Values
- // and check if the settings are preserved.
- SetAndCheckSuccessfulBit(2, true);
- SetAndCheckSuccessfulBit(2, false);
-
- // Set the number of tries for some partition to various Values
- // and check if the settings are preserved.
- SetAndCheckNumTriesLeft(2, 6);
- SetAndCheckNumTriesLeft(2, 5);
-
- // Set the priority for some partition to various Values
- // and check if the settings are preserved.
- SetAndCheckPriority(2, 2);
- SetAndCheckPriority(2, 0);
-
- // Check if the beginning offset for some of the partitions
- // are the same as what was set in AddPartition.
- CheckBeginningOffset(2, p2_offset);
- CheckBeginningOffset(3, p3_offset);
-
- // Check if the number of sectors for some of the partitions
- // are same as what was set in AddPartition.
- CheckNumSectors(2, p2_size);
- CheckNumSectors(3, p3_size);
-
- // Check if the partition type IDs for some of the partitions
- // are same as what was set in AddPartition.
- CheckPartitionTypeId(2, guid_chromeos_kernel);
- CheckPartitionTypeId(4, guid_efi);
-
- // Check if the partition unique IDs for some of the partitions
- // same as what was set in AddPartition.
- CheckPartitionUniqueId(2, p2guid);
- CheckPartitionUniqueId(3, p3guid);
-
- // Check if the partition numbers for some of the partitions are
- // retrievable by their unique IDs set in AddPartition.
- CheckPartitionNumberByUniqueId(p2guid, 2);
- CheckPartitionNumberByUniqueId(p3guid, 3);
-}
-
-int main(int argc, char **argv) {
- google::ParseCommandLineFlags(&argc, &argv, true);
- ::testing::InitGoogleTest(&argc, argv);
-
- // VLOG(2) logs at level -2. So if user gives --v=2, we should
- // set MinLogLevel to -2, so VLOG(2) and VLOG(1) will show up.
- logging::SetMinLogLevel(-FLAGS_v);
- return RUN_ALL_TESTS();
-}
diff --git a/utility/mount-encrypted.c b/utility/mount-encrypted.c
deleted file mode 100644
index 9dbedc2a..00000000
--- a/utility/mount-encrypted.c
+++ /dev/null
@@ -1,1349 +0,0 @@
-/* Copyright (c) 2012 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 tool will attempt to mount or create the encrypted stateful partition,
- * and the various bind mountable subdirectories.
- *
- */
-#define _GNU_SOURCE
-#define _FILE_OFFSET_BITS 64
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <grp.h>
-#include <pwd.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/statvfs.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/mount.h>
-#include <linux/fs.h>
-
-#include <glib.h>
-
-#include <openssl/rand.h>
-
-#define CHROMEOS_ENVIRONMENT
-#include "tlcl.h"
-#include "crossystem.h"
-
-#include "mount-encrypted.h"
-#include "mount-helpers.h"
-
-#define STATEFUL_MNT "mnt/stateful_partition"
-#define ENCRYPTED_MNT STATEFUL_MNT "/encrypted"
-#define BUF_SIZE 1024
-#define PROP_SIZE 64
-#define LOCKBOX_SIZE_MAX 0x45
-
-static const gchar * const kKernelCmdline = "/proc/cmdline";
-static const gchar * const kKernelCmdlineOption = " encrypted-stateful-key=";
-static const gchar * const kEncryptedFSType = "ext4";
-static const gchar * const kCryptDevName = "encstateful";
-static const gchar * const kTpmDev = "/dev/tpm0";
-static const gchar * const kNullDev = "/dev/null";
-static const gchar * const kNvramExport = "/tmp/lockbox.nvram";
-static const float kSizePercent = 0.3;
-static const float kMigrationSizeMultiplier = 1.1;
-static const uint32_t kLockboxIndex = 0x20000004;
-static const uint32_t kLockboxSizeV1 = 0x2c;
-static const uint32_t kLockboxSizeV2 = LOCKBOX_SIZE_MAX;
-static const uint32_t kLockboxSaltOffset = 0x5;
-static const uint64_t kSectorSize = 512;
-static const uint64_t kExt4BlockSize = 4096;
-static const uint64_t kExt4MinBytes = 16 * 1024 * 1024;
-static const char * const kStaticKeyDefault = "default unsafe static key";
-static const char * const kStaticKeyFactory = "factory unsafe static key";
-static const char * const kStaticKeyFinalizationNeeded = "needs finalization";
-static const int kModeProduction = 0;
-static const int kModeFactory = 1;
-static const int kCryptAllowDiscard = 1;
-
-enum migration_method {
- MIGRATE_TEST_ONLY,
- MIGRATE_FOR_REAL,
-};
-
-enum bind_dir {
- BIND_SOURCE,
- BIND_DEST,
-};
-
-static struct bind_mount {
- char * src; /* Location of bind source. */
- char * dst; /* Destination of bind. */
- char * previous; /* Migratable prior bind source. */
- char * pending; /* Location for pending deletion. */
- char * owner;
- char * group;
- mode_t mode;
- int submount; /* Submount is bound already. */
-} bind_mounts_default[] = {
- { ENCRYPTED_MNT "/var", "var",
- STATEFUL_MNT "/var", STATEFUL_MNT "/.var",
- "root", "root",
- S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH, 0 },
- { ENCRYPTED_MNT "/chronos", "home/chronos",
- STATEFUL_MNT "/home/chronos", STATEFUL_MNT "/home/.chronos",
- "chronos", "chronos",
- S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH, 1 },
- { },
-};
-
-#if DEBUG_ENABLED
-struct timeval tick = { };
-struct timeval tick_start = { };
-#endif
-
-static struct bind_mount *bind_mounts = NULL;
-static gchar *rootdir = NULL;
-static gchar *stateful_mount = NULL;
-static gchar *key_path = NULL;
-static gchar *needs_finalization_path = NULL;
-static gchar *block_path = NULL;
-static gchar *encrypted_mount = NULL;
-static gchar *dmcrypt_name = NULL;
-static gchar *dmcrypt_dev = NULL;
-static int has_tpm = 0;
-static int tpm_init_called = 0;
-static uint8_t nvram_data[LOCKBOX_SIZE_MAX];
-static uint32_t nvram_size = 0;
-
-static void tpm_init(void)
-{
- uint32_t result;
-
- if (tpm_init_called)
- return;
-
- DEBUG("Opening TPM");
-
- setenv("TPM_NO_EXIT", "1", 1);
- result = TlclLibInit();
-
- tpm_init_called = 1;
- has_tpm = (result == TPM_SUCCESS);
- INFO("TPM %s", has_tpm ? "ready" : "not available");
-}
-
-/* Returns TPM result status code, and on TPM_SUCCESS, stores ownership
- * flag to "owned".
- */
-static uint32_t tpm_owned(uint8_t *owned)
-{
- uint32_t result;
-
- tpm_init();
- DEBUG("Reading TPM Ownership Flag");
- if (!has_tpm)
- result = TPM_E_NO_DEVICE;
- else
- result = TlclGetOwnership(owned);
- DEBUG("TPM Ownership Flag returned: %s", result ? "FAIL" : "ok");
-
- return result;
-}
-
-static void tpm_close(void)
-{
- if (!has_tpm || !tpm_init_called)
- return;
- TlclLibClose();
- tpm_init_called = 0;
-}
-
-static void sha256(char *string, uint8_t *digest)
-{
- SHA256((unsigned char *)string, strlen(string), digest);
-}
-
-/* Extract the desired system key from the kernel's boot command line. */
-static int get_key_from_cmdline(uint8_t *digest)
-{
- int result = 0;
- gchar *buffer;
- gsize length;
- char *cmdline, *option_end;
- /* Option name without the leading space. */
- const gchar *option = kKernelCmdlineOption + 1;
-
- if (!g_file_get_contents(kKernelCmdline, &buffer, &length, NULL)) {
- PERROR(kKernelCmdline);
- return 0;
- }
-
- /* Find a string match either at start of string or following
- * a space.
- */
- cmdline = buffer;
- if (strncmp(cmdline, option, strlen(option)) == 0 ||
- (cmdline = strstr(cmdline, kKernelCmdlineOption))) {
- /* The "=" exists because it is in kKernelCmdlineOption. */
- cmdline = strstr(cmdline, "=");
- /* strchrnul() cannot return NULL. */
- option_end = strchrnul(cmdline, ' ');
- *option_end = '\0';
- sha256(cmdline, digest);
- debug_dump_hex("system key", digest, DIGEST_LENGTH);
- result = 1;
- }
-
- g_free(buffer);
- return result;
-}
-
-static int get_system_property(const char *prop, char *buf, size_t length)
-{
- const char *rc;
-
- DEBUG("Fetching System Property '%s'", prop);
- rc = VbGetSystemPropertyString(prop, buf, length);
- DEBUG("Got System Property 'mainfw_type': %s", rc ? buf : "FAIL");
-
- return rc != NULL;
-}
-
-static int has_chromefw(void)
-{
- static int state = -1;
- char fw[PROP_SIZE];
-
- /* Cache the state so we don't have to perform the query again. */
- if (state != -1)
- return state;
-
- if (!get_system_property("mainfw_type", fw, sizeof(fw)))
- state = 0;
- else
- state = strcmp(fw, "nonchrome") != 0;
- return state;
-}
-
-static int is_cr48(void)
-{
- static int state = -1;
- char hwid[PROP_SIZE];
-
- /* Cache the state so we don't have to perform the query again. */
- if (state != -1)
- return state;
-
- if (!get_system_property("hwid", hwid, sizeof(hwid)))
- state = 0;
- else
- state = strstr(hwid, "MARIO") != NULL;
- return state;
-}
-
-static uint32_t
-_read_nvram(uint8_t *buffer, size_t len, uint32_t index, uint32_t size)
-{
- uint32_t result;
-
- if (size > len) {
- ERROR("NVRAM size (0x%x > 0x%zx) is too big", size, len);
- return 0;
- }
-
- tpm_init();
- DEBUG("Reading NVRAM area 0x%x (size %u)", index, size);
- if (!has_tpm)
- result = TPM_E_NO_DEVICE;
- else
- result = TlclRead(index, buffer, size);
- DEBUG("NVRAM read returned: %s", result == TPM_SUCCESS ? "ok"
- : "FAIL");
-
- return result;
-}
-
-/*
- * TPM cases:
- * - does not exist at all (disabled in test firmware or non-chrome device).
- * - exists (below).
- *
- * TPM ownership cases:
- * - unowned (OOBE):
- * - expect modern lockbox (no migration allowed).
- * - owned: depends on NVRAM area (below).
- *
- * NVRAM area cases:
- * - no NVRAM area at all:
- * - interrupted install (cryptohome has the TPM password)
- * - ancient device (cr48, cryptohome has thrown away TPM password)
- * - broken device (cryptohome has thrown away/never had TPM password)
- * - must expect worst-case: no lockbox ever, and migration allowed.
- * - defined NVRAM area, but not written to ("Finalized"); interrupted OOBE:
- * - if legacy size, allow migration.
- * - if not, disallow migration.
- * - written ("Finalized") NVRAM area:
- * - if legacy size, allow migration.
- * - if not, disallow migration.
- *
- * When returning 1: (NVRAM area found and used)
- * - *digest populated with NVRAM area entropy.
- * - *migrate is 1 for NVRAM v1, 0 for NVRAM v2.
- * When returning 0: (NVRAM missing or error)
- * - *digest untouched.
- * - *migrate always 1
- */
-static int get_nvram_key(uint8_t *digest, int *migrate)
-{
- uint8_t owned = 0;
- uint8_t value[kLockboxSizeV2], bytes_anded, bytes_ored;
- uint32_t size, result, i;
- uint8_t *rand_bytes;
- uint32_t rand_size;
-
- /* Default to allowing migration (disallow when owned with NVRAMv2). */
- *migrate = 1;
-
- /* Ignore unowned TPM's NVRAM area. */
- result = tpm_owned(&owned);
- if (result != TPM_SUCCESS) {
- INFO("Could not read TPM Permanent Flags: error 0x%02x.",
- result);
- return 0;
- }
- if (!owned) {
- INFO("TPM not Owned, ignoring NVRAM area.");
- return 0;
- }
-
- /* Reading the NVRAM takes 40ms. Instead of querying the NVRAM area
- * for its size (which takes time), just read the expected size. If
- * it fails, then fall back to the older size. This means cleared
- * devices take 80ms (2 failed reads), legacy devices take 80ms
- * (1 failed read, 1 good read), and populated devices take 40ms,
- * which is the minimum possible time (instead of 40ms + time to
- * query NVRAM size).
- */
- size = kLockboxSizeV2;
- result = _read_nvram(value, sizeof(value), kLockboxIndex, size);
- if (result != TPM_SUCCESS) {
- size = kLockboxSizeV1;
- result = _read_nvram(value, sizeof(value), kLockboxIndex, size);
- if (result != TPM_SUCCESS) {
- /* No NVRAM area at all. */
- INFO("No NVRAM area defined: error 0x%02x", result);
- return 0;
- }
- /* Legacy NVRAM area. */
- INFO("Version 1 NVRAM area found.");
- } else {
- *migrate = 0;
- INFO("Version 2 NVRAM area found.");
- }
-
- debug_dump_hex("nvram", value, size);
-
- /* Ignore defined but unwritten NVRAM area. */
- bytes_ored = 0x0;
- bytes_anded = 0xff;
- for (i = 0; i < size; ++i) {
- bytes_ored |= value[i];
- bytes_anded &= value[i];
- }
- if (bytes_ored == 0x0 || bytes_anded == 0xff) {
- INFO("NVRAM area has been defined but not written.");
- return 0;
- }
-
- /* "Export" nvram data for use after the helper. */
- if (size <= sizeof(nvram_data)) {
- nvram_size = size;
- memcpy(nvram_data, value, size);
- }
-
- /* Choose random bytes to use based on NVRAM version. */
- if (*migrate) {
- rand_bytes = value;
- rand_size = size;
- } else {
- rand_bytes = value + kLockboxSaltOffset;
- if (kLockboxSaltOffset + DIGEST_LENGTH > size) {
- INFO("Impossibly small NVRAM area size (%d).", size);
- return 0;
- }
- rand_size = DIGEST_LENGTH;
- }
- if (rand_size < DIGEST_LENGTH) {
- INFO("Impossibly small rand_size (%d).", rand_size);
- return 0;
- }
- debug_dump_hex("rand_bytes", rand_bytes, rand_size);
-
- SHA256(rand_bytes, rand_size, digest);
- debug_dump_hex("system key", digest, DIGEST_LENGTH);
-
- return 1;
-}
-
-/* Find the system key used for decrypting the stored encryption key.
- * ChromeOS devices are required to use the NVRAM area, all the rest will
- * fallback through various places (kernel command line, BIOS UUID, and
- * finally a static value) for a system key.
- */
-static int find_system_key(int mode, uint8_t *digest, int *migration_allowed)
-{
- gchar *key;
- gsize length;
-
- /* By default, do not allow migration. */
- *migration_allowed = 0;
-
- /* Factory mode uses a static system key. */
- if (mode == kModeFactory) {
- INFO("Using factory insecure system key.");
- sha256((char *)kStaticKeyFactory, digest);
- debug_dump_hex("system key", digest, DIGEST_LENGTH);
- return 1;
- }
-
- /* Force ChromeOS devices into requiring the system key come from
- * NVRAM.
- */
- if (has_chromefw()) {
- int rc;
- rc = get_nvram_key(digest, migration_allowed);
-
- if (rc) {
- INFO("Using NVRAM as system key; already populated%s.",
- *migration_allowed ? " (legacy)" : "");
- } else {
- INFO("Using NVRAM as system key; finalization needed.");
- }
- return rc;
- }
-
- if (get_key_from_cmdline(digest)) {
- INFO("Using kernel command line argument as system key.");
- return 1;
- }
- if (g_file_get_contents("/sys/class/dmi/id/product_uuid",
- &key, &length, NULL)) {
- sha256(key, digest);
- debug_dump_hex("system key", digest, DIGEST_LENGTH);
- g_free(key);
- INFO("Using UUID as system key.");
- return 1;
- }
-
- INFO("Using default insecure system key.");
- sha256((char *)kStaticKeyDefault, digest);
- debug_dump_hex("system key", digest, DIGEST_LENGTH);
- return 1;
-}
-
-/* Returns 1 on success, 0 on failure. */
-static int get_random_bytes_tpm(unsigned char *buffer, int wanted)
-{
- uint32_t remaining = wanted;
-
- tpm_init();
- /* Read random bytes from TPM, which can return short reads. */
- while (remaining) {
- uint32_t result, size;
-
- result = TlclGetRandom(buffer + (wanted - remaining),
- remaining, &size);
- if (result != TPM_SUCCESS || size > remaining) {
- ERROR("TPM GetRandom failed: error 0x%02x.", result);
- return 0;
- }
- remaining -= size;
- }
-
- return 1;
-}
-
-/* Returns 1 on success, 0 on failure. */
-static int get_random_bytes(unsigned char *buffer, int wanted)
-{
- if (has_tpm && get_random_bytes_tpm(buffer, wanted))
- return 1;
-
- if (RAND_bytes(buffer, wanted))
- return 1;
- SSL_ERROR("RAND_bytes");
-
- return 0;
-}
-
-static char *choose_encryption_key(void)
-{
- unsigned char rand_bytes[DIGEST_LENGTH];
- unsigned char digest[DIGEST_LENGTH];
-
- if (!get_random_bytes(rand_bytes, sizeof(rand_bytes)))
- ERROR("No entropy source found -- using uninitialized stack");
-
- SHA256(rand_bytes, DIGEST_LENGTH, digest);
- debug_dump_hex("encryption key", digest, DIGEST_LENGTH);
-
- return stringify_hex(digest, DIGEST_LENGTH);
-}
-
-static int check_bind(struct bind_mount *bind, enum bind_dir dir)
-{
- struct passwd *user;
- struct group *group;
- const gchar *target;
-
- if (dir == BIND_SOURCE)
- target = bind->src;
- else
- target = bind->dst;
-
- if (access(target, R_OK) && mkdir(target, bind->mode)) {
- PERROR("mkdir(%s)", target);
- return -1;
- }
-
- /* Destination may be on read-only filesystem, so skip tweaks. */
- if (dir == BIND_DEST)
- return 0;
-
- if (!(user = getpwnam(bind->owner))) {
- PERROR("getpwnam(%s)", bind->owner);
- return -1;
- }
- if (!(group = getgrnam(bind->group))) {
- PERROR("getgrnam(%s)", bind->group);
- return -1;
- }
-
- /* Must do explicit chmod since mkdir()'s mode respects umask. */
- if (chmod(target, bind->mode)) {
- PERROR("chmod(%s)", target);
- return -1;
- }
- if (chown(target, user->pw_uid, group->gr_gid)) {
- PERROR("chown(%s)", target);
- return -1;
- }
-
- return 0;
-}
-
-static int migrate_contents(struct bind_mount *bind,
- enum migration_method method)
-{
- const gchar *previous = NULL;
- const gchar *pending = NULL;
- gchar *dotdir;
-
- /* Skip migration if the previous bind sources are missing. */
- if (bind->pending && access(bind->pending, R_OK) == 0)
- pending = bind->pending;
- if (bind->previous && access(bind->previous, R_OK) == 0)
- previous = bind->previous;
- if (!pending && !previous)
- return 0;
-
- /* Pretend migration happened. */
- if (method == MIGRATE_TEST_ONLY)
- return 1;
-
- check_bind(bind, BIND_SOURCE);
-
- /* Prefer the pending-delete location when doing migration. */
- if (!(dotdir = g_strdup_printf("%s/.", pending ? pending : previous))) {
- PERROR("g_strdup_printf");
- goto mark_for_removal;
- }
-
- INFO("Migrating bind mount contents %s to %s.", dotdir, bind->src);
- const gchar *cp[] = {
- "/bin/cp", "-a",
- dotdir,
- bind->src,
- NULL
- };
-
- if (runcmd(cp, NULL) != 0) {
- /* If the copy failed, it may have partially populated the
- * new source, so we need to remove the new source and
- * rebuild it. Regardless, the previous source must be removed
- * as well.
- */
- INFO("Failed to migrate %s to %s!", dotdir, bind->src);
- remove_tree(bind->src);
- check_bind(bind, BIND_SOURCE);
- }
-
-mark_for_removal:
- g_free(dotdir);
-
- /* The removal of the previous directory needs to happen at finalize
- * time, otherwise /var state gets lost on a migration if the
- * system is powered off before the encryption key is saved. Instead,
- * relocate the directory so it can be removed (or re-migrated).
- */
-
- if (previous) {
- /* If both pending and previous directory exists, we must
- * remove previous entirely now so it stops taking up disk
- * space. The pending area will stay pending to be deleted
- * later.
- */
- if (pending)
- remove_tree(pending);
- if (rename(previous, bind->pending)) {
- PERROR("rename(%s,%s)", previous, bind->pending);
- }
- }
-
- /* As noted above, failures are unrecoverable, so getting here means
- * "we're done" more than "it worked".
- */
- return 1;
-}
-
-static void finalized(void)
-{
- /* TODO(keescook): once ext4 supports secure delete, just unlink. */
- if (access(needs_finalization_path, R_OK) == 0) {
- /* This is nearly useless on SSDs. */
- shred(needs_finalization_path);
- unlink(needs_finalization_path);
- }
-}
-
-static void finalize(uint8_t *system_key, char *encryption_key)
-{
- struct bind_mount *bind;
-
- INFO("Writing keyfile %s.", key_path);
- if (!keyfile_write(key_path, system_key, encryption_key)) {
- ERROR("Failed to write %s -- aborting.", key_path);
- return;
- }
-
- finalized();
-
- for (bind = bind_mounts; bind->src; ++ bind) {
- if (!bind->pending || access(bind->pending, R_OK))
- continue;
- INFO("Removing %s.", bind->pending);
-#if DEBUG_ENABLED
- continue;
-#endif
- remove_tree(bind->pending);
- }
-}
-
-static void needs_finalization(char *encryption_key)
-{
- uint8_t useless_key[DIGEST_LENGTH];
- sha256((char *)kStaticKeyFinalizationNeeded, useless_key);
-
- INFO("Writing finalization intent %s.", needs_finalization_path);
- if (!keyfile_write(needs_finalization_path, useless_key,
- encryption_key)) {
- ERROR("Failed to write %s -- aborting.",
- needs_finalization_path);
- return;
- }
-}
-
-/* This triggers the live encryption key to be written to disk, encrypted
- * by the system key. It is intended to be called by Cryptohome once the
- * TPM is done being set up. If the system key is passed as an argument,
- * use it, otherwise attempt to query the TPM again.
- */
-static int finalize_from_cmdline(char *key)
-{
- uint8_t system_key[DIGEST_LENGTH];
- char *encryption_key;
- int migrate;
-
- /* Early sanity-check to see if the encrypted device exists,
- * instead of failing at the end of this function.
- */
- if (access(dmcrypt_dev, R_OK)) {
- ERROR("'%s' does not exist, giving up.", dmcrypt_dev);
- return EXIT_FAILURE;
- }
-
- if (key) {
- if (strlen(key) != 2 * DIGEST_LENGTH) {
- ERROR("Invalid key length.");
- return EXIT_FAILURE;
- }
-
- if (!hexify_string(key, system_key, DIGEST_LENGTH)) {
- ERROR("Failed to convert hex string to byte array");
- return EXIT_FAILURE;
- }
- } else {
- /* Factory mode will never call finalize from the command
- * line, so force Production mode here.
- */
- if (!find_system_key(kModeProduction, system_key, &migrate)) {
- ERROR("Could not locate system key.");
- return EXIT_FAILURE;
- }
- }
-
- encryption_key = dm_get_key(dmcrypt_dev);
- if (!encryption_key) {
- ERROR("Could not locate encryption key for %s.", dmcrypt_dev);
- return EXIT_FAILURE;
- }
-
- finalize(system_key, encryption_key);
-
- return EXIT_SUCCESS;
-}
-
-static void spawn_resizer(const char *device, uint64_t blocks,
- uint64_t blocks_max)
-{
- pid_t pid;
-
- /* Skip resize before forking, if it's not going to happen. */
- if (blocks >= blocks_max) {
- INFO("Resizing skipped. blocks:%" PRIu64 " >= blocks_max:%" PRIu64,
- blocks, blocks_max);
- return;
- }
-
- fflush(NULL);
- pid = fork();
- if (pid < 0) {
- PERROR("fork");
- return;
- }
- if (pid != 0) {
- INFO("Started filesystem resizing process %d.", pid);
- return;
- }
-
- /* Child */
- tpm_close();
- INFO_INIT("Resizer spawned.");
-
- if (daemon(0, 1)) {
- PERROR("daemon");
- goto out;
- }
-
- filesystem_resize(device, blocks, blocks_max);
-
-out:
- INFO_DONE("Done.");
- exit(0);
-}
-
-/* Do all the work needed to actually set up the encrypted partition.
- * Takes "mode" argument to help determine where the system key should
- * come from.
- */
-static int setup_encrypted(int mode)
-{
- int has_system_key;
- uint8_t system_key[DIGEST_LENGTH];
- char *encryption_key = NULL;
- int migrate_allowed = 0, migrate_needed = 0, rebuild = 0;
- gchar *lodev = NULL;
- uint64_t sectors;
- struct bind_mount *bind;
- int sparsefd;
- struct statvfs stateful_statbuf;
- uint64_t blocks_min, blocks_max;
- int valid_keyfile = 0;
-
- /* Use the "system key" to decrypt the "encryption key" stored in
- * the stateful partition.
- */
- has_system_key = find_system_key(mode, system_key, &migrate_allowed);
- if (has_system_key) {
- encryption_key = keyfile_read(key_path, system_key);
- } else {
- INFO("No usable system key found.");
- }
-
- if (encryption_key) {
- /* If we found a stored encryption key, we've already
- * finished a complete login and Cryptohome Finalize
- * so migration is finished.
- */
- migrate_allowed = 0;
- valid_keyfile = 1;
- } else {
- uint8_t useless_key[DIGEST_LENGTH];
- sha256((char *)kStaticKeyFinalizationNeeded, useless_key);
- encryption_key = keyfile_read(needs_finalization_path,
- useless_key);
- if (!encryption_key) {
- /* This is a brand new system with no keys. */
- INFO("Generating new encryption key.");
- encryption_key = choose_encryption_key();
- if (!encryption_key)
- return 0;
- rebuild = 1;
- } else {
- ERROR("Finalization unfinished! " \
- "Encryption key still on disk!");
- }
- }
-
- if (rebuild) {
- uint64_t fs_bytes_max;
-
- /* Wipe out the old files, and ignore errors. */
- unlink(key_path);
- unlink(block_path);
-
- /* Calculate the desired size of the new partition. */
- if (statvfs(stateful_mount, &stateful_statbuf)) {
- PERROR(stateful_mount);
- return 0;
- }
- fs_bytes_max = stateful_statbuf.f_blocks;
- fs_bytes_max *= kSizePercent;
- fs_bytes_max *= stateful_statbuf.f_frsize;
-
- INFO("Creating sparse backing file with size %" PRIu64 ".",
- fs_bytes_max);
-
- /* Create the sparse file. */
- sparsefd = sparse_create(block_path, fs_bytes_max);
- if (sparsefd < 0) {
- PERROR(block_path);
- return 0;
- }
- } else {
- sparsefd = open(block_path, O_RDWR | O_NOFOLLOW);
- if (sparsefd < 0) {
- PERROR(block_path);
- return 0;
- }
- }
-
- /* Set up loopback device. */
- INFO("Loopback attaching %s (named %s).", block_path, dmcrypt_name);
- lodev = loop_attach(sparsefd, dmcrypt_name);
- if (!lodev || strlen(lodev) == 0) {
- ERROR("loop_attach failed");
- goto failed;
- }
-
- /* Get size as seen by block device. */
- sectors = blk_size(lodev) / kSectorSize;
- if (!sectors) {
- ERROR("Failed to read device size");
- goto lo_cleanup;
- }
-
- /* Mount loopback device with dm-crypt using the encryption key. */
- INFO("Setting up dm-crypt %s as %s.", lodev, dmcrypt_dev);
- if (!dm_setup(sectors, encryption_key, dmcrypt_name, lodev,
- dmcrypt_dev, kCryptAllowDiscard)) {
- /* If dm_setup() fails, it could be due to lacking
- * "allow_discard" support, so try again with discard
- * disabled. There doesn't seem to be a way to query
- * the kernel for this feature short of a fallible
- * version test or just trying to set up the dm table
- * again, so do the latter.
- */
- if (!dm_setup(sectors, encryption_key, dmcrypt_name, lodev,
- dmcrypt_dev, !kCryptAllowDiscard)) {
- ERROR("dm_setup failed");
- goto lo_cleanup;
- }
- INFO("%s: dm-crypt does not support discard; disabling.",
- dmcrypt_dev);
- }
-
- /* Decide now if any migration will happen. If so, we will not
- * grow the new filesystem in the background, since we need to
- * copy the contents over before /var is valid again.
- */
- if (!rebuild)
- migrate_allowed = 0;
- if (migrate_allowed) {
- for (bind = bind_mounts; bind->src; ++ bind) {
- if (migrate_contents(bind, MIGRATE_TEST_ONLY))
- migrate_needed = 1;
- }
- }
-
- /* Calculate filesystem min/max size. */
- blocks_max = sectors / (kExt4BlockSize / kSectorSize);
- blocks_min = kExt4MinBytes / kExt4BlockSize;
- if (migrate_needed && migrate_allowed) {
- uint64_t fs_bytes_min;
- uint64_t calc_blocks_min;
- /* When doing a migration, the new filesystem must be
- * large enough to hold what we're going to migrate.
- * Instead of walking the bind mount sources, which would
- * be IO and time expensive, just read the bytes-used
- * value from statvfs (plus 10% for overhead). It will
- * be too large, since it includes the eCryptFS data, so
- * we must cap at the max filesystem size just in case.
- */
-
- /* Bytes used in stateful partition plus 10%. */
- fs_bytes_min = stateful_statbuf.f_blocks -
- stateful_statbuf.f_bfree;
- fs_bytes_min *= stateful_statbuf.f_frsize;
- DEBUG("Stateful bytes used: %" PRIu64 "", fs_bytes_min);
- fs_bytes_min *= kMigrationSizeMultiplier;
-
- /* Minimum blocks needed for that many bytes. */
- calc_blocks_min = fs_bytes_min / kExt4BlockSize;
- /* Do not use more than blocks_max. */
- if (calc_blocks_min > blocks_max)
- calc_blocks_min = blocks_max;
- /* Do not use less than blocks_min. */
- else if (calc_blocks_min < blocks_min)
- calc_blocks_min = blocks_min;
-
- DEBUG("Maximum fs blocks: %" PRIu64 "", blocks_max);
- DEBUG("Minimum fs blocks: %" PRIu64 "", blocks_min);
- DEBUG("Migration blocks chosen: %" PRIu64 "", calc_blocks_min);
- blocks_min = calc_blocks_min;
- }
-
- if (rebuild) {
- INFO("Building filesystem on %s "
- "(blocksize:%" PRIu64 ", min:%" PRIu64 ", max:%" PRIu64 ").",
- dmcrypt_dev, kExt4BlockSize, blocks_min, blocks_max);
- if (!filesystem_build(dmcrypt_dev, kExt4BlockSize,
- blocks_min, blocks_max))
- goto dm_cleanup;
- }
-
- /* Mount the dm-crypt partition finally. */
- INFO("Mounting %s onto %s.", dmcrypt_dev, encrypted_mount);
- if (access(encrypted_mount, R_OK) &&
- mkdir(encrypted_mount, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) {
- PERROR(dmcrypt_dev);
- goto dm_cleanup;
- }
- if (mount(dmcrypt_dev, encrypted_mount, kEncryptedFSType,
- MS_NODEV | MS_NOEXEC | MS_NOSUID | MS_RELATIME,
- "discard,commit=600")) {
- PERROR("mount(%s,%s)", dmcrypt_dev, encrypted_mount);
- goto dm_cleanup;
- }
-
- /* Always spawn filesystem resizer, in case growth was interrupted. */
- /* TODO(keescook): if already full size, don't resize. */
- spawn_resizer(dmcrypt_dev, blocks_min, blocks_max);
-
- /* If the legacy lockbox NVRAM area exists, we've rebuilt the
- * filesystem, and there are old bind sources on disk, attempt
- * migration.
- */
- if (migrate_needed && migrate_allowed) {
- /* Migration needs to happen before bind mounting because
- * some partitions were not already on the stateful partition,
- * and would be over-mounted by the new bind mount.
- */
- for (bind = bind_mounts; bind->src; ++ bind)
- migrate_contents(bind, MIGRATE_FOR_REAL);
- }
-
- /* Perform bind mounts. */
- for (bind = bind_mounts; bind->src; ++ bind) {
- INFO("Bind mounting %s onto %s.", bind->src, bind->dst);
- if (check_bind(bind, BIND_SOURCE) ||
- check_bind(bind, BIND_DEST))
- goto unbind;
- if (mount(bind->src, bind->dst, "none", MS_BIND, NULL)) {
- PERROR("mount(%s,%s)", bind->src, bind->dst);
- goto unbind;
- }
- }
-
- /* When we are creating the encrypted mount for the first time,
- * either finalize immediately, or write the encryption key to
- * disk (*sigh*) to handle the seemingly endless broken or
- * wedged TPM states.
- */
- if (rebuild) {
- /* Devices that already have the NVRAM area populated and
- * are being rebuilt don't need to wait for Cryptohome
- * because the NVRAM area isn't going to change.
- *
- * Devices that do not have the NVRAM area populated
- * may potentially never have the NVRAM area populated,
- * which means we have to write the encryption key to
- * disk until we finalize. Once secure deletion is
- * supported on ext4, this won't be as horrible.
- */
- if (has_system_key)
- finalize(system_key, encryption_key);
- else
- needs_finalization(encryption_key);
- } else {
- /* If we're not rebuilding and we have a sane system
- * key, then we must either need finalization (if we
- * failed to finalize in Cryptohome), or we have already
- * finalized, but maybe failed to clean up.
- */
- if (has_system_key) {
- if (!valid_keyfile)
- finalize(system_key, encryption_key);
- else
- finalized();
- }
- }
-
- free(lodev);
- return 1;
-
-unbind:
- for (bind = bind_mounts; bind->src; ++ bind) {
- INFO("Unmounting %s.", bind->dst);
- umount(bind->dst);
- }
-
- INFO("Unmounting %s.", encrypted_mount);
- umount(encrypted_mount);
-
-dm_cleanup:
- INFO("Removing %s.", dmcrypt_dev);
- /* TODO(keescook): something holds this open briefly on mkfs failure
- * and I haven't been able to catch it yet. Adding an "fuser" call
- * here is sufficient to lose the race. Instead, just sleep during
- * the error path.
- */
- sleep(1);
- dm_teardown(dmcrypt_dev);
-
-lo_cleanup:
- INFO("Unlooping %s.", lodev);
- loop_detach(lodev);
-
-failed:
- free(lodev);
-
- return 0;
-}
-
-/* Clean up all bind mounts, mounts, attaches, etc. Only the final
- * action informs the return value. This makes it so that failures
- * can be cleaned up from, and continue the shutdown process on a
- * second call. If the loopback cannot be found, claim success.
- */
-static int shutdown(void)
-{
- struct bind_mount *bind;
-
- for (bind = bind_mounts; bind->src; ++ bind) {
- INFO("Unmounting %s.", bind->dst);
- errno = 0;
- /* Allow either success or a "not mounted" failure. */
- if (umount(bind->dst)) {
- if (errno != EINVAL) {
- PERROR("umount(%s)", bind->dst);
- return EXIT_FAILURE;
- }
- }
- }
-
- INFO("Unmounting %s.", encrypted_mount);
- errno = 0;
- /* Allow either success or a "not mounted" failure. */
- if (umount(encrypted_mount)) {
- if (errno != EINVAL) {
- PERROR("umount(%s)", encrypted_mount);
- return EXIT_FAILURE;
- }
- }
-
- /*
- * Force syncs to make sure we don't tickle racey/buggy kernel
- * routines that might be causing crosbug.com/p/17610.
- */
- sync();
-
- /* Optionally run fsck on the device after umount. */
- if (getenv("MOUNT_ENCRYPTED_FSCK")) {
- char *cmd;
-
- if (asprintf(&cmd, "fsck -a %s", dmcrypt_dev) == -1)
- PERROR("asprintf");
- else {
- int rc;
-
- rc = system(cmd);
- if (rc != 0)
- ERROR("'%s' failed: %d", cmd, rc);
- }
- }
-
- INFO("Removing %s.", dmcrypt_dev);
- if (!dm_teardown(dmcrypt_dev))
- ERROR("dm_teardown(%s)", dmcrypt_dev);
- sync();
-
- INFO("Unlooping %s (named %s).", block_path, dmcrypt_name);
- if (!loop_detach_name(dmcrypt_name)) {
- ERROR("loop_detach_name(%s)", dmcrypt_name);
- return EXIT_FAILURE;
- }
- sync();
-
- return EXIT_SUCCESS;
-}
-
-static void check_mount_states(void)
-{
- struct bind_mount *bind;
-
- /* Verify stateful partition exists. */
- if (access(stateful_mount, R_OK)) {
- INFO("%s does not exist.", stateful_mount);
- exit(1);
- }
- /* Verify stateful is either a separate mount, or that the
- * root directory is writable (i.e. a factory install, dev mode
- * where root remounted rw, etc).
- */
- if (same_vfs(stateful_mount, rootdir) && access(rootdir, W_OK)) {
- INFO("%s is not mounted.", stateful_mount);
- exit(1);
- }
-
- /* Verify encrypted partition is missing or not already mounted. */
- if (access(encrypted_mount, R_OK) == 0 &&
- !same_vfs(encrypted_mount, stateful_mount)) {
- INFO("%s already appears to be mounted.", encrypted_mount);
- exit(0);
- }
-
- /* Verify that bind mount targets exist. */
- for (bind = bind_mounts; bind->src; ++ bind) {
- if (access(bind->dst, R_OK)) {
- PERROR("%s mount point is missing.", bind->dst);
- exit(1);
- }
- }
-
- /* Verify that old bind mounts on stateful haven't happened yet. */
- for (bind = bind_mounts; bind->src; ++ bind) {
- if (bind->submount)
- continue;
-
- if (same_vfs(bind->dst, stateful_mount)) {
- INFO("%s already bind mounted.", bind->dst);
- exit(1);
- }
- }
-
- INFO("VFS mount state sanity check ok.");
-}
-
-static int report_info(void)
-{
- uint8_t system_key[DIGEST_LENGTH];
- uint8_t owned = 0;
- struct bind_mount *mnt;
- int migrate = -1;
-
- printf("TPM: %s\n", has_tpm ? "yes" : "no");
- if (has_tpm) {
- printf("TPM Owned: %s\n", tpm_owned(&owned) != TPM_SUCCESS ?
- "fail" : (owned ? "yes" : "no"));
- }
- printf("ChromeOS: %s\n", has_chromefw() ? "yes" : "no");
- printf("CR48: %s\n", is_cr48() ? "yes" : "no");
- if (has_chromefw()) {
- int rc;
- rc = get_nvram_key(system_key, &migrate);
- if (!rc)
- printf("NVRAM: missing.\n");
- else {
- printf("NVRAM: %s, %s.\n",
- migrate ? "legacy" : "modern",
- rc ? "available" : "ignored");
- }
- }
- else {
- printf("NVRAM: not present\n");
- }
-
- printf("rootdir: %s\n", rootdir);
- printf("stateful_mount: %s\n", stateful_mount);
- printf("key_path: %s\n", key_path);
- printf("block_path: %s\n", block_path);
- printf("encrypted_mount: %s\n", encrypted_mount);
- printf("dmcrypt_name: %s\n", dmcrypt_name);
- printf("dmcrypt_dev: %s\n", dmcrypt_dev);
- printf("bind mounts:\n");
- for (mnt = bind_mounts; mnt->src; ++mnt) {
- printf("\tsrc:%s\n", mnt->src);
- printf("\tdst:%s\n", mnt->dst);
- printf("\tprevious:%s\n", mnt->previous);
- printf("\tpending:%s\n", mnt->pending);
- printf("\towner:%s\n", mnt->owner);
- printf("\tmode:%o\n", mnt->mode);
- printf("\tsubmount:%d\n", mnt->submount);
- printf("\n");
- }
-
- return EXIT_SUCCESS;
-}
-
-/* This expects "mnt" to be allocated and initialized to NULL bytes. */
-static int dup_bind_mount(struct bind_mount *mnt, struct bind_mount *old,
- char *dir)
-{
- if (old->src && asprintf(&mnt->src, "%s%s", dir, old->src) == -1)
- goto fail;
- if (old->dst && asprintf(&mnt->dst, "%s%s", dir, old->dst) == -1)
- goto fail;
- if (old->previous && asprintf(&mnt->previous, "%s%s", dir,
- old->previous) == -1)
- goto fail;
- if (old->pending && asprintf(&mnt->pending, "%s%s", dir,
- old->pending) == -1)
- goto fail;
- if (!(mnt->owner = strdup(old->owner)))
- goto fail;
- if (!(mnt->group = strdup(old->group)))
- goto fail;
- mnt->mode = old->mode;
- mnt->submount = old->submount;
-
- return 0;
-
-fail:
- perror(__FUNCTION__);
- return 1;
-}
-
-static void prepare_paths(void)
-{
- char *dir = NULL;
- struct bind_mount *old;
- struct bind_mount *mnt;
-
- mnt = bind_mounts = calloc(sizeof(bind_mounts_default) /
- sizeof(*bind_mounts_default),
- sizeof(*bind_mounts_default));
- if (!mnt) {
- perror("calloc");
- exit(1);
- }
-
- if ((dir = getenv("MOUNT_ENCRYPTED_ROOT")) != NULL) {
- unsigned char digest[DIGEST_LENGTH];
- gchar *hex;
-
- if (asprintf(&rootdir, "%s/", dir) == -1)
- goto fail;
-
- /* Generate a shortened hash for non-default cryptnames,
- * which will get re-used in the loopback name, which
- * must be less than 64 (LO_NAME_SIZE) bytes. */
- sha256(dir, digest);
- hex = stringify_hex(digest, sizeof(digest));
- hex[17] = '\0';
- if (asprintf(&dmcrypt_name, "%s_%s", kCryptDevName,
- hex) == -1)
- goto fail;
- g_free(hex);
- } else {
- rootdir = "/";
- if (!(dmcrypt_name = strdup(kCryptDevName)))
- goto fail;
- }
-
- if (asprintf(&stateful_mount, "%s%s", rootdir, STATEFUL_MNT) == -1)
- goto fail;
- if (asprintf(&key_path, "%s%s", rootdir,
- STATEFUL_MNT "/encrypted.key") == -1)
- goto fail;
- if (asprintf(&needs_finalization_path, "%s%s", rootdir,
- STATEFUL_MNT "/encrypted.needs-finalization") == -1)
- goto fail;
- if (asprintf(&block_path, "%s%s", rootdir,
- STATEFUL_MNT "/encrypted.block") == -1)
- goto fail;
- if (asprintf(&encrypted_mount, "%s%s", rootdir, ENCRYPTED_MNT) == -1)
- goto fail;
- if (asprintf(&dmcrypt_dev, "/dev/mapper/%s", dmcrypt_name) == -1)
- goto fail;
-
- for (old = bind_mounts_default; old->src; ++old) {
- if (dup_bind_mount(mnt++, old, rootdir))
- exit(1);
- }
-
- return;
-
-fail:
- perror("asprintf");
- exit(1);
-}
-
-/* Exports NVRAM contents to tmpfs for use by install attributes */
-void nvram_export(uint8_t *data, uint32_t size)
-{
- int fd;
- DEBUG("Export NVRAM contents");
- if (!size || !data)
- return;
- fd = open(kNvramExport, O_WRONLY|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR);
- if (fd < 0) {
- perror("open(nvram_export)");
- return;
- }
- if (write(fd, data, size) != size) {
- /* Don't leave broken files around */
- unlink(kNvramExport);
- }
- close(fd);
-}
-
-int main(int argc, char *argv[])
-{
- int okay;
- int mode = kModeProduction;
-
- INFO_INIT("Starting.");
- prepare_paths();
-
- if (argc > 1) {
- if (!strcmp(argv[1], "umount"))
- return shutdown();
- else if (!strcmp(argv[1], "info"))
- return report_info();
- else if (!strcmp(argv[1], "finalize"))
- return finalize_from_cmdline(argc > 2 ? argv[2] : NULL);
- else if (!strcmp(argv[1], "factory"))
- mode = kModeFactory;
- else {
- fprintf(stderr,
- "Usage: %s [info|finalize|umount|factory]\n",
- argv[0]);
- return 1;
- }
- }
-
- check_mount_states();
-
- okay = setup_encrypted(mode);
- /* If we fail, let chromeos_startup handle the stateful wipe. */
-
- if (okay)
- nvram_export(nvram_data, nvram_size);
-
- INFO_DONE("Done.");
-
- /* Continue boot. */
- return okay ? EXIT_SUCCESS : EXIT_FAILURE;
-}
diff --git a/utility/mount-encrypted.h b/utility/mount-encrypted.h
deleted file mode 100644
index e48617d9..00000000
--- a/utility/mount-encrypted.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/* Copyright (c) 2012 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.
- *
- * Private header file for mount-encrypted helper tool.
- */
-#ifndef _MOUNT_ENCRYPTED_H_
-#define _MOUNT_ENCRYPTED_H_
-
-/* #define DEBUG_ENABLED 1 */
-#define DEBUG_TIME_DELTA 1
-
-#include <openssl/err.h>
-#include <openssl/sha.h>
-
-#define DIGEST_LENGTH SHA256_DIGEST_LENGTH
-
-#define _ERROR(f, a...) do { \
- fprintf(stderr, "ERROR[pid:%d] %s (%s, %d): ", \
- getpid(), __func__, __FILE__, __LINE__); \
- fprintf(stderr, f, ## a); \
-} while (0)
-#define ERROR(f, a...) do { \
- _ERROR(f, ## a); \
- fprintf(stderr, "\n"); \
- fflush(stderr); \
-} while (0)
-#define PERROR(f, a...) do { \
- _ERROR(f, ## a); \
- fprintf(stderr, ": %s\n", strerror(errno)); \
- fflush(stderr); \
-} while (0)
-
-#define SSL_ERROR(f, a...) do { \
- ERR_load_crypto_strings(); \
- _ERROR(f, ## a); \
- fprintf(stderr, "%s\n", ERR_error_string(ERR_get_error(), NULL)); \
- fflush(stderr); \
-} while (0)
-
-#if DEBUG_ENABLED
-extern struct timeval tick;
-extern struct timeval tick_start;
-# define TICK_INIT() do { \
- gettimeofday(&tick, NULL); \
- tick_start = tick; \
-} while (0)
-# ifdef DEBUG_TIME_DELTA
-/* This timeval helper copied from glibc manual. */
-static inline int timeval_subtract(struct timeval *result,
- struct timeval *x,
- struct timeval *y)
-{
- /* Perform the carry for the later subtraction by updating y. */
- if (x->tv_usec < y->tv_usec) {
- int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
- y->tv_usec -= 1000000 * nsec;
- y->tv_sec += nsec;
- }
- if (x->tv_usec - y->tv_usec > 1000000) {
- int nsec = (x->tv_usec - y->tv_usec) / 1000000;
- y->tv_usec += 1000000 * nsec;
- y->tv_sec -= nsec;
- }
-
- /* Compute the time remaining to wait.
- * tv_usec is certainly positive.
- */
- result->tv_sec = x->tv_sec - y->tv_sec;
- result->tv_usec = x->tv_usec - y->tv_usec;
-
- /* Return 1 if result is negative. */
- return x->tv_sec < y->tv_sec;
-}
-# define TICK_REPORT() do { \
- struct timeval now, diff; \
- gettimeofday(&now, NULL); \
- timeval_subtract(&diff, &now, &tick); \
- printf("\tTook: [pid:%d, %2lu.%06lus]\n", getpid(), \
- (unsigned long)diff.tv_sec, (unsigned long)diff.tv_usec); \
- tick = now; \
-} while (0)
-# else
-# define TICK_REPORT() do { \
- gettimeofday(&tick, NULL); \
- printf("[%2d.%06d] ", (int)tick.tv_sec, (int)tick.tv_usec); \
-} while (0)
-# endif
-# define TICK_DONE() do { \
- struct timeval tick_done; \
- TICK_REPORT(); \
- timeval_subtract(&tick_done, &tick, &tick_start); \
- printf("Process Lifetime: [pid:%d, %2d.%06ds]\n", getpid(), \
- (int)tick_done.tv_sec, (int)tick_done.tv_usec); \
-} while (0)
-#else
-# define TICK_INIT() do { } while (0)
-# define TICK_REPORT() do { } while (0)
-# define TICK_DONE() do { } while (0)
-#endif
-
-#define _INFO(f, a...) do { \
- printf("[pid:%d] ", getpid()); \
- printf(f, ## a); \
- printf("\n"); \
- fflush(stdout); \
-} while (0)
-#define INFO(f, a...) do { \
- TICK_REPORT(); \
- _INFO(f, ## a); \
-} while (0)
-#define INFO_INIT(f, a...) do { \
- TICK_INIT(); \
- INFO(f, ## a); \
-} while (0)
-#define INFO_DONE(f, a...) do { \
- TICK_DONE(); \
- INFO(f, ## a); \
-} while (0)
-#if DEBUG_ENABLED
-# define DEBUG(f, a...) do { \
- TICK_REPORT(); \
- _INFO(f, ## a); \
-} while (0)
-#else
-# define DEBUG(f, a...) do { } while (0)
-#endif
-
-#if DEBUG_ENABLED
-static inline void debug_dump_hex(const char *name, uint8_t *data,
- uint32_t size)
-{
- int i;
- printf("%s: ", name);
- for (i = 0; i < size; i++) {
- printf("%02x ", data[i]);
- }
- printf("\n");
-}
-#else
-# define debug_dump_hex(n, d, s) do { } while (0)
-#endif
-
-#endif /* _MOUNT_ENCRYPTED_H_ */
diff --git a/utility/mount-helpers.c b/utility/mount-helpers.c
deleted file mode 100644
index aed5ef06..00000000
--- a/utility/mount-helpers.c
+++ /dev/null
@@ -1,803 +0,0 @@
-/* Copyright (c) 2012 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 collection of helper utilities for use with the "mount-encrypted"
- * utility.
- *
- */
-#define _GNU_SOURCE
-#define _FILE_OFFSET_BITS 64
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <math.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/mount.h>
-#include <linux/fs.h>
-#include <linux/loop.h>
-
-#include <glib.h>
-#include <glib/gstdio.h>
-
-#include <openssl/evp.h>
-
-#include "mount-encrypted.h"
-#include "mount-helpers.h"
-
-static const gchar * const kRootDir = "/";
-static const gchar * const kLoopTemplate = "/dev/loop%d";
-static const int kLoopMajor = 7;
-static const int kLoopMax = 8;
-static const unsigned int kResizeStepSeconds = 2;
-static const uint64_t kResizeBlocks = 32768 * 10;
-static const uint64_t kBlocksPerGroup = 32768;
-static const uint64_t kInodeRatioDefault = 16384;
-static const uint64_t kInodeRatioMinimum = 2048;
-static const gchar * const kExt4ExtendedOptions = "discard,lazy_itable_init";
-
-int remove_tree(const char *tree)
-{
- const gchar *rm[] = {
- "/bin/rm", "-rf", tree,
- NULL
- };
-
- return runcmd(rm, NULL);
-}
-
-uint64_t blk_size(const char *device)
-{
- uint64_t bytes;
- int fd;
- if ((fd = open(device, O_RDONLY | O_NOFOLLOW)) < 0) {
- PERROR("open(%s)", device);
- return 0;
- }
- if (ioctl(fd, BLKGETSIZE64, &bytes)) {
- PERROR("ioctl(%s, BLKGETSIZE64)", device);
- return 0;
- }
- close(fd);
- return bytes;
-}
-
-int runcmd(const gchar *argv[], gchar **output)
-{
- gint rc;
- gchar *out = NULL, *errout = NULL;
- GError *err = NULL;
-
- g_spawn_sync(kRootDir, (gchar **)argv, NULL, 0, NULL, NULL,
- &out, &errout, &rc, &err);
- if (err) {
- ERROR("%s: %s", argv[0], err->message);
- g_error_free(err);
- return -1;
- }
-
- if (rc)
- ERROR("%s failed (%d)\n%s\n%s", argv[0], rc, out, errout);
-
- if (output)
- *output = out;
- else
- g_free(out);
- g_free(errout);
-
- return rc;
-}
-
-int same_vfs(const char *mnt_a, const char *mnt_b)
-{
- struct stat stat_a, stat_b;
-
- if (lstat(mnt_a, &stat_a)) {
- PERROR("lstat(%s)", mnt_a);
- exit(1);
- }
- if (lstat(mnt_b, &stat_b)) {
- PERROR("lstat(%s)", mnt_b);
- exit(1);
- }
- return (stat_a.st_dev == stat_b.st_dev);
-}
-
-/* Returns allocated string that holds [length]*2 + 1 characters. */
-char *stringify_hex(uint8_t *binary, size_t length)
-{
- char *string;
- size_t i;
-
- string = malloc(length * 2 + 1);
- if (!string) {
- PERROR("malloc");
- return NULL;
- }
- for (i = 0; i < length; ++i)
- sprintf(string + (i * 2), "%02x", binary[i]);
- string[length * 2] = '\0';
-
- return string;
-}
-
-/* Returns allocated byte array that holds strlen([string])/2 bytes. */
-uint8_t *hexify_string(char *string, uint8_t *binary, size_t length)
-{
- size_t bytes, i;
-
- bytes = strlen(string) / 2;
- if (bytes > length) {
- ERROR("Hex string too long (%zu) for byte array (%zu)",
- bytes, length);
- return NULL;
- }
-
- for (i = 0; i < bytes; ++i) {
- if (sscanf(&string[i * 2], "%2hhx", &binary[i]) != 1) {
- ERROR("Invalid hex code at byte %zu.", i);
- return NULL;
- }
- }
-
- return binary;
-}
-
-/* Overwrite file contents. Useless on SSD. :( */
-void shred(const char *pathname)
-{
- uint8_t patterns[] = { 0xA5, 0x5A, 0xFF, 0x00 };
- FILE *target;
- struct stat info;
- uint8_t *pattern;
- int fd, i;
-
- /* Give up if we can't safely open or stat the target. */
- if ((fd = open(pathname, O_WRONLY | O_NOFOLLOW)) < 0) {
- PERROR(pathname);
- return;
- }
- if (fstat(fd, &info)) {
- close(fd);
- PERROR(pathname);
- return;
- }
- if (!(target = fdopen(fd, "w"))) {
- close(fd);
- PERROR(pathname);
- return;
- }
- /* Ignore errors here, since there's nothing we can really do. */
- pattern = malloc(info.st_size);
- for (i = 0; i < sizeof(patterns); ++i) {
- memset(pattern, patterns[i], info.st_size);
- if (fseek(target, 0, SEEK_SET))
- PERROR(pathname);
- if (fwrite(pattern, info.st_size, 1, target) != 1)
- PERROR(pathname);
- if (fflush(target))
- PERROR(pathname);
- if (fdatasync(fd))
- PERROR(pathname);
- }
- free(pattern);
- /* fclose() closes the fd too. */
- fclose(target);
-}
-
-static int is_loop_device(int fd)
-{
- struct stat info;
-
- return (fstat(fd, &info) == 0 && S_ISBLK(info.st_mode) &&
- major(info.st_rdev) == kLoopMajor);
-}
-
-static int loop_is_attached(int fd, struct loop_info64 *info)
-{
- struct loop_info64 local_info;
-
- return ioctl(fd, LOOP_GET_STATUS64, info ? info : &local_info) == 0;
-}
-
-/* Returns either the matching loopback name, or next available, if NULL. */
-static int loop_locate(gchar **loopback, const char *name)
-{
- int i, fd, namelen = 0;
-
- if (name) {
- namelen = strlen(name);
- if (namelen >= LO_NAME_SIZE) {
- ERROR("'%s' too long (>= %d)", name, LO_NAME_SIZE);
- return -1;
- }
- }
-
- *loopback = NULL;
- for (i = 0; i < kLoopMax; ++i) {
- struct loop_info64 info;
- int attached;
-
- g_free(*loopback);
- *loopback = g_strdup_printf(kLoopTemplate, i);
- if (!*loopback) {
- PERROR("g_strdup_printf");
- return -1;
- }
-
- fd = open(*loopback, O_RDONLY | O_NOFOLLOW);
- if (fd < 0) {
- PERROR("open(%s)", *loopback);
- goto failed;
- }
- if (!is_loop_device(fd)) {
- close(fd);
- continue;
- }
-
- memset(&info, 0, sizeof(info));
- attached = loop_is_attached(fd, &info);
- close(fd);
-
- if (attached)
- DEBUG("Saw %s on %s", info.lo_file_name, *loopback);
-
- if ((attached && name &&
- strncmp((char *)info.lo_file_name, name, namelen) == 0) ||
- (!attached && !name)) {
- DEBUG("Using %s", *loopback);
- /* Reopen for working on it. */
- fd = open(*loopback, O_RDWR | O_NOFOLLOW);
- if (is_loop_device(fd) &&
- loop_is_attached(fd, NULL) == attached)
- return fd;
- }
- }
- ERROR("Ran out of loopback devices");
-
-failed:
- g_free(*loopback);
- *loopback = NULL;
- return -1;
-}
-
-static int loop_detach_fd(int fd)
-{
- if (ioctl(fd, LOOP_CLR_FD, 0)) {
- PERROR("LOOP_CLR_FD");
- return 0;
- }
- return 1;
-}
-
-int loop_detach(const gchar *loopback)
-{
- int fd, rc = 1;
-
- fd = open(loopback, O_RDONLY | O_NOFOLLOW);
- if (fd < 0) {
- PERROR("open(%s)", loopback);
- return 0;
- }
- if (!is_loop_device(fd) || !loop_is_attached(fd, NULL) ||
- !loop_detach_fd(fd))
- rc = 0;
-
- close (fd);
- return rc;
-}
-
-int loop_detach_name(const char *name)
-{
- gchar *loopback = NULL;
- int loopfd, rc;
-
- loopfd = loop_locate(&loopback, name);
- if (loopfd < 0)
- return 0;
- rc = loop_detach_fd(loopfd);
-
- close(loopfd);
- g_free(loopback);
- return rc;
-}
-
-/* Closes fd, returns name of loopback device pathname. */
-gchar *loop_attach(int fd, const char *name)
-{
- gchar *loopback = NULL;
- int loopfd;
- struct loop_info64 info;
-
- loopfd = loop_locate(&loopback, NULL);
- if (loopfd < 0)
- return NULL;
- if (ioctl(loopfd, LOOP_SET_FD, fd) < 0) {
- PERROR("LOOP_SET_FD");
- goto failed;
- }
-
- memset(&info, 0, sizeof(info));
- strncpy((char*)info.lo_file_name, name, LO_NAME_SIZE);
- if (ioctl(loopfd, LOOP_SET_STATUS64, &info)) {
- PERROR("LOOP_SET_STATUS64");
- goto failed;
- }
-
- close(loopfd);
- close(fd);
- return loopback;
-failed:
- close(loopfd);
- close(fd);
- g_free(loopback);
- return 0;
-}
-
-int dm_setup(uint64_t sectors, const gchar *encryption_key, const char *name,
- const gchar *device, const char *path, int discard)
-{
- /* Mount loopback device with dm-crypt using the encryption key. */
- gchar *table = g_strdup_printf("0 %" PRIu64 " crypt " \
- "aes-cbc-essiv:sha256 %s " \
- "0 %s 0%s",
- sectors,
- encryption_key,
- device,
- discard ? " 1 allow_discards" : "");
- if (!table) {
- PERROR("g_strdup_printf");
- return 0;
- }
-
- const gchar *argv[] = {
- "/sbin/dmsetup",
- "create", name,
- "--noudevrules", "--noudevsync",
- "--table", table,
- NULL
- };
-
- /* TODO(keescook): replace with call to libdevmapper. */
- if (runcmd(argv, NULL) != 0) {
- g_free(table);
- return 0;
- }
- g_free(table);
-
- /* Make sure the dm-crypt device showed up. */
- if (access(path, R_OK)) {
- ERROR("%s does not exist", path);
- return 0;
- }
-
- return 1;
-}
-
-int dm_teardown(const gchar *device)
-{
- const char *argv[] = {
- "/sbin/dmsetup",
- "remove", device,
- "--noudevrules", "--noudevsync",
- NULL
- };
- /* TODO(keescook): replace with call to libdevmapper. */
- if (runcmd(argv, NULL) != 0)
- return 0;
- return 1;
-}
-
-char *dm_get_key(const gchar *device)
-{
- gchar *output = NULL;
- char *key;
- int i;
- const char *argv[] = {
- "/sbin/dmsetup",
- "table", "--showkeys",
- device,
- NULL
- };
- /* TODO(keescook): replace with call to libdevmapper. */
- if (runcmd(argv, &output) != 0)
- return NULL;
-
- /* Key is 4th field in the output. */
- for (i = 0, key = strtok(output, " ");
- i < 4 && key;
- ++i, key = strtok(NULL, " ")) { }
-
- /* Create a copy of the key and free the output buffer. */
- if (key) {
- key = strdup(key);
- g_free(output);
- }
-
- return key;
-}
-
-int sparse_create(const char *path, uint64_t bytes)
-{
- int sparsefd;
-
- sparsefd = open(path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW,
- S_IRUSR | S_IWUSR);
- if (sparsefd < 0)
- goto out;
-
- if (ftruncate(sparsefd, bytes)) {
- int saved_errno = errno;
-
- close(sparsefd);
- unlink(path);
- errno = saved_errno;
-
- sparsefd = -1;
- }
-
-out:
- return sparsefd;
-}
-
-/* When creating a filesystem that will grow, the inode ratio is calculated
- * using the starting size not the hinted "resize" size, which means the
- * number of inodes can be highly constrained on tiny starting filesystems.
- * Instead, calculate what the correct inode ratio should be for a given
- * filesystem based on its expected starting and ending sizes.
- *
- * inode-ratio_mkfs =
- *
- * ceil(blocks_max / group-ratio) * size_mkfs
- * ------------------------------------------------------------------
- * ceil(size_max / inode-ratio_max) * ceil(blocks_mkfs / group-ratio)
- */
-static uint64_t get_inode_ratio(uint64_t block_bytes_in,
- uint64_t blocks_mkfs_in,
- uint64_t blocks_max_in)
-{
- double block_bytes = (double)block_bytes_in;
- double blocks_mkfs = (double)blocks_mkfs_in;
- double blocks_max = (double)blocks_max_in;
-
- double size_max, size_mkfs, groups_max, groups_mkfs, inodes_max;
- double denom, inode_ratio_mkfs;
-
- size_max = block_bytes * blocks_max;
- size_mkfs = block_bytes * blocks_mkfs;
-
- groups_max = ceil(blocks_max / kBlocksPerGroup);
- groups_mkfs = ceil(blocks_mkfs / kBlocksPerGroup);
-
- inodes_max = ceil(size_max / kInodeRatioDefault);
-
- denom = inodes_max * groups_mkfs;
- /* Make sure we never trigger divide-by-zero. */
- if (denom == 0.0)
- goto failure;
- inode_ratio_mkfs = (groups_max * size_mkfs) / denom;
-
- /* Make sure we never calculate anything totally huge. */
- if (inode_ratio_mkfs > blocks_mkfs)
- goto failure;
- /* Make sure we never calculate anything totally tiny. */
- if (inode_ratio_mkfs < kInodeRatioMinimum)
- goto failure;
-
- return (uint64_t)inode_ratio_mkfs;
-
-failure:
- return kInodeRatioDefault;
-}
-
-/* Creates an ext4 filesystem.
- * device: path to block device to create filesystem on.
- * block_bytes: bytes per block to use for filesystem.
- * blocks_min: starting number of blocks on filesystem.
- * blocks_max: largest expected size in blocks of filesystem, for growth hints.
- *
- * Returns 1 on success, 0 on failure.
- */
-int filesystem_build(const char *device, uint64_t block_bytes,
- uint64_t blocks_min, uint64_t blocks_max)
-{
- int rc = 0;
- uint64_t inode_ratio;
-
- gchar *blocksize = g_strdup_printf("%" PRIu64, block_bytes);
- if (!blocksize) {
- PERROR("g_strdup_printf");
- goto out;
- }
-
- gchar *blocks_str;
- blocks_str = g_strdup_printf("%" PRIu64, blocks_min);
- if (!blocks_str) {
- PERROR("g_strdup_printf");
- goto free_blocksize;
- }
-
- gchar *extended;
- if (blocks_min < blocks_max) {
- extended = g_strdup_printf("%s,resize=%" PRIu64,
- kExt4ExtendedOptions, blocks_max);
- } else {
- extended = g_strdup_printf("%s", kExt4ExtendedOptions);
- }
- if (!extended) {
- PERROR("g_strdup_printf");
- goto free_blocks_str;
- }
-
- inode_ratio = get_inode_ratio(block_bytes, blocks_min, blocks_max);
- gchar *inode_ratio_str = g_strdup_printf("%" PRIu64, inode_ratio);
- if (!inode_ratio_str) {
- PERROR("g_strdup_printf");
- goto free_extended;
- }
-
- const gchar *mkfs[] = {
- "/sbin/mkfs.ext4",
- "-T", "default",
- "-b", blocksize,
- "-m", "0",
- "-O", "^huge_file,^flex_bg",
- "-i", inode_ratio_str,
- "-E", extended,
- device,
- blocks_str,
- NULL
- };
-
- rc = (runcmd(mkfs, NULL) == 0);
- if (!rc)
- goto free_inode_ratio_str;
-
- const gchar *tune2fs[] = {
- "/sbin/tune2fs",
- "-c", "0",
- "-i", "0",
- device,
- NULL
- };
- rc = (runcmd(tune2fs, NULL) == 0);
-
-free_inode_ratio_str:
- g_free(inode_ratio_str);
-free_extended:
- g_free(extended);
-free_blocks_str:
- g_free(blocks_str);
-free_blocksize:
- g_free(blocksize);
-out:
- return rc;
-}
-
-/* Spawns a filesystem resizing process. */
-int filesystem_resize(const char *device, uint64_t blocks, uint64_t blocks_max)
-{
- /* Ignore resizing if we know the filesystem was built to max size. */
- if (blocks >= blocks_max) {
- INFO("Resizing aborted. blocks:%" PRIu64 " >= blocks_max:%" PRIu64,
- blocks, blocks_max);
- return 1;
- }
-
- /* TODO(keescook): Read superblock to find out the current size of
- * the filesystem (since statvfs does not report the correct value).
- * For now, instead of doing multi-step resizing, just resize to the
- * full size of the block device in one step.
- */
- blocks = blocks_max;
-
- INFO("Resizing started in %d second steps.", kResizeStepSeconds);
-
- do {
- gchar *blocks_str;
-
- sleep(kResizeStepSeconds);
-
- blocks += kResizeBlocks;
- if (blocks > blocks_max)
- blocks = blocks_max;
-
- blocks_str = g_strdup_printf("%" PRIu64, blocks);
- if (!blocks_str) {
- PERROR("g_strdup_printf");
- return 0;
- }
-
- const gchar *resize[] = {
- "/sbin/resize2fs",
- "-f",
- device,
- blocks_str,
- NULL
- };
-
- INFO("Resizing filesystem on %s to %" PRIu64 ".", device, blocks);
- if (runcmd(resize, NULL)) {
- ERROR("resize2fs failed");
- return 0;
- }
- g_free(blocks_str);
- } while (blocks < blocks_max);
-
- INFO("Resizing finished.");
- return 1;
-}
-
-char *keyfile_read(const char *keyfile, uint8_t *system_key)
-{
- char *key = NULL;
- unsigned char *cipher = NULL;
- gsize length;
- uint8_t *plain = NULL;
- int plain_length, final_len;
- GError *error = NULL;
- EVP_CIPHER_CTX ctx;
- const EVP_CIPHER *algo = EVP_aes_256_cbc();
-
- DEBUG("Reading keyfile %s", keyfile);
- if (EVP_CIPHER_key_length(algo) != DIGEST_LENGTH) {
- ERROR("cipher key size mismatch (got %d, want %d)",
- EVP_CIPHER_key_length(algo), DIGEST_LENGTH);
- goto out;
- }
-
- if (access(keyfile, R_OK)) {
- /* This file being missing is handled in caller, so
- * do not emit error message.
- */
- INFO("%s does not exist.", keyfile);
- goto out;
- }
-
- if (!g_file_get_contents(keyfile, (gchar **)&cipher, &length,
- &error)) {
- ERROR("Unable to read %s: %s", keyfile, error->message);
- g_error_free(error);
- goto out;
- }
- plain = malloc(length + EVP_CIPHER_block_size(algo));
- if (!plain) {
- PERROR("malloc");
- goto free_cipher;
- }
-
- DEBUG("Decrypting keyfile %s", keyfile);
- /* Use the default IV. */
- if (!EVP_DecryptInit(&ctx, algo, system_key, NULL)) {
- SSL_ERROR("EVP_DecryptInit");
- goto free_plain;
- }
- if (!EVP_DecryptUpdate(&ctx, plain, &plain_length, cipher, length)) {
- SSL_ERROR("EVP_DecryptUpdate");
- goto free_ctx;
- }
- if (!EVP_DecryptFinal(&ctx, plain+plain_length, &final_len)) {
- SSL_ERROR("EVP_DecryptFinal");
- goto free_ctx;
- }
- plain_length += final_len;
-
- if (plain_length != DIGEST_LENGTH) {
- ERROR("Decrypted encryption key length (%d) is not %d.",
- plain_length, DIGEST_LENGTH);
- goto free_ctx;
- }
-
- debug_dump_hex("encryption key", plain, DIGEST_LENGTH);
-
- key = stringify_hex(plain, DIGEST_LENGTH);
-
-free_ctx:
- EVP_CIPHER_CTX_cleanup(&ctx);
-free_plain:
- free(plain);
-free_cipher:
- g_free(cipher);
-out:
- DEBUG("key:%p", key);
- return key;
-}
-
-int keyfile_write(const char *keyfile, uint8_t *system_key, char *string)
-{
- int rc = 0;
- size_t length;
- uint8_t plain[DIGEST_LENGTH];
- uint8_t *cipher = NULL;
- int cipher_length, final_len;
- GError *error = NULL;
- EVP_CIPHER_CTX ctx;
- const EVP_CIPHER *algo = EVP_aes_256_cbc();
- mode_t mask;
-
- DEBUG("Staring to process keyfile %s", keyfile);
- /* Have key file be read/write only by root user. */
- mask = umask(0077);
-
- if (EVP_CIPHER_key_length(algo) != DIGEST_LENGTH) {
- ERROR("cipher key size mismatch (got %d, want %d)",
- EVP_CIPHER_key_length(algo), DIGEST_LENGTH);
- goto out;
- }
-
- if (access(keyfile, R_OK) == 0) {
- ERROR("%s already exists.", keyfile);
- goto out;
- }
-
- length = strlen(string);
- if (length != sizeof(plain) * 2) {
- ERROR("Encryption key string length (%zu) is not %zu.",
- length, sizeof(plain) * 2);
- goto out;
- }
-
- length = sizeof(plain);
- if (!hexify_string(string, plain, length)) {
- ERROR("Failed to convert encryption key to byte array");
- goto out;
- }
-
- debug_dump_hex("encryption key", plain, DIGEST_LENGTH);
-
- cipher = malloc(length + EVP_CIPHER_block_size(algo));
- if (!cipher) {
- PERROR("malloc");
- goto out;
- }
-
- DEBUG("Encrypting keyfile %s", keyfile);
- /* Use the default IV. */
- if (!EVP_EncryptInit(&ctx, algo, system_key, NULL)) {
- SSL_ERROR("EVP_EncryptInit");
- goto free_cipher;
- }
- if (!EVP_EncryptUpdate(&ctx, cipher, &cipher_length,
- (unsigned char *)plain, length)) {
- SSL_ERROR("EVP_EncryptUpdate");
- goto free_ctx;
- }
- if (!EVP_EncryptFinal(&ctx, cipher+cipher_length, &final_len)) {
- SSL_ERROR("EVP_EncryptFinal");
- goto free_ctx;
- }
- length = cipher_length + final_len;
-
- DEBUG("Writing %zu bytes to %s", length, keyfile);
- /* TODO(keescook): use fd here, and set secure delete. Unsupported
- * by ext4 currently. :(
- * int f;
- * ioctl(fd, EXT2_IOC_GETFLAGS, &f);
- * f |= EXT2_SECRM_FL;
- * ioctl(fd, EXT2_IOC_SETFLAGS, &f);
- */
- if (!g_file_set_contents(keyfile, (gchar *)cipher, length, &error)) {
- ERROR("Unable to write %s: %s", keyfile, error->message);
- g_error_free(error);
- goto free_ctx;
- }
-
- rc = 1;
-
-free_ctx:
- EVP_CIPHER_CTX_cleanup(&ctx);
-free_cipher:
- free(cipher);
-out:
- umask(mask);
- DEBUG("keyfile write rc:%d", rc);
- return rc;
-}
diff --git a/utility/mount-helpers.h b/utility/mount-helpers.h
deleted file mode 100644
index d2aa1795..00000000
--- a/utility/mount-helpers.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* Copyright (c) 2012 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.
- *
- * Header file for mount helpers.
- */
-#ifndef _MOUNT_HELPERS_H_
-#define _MOUNT_HELPERS_H_
-
-/* General utility functions. */
-uint64_t blk_size(const char *device);
-int remove_tree(const char *tree);
-int runcmd(const gchar *argv[], gchar **output);
-int same_vfs(const char *mnt_a, const char *mnt_b);
-char *stringify_hex(uint8_t *binary, size_t length);
-uint8_t *hexify_string(char *string, uint8_t *binary, size_t length);
-void shred(const char *keyfile);
-
-/* Loopback device attach/detach helpers. */
-gchar *loop_attach(int fd, const char *name);
-int loop_detach(const gchar *loopback);
-int loop_detach_name(const char *name);
-
-/* Encrypted device mapper setup/teardown. */
-int dm_setup(uint64_t bytes, const gchar *encryption_key, const char *name,
- const gchar *device, const char *path, int discard);
-int dm_teardown(const gchar *device);
-char *dm_get_key(const gchar *device);
-
-/* Sparse file creation. */
-int sparse_create(const char *path, uint64_t bytes);
-
-/* Filesystem creation. */
-int filesystem_build(const char *device, uint64_t block_bytes,
- uint64_t blocks_min, uint64_t blocks_max);
-int filesystem_resize(const char *device, uint64_t blocks, uint64_t blocks_max);
-
-/* Encrypted keyfile handling. */
-char *keyfile_read(const char *keyfile, uint8_t *system_key);
-int keyfile_write(const char *keyfile, uint8_t *system_key, char *plain);
-
-#endif /* _MOUNT_HELPERS_H_ */